Closed
Description
There is a scenario where cargo fails to rebuild when the execution of a build script is interrupted (such as hitting ctrl-c). There are a variety of ways this can happen, the test below illustrates one way.
The fundamental problem is that the fingerprint does not track enough information about the execution of a build script as a dependency. #6720 added tracking the invoked.timestamp
file, but that is not sufficient.
I've been pondering various ways to fix this, but not loving the options. I would be interested if anyone has any more ideas. Bonus points if both this and #6733 can be fixed. Some options:
- Build script fingerprint of registry dependencies is not tracked in fingerprint. #6733 mentions adding the info from
build_script_local_fingerprints
, but there are some complications with updating that after the build is done (it would need to do everything thatprepare_build_cmd
does, too). - Add another file that is written in the fingerprint dir that tracks the completion of running the build script, perhaps with a sequence number bumped each time it is run.
- When the build script starts, write
invoked.timestamp.start
(and deleteinvoked.timestamp
) and then when the build script succeeds, rename it toinvoked.timestamp
. I think this should work, but I'm not sure. - (Crazy) Switch to a database for fingerprint tracking to make it easier to track dependencies.
Example
(This currently fails on the last line where the build succeeds when it should fail.)
#[test]
fn script_fails_stay_dirty() {
let p = project()
.file(
"build.rs",
r#"
mod helper;
fn main() {
println!("cargo:rerun-if-changed=build.rs");
helper::doit();
}
"#,
)
.file("helper.rs", "pub fn doit() {}")
.file("src/lib.rs", "")
.build();
p.cargo("build").run();
p.change_file("helper.rs", r#"pub fn doit() {panic!("Crash!");}"#);
p.cargo("build")
.with_stderr_contains("[..]Crash![..]")
.with_status(101)
.run();
// There was a bug where this second call would be "fresh".
p.cargo("build")
.with_stderr_contains("[..]Crash![..]")
.with_status(101)
.run();
}