-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Description
The fingerprint for running a build script does not include information about links
dependency build scripts. This means that if the dependent build script runs, but the top-level one does not (such as if it was cancelled, or built separately), it will not re-run the top-level build script.
Fixing this may be quite difficult. Due to the way build script Fingerprint::locals
are recomputed within the closure, the information for the links dependencies is not readily available. These Fingerprints could be shared with Arc
in Context::fingerprints
, but that would require making locals
a Mutex (or changing the entire Fingerprint to be Arc<Mutex<Fingerprint>>
). This is also complicated by the fact that build script fingerprints need access to Context::build_explicit_deps
which is not pre-populated before fingerprints are computed.
Below is a demonstration of the problem.
#[test]
fn links_interrupted_can_restart() {
// Test for a `links` dependent build script getting canceled and then
// restarted. Steps:
// 1. Build to establish fingerprints.
// 2. Change something (an env var in this case) that triggers the
// dependent build script to run again. Kill the top-level build script
// while it is running (such as hitting Ctrl-C).
// 3. Run the build again, it should re-run the build script.
let bar = project()
.at("bar")
.file(
"Cargo.toml",
r#"
[package]
name = "bar"
version = "0.5.0"
authors = []
links = "foo"
build = "build.rs"
"#,
)
.file("src/lib.rs", "")
.file(
"build.rs",
r#"
fn main() {
println!("cargo:rerun-if-env-changed=SOMEVAR");
}
"#,
)
.build();
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo"
version = "0.5.0"
authors = []
build = "build.rs"
[dependencies.bar]
path = '{}'
"#,
bar.root().display()
),
)
.file("src/lib.rs", "")
.file(
"build.rs",
r#"
use std::env;
fn main() {
println!("cargo:rebuild-if-changed=build.rs");
if std::path::Path::new("abort").exists() {
panic!("Crash!");
}
}
"#,
)
.build();
p.cargo("build").run();
// Simulate the user hitting Ctrl-C during a build.
p.change_file("abort", "");
// Set SOMEVAR to trigger a rebuild.
p.cargo("build")
.env("SOMEVAR", "1")
.with_stderr_contains("[..]Crash![..]")
.with_status(101)
.run();
fs::remove_file(p.root().join("abort")).unwrap();
// Try again without aborting the script.
// ***This is currently broken, the script does not re-run.
p.cargo("build -v")
.env("SOMEVAR", "1")
.with_stderr_contains("[RUNNING] [..]/foo-[..]/build-script-build[..]")
.run();
}