Skip to content

Commit

Permalink
Implement cargo:rerun-if-env-changed=FOO
Browse files Browse the repository at this point in the history
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 rust-lang#2776
  • Loading branch information
alexcrichton committed Jun 14, 2017
1 parent bbb38dc commit fe8bbb7
Show file tree
Hide file tree
Showing 6 changed files with 276 additions and 82 deletions.
5 changes: 4 additions & 1 deletion src/cargo/ops/cargo_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,7 @@ fn scrape_target_config(config: &Config, triple: &str)
env: Vec::new(),
metadata: Vec::new(),
rerun_if_changed: Vec::new(),
rerun_if_env_changed: Vec::new(),
warnings: Vec::new(),
};
// We require deterministic order of evaluation, so we must sort the pairs by key first.
Expand Down Expand Up @@ -745,7 +746,9 @@ fn scrape_target_config(config: &Config, triple: &str)
output.env.push((name.clone(), val.to_string()));
}
}
"warning" | "rerun-if-changed" => {
"warning" |
"rerun-if-changed" |
"rerun-if-env-changed" => {
bail!("`{}` is not supported in build script overrides", k);
}
_ => {
Expand Down
4 changes: 2 additions & 2 deletions src/cargo/ops/cargo_rustc/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use util::{self, internal, Config, profile, Cfg, CfgExpr};
use util::errors::{CargoResult, CargoResultExt};

use super::TargetConfig;
use super::custom_build::{BuildState, BuildScripts};
use super::custom_build::{BuildState, BuildScripts, BuildDeps};
use super::fingerprint::Fingerprint;
use super::layout::Layout;
use super::links::Links;
Expand All @@ -38,7 +38,7 @@ pub struct Context<'a, 'cfg: 'a> {
pub compilation: Compilation<'cfg>,
pub packages: &'a PackageSet<'cfg>,
pub build_state: Arc<BuildState>,
pub build_explicit_deps: HashMap<Unit<'a>, (PathBuf, Vec<String>)>,
pub build_explicit_deps: HashMap<Unit<'a>, BuildDeps>,
pub fingerprints: HashMap<Unit<'a>, Arc<Fingerprint>>,
pub compiled: HashSet<Unit<'a>>,
pub build_config: BuildConfig,
Expand Down
36 changes: 29 additions & 7 deletions src/cargo/ops/cargo_rustc/custom_build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ pub struct BuildOutput {
pub metadata: Vec<(String, String)>,
/// Paths to trigger a rerun of this build script.
pub rerun_if_changed: Vec<String>,
/// Environment variables which, when changed, will cause a rebuild.
pub rerun_if_env_changed: Vec<String>,
/// Warnings generated by this build,
pub warnings: Vec<String>,
}
Expand Down Expand Up @@ -59,6 +61,12 @@ pub struct BuildScripts {
pub plugins: BTreeSet<PackageId>,
}

pub struct BuildDeps {
pub build_script_output: PathBuf,
pub rerun_if_changed: Vec<String>,
pub rerun_if_env_changed: Vec<String>,
}

/// Prepares a `Work` that executes the target as a custom build script.
///
/// The `req` given is the requirement which this run of the build script will
Expand Down Expand Up @@ -181,11 +189,8 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>)
// Check to see if the build script has already run, and if it has keep
// track of whether it has told us about some explicit dependencies
let prev_output = BuildOutput::parse_file(&output_file, &pkg_name).ok();
let rerun_if_changed = match prev_output {
Some(ref prev) => prev.rerun_if_changed.clone(),
None => Vec::new(),
};
cx.build_explicit_deps.insert(*unit, (output_file.clone(), rerun_if_changed));
let deps = BuildDeps::new(&output_file, prev_output.as_ref());
cx.build_explicit_deps.insert(*unit, deps);

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

})?;

paths::write(&output_file, &output.stdout)?;
paths::write(&err_file, &output.stderr)?;

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

if json_messages {
Expand Down Expand Up @@ -337,6 +342,7 @@ impl BuildOutput {
let mut env = Vec::new();
let mut metadata = Vec::new();
let mut rerun_if_changed = Vec::new();
let mut rerun_if_env_changed = Vec::new();
let mut warnings = Vec::new();
let whence = format!("build script of `{}`", pkg_name);

Expand Down Expand Up @@ -378,6 +384,7 @@ impl BuildOutput {
"rustc-env" => env.push(BuildOutput::parse_rustc_env(value, &whence)?),
"warning" => warnings.push(value.to_string()),
"rerun-if-changed" => rerun_if_changed.push(value.to_string()),
"rerun-if-env-changed" => rerun_if_env_changed.push(value.to_string()),
_ => metadata.push((key.to_string(), value.to_string())),
}
}
Expand All @@ -389,6 +396,7 @@ impl BuildOutput {
env: env,
metadata: metadata,
rerun_if_changed: rerun_if_changed,
rerun_if_env_changed: rerun_if_env_changed,
warnings: warnings,
})
}
Expand Down Expand Up @@ -436,6 +444,20 @@ impl BuildOutput {
}
}

impl BuildDeps {
pub fn new(output_file: &Path, output: Option<&BuildOutput>) -> BuildDeps {
BuildDeps {
build_script_output: output_file.to_path_buf(),
rerun_if_changed: output.map(|p| &p.rerun_if_changed)
.cloned()
.unwrap_or_default(),
rerun_if_env_changed: output.map(|p| &p.rerun_if_env_changed)
.cloned()
.unwrap_or_default(),
}
}
}

/// Compute the `build_scripts` map in the `Context` which tracks what build
/// scripts each package depends on.
///
Expand Down
Loading

0 comments on commit fe8bbb7

Please sign in to comment.