-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for [env] section in .cargo/config.toml #9175
Conversation
This adds support for an `[env]` section in the config.toml files. Environment variables set in this section will be applied to the environment of any processes executed by cargo. ``` [env] FOOBAR = "Apple" PATH_TO_SOME_TOOL = { value = "bin/tool", relative = true } USERNAME = { value = "test_user", force = true } ```
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @ehuss (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
Fix formatting errors
Added the `-Z configurable-env` option which controls whether the data from the [env] section is used. Updated the tests to pass the flag and to masquerade as the nightly cargo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR! Since it's been a few months since I've at least thought about this could you detail your expected use case with this as well? I'm not sure if this should close #4121 since that seems like a different feature request for Cargo
src/cargo/util/config/mod.rs
Outdated
@@ -1244,6 +1248,39 @@ impl Config { | |||
&self.progress_config | |||
} | |||
|
|||
/// Create an EnvConfigValue hashmap from the "env" table | |||
fn get_env_config(&self) -> CargoResult<EnvConfig> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to do custom serde deserialization (e.g. via #[serde(untagged)]
) instead of having custom deserialization logic here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I tried that originally and could not get it to work. I had something like:
#[derive(Debug, Deserialize)]
#[serde(transparent)]
pub struct EnvConfig {
vars: HashMap<String, EnvConfigValue>
}
#[derive(Debug, Deserialize)]
#[serde(untagged)]
pub enum EnvConfigValue {
Simple(String),
WithOptions{
value: Value<String>,
force: bool,
relative: bool,
}
}
The problem was serde would never parse the Value<T>
type in the WithOptions
variant, it worked if it was a regular String
. I'm not sure why, maybe the entire "path" from the root of the deserialization needs to be Value<T>
types in order for them to be handle correctly in some inner struct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this structure may work instead?
#[derive(Debug, Deserialize)]
#[serde(untagged)]
pub enum EnvConfigValue {
Simple(String),
WithOptions(WithOptions),
}
#[derive(Debug, Deserialize)]
pub struct WithOptions {
value: Value<String>,
force: bool,
relative: bool,
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, that doesn't work either. It seems like untagged
and the Value<T>
types do not play nicely together, it will never select a variant with that type. Latest commit does contain a struct/enum layout that does work though. So no more custom logic.
My specific use case is that the rust-cpython and pyo3 crates both look for a
It seems to be a common thread that comes up during any search for "environment variables in cargo", crates people are using need to find libraries or tools (such as openssl, ffmpeg, python) and the crates use environment variables for that. If you have those dependencies at a known relative location you prefer not to have to rely on global environment variables for that. You can set them locally before you run You are right, I don't think it solves every aspect of #4121 because there are two different use cases in that issue and the comments. What some would like is a "prebuild" script that runs before dependencies are built that would allow you to set environment variables (and maybe some other settings) that the dependencies would consume. I would love to have a prebuild script myself, but I know there is some reticence about going down that road. |
I confirm we have exactly the same use case. |
Thanks for the explanation! That all sounds quite reasonable to me and I'd be happy to r+ this especially given that it's unstable. I think we'll want more team sign-off once a motion is made to stabilize, but for now seems good! |
`untagged` enum variants are not recognised by serde if the variant contains a `Value<T>` type. This change uses an transparent "inner" enum `Value<T>` member, which is handled correctly by serde.
@bors: r+ Looks great to me, thanks! |
📌 Commit 05acf73 has been approved by |
☀️ Test successful - checks-actions |
This is going to be very helpful for a number of my projects. Thanks guys. |
Big thanks to @wickerwaka for implementing this! I guess #8839 can also be closed based on this? |
Update cargo 11 commits in bf5a5d5e5d3ae842a63bfce6d070dfd438cf6070..572e201536dc2e4920346e28037b63c0f4d88b3c 2021-02-18 15:49:14 +0000 to 2021-02-24 16:51:20 +0000 - Pass the error message format to rustdoc (rust-lang/cargo#9128) - Fix test target_in_environment_contains_lower_case (rust-lang/cargo#9203) - Fix hang on broken stderr. (rust-lang/cargo#9201) - Make it more clear which module is being tested when running cargo test (rust-lang/cargo#9195) - Updates to edition handling. (rust-lang/cargo#9184) - Add --cfg and --rustc-cfg flags to output compiler configuration (rust-lang/cargo#9002) - Run rustdoc doctests relative to the workspace (rust-lang/cargo#9105) - Add support for [env] section in .cargo/config.toml (rust-lang/cargo#9175) - Add schema field and `features2` to the index. (rust-lang/cargo#9161) - Document the default location where cargo install emitting build artifacts (rust-lang/cargo#9189) - Do not exit prematurely if anything failed installing. (rust-lang/cargo#9185)
Perhaps there should be a test that shows what happens if a dependency requires an environment variable. I tried testing this change in that manner with an environment variable that points to the path of a shared library. |
Could you provide some more details on this? Environment variables are getting set for both |
Is there a way to obtain the same functionality of this Cargo.toml env section from a |
@wickerwaka Sorry for the late reply. Here's an example I'm using with https://github.com/Twinklebear/oidn-rs:
cargo build executes just fine, however cargo run will see an error about not finding the shared object file. I'm assuming this is because at runtime these environment variables are not used. |
Shouldn't this have a tracking issue for the |
Sure, posted #9539 as a tracking issue. |
This adds support for an
[env]
section in the config.toml files. Environment variables set in this section will be applied to the environment of any processes executed by cargo.This is implemented to follow the recommendations in #8839 (comment)
Variables have optional
force
andrelative
flags.force
means the variable can override an existing environment variable.relative
means the variable represents a path relative to the location of the directory that contains the.cargo/
directory that contains theconfig.toml
file. A relative variable will have an absolute path prepended to it before setting it in the environment.Fixes #4121