What is the correlation between two cargo.toml in the file hierarchy

What exact is the correlation between cargo.toml files in different directories?

Today I've bumped into an issue when trying to run cargo tests in my directory.

I do understand the "error". But I'm not quite comfortable with it yet: basically my tree structure was something like this:

.
├── Cargo.lock
├── Cargo.toml
├── README.md
├── ch8_3_human_resources
│   ├── Cargo.lock
│   ├── Cargo.toml
│   ├── src
│   │   ├── database.rs
│   │   ├── lib.rs
│   │   └── main.rs
│

The "problem" I had was that I have moved files from ./src/main.rs into this 8_3 project, but the Cargo.toml was "left hanging" there.

What surprised me is that I was at the directory ch8_3_human_resources , which I thought was considered a "standalone" project.

I had no idea of this "fetch the parent cargo.toml" feature.

I did read the cargo documentation and couldn't find anywhere a documentation between multiple cargo.toml files in the file structure.

Does the parent project affects the ch8_3_human_resources project in any way? Are stuff like dependencies "inherited" by the child project? Is the parent project implicitly correlated to projects installed in the subdirectory?

When I do a cargo run in the parent, will they consider all subdirectories as part of the project and will build everything there?

You might be interested in learning about Cargo workspaces: Cargo Workspaces - The Rust Programming Language

If the top-level Cargo.toml file is not a workspace with ch8_3_human_resources as a member, it shouldn't affect your ch8_3_human_resources crate. What is the error you've encountered?

The error I've found, while issuing a cargo test at the directory ch8_3_human_resources was;

abpicoli@DESKTOP-EPFPMPH:/mnt/e/projetos/my_rust_journal/ch8_3_human_resources$ cargo test
error: failed to parse manifest at `/mnt/e/projetos/my_rust_journal/Cargo.toml`

Caused by:
  no targets specified in the manifest
  either src/lib.rs, src/main.rs, a [lib] section, or [[bin]] section must be present

That is, cargo did try to fetch the parent directory and look for cargo.toml files there. And then rejected the child build.

That's an error you should not encounter if ch8_3_human_resources has a Cargo.toml file, as is suggested by your directory tree, are you sure it is present?

See answer below.

I did read the documentation about workspaces before posting this message. What is not clear is if is there an "implicit" workspace implied just by the fact that the parent directory has a cargo.toml file or not.

Yes, because when I comment the cargo.toml in the parent directory to cargo.toml.off or simply add a src/lib.rs in the parent directory, cargo resumed working normally.

Well... normally in the sense of ... "BOOM!" with all the errors in compilation and such :smiley:

Hm, very interesting. I thought if any package farther up the file system hierarchy doesn't explicitly contain the package as a workspace member it will have its own workspace. But I tested it locally and you are right, Cargo tries to get the Cargo.toml file that is highest up the file tree as the workspace manifest. So you need to explicitly exclude it from the workspace of the top-level package.

You can do so by adding an empty [workspace] to your ch8_3_human_resources/Cargo.toml file. That makes your package have its own, stand-alone workspace. Alternatively, you can exclude ch8_3_human_resources from the workspace of the package in the directory containing ch8_3_human_resources by adding

[workspace]
exclude = ["ch8_3_human_resources"] 

to that Cargo.toml file.

1 Like

But there is something more fundamental here, right? I think that perhaps we do have a bug here.

I think it is acceptable to have a warning that hey, the parent cargo.toml is invalid, when I'm building the child.

But not automatically consider that if there is a cargo.toml somewhere in the parent hierarchy, everything must be valid to check if there is a workspace definition somewhere.

Just did another test:

abpicoli@DESKTOP-EPFPMPH:/mnt/e/projetos$ touch Cargo.toml
abpicoli@DESKTOP-EPFPMPH:/mnt/e/projetos$ cd my_rust_journal/ch8_human_resources
-bash: cd: my_rust_journal/ch8_human_resources: No such file or directory
abpicoli@DESKTOP-EPFPMPH:/mnt/e/projetos$ cd my_rust_journal/ch8_3*
abpicoli@DESKTOP-EPFPMPH:/mnt/e/projetos/my_rust_journal/ch8_3_human_resources$ cargo test
error: failed to parse manifest at `/mnt/e/projetos/Cargo.toml`

Caused by:
  virtual manifests must be configured with [workspace]

And then going even further:

touch /mnt/e/Cargo.toml
rm /mnt/e/projetos/Cargo.toml
abpicoli@DESKTOP-EPFPMPH:/mnt/e/projetos/my_rust_journal/ch8_3_human_resources$ cargo test
error: failed to parse manifest at `/mnt/e/Cargo.toml`

Caused by:
  virtual manifests must be configured with [workspace]

Now, imagine you are somewhere in a shared server, and then some intern decides to play with rust and add an invalid cargo.toml in the / directory . As root.

Every single cargo build attempt in that server will fail. Except those with a [workspace] section inside it.

THe only point I can see is that right now there is very likely a lot of people using this "bug" as a feature :smiley:

I don't think so. It's just how Cargo discovers workspaces:

When inside a subdirectory within the workspace, Cargo will automatically search the parent directories for a Cargo.toml file with a [workspace] definition to determine which workspace to use.

We just short-circuit the search by creating a workspace for our package.

I find that highly unlikely and if your interns have access to the root directory with root access, you have different problems than a broken /Cargo.toml file :smile:

3 Likes

If an intern has root access to a shared server, I’d say you have worse problems than Cargo’s workspace discovery algorithm :smile:

People do run into problems with broken Cargo.toml in their home directories, running builds under /tmp/, and the like.

Here's a related RFC (accepted by the Cargo team).

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.