cargo icon indicating copy to clipboard operation
cargo copied to clipboard

Cargo fails to detect environment variable is newly set and rebuild if the environment variable is set in `config.toml`

Open usamoi opened this issue 2 years ago • 4 comments

Problem

The problem can be only reproduced if the environment variable is "not set" in the first run, and "set" in the second run.

Steps

Incorrect behaivor

.cargo/config.toml:

[env]
Z = "0"

src/main.rs:

fn main() {
    println!("{:?}", option_env!("Z"));
}

run these commands:

cargo run     # first build, output Some("0")
Z=1 cargo run # cargo does not notice the environment variable is set and runs it, output Some("0")

Correct behaivor if we do not use a config.toml

src/main.rs:

fn main() {
    println!("{:?}", option_env!("Z"));
}

run these commands:

cargo run     # first build, output None
Z=1 cargo run # cargo does know the environment variable is set and rebuilds it, output Some("1")

Correct behaivor if we change the environment variable from a value to another value

.cargo/config.toml:

[env]
Z = "0"

src/main.rs:

fn main() {
    println!("{:?}", option_env!("Z"));
}

run these commands:

Z=2 cargo run # first build, output Some("2")
Z=1 cargo run # cargo does know the environment variable changes and rebuilds it, output Some("1")

Possible Solution(s)

No response

Notes

No response

Version

cargo 1.77.0-nightly (ac6bbb332 2023-12-26)
cargo 1.75.0 (1d8b05cdd 2023-11-20)

usamoi avatar Jan 11 '24 00:01 usamoi

By the way, it may be related to question #10358 & #12434.

heisen-li avatar Jan 11 '24 08:01 heisen-li

By the way, it may be related to question #10358 & #12434.

Hmm… I don't quite think so. It is related to cargo's own dep-info file failed to track env vars from [env] table. Cargo removes those here:

https://github.com/rust-lang/cargo/blob/0c98d6ec3a3fc72683fe00963b8a55ffaa204d2a/src/cargo/core/compiler/fingerprint/mod.rs#L2017-L2019

env vars from [env] were applied to rustc_cmd in fill_env() earlier before this call.

weihanglo avatar Jan 11 '24 14:01 weihanglo

Note: #13596 was an attempt of addressing this issue. In that PR, maintainers expected that kind of environment variable detection to be in the fingerprint code, where Cargo's dep-info logic is located.

weihanglo avatar Oct 09 '24 01:10 weihanglo

#14154 is another case that Cargo's depinfo strips internal set environment variables (such as CARGO_PKG_README) causing the rebuild detection failure.

weihanglo avatar Oct 09 '24 11:10 weihanglo

#14154 is another case that Cargo's depinfo strips internal set environment variables (such as CARGO_PKG_README) causing the rebuild detection failure.

If the user just wants the environment variables in the [env] table to trigger recompilation, can we just fix that

This is a likely solution, env_keys is a HashSet contains the key defined in [env] table

    on_disk_info.env.retain(|(key, _)| {
        !rustc_cmd.get_envs().contains_key(key) || key == CARGO_ENV || env_keys.contains(key)
    });

linyihai avatar Oct 17 '24 09:10 linyihai

@linyihai

That seems worth a try!

For #14154 we could reopen if a fix doesn't cover it.

weihanglo avatar Oct 17 '24 13:10 weihanglo