I'm working on a tool that wraps multiple cargo build
invocations and trying to make a progress bar for the overall output. Towards this end, I need to know, for each invocation, how many artifacts the cargo build
needs to build, which I believe is the point of the cargo metadata
command (and corresponding cargo_metadata
crate that wraps it for Rust).
The problem is that I'm building in a workspace where I have something like the following setup:
- Crate A exists in my workspace.
- Crate B has an optional dependency on Crate A, if the
a
feature is supplied. - Crate C depends on Crate B but doesn't require the
a
feature. - Crate D depends on Crate B and requires the
a
feature.
When I run cargo metadata
, it builds the dependency tree for the entire workspace, so I see that Crate B depends on Crate A (because Crate D requires the feature, and features are additive). However, when I run cargo build -p C
to only build Crate C, the feature is not enabled (because Crate D doesn't appear) so only crates B and C are built. Thus, naively reading the dependency tree provided says 3 crates, but then cargo build
only reports 2 crates.
The docs for cargo metadata
suggest that there is some notion of a "current package" which controls which features are enabled and which dependencies are listed. It seems like I should be able to set the "current package" to Crate C, which will set the features based on that. However, I can't find anything in the documentation explaining how to do that, and setting the --manifest-path
argument to the manifest for Crate C instead of the overall workspace doesn't change anything.
Am I missing some way of setting this "current crate" that lets me achieve this behavior? Or am I reading something into the docs that isn't intended and there's actually now way to accomplish this?
I can get this behavior I want by parsing the packages
field of the cargo metadata
output, and manually reimplementing the feature unification and dependency selection logic done by cargo, but I'd prefer to not do all that work if I don't have to.