Cargo workspace and dependices building

I have a larg-ish cargo workspace with a lot of dependices. I was under the impression that one of the point of the workspace was joint depndency resolution such that you would always use the same ones.

However, though the dependencies seems to be resolved correctly to the same versions there still seem to be a lot of unneeded re-building going on. If I for example:

  1. Clean out all cargo temporary files
  2. cargo build --release # This will build all crates and binaries in my workspace
  3. cargo build --release -p one_single_binary # This rebuilds all external and workspace dependencies
  4. cd one_single_binary && cargo build --release # This again rebuilds everything

I would have expected step 3 & 4 to effectivly be no-ops since everything is done. This is a bit painful as rebuilding all dependencies is slow and when developing and testing several crates and binaries in total leads to a lot of seemingly unecissary waiting for builds.

Is this caching simply not implemented or am I missing something that makes it impossible to actually re-use the results?

regards

I believe this is by design. Building a single crate will only take into account the feature flags of it and it's direct dependencies, and not include any feature flags enabled by other crates in the workspace.

I feel your pain... At work we have a large project with lots of crates that have different (and sometimes mutually exclusive) sets of feature flags. The project likes to rebuild itself quite a lot, especially in CI because whoever set up the jobs wrote a makefile that tests individual crates with their own sets of feature flags.

One suggestion I have is to check out sccache. It caches all builds keyed on things like the feature flags and environment variables, rather than just the most recent build like Cargo, so it tends to handle this sort of cache thrashing better.

Right - thanks. I was hoping that the workspace would solve that feature flag problem since I read that it specifically use the same set of feature flags for all crates in the workspace.

However - even if that is the case (that the feature flags resolve differently) step 2 should be identical to step 3 or step 1 (either resoled using the full workspace or only that binary) - however cargo does not seem to treat it so (since both step 2 and 3 do full re-builds).

I.e. even if I made sure that all dependencies were specified using consistent feature flags in all crates in the workspace the problem would remain.

Right - thanks. I was hoping that the workspace would solve that feature flag problem since I read that it specifically use the same set of feature flags for all crates in the workspace.

As I understand it: all builds of the workspace get the same flags for all their dependencies. But when you cargo build -p package, as it is currently defined, you're opting out of building the workspace and into non-workspace-like behavior. I'm not sure why your step 4 would rebuild after step 3, though.

What you can do instead is cargo build --release --bin one_single_binary. That way, you're selecting targets, not packages. (Unfortunately, there is no command-line option to select a single lib target in a workspace.)

I entirely agree this is unfortunate and it should be easier to get better default behavior.


One solution that some workspace-using projects apply is the so-called “workspace hack”. cargo-hakari has an explanation of what a workspace-hack is and how it works, but in brief, it is an extra package that creates dependencies from everything in the workspace to all the external dependencies, so that the feature set never changes between builds.

1 Like

Thank you for those links - I will give that a try and hopefully that solves my problem :slight_smile:

tis 20 juni 2023 kl. 23:28 skrev Kevin Reid via The Rust Programming Language Forum <notifications@rust-lang.discoursemail.com>:

How does this interact with the v2 feature resolver?

In particular, I have been considering splitting out some codegen utilities in one of my projects into a separate crate that will appear in both the dependencies and build-dependencies cargo sections with different feature flags. Will putting the codegen crate into the same workspace as the main project force the build-only features to be included in the main build as well?


Edit: After some research, this pattern is supposed to work, but there are some subtleties to consider. In particular, the build-time features need to be excluded from the default build of the codegen crate. If they aren’t, they become ordinary dependencies of the workspace and are unified normally.

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.