Skip to content

Commit b4b7ed5

Browse files
committed
Auto merge of #4125 - alexcrichton:rerun-if-env-changed, r=matklad
Implement `cargo:rerun-if-env-changed=FOO` This commit implements a new method of rerunning a build script if an environment variable changes. Environment variables are one of the primary methods of giving inputs to a build script today, and this'll help situations where if you change an env var you don't have to remember to clean out an old build directory to ensure fresh results. Closes #2776
2 parents 0ae95d2 + fe8bbb7 commit b4b7ed5

File tree

6 files changed

+276
-82
lines changed

6 files changed

+276
-82
lines changed

Diff for: src/cargo/ops/cargo_compile.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,7 @@ fn scrape_target_config(config: &Config, triple: &str)
703703
env: Vec::new(),
704704
metadata: Vec::new(),
705705
rerun_if_changed: Vec::new(),
706+
rerun_if_env_changed: Vec::new(),
706707
warnings: Vec::new(),
707708
};
708709
// We require deterministic order of evaluation, so we must sort the pairs by key first.
@@ -745,7 +746,9 @@ fn scrape_target_config(config: &Config, triple: &str)
745746
output.env.push((name.clone(), val.to_string()));
746747
}
747748
}
748-
"warning" | "rerun-if-changed" => {
749+
"warning" |
750+
"rerun-if-changed" |
751+
"rerun-if-env-changed" => {
749752
bail!("`{}` is not supported in build script overrides", k);
750753
}
751754
_ => {

Diff for: src/cargo/ops/cargo_rustc/context.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use util::{self, internal, Config, profile, Cfg, CfgExpr};
1717
use util::errors::{CargoResult, CargoResultExt};
1818

1919
use super::TargetConfig;
20-
use super::custom_build::{BuildState, BuildScripts};
20+
use super::custom_build::{BuildState, BuildScripts, BuildDeps};
2121
use super::fingerprint::Fingerprint;
2222
use super::layout::Layout;
2323
use super::links::Links;
@@ -38,7 +38,7 @@ pub struct Context<'a, 'cfg: 'a> {
3838
pub compilation: Compilation<'cfg>,
3939
pub packages: &'a PackageSet<'cfg>,
4040
pub build_state: Arc<BuildState>,
41-
pub build_explicit_deps: HashMap<Unit<'a>, (PathBuf, Vec<String>)>,
41+
pub build_explicit_deps: HashMap<Unit<'a>, BuildDeps>,
4242
pub fingerprints: HashMap<Unit<'a>, Arc<Fingerprint>>,
4343
pub compiled: HashSet<Unit<'a>>,
4444
pub build_config: BuildConfig,

Diff for: src/cargo/ops/cargo_rustc/custom_build.rs

+29-7
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ pub struct BuildOutput {
2828
pub metadata: Vec<(String, String)>,
2929
/// Paths to trigger a rerun of this build script.
3030
pub rerun_if_changed: Vec<String>,
31+
/// Environment variables which, when changed, will cause a rebuild.
32+
pub rerun_if_env_changed: Vec<String>,
3133
/// Warnings generated by this build,
3234
pub warnings: Vec<String>,
3335
}
@@ -59,6 +61,12 @@ pub struct BuildScripts {
5961
pub plugins: BTreeSet<PackageId>,
6062
}
6163

64+
pub struct BuildDeps {
65+
pub build_script_output: PathBuf,
66+
pub rerun_if_changed: Vec<String>,
67+
pub rerun_if_env_changed: Vec<String>,
68+
}
69+
6270
/// Prepares a `Work` that executes the target as a custom build script.
6371
///
6472
/// The `req` given is the requirement which this run of the build script will
@@ -181,11 +189,8 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>)
181189
// Check to see if the build script has already run, and if it has keep
182190
// track of whether it has told us about some explicit dependencies
183191
let prev_output = BuildOutput::parse_file(&output_file, &pkg_name).ok();
184-
let rerun_if_changed = match prev_output {
185-
Some(ref prev) => prev.rerun_if_changed.clone(),
186-
None => Vec::new(),
187-
};
188-
cx.build_explicit_deps.insert(*unit, (output_file.clone(), rerun_if_changed));
192+
let deps = BuildDeps::new(&output_file, prev_output.as_ref());
193+
cx.build_explicit_deps.insert(*unit, deps);
189194

190195
fs::create_dir_all(&script_output)?;
191196
fs::create_dir_all(&build_output)?;
@@ -246,8 +251,6 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>)
246251

247252
})?;
248253

249-
paths::write(&output_file, &output.stdout)?;
250-
paths::write(&err_file, &output.stderr)?;
251254

252255
// After the build command has finished running, we need to be sure to
253256
// remember all of its output so we can later discover precisely what it
@@ -256,6 +259,8 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>)
256259
// This is also the location where we provide feedback into the build
257260
// state informing what variables were discovered via our script as
258261
// well.
262+
paths::write(&output_file, &output.stdout)?;
263+
paths::write(&err_file, &output.stderr)?;
259264
let parsed_output = BuildOutput::parse(&output.stdout, &pkg_name)?;
260265

261266
if json_messages {
@@ -337,6 +342,7 @@ impl BuildOutput {
337342
let mut env = Vec::new();
338343
let mut metadata = Vec::new();
339344
let mut rerun_if_changed = Vec::new();
345+
let mut rerun_if_env_changed = Vec::new();
340346
let mut warnings = Vec::new();
341347
let whence = format!("build script of `{}`", pkg_name);
342348

@@ -378,6 +384,7 @@ impl BuildOutput {
378384
"rustc-env" => env.push(BuildOutput::parse_rustc_env(value, &whence)?),
379385
"warning" => warnings.push(value.to_string()),
380386
"rerun-if-changed" => rerun_if_changed.push(value.to_string()),
387+
"rerun-if-env-changed" => rerun_if_env_changed.push(value.to_string()),
381388
_ => metadata.push((key.to_string(), value.to_string())),
382389
}
383390
}
@@ -389,6 +396,7 @@ impl BuildOutput {
389396
env: env,
390397
metadata: metadata,
391398
rerun_if_changed: rerun_if_changed,
399+
rerun_if_env_changed: rerun_if_env_changed,
392400
warnings: warnings,
393401
})
394402
}
@@ -436,6 +444,20 @@ impl BuildOutput {
436444
}
437445
}
438446

447+
impl BuildDeps {
448+
pub fn new(output_file: &Path, output: Option<&BuildOutput>) -> BuildDeps {
449+
BuildDeps {
450+
build_script_output: output_file.to_path_buf(),
451+
rerun_if_changed: output.map(|p| &p.rerun_if_changed)
452+
.cloned()
453+
.unwrap_or_default(),
454+
rerun_if_env_changed: output.map(|p| &p.rerun_if_env_changed)
455+
.cloned()
456+
.unwrap_or_default(),
457+
}
458+
}
459+
}
460+
439461
/// Compute the `build_scripts` map in the `Context` which tracks what build
440462
/// scripts each package depends on.
441463
///

0 commit comments

Comments
 (0)