We are building both compiled libraries (FFI) and executables for distribution. As part of this process, we need a simple and reliable way to to output target dependency information in a machine readable format:
-
So that we can build a custom SBOM
a) What are the version(s) of our dependencies
b) What features were enabled during build, etc. -
So that we can cross-check this list against a dependency/license allow-list. We're not looking for anything fancy in terms of license compatibility. We have the allow-list for that.
I've played with various things in the ecosystem and I can't seem to find anything that works well or is guaranteed to keep working in the future. Here are a few options I've explored:
== cargo metadata ==
This seems to be what everyone else uses under the hood, but it has the limitation that it resolves everything in the workspace collectively, whereas I only want a dependency list for 1) a single target and 2) for the features enabled on that target
https://github.com/rust-lang/cargo/issues/7754
== cargo license ==
This was working well for a time, until we introduced features. Some of our customers want a build that excludes certain features because of licensing/footprint issues.
== cargo tree ==
Cargo tree actually does exactly what we need:
cargo tree -e normal -p target --no-default-features
The problem is the output isn't in a machine readable format! JSON would be ideal.
== parsing cargo build ==
You can tell cargo to output build events in JSON with:
cargo build -p target --message-format json > build.log
And then use structs defined in cargo-metadata to read them. So we could do our builds outputting this log, and then look back at the log. This might work for a time if we're willing to parse the PackageId string, but the representation isn't guaranteed to be stable:
Question
Is there some easier way of producing what I need? Am I missing something or is this a gap in the ecosystem ATM?