Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Freshness from DependencyQueue #6832

Merged
merged 8 commits into from Apr 11, 2019
Merged
9 changes: 8 additions & 1 deletion src/bin/cargo/commands/owner.rs
Expand Up @@ -7,7 +7,14 @@ pub fn cli() -> App {
.about("Manage the owners of a crate on the registry")
.arg(opt("quiet", "No output printed to stdout").short("q"))
.arg(Arg::with_name("crate"))
.arg(multi_opt("add", "LOGIN", "Name of a user or team to invite as an owner").short("a"))
.arg(
multi_opt(
"add",
"LOGIN",
"Name of a user or team to invite as an owner",
)
.short("a"),
)
.arg(
multi_opt(
"remove",
Expand Down
13 changes: 8 additions & 5 deletions src/bin/cargo/commands/test.rs
Expand Up @@ -19,8 +19,11 @@ pub fn cli() -> App {
.last(true),
)
.arg(
opt("quiet", "Display one character per test instead of one line")
.short("q")
opt(
"quiet",
"Display one character per test instead of one line",
)
.short("q"),
)
.arg_targets_all(
"Test only this package's library unit tests",
Expand Down Expand Up @@ -131,9 +134,9 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
} else if test_name.is_some() {
if let CompileFilter::Default { .. } = compile_opts.filter {
compile_opts.filter = ops::CompileFilter::new(
LibRule::Default, // compile the library, so the unit tests can be run filtered
FilterRule::All, // compile the binaries, so the unit tests in binaries can be run filtered
FilterRule::All, // compile the tests, so the integration tests can be run filtered
LibRule::Default, // compile the library, so the unit tests can be run filtered
FilterRule::All, // compile the binaries, so the unit tests in binaries can be run filtered
FilterRule::All, // compile the tests, so the integration tests can be run filtered
FilterRule::none(), // specify --examples to unit test binaries filtered
FilterRule::none(), // specify --benches to unit test benchmarks filtered
); // also, specify --doc to run doc tests filtered
Expand Down
3 changes: 2 additions & 1 deletion src/bin/cargo/commands/version.rs
Expand Up @@ -3,7 +3,8 @@ use crate::command_prelude::*;
use crate::cli;

pub fn cli() -> App {
subcommand("version").about("Show version information")
subcommand("version")
.about("Show version information")
.arg(opt("quiet", "No output printed to stdout").short("q"))
}

Expand Down
4 changes: 1 addition & 3 deletions src/cargo/core/compiler/build_context/mod.rs
Expand Up @@ -265,9 +265,7 @@ impl TargetConfig {
}
"rustc-cdylib-link-arg" => {
let args = value.list(k)?;
output
.linker_args
.extend(args.iter().map(|v| v.0.clone()));
output.linker_args.extend(args.iter().map(|v| v.0.clone()));
}
"rustc-cfg" => {
let list = value.list(k)?;
Expand Down
7 changes: 6 additions & 1 deletion src/cargo/core/compiler/context/compilation_files.rs
Expand Up @@ -166,8 +166,13 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
}
}

/// Returns the root of the build output tree.
/// Returns the root of the build output tree for the target
pub fn target_root(&self) -> &Path {
self.target.as_ref().unwrap_or(&self.host).dest()
}

/// Returns the root of the build output tree for the host
pub fn host_root(&self) -> &Path {
self.host.dest()
}

Expand Down
7 changes: 4 additions & 3 deletions src/cargo/core/compiler/context/mod.rs
Expand Up @@ -430,9 +430,10 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
path.display()
)
};
let suggestion = "Consider changing their names to be unique or compiling them separately.\n\
This may become a hard error in the future; see \
<https://github.com/rust-lang/cargo/issues/6313>.";
let suggestion =
"Consider changing their names to be unique or compiling them separately.\n\
This may become a hard error in the future; see \
<https://github.com/rust-lang/cargo/issues/6313>.";
let report_collision = |unit: &Unit<'_>,
other_unit: &Unit<'_>,
path: &PathBuf|
Expand Down
134 changes: 80 additions & 54 deletions src/cargo/core/compiler/custom_build.rs
Expand Up @@ -8,10 +8,10 @@ use std::sync::{Arc, Mutex};
use crate::core::PackageId;
use crate::util::errors::{CargoResult, CargoResultExt};
use crate::util::machine_message;
use crate::util::Cfg;
use crate::util::{self, internal, paths, profile};
use crate::util::{Cfg, Freshness};

use super::job::Work;
use super::job::{Freshness, Job, Work};
use super::{fingerprint, Context, Kind, TargetConfig, Unit};

/// Contains the parsed output of a custom build script.
Expand Down Expand Up @@ -80,32 +80,19 @@ pub struct BuildDeps {
/// prepare work for. If the requirement is specified as both the target and the
/// host platforms it is assumed that the two are equal and the build script is
/// only run once (not twice).
pub fn prepare<'a, 'cfg>(
cx: &mut Context<'a, 'cfg>,
unit: &Unit<'a>,
) -> CargoResult<(Work, Work, Freshness)> {
pub fn prepare<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult<Job> {
let _p = profile::start(format!(
"build script prepare: {}/{}",
unit.pkg,
unit.target.name()
));

let key = (unit.pkg.package_id(), unit.kind);
let overridden = cx.build_script_overridden.contains(&key);
let (work_dirty, work_fresh) = if overridden {
(Work::noop(), Work::noop())
} else {
build_work(cx, unit)?
};

if cx.bcx.build_config.build_plan {
Ok((work_dirty, work_fresh, Freshness::Dirty))
if cx.build_script_overridden.contains(&key) {
fingerprint::prepare_target(cx, unit, false)
} else {
// Now that we've prep'd our work, build the work needed to manage the
// fingerprint and then start returning that upwards.
let (freshness, dirty, fresh) = fingerprint::prepare_build_cmd(cx, unit)?;

Ok((work_dirty.then(dirty), work_fresh.then(fresh), freshness))
build_work(cx, unit)
}
}

Expand All @@ -125,7 +112,7 @@ fn emit_build_output(output: &BuildOutput, package_id: PackageId) {
});
}

fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult<(Work, Work)> {
fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult<Job> {
assert!(unit.mode.is_run_custom_build());
let bcx = &cx.bcx;
let dependencies = cx.dep_targets(unit);
Expand Down Expand Up @@ -248,7 +235,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes
let output_file = script_run_dir.join("output");
let err_file = script_run_dir.join("stderr");
let root_output_file = script_run_dir.join("root-output");
let host_target_root = cx.files().target_root().to_path_buf();
let host_target_root = cx.files().host_root().to_path_buf();
let all = (
id,
pkg_name.clone(),
Expand All @@ -260,22 +247,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes
let kind = unit.kind;
let json_messages = bcx.build_config.json_messages();
let extra_verbose = bcx.config.extra_verbose();

// 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_script_out_dir = paths::read_bytes(&root_output_file)
.and_then(|bytes| util::bytes2path(&bytes))
.unwrap_or_else(|_| script_out_dir.clone());

let prev_output = BuildOutput::parse_file(
&output_file,
&pkg_name,
&prev_script_out_dir,
&script_out_dir,
)
.ok();
let deps = BuildDeps::new(&output_file, prev_output.as_ref());
cx.build_explicit_deps.insert(*unit, deps);
let (prev_output, prev_script_out_dir) = prev_build_output(cx, unit);

fs::create_dir_all(&script_dir)?;
fs::create_dir_all(&script_out_dir)?;
Expand Down Expand Up @@ -392,7 +364,17 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes
Ok(())
});

Ok((dirty, fresh))
let mut job = if cx.bcx.build_config.build_plan {
Job::new(Work::noop(), Freshness::Dirty)
} else {
fingerprint::prepare_target(cx, unit, false)?
};
if job.freshness() == Freshness::Dirty {
job.before(dirty);
} else {
job.before(fresh);
}
Ok(job)
}

impl BuildState {
Expand Down Expand Up @@ -637,22 +619,20 @@ pub fn build_map<'b, 'cfg>(cx: &mut Context<'b, 'cfg>, units: &[Unit<'b>]) -> Ca
return Ok(&out[unit]);
}

{
let key = unit
.pkg
.manifest()
.links()
.map(|l| (l.to_string(), unit.kind));
let build_state = &cx.build_state;
if let Some(output) = key.and_then(|k| build_state.overrides.get(&k)) {
let key = (unit.pkg.package_id(), unit.kind);
cx.build_script_overridden.insert(key);
build_state
.outputs
.lock()
.unwrap()
.insert(key, output.clone());
}
let key = unit
.pkg
.manifest()
.links()
.map(|l| (l.to_string(), unit.kind));
let build_state = &cx.build_state;
if let Some(output) = key.and_then(|k| build_state.overrides.get(&k)) {
let key = (unit.pkg.package_id(), unit.kind);
cx.build_script_overridden.insert(key);
build_state
.outputs
.lock()
.unwrap()
.insert(key, output.clone());
}

let mut ret = BuildScripts::default();
Expand All @@ -661,6 +641,10 @@ pub fn build_map<'b, 'cfg>(cx: &mut Context<'b, 'cfg>, units: &[Unit<'b>]) -> Ca
add_to_link(&mut ret, unit.pkg.package_id(), unit.kind);
}

if unit.mode.is_run_custom_build() {
parse_previous_explicit_deps(cx, unit)?;
}

// We want to invoke the compiler deterministically to be cache-friendly
// to rustc invocation caching schemes, so be sure to generate the same
// set of build script dependency orderings via sorting the targets that
Expand Down Expand Up @@ -694,4 +678,46 @@ pub fn build_map<'b, 'cfg>(cx: &mut Context<'b, 'cfg>, units: &[Unit<'b>]) -> Ca
scripts.to_link.push((pkg, kind));
}
}

fn parse_previous_explicit_deps<'a, 'cfg>(
cx: &mut Context<'a, 'cfg>,
unit: &Unit<'a>,
) -> CargoResult<()> {
let script_run_dir = cx.files().build_script_run_dir(unit);
let output_file = script_run_dir.join("output");
let (prev_output, _) = prev_build_output(cx, unit);
let deps = BuildDeps::new(&output_file, prev_output.as_ref());
cx.build_explicit_deps.insert(*unit, deps);
Ok(())
}
}

/// Returns the previous parsed `BuildOutput`, if any, from a previous
/// execution.
///
/// Also returns the directory containing the output, typically used later in
/// processing.
fn prev_build_output<'a, 'cfg>(
cx: &mut Context<'a, 'cfg>,
unit: &Unit<'a>,
) -> (Option<BuildOutput>, PathBuf) {
let script_out_dir = cx.files().build_script_out_dir(unit);
let script_run_dir = cx.files().build_script_run_dir(unit);
let root_output_file = script_run_dir.join("root-output");
let output_file = script_run_dir.join("output");

let prev_script_out_dir = paths::read_bytes(&root_output_file)
.and_then(|bytes| util::bytes2path(&bytes))
.unwrap_or_else(|_| script_out_dir.clone());

(
BuildOutput::parse_file(
&output_file,
&unit.pkg.to_string(),
&prev_script_out_dir,
&script_out_dir,
)
.ok(),
prev_script_out_dir,
)
}