Should cargo read all Cargo.tomls in a workspace when building one specific crate?

In https://hg.mozilla.org/mozilla-central / https://github.com/mozilla/gecko, we have a global workspace, with a few members. Then we have different kinds of builds that may of may not build the entire set of members.

One of those builds only builds toolkit/crashreporter/rust, and the only dependency that crash has is rustc-demangle, which has no dependency.

And while it’s not visible when building with a recent version of cargo/rust, I somehow tried to build with an older version (1.27), which was what we claimed to be the minimum supported. And it turns out, because cargo apparently reads every Cargo.toml in the workspace, it fails because some unrelated crates have an edition set in their Cargo.toml, and that was still unstable in 1.27.

Steps to reproduce:

  • Clone one of the repos mentioned above.
  • rustup toolchain install 1.27.0
  • From the top directory in the clone, run cargo +1.27.0 rustc --manifest-path toolkit/crashreporter/rust/Cargo.toml --lib.

That fails with:

error: failed to parse manifest at `/home/glandium/gecko/js/src/wasm/cranelift/Cargo.toml`

Caused by:
  editions are unstable

Caused by:
  feature `edition` is required

this Cargo does not support nightly features, but if you
switch to nightly channel you can add
`cargo-features = ["edition"]` to enable this feature

Doing the same with 1.30 instead of 1.27 fails with:

error: failed to parse manifest at `/home/glandium/gecko/media/webrtc/signaling/src/sdp/rsdparsa_capi/Cargo.toml`

Caused by:
  feature `rename-dependency` is required

this Cargo does not support nightly features, but if you
switch to nightly channel you can add
`cargo-features = ["rename-dependency"]` to enable this feature
1 Like

I think this is the expected behavior. The core property of the workspace is that all crates share the same Cargo.lock. Cargo needs to verify that the lock file matches Cargo.tomls, and that requires reading and understanding them.

2 Likes

That it verifies the entire lock is how it does things now. But strictly speaking, Cargo doesn’t need to do that. It needs to verify that what’s relevant to what it’s going to build matches the corresponding Cargo.tomls.

That depends on what properties do we want from a lock file. Let’s say that there are unrelated crates in the workspace, A and B, which both depend on non-workspace crate C. First, we build workspace fully, so Cargo.lock is up to date. Then, we change B’s Cargo.toml to forbid the specific minor version of C that is currently use. Now, what could happen when we build A?

  • we can parse Cargo.tomls from the whole workspace, and notice that we need to change the version of C dependency (this is the current behavior)
  • we can very Cargo.lock only against our own Cargo.toml, and build with a version of C which no longer works for workspace as a whole

Both of this are valid options. However, the first one maintains an important invariant that, if cargo builds something, then Cargo.lock is valid.

We don’t need to read all Cargo.tomls if we are ready to sacrifice “lock file is always valid” invariant.

4 Likes

The vast majority of the time, there aren’t any modifications to take care of.