From 0d8ebe9109b260736591e23fccf48e717714e1c3 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 20 Apr 2018 13:20:38 -0700 Subject: [PATCH] Avoid running `build.rs` too often. --- .../compiler/context/unit_dependencies.rs | 12 ++++------ src/cargo/core/compiler/custom_build.rs | 3 +++ src/cargo/core/profiles.rs | 12 ++++++++++ src/cargo/ops/cargo_clean.rs | 24 +++++++++++++------ 4 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/cargo/core/compiler/context/unit_dependencies.rs b/src/cargo/core/compiler/context/unit_dependencies.rs index 0e1c9c078..b329de85a 100644 --- a/src/cargo/core/compiler/context/unit_dependencies.rs +++ b/src/cargo/core/compiler/context/unit_dependencies.rs @@ -132,7 +132,7 @@ fn compute_deps<'a, 'b, 'cfg>( if unit.target.is_custom_build() { return Ok(ret); } - ret.extend(dep_build_script(unit)); + ret.extend(dep_build_script(cx, unit)); // If this target is a binary, test, example, etc, then it depends on // the library of the same package. The call to `resolve.deps` above @@ -180,7 +180,7 @@ fn compute_deps_custom_build<'a, 'cfg>( if !unit.target.linkable() || unit.pkg.manifest().links().is_none() { return None; } - dep_build_script(unit) + dep_build_script(cx, unit) }) .chain(Some(( new_unit( @@ -250,7 +250,7 @@ fn compute_deps_doc<'a, 'cfg>( } // Be sure to build/run the build script for documented libraries as - ret.extend(dep_build_script(unit)); + ret.extend(dep_build_script(cx, unit)); // If we document a binary, we need the library available if unit.target.is_bin() { @@ -278,7 +278,7 @@ fn maybe_lib<'a>( /// script itself doesn't have any dependencies, so even in that case a unit /// of work is still returned. `None` is only returned if the package has no /// build script. -fn dep_build_script<'a>(unit: &Unit<'a>) -> Option<(Unit<'a>, ProfileFor)> { +fn dep_build_script<'a>(cx: &Context, unit: &Unit<'a>) -> Option<(Unit<'a>, ProfileFor)> { unit.pkg .targets() .iter() @@ -286,13 +286,11 @@ fn dep_build_script<'a>(unit: &Unit<'a>) -> Option<(Unit<'a>, ProfileFor)> { .map(|t| { // The profile stored in the Unit is the profile for the thing // the custom build script is running for. - // TODO: Fix this for different profiles that don't affect the - // build.rs environment variables. ( Unit { pkg: unit.pkg, target: t, - profile: unit.profile, + profile: cx.profiles.get_profile_run_custom_build(&unit.profile), kind: unit.kind, mode: CompileMode::RunCustomBuild, }, diff --git a/src/cargo/core/compiler/custom_build.rs b/src/cargo/core/compiler/custom_build.rs index 96638bf0f..02fd48de0 100644 --- a/src/cargo/core/compiler/custom_build.rs +++ b/src/cargo/core/compiler/custom_build.rs @@ -118,6 +118,9 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes // environment variables. Note that the profile-related environment // variables are not set with this the build script's profile but rather the // package's library profile. + // NOTE: If you add any profile flags, be sure to update + // `Profiles::get_profile_run_custom_build` so that those flags get + // carried over. let to_exec = to_exec.into_os_string(); let mut cmd = cx.compilation.host_process(to_exec, unit.pkg)?; cmd.env("OUT_DIR", &build_output) diff --git a/src/cargo/core/profiles.rs b/src/cargo/core/profiles.rs index c76be468c..ac3651fe0 100644 --- a/src/cargo/core/profiles.rs +++ b/src/cargo/core/profiles.rs @@ -90,6 +90,18 @@ impl Profiles { profile } + /// The profile for *running* a `build.rs` script is only used for setting + /// a few environment variables. To ensure proper de-duplication of the + /// running `Unit`, this uses a stripped-down profile (so that unrelated + /// profile flags don't cause `build.rs` to needlessly run multiple + /// times). + pub fn get_profile_run_custom_build(&self, for_unit_profile: &Profile) -> Profile { + let mut result = Profile::default(); + result.debuginfo = for_unit_profile.debuginfo; + result.opt_level = for_unit_profile.opt_level; + result + } + /// This returns a generic base profile. This is currently used for the /// `[Finished]` line. It is not entirely accurate, since it doesn't /// select for the package that was actually built. diff --git a/src/cargo/ops/cargo_clean.rs b/src/cargo/ops/cargo_clean.rs index 21e195212..3c0321c42 100644 --- a/src/cargo/ops/cargo_clean.rs +++ b/src/cargo/ops/cargo_clean.rs @@ -49,13 +49,23 @@ pub fn clean(ws: &Workspace, opts: &CleanOptions) -> CargoResult<()> { for kind in [Kind::Host, Kind::Target].iter() { for mode in CompileMode::all_modes() { for profile_for in ProfileFor::all_values() { - let profile = profiles.get_profile( - &pkg.name(), - ws.is_member(pkg), - *profile_for, - *mode, - opts.release, - ); + let profile = if mode.is_run_custom_build() { + profiles.get_profile_run_custom_build(&profiles.get_profile( + &pkg.name(), + ws.is_member(pkg), + *profile_for, + CompileMode::Build, + opts.release, + )) + } else { + profiles.get_profile( + &pkg.name(), + ws.is_member(pkg), + *profile_for, + *mode, + opts.release, + ) + }; units.push(Unit { pkg, target, -- 2.39.5