rename __set_env to env and make it un-hidden#1656
Conversation
NobodyXu
left a comment
There was a problem hiding this comment.
Thank you!
I went with env (same name as the env member) for consistency with std::process::Command but of course we could bikeshed that.
This is also consistent with other function naming (i.e. pic), sothe naming LGTM
If we're going to expose this, would we want to make sure all child processes see these variables?
Yeah I think should be
@oconnor663 do you want to do all of that within this PR, or do you want me to merge this and cut a release now? |
madsmtm
left a comment
There was a problem hiding this comment.
I think we should support something like this! The reason I haven't added it myself is that cc itself accesses environment variables with std::env::var, and I wanted it to be completely clear what those do?
E.g. if I call build.env("CC", "clang"), does that change the compiler to be clang, or must I do std::env::set_var("CC", "clang")? I tend to think that the answer is "yes", but I'm unsure if there could be a downside to it?
(Whatever we figure out here should be documented in Build::env).
I agree and we should change I can't think of downside doing so |
|
Kcc @madsmtm I'd like to merge this and open another PR to update |
I'd prefer to do that first, and also update all the tests that use |
Thanks you are right, but I'm wondering if we should try to access And I'm think we don't need to emit a rerun for it, given that it is set at the build script? Line 3841 in 0767349
Do we really need to override those? Is there any use case?
Yes that does sound much better, given that this PR can be edited by maintainer, I could make some commits later when I have time |
Yes to both of those.
Hmm, not that I really know of? But we'd currently allow overwriting e.g. |
|
I kinda think there's a few semantically different "kinds" of environment variables:
I'm fairly certain that I'm unsure about category 2 and 3, but I'm somewhat leaning towards not allowing overriding them? They're all meant to be controlled by the end user, not the build script / |
|
Yeah agree, however I think env wise, keeping |
i think WAM/WASI, know wrapper might be worth overriding, as there's currently no way to override it using cc api |
|
I actually think the whole thing should be refactored a lot. For example, Maybe the design I want should instead be something like: // Free method, does not need to touch `Build` at all.
#[allow(clippy::disallowed_methods)] // Cargo env, no need for rerun-if-env-changed
fn cargo_env_var(key: &str) -> Option<OsString> {
std::env::var_os(key)
}
impl Build {
/// Look up an environment variable, but allow it to be overwritten by `Build::env`.
fn get_env_overridable(&self, key: &str) -> Option<Cow<'static, OsStr>> {
// Try to look up in overrides first.
if let Some((_, value)) = self.env_override.iter().find(|(k, _)| k == key) {
return Some(Cow::Borrowed(value));
}
// If not found in overrides, look up from environment.
Some(Cow::Owned(self.get_cc_env(key)?))
}
/// Look up an environment variable, and tell Cargo that we used it.
#[allow(clippy::disallowed_methods)] // We emit rerun-if-env-changed
fn get_env(&self, key: &str) -> Option<OsString> {
// Tell Cargo that we're going to depend on this env var.
if self.emit_rerun_if_env_changed && key != "PATH" {
self.cargo_output.print_metadata(&format_args!("cargo:rerun-if-env-changed={v}"));
}
// And look it up in the environment.
Some(std::env::var_os(key)?)
}
}And we'd have environment variable "category" 1 call
I would rather start with them not being override-able, we can always allow it in the future. That is, if we make category 2 and 3 call |
|
I think part of the reason we cache it, is to avoid emitting the re-run tag, which does involve some I/O and could be expensive, and could even block the thread? |
I guess, but still, it's gonna be orders of magnitude less compared to the C compiler invocation itself. Anyhow, I'm not gonna block on that, |
|
I can change it to just a Sorry I don't know why I was being stubborn on either cache the entire thing or nothing mindset |
Still feels unnecessary to me, especially since most users are gonna run I think if we want to do caching, I'd probably prefer to have it at a higher level; e.g. instead of caching But that's also dangerous if you suddenly change To expand a bit more on why I'm against caching in To give a concrete example, what if the user did: let mut build = Build::new().file("foobar.c");
// We don't want metadata for this compilation run.
build.cargo_metadata(false).compile("foo");
// But for this one, we do!
build.cargo_metadata(true).compile("bar");It's not a use-case I feel is necessary to support, and I know we could solve it by including But yeah, I'm digressing, again, I'm fine with either form of caching ( |
|
Yeah letting cargo do the caching is right thing to do. Too much can change in the env, I'll just remove the caching |
So that user can change self.env of each Build and actually change behavior
Removed env_cache from BuildCache structure and related code.
Removed unused Env type definition.
|
cc @madsmtm I've removed the env caching, please take another look |
|
cc @madsmtm pinging |
|
I plan to merge this tomorrow to include this in next release, if no further feedback is given |
There was a problem hiding this comment.
IMO, calling build.env("foo", "bar").get_compiler().env() should return the env vars set, same with and build.env("foo", "bar").get_compiler().to_command().get_envs().
I also still think we should be deliberate about envs that are overridable with a get_env_overridable or similar.
|
I can also do these in a follow-up PR, as long as we're fine with delaying the release until the follow-up lands too. |
Yep I can delay that until it's done, that's fine with me @madsmtm |
|
I filed #1682 to implement the changes I propose. |
Related to #1655. I went with
env(same name as theenvmember) for consistency withstd::process::Commandbut of course we could bikeshed that.One doubt I have about this change is that it looks like there are some places where we don't consult
self.envwhen buildingCommandobjects to invoke. Here's one:cc-rs/src/lib.rs
Lines 1809 to 1817 in 8124fc5
If we're going to expose this, would we want to make sure all child processes see these variables?
Also I'm not sure what would be a clean way to test this. So this PR is more of a discussion starter :)