Skip to content
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

fix(build-rs): Implicitly report rerun-if-env-changed for input #14911

Merged
merged 2 commits into from
Dec 11, 2024

Conversation

epage
Copy link
Contributor

@epage epage commented Dec 9, 2024

What does this PR try to resolve?

As we abstract away the env variables, users can't do a good job of
reporting these, so we'll do it ourselves.

How should we test and review this PR?

This isn't the shortest path to this solution because I had originally designed this like more like build_env but in a way to allow users to choose what policies they want (rather than baking in their HOST/TARGET scheme).
I decided to not support a custom env yet to make this more incremental and to see what feedback we get but I left the implementation in a way that would make it easy to support it.

I made is_present part of Env because I was unsure if callers of the API would want to handle that differently for rerun-if-env-changed or other parts.

Additional information

CC @CAD97

I made a dedicated `Env::is_present` function in case we want to handle
`rerun-if-env-changed` differently in that case.
@rustbot
Copy link
Collaborator

rustbot commented Dec 9, 2024

r? @weihanglo

rustbot has assigned @weihanglo.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Dec 9, 2024
Copy link
Contributor

@CAD97 CAD97 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 on direction from me.

cargo::rerun-on-env-changed is purely additive and doesn't disable a default watch set like cargo::rerun-on-changed does, so emitting it automatically seems like a good idea.

Although, I'm not sure it's actually needed for the CARGO_ environment? It depends on how aggressive Cargo is at caching the buildscript and if any of this environment can change without necessarily requiring a recompile.

crates/build-rs/src/input.rs Outdated Show resolved Hide resolved
fn is_present(key: &str) -> bool {
var_os(key).is_some()
}

