rust-lang / cargo

The Rust package manager
https://doc.rust-lang.org/cargo
Apache License 2.0
12.5k stars 2.37k forks source link

Give more information to third party subcommands and/or a way to query cargo #8842

Open ChrisDenton opened 3 years ago

ChrisDenton commented 3 years ago

Describe the problem you are trying to solve

Cargo gives a veritable wealth of information to build scripts. In contrast, subcommands get a single variable: CARGO. This gives the path of the cargo binary. Useful but not much to go on.

This means if subcommands (or other third party tools) want any information they have to either reimplement parts of cargo or try to scrounge what little information they can from build-plan (unstable, unreliable) or metadata (limited).

For example, something as simple getting the default target (usually the host) or the output directory.

Describe the solution you'd like

I can think of two solutions. Implementing one does not exclude implementing the other.

  1. When starting a subcommand, set the same (or similar) environment variables to build scripts so it's almost as if the command is a build script in the root package. Obviously the variables passed to build scripts can depend on arguments passed in on the command line or perhaps even the command itself, so these values should instead be set to reasonable defaults. This would at least give subcommands a baseline to work from.

  2. Have a built in query-build command (actual name to be decided). The user of this command can pass in arguments in the same manner as how they are passed to cargo build. This would effectively do a dry run of setting up the environment for a build script but instead of invoking one, it only collects the environment variables into json. This information is then printed.

The second option would be good for any tools trying to integrate with Cargo, not just subcommands. A simplified version of it would be to just have a command that spits out some limited set of defaults. E.g., default target, output directory, rustc path, etc.

Notes

I'm not sure how easy or hard either of these is to implement. Looking at the code I'm not entirely certain where to begin.

pinkforest commented 3 years ago

Does one as an user implicitly expect to CARGO_MANIFEST_DIR being set when running any cargo command whether it is sub-command or not?

I did :)

While the documentation doesn't explicitly rule out other environment variables,

It does define only one variable gets passed down quite clearly:

Environment variables Cargo sets for 3rd party subcommands

Cargo exposes this environment variable to 3rd party subcommands (ie. programs named cargo-foobar placed in $PATH):
CARGO β€” Path to the cargo binary performing the build.

And this seems to be the truth I found the hard way :)

I would like as an user to see the environment variables like CARGO_MANIFEST_DIR passed/available as current working directory may not be optimal so I can run sub-commands same way I run my test.

I wonder what was the reasoning for these environment variables not being passed explicitly down in more numbers or was it due to accidental security through obscurity pattern to hide path(s) for good and bad whilst fearing some other information e.g. secrets could leak out to sub-command?

httmock relies on CARGO_MANIFEST_DIR when I gave relative path with some of my mocks

It works fine with cargo test but when I ran it thru sub-command tarpaulin it didn't find the env

Perhaps the document should be more explicit about warning this seemingly unexpected implicit behavior and document the reason why?

epage commented 2 years ago

I would like as an user to see the environment variables like CARGO_MANIFEST_DIR passed/available as current working directory may not be optimal so I can run sub-commands same way I run my test.

I wonder what was the reasoning for these environment variables not being passed explicitly down in more numbers or was it due to accidental security through obscurity pattern to hide path(s) for good and bad whilst fearing some other information e.g. secrets could leak out to sub-command?

For CARGO_MANIFEST_DIR, I'm assuming cargo doesn't know it. Subcommands, not cargo, accept --manifest-path for an explicit manifest to then determine the manifest dir. They then infer the manifest-path if it isn't set.

I know a lot of us use cargo_metadata for querying cargo for manifest information in our custom subcommands. I've written clap_cargo::Manifest to help with handling the optional parameter and bridging things with cargo_metadata.

I'm assuming cargo looking up CARGO_MANIFEST_DIR would add a performance hit to a lot of commands because that and other env variables will likely be insufficient and will need to call cargo_metadata anyways.

ChrisDenton commented 2 years ago

Tbh I wrote the OP early(ish) on in my Rust career when I was trying to extend Cargo with a custom command. Nowadays I'd probably write something that better details the use case I was aiming for πŸ˜€.

Now I'm more experienced I can understand why this may not be the default. Still, I do think it's worth while to have some way to figure out how Cargo collects and collates all the configuration options (e.g. from the environment, from the current directory, from CARGO_HOME, from the command line, etc),

I remember I did write a patch to output this info (via a metadata like command mentioned in the OP) but unfortunately I didn't really have the bandwidth to pursue it further at the time so I've no idea how robust it was.