You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Using rerun-if-changed to a file that changes, but changes with old timestamps, Cargo won't detect that it needs to run. For example:
Extract a tarball with file foo with timestamp 1.
cargo build with rerun-if-changed of foo. This marks the build script as timestamp 5.
Extract a different tarball with file foo with timestamp 2.
Run cargo build again, it doesn't pick up the change from timestamp 1 to 2 because both values are less than 5.
I would expect any change to the file to cause it to re-run the build script.
The real-world use case is in the rust LLVM build system. It extracts LLVM from a downloaded tarball. The rustc_llvm build script has a rerun-if-changed=/path/to/llvm-config. When rustbuild determines a new tarball needs to be downloaded, the rustc_llvm build script doesn't get the memo and doesn't get rerun. This can cause it to link against the wrong file.
Steps
The following is a test using Cargo's testsuite:
#[cargo_test]fnpast_rerun_if_changed(){// Tests that a file that changes with an old timestamp triggers a build// script to rerun. This can happen when extracting files from a tarball// which preserves the timestamps.let p = project().file("src/lib.rs","").file("build.rs",r#" fn main() { println!("cargo:rerun-if-changed=somefile"); } "#,).file("somefile","").build();// Simulate extracting some tarball.let now = std::time::SystemTime::now();let time_a = FileTime::from_system_time(now - Duration::new(60*10,0));let time_b = FileTime::from_system_time(now - Duration::new(60*5,0));let somefile = p.root().join("somefile");
filetime::set_file_times(&somefile, time_a, time_a).unwrap();
p.cargo("check").run();// Simulate extracting a different tarball, but whose timestamp is still// in the past.
p.change_file("somefile","123");
filetime::set_file_times(&somefile, time_b, time_b).unwrap();// FIXME: This should trigger a rebuild, but it currently does not.
p.cargo("check -v").with_stderr("\[COMPILING] foo [..][RUNNING] `[ROOT]/foo/target/debug/build/foo-[..]/build-script-build`[RUNNING] `rustc --crate-name foo [..][FINISHED] [..]",).run();}
Possible Solution(s)
A few possible options:
Hash the timestamp and file size of all rerun-if-changed files, and include that in the final hash (instead of just comparing the timestamps). This could potentially trigger rebuilds more often, though offhand I can't think of how it could happen.
Problem
Using
rerun-if-changedto a file that changes, but changes with old timestamps, Cargo won't detect that it needs to run. For example:foowith timestamp 1.cargo buildwithrerun-if-changedoffoo. This marks the build script as timestamp 5.foowith timestamp 2.cargo buildagain, it doesn't pick up the change from timestamp 1 to 2 because both values are less than 5.I would expect any change to the file to cause it to re-run the build script.
The real-world use case is in the rust LLVM build system. It extracts LLVM from a downloaded tarball. The
rustc_llvmbuild script has arerun-if-changed=/path/to/llvm-config. When rustbuild determines a new tarball needs to be downloaded, therustc_llvmbuild script doesn't get the memo and doesn't get rerun. This can cause it to link against the wrong file.Steps
The following is a test using Cargo's testsuite:
Possible Solution(s)
A few possible options:
Notes
No response
Version