#[track_caller]
fn var_or_panic(key: &str) -> std::ffi::OsString {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing this to e.g. ENV.require(key) may be a good idea to keep env access more uniform, and paves the way towards maybe supporting a different protocol in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I intentionally kept it off.

I see two ways of going

  • Minimum interface for what is needed
  • Every input being an inherent function on the trait

I went with the former. I only included is_present on the trait because I was concerned about what the right policy is for re-run if changed in that case. The direction I went with doesn't specialize it but I figured I'd still leave that door open. I'm not seeing a reason to specialize this atm and would rather wait for use cases rather than speculatively adding functionality to the trait.

Since we can add this as an inherent function, we can likely do so without a breaking change (yes, there are caveats). Even then, its not a big deal to make a breaking change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Especially since the trait/type aren't pub (yet?) and are just internal helpers.

@epage
Copy link
Contributor Author

epage commented Dec 9, 2024

Although, I'm not sure it's actually needed for the CARGO_ environment? It depends on how aggressive Cargo is at caching the buildscript and if any of this environment can change without necessarily requiring a recompile.

The only cases I saw us specially handle are

let current = if key == CARGO_ENV {
Some(cargo_exe.to_str().ok_or_else(|| {
format_err!(
"cargo exe path {} must be valid UTF-8",
cargo_exe.display()
)
})?)
} else {
if let Some(value) = gctx.env_config()?.get(key) {
value.to_str()
} else {
gctx.get_env(key).ok()
}
};

and
// This is a bit of a tricky statement, but here we're *removing* the
// dependency on environment variables that were defined specifically for
// the command itself. Environment variables returned by `get_envs` includes
// environment variables like:
//
// * `OUT_DIR` if applicable
// * env vars added by a build script, if any
//
// The general idea here is that the dep info file tells us what, when
// changed, should cause us to rebuild the crate. These environment
// variables are synthesized by Cargo and/or the build script, and the
// intention is that their values are tracked elsewhere for whether the
// crate needs to be rebuilt.
//
// For example a build script says when it needs to be rerun and otherwise
// it's assumed to produce the same output, so we're guaranteed that env
// vars defined by the build script will always be the same unless the build
// script itself reruns, in which case the crate will rerun anyway.
//
// For things like `OUT_DIR` it's a bit sketchy for now. Most of the time
// that's used for code generation but this is technically buggy where if
// you write a binary that does `println!("{}", env!("OUT_DIR"))` we won't
// recompile that if you move the target directory. Hopefully that's not too
// bad of an issue for now...
//
// This also includes `CARGO` since if the code is explicitly wanting to
// know that path, it should be rebuilt if it changes. The CARGO path is
// not tracked elsewhere in the fingerprint.
//
// For cargo#13280, We trace env vars that are defined in the `[env]` config table.
on_disk_info.env.retain(|(key, _)| {
env_config.contains_key(key) || !rustc_cmd.get_envs().contains_key(key) || key == CARGO_ENV
});

Which makes sense. We can set a lot and we likely don't want to re-run if all of it has changed. Some we'll rebuild for anyways because some of the fingerprint has changed but I figure its better to be over aggressive than under aggressive or having to maintain a perfectly curated set of ENVs

As we abstract aware the env variables, users can't do a good job of
reporting these, so we'll do it ourselves.

We could make the traits public and take and explicit `env` parameter.
I figured we can wait until there is a motivating use case.
`build_env` does have a fancier `Env` impl where you pass it HOST and
TARGET and it automatically looks up values for those with a fallback
scheme.
@epage epage force-pushed the build-rs-env branch 2 times, most recently from 2a6a33d to 0227c51 Compare December 10, 2024 18:38
@rustbot rustbot added the A-build-scripts Area: build.rs scripts label Dec 10, 2024
Copy link
Member

@Muscraft Muscraft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This seems like a great incremental step overall.

@Muscraft Muscraft added this pull request to the merge queue Dec 10, 2024
Copy link
Member

@weihanglo weihanglo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which makes sense. We can set a lot and we likely don't want to re-run if all of it has changed. Some we'll rebuild for anyways because some of the fingerprint has changed but I figure its better to be over aggressive than under aggressive or having to maintain a perfectly curated set of ENVs

Agree with this. While we don't recommend user to hand-write rerun-if-env-changed with cargo internal envs, as a build script helper crate it should be fine as an implementation detail.

Merged via the queue into rust-lang:master with commit 298e403 Dec 11, 2024
20 checks passed
@epage epage deleted the build-rs-env branch December 11, 2024 01:33
bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 14, 2024
Update cargo

18 commits in 20a443231846b81c7b909691ec3f15eb173f2b18..7847c03965260b5dcc8d93218d6af295a717abb6
2024-12-06 21:56:56 +0000 to 2024-12-13 18:06:39 +0000
- fix(base): Support bases in patches in virtual manifests  (rust-lang/cargo#14931)
- fix(resolver): Report invalid index entries  (rust-lang/cargo#14927)
- feat: Implement `--depth workspace` for `cargo tree` command (rust-lang/cargo#14928)
- fix(resolver): In errors, show rejected versions over alt versions (rust-lang/cargo#14923)
- fix: emit_serialized_unit_graph uses the configured shell (rust-lang/cargo#14926)
- fix(script): Don't override the release profile (rust-lang/cargo#14925)
- feature(SourceId): use stable hash from rustc-stable-hash (rust-lang/cargo#14917)
- fix(resolver): Don't report all versions as rejected  (rust-lang/cargo#14921)
- fix(resolver): Report unmatched versions, rather than saying no package (rust-lang/cargo#14897)
- fix(build-rs): Implicitly report rerun-if-env-changed for input (rust-lang/cargo#14911)
- a faster hash for ActivationsKey (rust-lang/cargo#14915)
- feat(build-script): Pass CARGO_CFG_FEATURE  (rust-lang/cargo#14902)
- fix(build-rs): Correctly refer to the item in assert (rust-lang/cargo#14913)
- chore: update auto-label to include build-rs crate (rust-lang/cargo#14912)
- refactor: use Path::push to construct remap-path-prefix (rust-lang/cargo#14908)
- feat(build-rs): Add the 'error' directive (rust-lang/cargo#14910)
- fix(build-std): determine root crates by target spec `std:bool` (rust-lang/cargo#14899)
- SemVer: Add section on RPIT capturing (rust-lang/cargo#14849)
bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 14, 2024
Update cargo

19 commits in 20a443231846b81c7b909691ec3f15eb173f2b18..769f622e12db0001431d8ae36d1093fb8727c5d9
2024-12-06 21:56:56 +0000 to 2024-12-14 04:27:35 +0000
- test(build-std): dont require rustup (rust-lang/cargo#14933)
- fix(base): Support bases in patches in virtual manifests  (rust-lang/cargo#14931)
- fix(resolver): Report invalid index entries  (rust-lang/cargo#14927)
- feat: Implement `--depth workspace` for `cargo tree` command (rust-lang/cargo#14928)
- fix(resolver): In errors, show rejected versions over alt versions (rust-lang/cargo#14923)
- fix: emit_serialized_unit_graph uses the configured shell (rust-lang/cargo#14926)
- fix(script): Don't override the release profile (rust-lang/cargo#14925)
- feature(SourceId): use stable hash from rustc-stable-hash (rust-lang/cargo#14917)
- fix(resolver): Don't report all versions as rejected  (rust-lang/cargo#14921)
- fix(resolver): Report unmatched versions, rather than saying no package (rust-lang/cargo#14897)
- fix(build-rs): Implicitly report rerun-if-env-changed for input (rust-lang/cargo#14911)
- a faster hash for ActivationsKey (rust-lang/cargo#14915)
- feat(build-script): Pass CARGO_CFG_FEATURE  (rust-lang/cargo#14902)
- fix(build-rs): Correctly refer to the item in assert (rust-lang/cargo#14913)
- chore: update auto-label to include build-rs crate (rust-lang/cargo#14912)
- refactor: use Path::push to construct remap-path-prefix (rust-lang/cargo#14908)
- feat(build-rs): Add the 'error' directive (rust-lang/cargo#14910)
- fix(build-std): determine root crates by target spec `std:bool` (rust-lang/cargo#14899)
- SemVer: Add section on RPIT capturing (rust-lang/cargo#14849)
@rustbot rustbot added this to the 1.85.0 milestone Dec 14, 2024
github-actions bot pushed a commit to rust-lang/miri that referenced this pull request Dec 15, 2024
Update cargo

19 commits in 20a443231846b81c7b909691ec3f15eb173f2b18..769f622e12db0001431d8ae36d1093fb8727c5d9
2024-12-06 21:56:56 +0000 to 2024-12-14 04:27:35 +0000
- test(build-std): dont require rustup (rust-lang/cargo#14933)
- fix(base): Support bases in patches in virtual manifests  (rust-lang/cargo#14931)
- fix(resolver): Report invalid index entries  (rust-lang/cargo#14927)
- feat: Implement `--depth workspace` for `cargo tree` command (rust-lang/cargo#14928)
- fix(resolver): In errors, show rejected versions over alt versions (rust-lang/cargo#14923)
- fix: emit_serialized_unit_graph uses the configured shell (rust-lang/cargo#14926)
- fix(script): Don't override the release profile (rust-lang/cargo#14925)
- feature(SourceId): use stable hash from rustc-stable-hash (rust-lang/cargo#14917)
- fix(resolver): Don't report all versions as rejected  (rust-lang/cargo#14921)
- fix(resolver): Report unmatched versions, rather than saying no package (rust-lang/cargo#14897)
- fix(build-rs): Implicitly report rerun-if-env-changed for input (rust-lang/cargo#14911)
- a faster hash for ActivationsKey (rust-lang/cargo#14915)
- feat(build-script): Pass CARGO_CFG_FEATURE  (rust-lang/cargo#14902)
- fix(build-rs): Correctly refer to the item in assert (rust-lang/cargo#14913)
- chore: update auto-label to include build-rs crate (rust-lang/cargo#14912)
- refactor: use Path::push to construct remap-path-prefix (rust-lang/cargo#14908)
- feat(build-rs): Add the 'error' directive (rust-lang/cargo#14910)
- fix(build-std): determine root crates by target spec `std:bool` (rust-lang/cargo#14899)
- SemVer: Add section on RPIT capturing (rust-lang/cargo#14849)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-build-scripts Area: build.rs scripts S-waiting-on-review Status: Awaiting review from the assignee but also interested parties.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants