From 1caae5107201f90ad9a2eec0bb721e4da051eff4 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 16 Apr 2019 13:31:40 -0700 Subject: [PATCH 1/2] Start preparing Cargo for pipelined rustc compilation This commit starts to lay the groundwork for #6660 where Cargo will invoke rustc in a "pipelined" fashion. The goal here is to execute one command to produce both an `*.rmeta` file as well as an `*.rlib` file for candidate compilations. In that case if another rlib depends on that compilation, then it can start as soon as the `*.rmeta` is ready and not have to wait for the `*.rlib` compilation. The major refactoring in this commit is to add a new form of `CompileMode`: `BuildRmeta`. This mode is introduced to represent that a dependency edge only depends on the metadata of a compilation rather than the the entire linked artifact. After this is introduced the next major change is to actually hook this up into the dependency graph. The approach taken by this commit is to have a postprocessing pass over the dependency graph. After we build a map of all dependencies between units a "pipelining" pass runs and actually introduces the `BuildRmeta` mode. This also makes it trivial to disable/enable pipelining which we'll probably want to do for a preview period at least! The `pipeline_compilations` function is intended to be extensively documented with the graph that it creates as well as how it works in terms of adding `BuildRmeta` nodes into the dependency graph. This commit is not all that will be required for pieplining compilations. It does, however, get the entire test suite passing with this refactoring. The way this works is by ensuring that a pipelined unit, one split from `Build` into both `Build` and `BuildRmeta`, to be a unit that doesn't actually do any work. That way the `BuildRmeta` actually does all the work currently and we should have a working Cargo like we did before. Subsequent commits will work in updating the `JobQueue` to account for pipelining... Note that this commit itself doesn't really contain any tests because there's no functional change to Cargo, only internal refactorings. This does have a large impact on the test suite because the `--emit` flag has now changed by default, so lots of test assertions needed updating. --- src/cargo/core/compiler/build_config.rs | 7 +- src/cargo/core/compiler/build_context/mod.rs | 17 +- .../compiler/context/compilation_files.rs | 71 +++--- src/cargo/core/compiler/context/mod.rs | 30 +++ .../compiler/context/unit_dependencies.rs | 208 ++++++++++++++++- src/cargo/core/compiler/fingerprint.rs | 55 +++-- src/cargo/core/compiler/mod.rs | 25 +- src/cargo/core/compiler/output_depinfo.rs | 5 +- src/cargo/core/compiler/unit.rs | 6 + src/cargo/core/manifest.rs | 31 +++ src/cargo/core/profiles.rs | 1 + src/cargo/ops/cargo_compile.rs | 9 +- tests/testsuite/build.rs | 78 +++---- tests/testsuite/build_lib.rs | 2 +- tests/testsuite/build_script.rs | 10 +- tests/testsuite/cfg.rs | 4 +- tests/testsuite/clean.rs | 1 + tests/testsuite/cross_compile.rs | 2 +- tests/testsuite/dep_info.rs | 5 +- tests/testsuite/freshness.rs | 4 +- tests/testsuite/profile_overrides.rs | 14 +- tests/testsuite/profile_targets.rs | 216 +++++++++--------- tests/testsuite/profiles.rs | 17 +- tests/testsuite/run.rs | 8 +- tests/testsuite/rustc.rs | 26 +-- 25 files changed, 596 insertions(+), 256 deletions(-) diff --git a/src/cargo/core/compiler/build_config.rs b/src/cargo/core/compiler/build_config.rs index 2056408097e..0999a76faa8 100644 --- a/src/cargo/core/compiler/build_config.rs +++ b/src/cargo/core/compiler/build_config.rs @@ -127,6 +127,7 @@ pub enum CompileMode { Test, /// Building a target with `rustc` (lib or bin). Build, + BuildRmeta, /// Building a target with `rustc` to emit `rmeta` metadata only. If /// `test` is true, then it is also compiled with `--test` to check it like /// a test. @@ -154,6 +155,7 @@ impl ser::Serialize for CompileMode { match *self { Test => "test".serialize(s), Build => "build".serialize(s), + BuildRmeta => "build-rmeta".serialize(s), Check { .. } => "check".serialize(s), Bench => "bench".serialize(s), Doc { .. } => "doc".serialize(s), @@ -202,9 +204,10 @@ impl CompileMode { /// List of all modes (currently used by `cargo clean -p` for computing /// all possible outputs). pub fn all_modes() -> &'static [CompileMode] { - static ALL: [CompileMode; 9] = [ + static ALL: &[CompileMode] = &[ CompileMode::Test, CompileMode::Build, + CompileMode::BuildRmeta, CompileMode::Check { test: true }, CompileMode::Check { test: false }, CompileMode::Bench, @@ -213,6 +216,6 @@ impl CompileMode { CompileMode::Doctest, CompileMode::RunCustomBuild, ]; - &ALL + ALL } } diff --git a/src/cargo/core/compiler/build_context/mod.rs b/src/cargo/core/compiler/build_context/mod.rs index 858f7ae9074..18badc4bc81 100644 --- a/src/cargo/core/compiler/build_context/mod.rs +++ b/src/cargo/core/compiler/build_context/mod.rs @@ -8,9 +8,9 @@ use crate::core::profiles::Profiles; use crate::core::{Dependency, Workspace}; use crate::core::{PackageId, PackageSet, Resolve}; use crate::util::errors::CargoResult; -use crate::util::{profile, Cfg, Config, Rustc}; -use crate::core::compiler::{Unit, Kind, BuildConfig, BuildOutput}; +use crate::core::compiler::{Unit, Kind, BuildConfig, BuildOutput, CompileMode}; use crate::core::compiler::unit::UnitInterner; +use crate::util::{profile, Cfg, Config, Rustc}; mod target_info; pub use self::target_info::{FileFlavor, TargetInfo}; @@ -179,7 +179,18 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> { } pub fn extra_args_for(&self, unit: &Unit<'a>) -> Option<&Vec> { - self.extra_compiler_args.get(unit) + // Extra arguments are currently only registered for top-level units and + // this is how `cargo rustc` and `cargo rustdoc` are implemented. We may + // split a top level unit though for pipelining, and the actual work + // happens in the `BuildRmeta` stage and not the `Build` stage. To + // handle that difference and ensure arguments get to the right place be + // sure to switch `BuildRmeta` modes to `Build` for lookup. + if unit.mode == CompileMode::BuildRmeta { + let build = unit.with_mode(CompileMode::Build, self.units); + self.extra_compiler_args.get(&build) + } else { + self.extra_compiler_args.get(unit) + } } } diff --git a/src/cargo/core/compiler/context/compilation_files.rs b/src/cargo/core/compiler/context/compilation_files.rs index 217022f7132..47e8a60934a 100644 --- a/src/cargo/core/compiler/context/compilation_files.rs +++ b/src/cargo/core/compiler/context/compilation_files.rs @@ -8,7 +8,7 @@ use std::sync::Arc; use lazycell::LazyCell; use log::info; -use super::{BuildContext, Context, FileFlavor, Kind, Layout}; +use super::{BuildContext, Context, FileFlavor, Kind, Layout, CompileMode}; use crate::core::compiler::Unit; use crate::core::{TargetKind, Workspace}; use crate::util::{self, CargoResult}; @@ -299,18 +299,19 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> { let mut ret = Vec::new(); let mut unsupported = Vec::new(); - { - if unit.mode.is_check() { + match unit.mode { + CompileMode::BuildRmeta | CompileMode::Check { .. } => { // This may be confusing. rustc outputs a file named `lib*.rmeta` // for both libraries and binaries. let path = out_dir.join(format!("lib{}.rmeta", file_stem)); ret.push(OutputFile { - path, + path: path.clone(), hardlink: None, export_path: None, flavor: FileFlavor::Linkable, }); - } else { + } + CompileMode::Test | CompileMode::Build | CompileMode::Bench => { let mut add = |crate_type: &str, flavor: FileFlavor| -> CargoResult<()> { let crate_type = if crate_type == "lib" { "rlib" @@ -324,34 +325,35 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> { bcx.target_triple(), )?; - match file_types { - Some(types) => { - for file_type in types { - let path = out_dir.join(file_type.filename(&file_stem)); - let hardlink = link_stem - .as_ref() - .map(|&(ref ld, ref ls)| ld.join(file_type.filename(ls))); - let export_path = if unit.target.is_custom_build() { - None - } else { - self.export_dir.as_ref().and_then(|export_dir| { - hardlink.as_ref().and_then(|hardlink| { - Some(export_dir.join(hardlink.file_name().unwrap())) - }) - }) - }; - ret.push(OutputFile { - path, - hardlink, - export_path, - flavor: file_type.flavor, - }); - } - } + let types = match file_types { + Some(types) => types, // Not supported; don't worry about it. None => { unsupported.push(crate_type.to_string()); + return Ok(()); } + }; + + for file_type in types { + let path = out_dir.join(file_type.filename(&file_stem)); + let hardlink = link_stem + .as_ref() + .map(|&(ref ld, ref ls)| ld.join(file_type.filename(ls))); + let export_path = if unit.target.is_custom_build() { + None + } else { + self.export_dir.as_ref().and_then(|export_dir| { + hardlink.as_ref().and_then(|hardlink| { + Some(export_dir.join(hardlink.file_name().unwrap())) + }) + }) + }; + ret.push(OutputFile { + path, + hardlink, + export_path, + flavor: file_type.flavor, + }); } Ok(()) }; @@ -381,6 +383,9 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> { } } } + CompileMode::Doc { .. } | CompileMode::Doctest | CompileMode::RunCustomBuild => { + return Ok(Arc::new(ret)); + } } if ret.is_empty() { if !unsupported.is_empty() { @@ -425,6 +430,14 @@ fn compute_metadata<'a, 'cfg>( cx: &Context<'a, 'cfg>, metas: &mut HashMap, Option>, ) -> Option { + // Check to see if this is a pipelined unit which means that it doesn't + // actually do any work, but rather its dependency on an rmeta unit will do + // all the work. In that case we'll take the same metadata as our rmeta + // compile to ensure that our file names all align. + if let Some(rmeta) = cx.rmeta_unit_if_pipelined(unit) { + return compute_metadata(&rmeta, cx, metas); + } + // No metadata for dylibs because of a couple issues: // - macOS encodes the dylib name in the executable, // - Windows rustc multiple files of which we can't easily link all of them. diff --git a/src/cargo/core/compiler/context/mod.rs b/src/cargo/core/compiler/context/mod.rs index 3eb20bb4bde..878824381ad 100644 --- a/src/cargo/core/compiler/context/mod.rs +++ b/src/cargo/core/compiler/context/mod.rs @@ -42,6 +42,18 @@ pub struct Context<'a, 'cfg: 'a> { unit_dependencies: HashMap, Vec>>, files: Option>, package_cache: HashMap, + + // A map from a unit to the dependencies listed for it which are considered + // as "order only" dependencies. These dependencies are only used to + // sequence compilation correctly and shouldn't inject `--extern` flags, for + // example. + pub order_only_dependencies: HashMap, HashSet>>, + + // A set of units which have been "pipelined". These units are in `Build` + // mode and depend on a `BuildRmeta` mode unit. The pipelined `Build` units + // should do no work because the `BuildRmeta` unit will do all the work for + // them. + pub pipelined_units: HashSet>, } impl<'a, 'cfg> Context<'a, 'cfg> { @@ -76,6 +88,8 @@ impl<'a, 'cfg> Context<'a, 'cfg> { unit_dependencies: HashMap::new(), files: None, package_cache: HashMap::new(), + order_only_dependencies: HashMap::new(), + pipelined_units: HashSet::new(), }) } @@ -266,6 +280,8 @@ impl<'a, 'cfg> Context<'a, 'cfg> { self.bcx, &mut self.unit_dependencies, &mut self.package_cache, + &mut self.order_only_dependencies, + &mut self.pipelined_units, )?; let files = CompilationFiles::new( units, @@ -453,6 +469,20 @@ impl<'a, 'cfg> Context<'a, 'cfg> { } Ok(()) } + + /// Returns the `BuildRmeta` unit which is actually doing compilation if the + /// `unit` specified has been pipelined. + /// + /// If the unit specified has not been pipelined then `None` will be + /// returned. + pub fn rmeta_unit_if_pipelined(&self, unit: &Unit<'a>) -> Option> { + if self.pipelined_units.contains(unit) { + assert_eq!(unit.mode, CompileMode::Build); + Some(unit.with_mode(CompileMode::BuildRmeta, self.bcx.units)) + } else { + None + } + } } #[derive(Default)] diff --git a/src/cargo/core/compiler/context/unit_dependencies.rs b/src/cargo/core/compiler/context/unit_dependencies.rs index 618c925b37a..6218ca069ec 100644 --- a/src/cargo/core/compiler/context/unit_dependencies.rs +++ b/src/cargo/core/compiler/context/unit_dependencies.rs @@ -16,6 +16,7 @@ //! graph of `Unit`s, which capture these properties. use std::cell::RefCell; +use std::mem; use std::collections::{HashMap, HashSet}; use log::trace; @@ -31,6 +32,8 @@ use crate::CargoResult; struct State<'a: 'tmp, 'cfg: 'a, 'tmp> { bcx: &'tmp BuildContext<'a, 'cfg>, deps: &'tmp mut HashMap, Vec>>, + order_only_dependencies: &'tmp mut HashMap, HashSet>>, + pipelined_units: &'tmp mut HashSet>, pkgs: RefCell<&'tmp mut HashMap>, waiting_on_download: HashSet, downloads: Downloads<'a, 'cfg>, @@ -41,6 +44,8 @@ pub fn build_unit_dependencies<'a, 'cfg>( bcx: &BuildContext<'a, 'cfg>, deps: &mut HashMap, Vec>>, pkgs: &mut HashMap, + order_only_dependencies: &mut HashMap, HashSet>>, + pipelined_units: &mut HashSet>, ) -> CargoResult<()> { assert!(deps.is_empty(), "can only build unit deps once"); @@ -50,6 +55,8 @@ pub fn build_unit_dependencies<'a, 'cfg>( pkgs: RefCell::new(pkgs), waiting_on_download: HashSet::new(), downloads: bcx.packages.enable_download()?, + order_only_dependencies, + pipelined_units, }; loop { @@ -84,10 +91,15 @@ pub fn build_unit_dependencies<'a, 'cfg>( break; } } - trace!("ALL UNIT DEPENDENCIES {:#?}", state.deps); connect_run_custom_build_deps(&mut state); + trace!("BEFORE PIPELINING {:#?}", state.deps); + + pipeline_compilations(&mut state)?; + + trace!("ALL UNIT DEPENDENCIES {:#?}", state.deps); + // Dependencies are used in tons of places throughout the backend, many of // which affect the determinism of the build itself. As a result be sure // that dependency lists are always sorted to ensure we've always got a @@ -501,6 +513,200 @@ fn connect_run_custom_build_deps(state: &mut State<'_, '_, '_>) { } } +fn pipeline_compilations(state: &mut State<'_, '_, '_>) -> CargoResult<()> { + // Disable pipelining in build plan mode for now. Pipelining doesn't really + // reflect well to the build plan and only really gets benefits within Cargo + // itself, so let's not export it just yet. + if state.bcx.build_config.build_plan { + return Ok(()) + } + + // Additionally use a config variable for testing for now while the + // pipelining implementation is still relatively new. This should allow easy + // disabling if there's accidental bugs or just for local testing. + if !state.bcx.config.get_bool("build.pipelining")?.map(|t| t.val).unwrap_or(true) { + return Ok(()); + } + + // First thing to do is to restructure the dependency graph in two ways: + // + // 1. First, we need to split all rlib builds into an actual build which + // depends on the metadata build. The metadata build will actually do all + // the work and the normal build will be an effective noop. + // + // 2. Next, for candidate dependencies, we depend on rmeta builds instead of + // full builds. This ensures that we're only depending on what's + // absolutely necessary, ensuring we don't wait too long to start + // compilations. + let mut new_nodes = Vec::new(); + for (unit, deps) in state.deps.iter_mut() { + // Only building rlibs are candidates for pipelining. The first check + // here is effectively "is this an rlib" and the second filters out all + // other forms of units that aren't compilations (like unit tests, + // documentation, etc). + if unit.target.requires_upstream_objects() || unit.mode != CompileMode::Build { + continue; + } + state.pipelined_units.insert(*unit); + + // Update all `deps`, that we can, to depend on `BuildRmeta` instead of + // `Build`. This is where we get pipelining wins by hoping that our + // dependencies can be fulfilled faster by only depending on metadata + // information. + for dep in deps.iter_mut() { + if dep.target.requires_upstream_objects() { + continue; + } + match dep.mode { + CompileMode::Build => {} + _ => continue, + } + *dep = dep.with_mode(CompileMode::BuildRmeta, state.bcx.units); + } + + // Rewrite our `Build` unit and its dependencies. Our `Build` unit will + // now only depend on the `BuildRmeta` unit which we're about to create. + // Our `BuildRmeta` unit then actually lists all of the dependencies + // that we previously had. + let build_rmeta = unit.with_mode(CompileMode::BuildRmeta, state.bcx.units); + let new_deps = vec![build_rmeta]; + new_nodes.push((build_rmeta, mem::replace(deps, new_deps))); + + // As a bit of side information flag that the `Build` -> `BuildRmeta` + // dependency we've created here is an "order only" dependency which + // means we won't try to pass `--extern` to ourselves which would be + // silly. + state + .order_only_dependencies + .entry(*unit) + .or_insert_with(HashSet::new) + .insert(build_rmeta); + } + state.deps.extend(new_nodes); + + // The next step we need to perform is to add more dependencies in the + // dependency graph (more than we've already done). Let's take an example + // dependency graph like: + // + // A (exe) -> B (rlib) -> C (rlib) + // + // our above loop transformed this graph into: + // + // A (exe) -> B (rlib) -> B (rmeta) -> C (remta) + // ^ + // | + // C (rlib) + // + // This is actually incorrect because "A (exe)" actually depends on "C + // (rlib)". Technically just the linking phase depends on it but we take a + // coarse approximation and say the entirety of "A (exe)" depend on it. + // + // The graph that we actually want is: + // + // A (exe) -> B (rlib) -> B (rmeta) -> C (remta) + // \ ^ + // \ | + // -------------------> C (rlib) + // + // To do this transformation we're going to take a look at all rlib builds + // which now depend on just an `BuildRmeta` node. We walk from these nodes + // higher up to the root of the dependency graph (all paths to the root). As + // soon as any path has a node that is not `BuildRmeta` we add a dependency + // in its list of dependencies to the `Build` version of our unit. + // + // In reality this means that the graph we produce will be: + // + // A (exe) -> B (rlib) -> B (rmeta) -> C (remta) + // \ ^ + // \ | + // --------> C (rlib) + // + // and this should have the same performance characteristics as our desired + // graph from above because "B (rlib)" is a free phantom dependency node. + let mut reverse_deps = HashMap::new(); + for (unit, deps) in state.deps.iter() { + for dep in deps { + reverse_deps + .entry(*dep) + .or_insert_with(HashSet::new) + .insert(*unit); + } + } + + let mut updated = HashSet::new(); + for build_unit in state.pipelined_units.clone() { + let build_rmeta_unit = build_unit.with_mode(CompileMode::BuildRmeta, state.bcx.units); + update_built_parents( + &build_unit, + &build_rmeta_unit, + state, + &reverse_deps, + &mut updated, + ); + } + + return Ok(()); + + /// Walks the dependency graph upwards from `build_rmeta_unit` to find a + /// unit which is *not* `BuildRmeta`. When found, adds `build_unit` to that + /// unit's list of dependencies. + fn update_built_parents<'a>( + build_unit: &Unit<'a>, + build_rmeta_unit: &Unit<'a>, + state: &mut State<'a, '_, '_>, + reverse_deps: &HashMap, HashSet>>, + updated: &mut HashSet<(Unit<'a>, Unit<'a>)>, + ) { + debug_assert_eq!(build_rmeta_unit.mode, CompileMode::BuildRmeta); + debug_assert_eq!(build_unit.mode, CompileMode::Build); + + // There may be multiple paths to the root of the depenency graph as we + // walk upwards, but we don't want to add units more than once. Use a + // visited set to guard against this. + if !updated.insert((*build_unit, *build_rmeta_unit)) { + return; + } + + // Look for anything that depends on our `BuildRmeta` unit. If nothing + // depends on us then we've reached the root of the graph, and nothing + // needs to depend on the `Build` version! + let parents = match reverse_deps.get(build_rmeta_unit) { + Some(list) => list, + None => return, + }; + + for parent in parents { + match parent.mode { + // If a `BuildRmeta` depends on this `BuildRmeta`, then we + // recurse and keep walking up the graph to add the `build_unit` + // into the dependency list + CompileMode::BuildRmeta => { + update_built_parents(build_unit, parent, state, reverse_deps, updated); + } + // ... otherwise this unit is not a `BuildRmeta`, but very + // likely a `Build`. In that case for it to actually execute we + // need to finish all transitive `BuildRmeta` units, so we + // update its list of dependencies to include the full built + // artifact. + _ => { + // If these are the same that means we're propagating the + // `BuildRmeta` unit to the `Build` of itself so we can + // safely skip that. + if parent == build_unit { + continue; + } + state.deps.get_mut(parent).unwrap().push(*build_unit); + state + .order_only_dependencies + .entry(*parent) + .or_insert_with(HashSet::new) + .insert(*build_unit); + } + } + } + } +} + impl<'a, 'cfg, 'tmp> State<'a, 'cfg, 'tmp> { fn get(&mut self, id: PackageId) -> CargoResult> { let mut pkgs = self.pkgs.borrow_mut(); diff --git a/src/cargo/core/compiler/fingerprint.rs b/src/cargo/core/compiler/fingerprint.rs index e7a2b378542..8017cede2ef 100644 --- a/src/cargo/core/compiler/fingerprint.rs +++ b/src/cargo/core/compiler/fingerprint.rs @@ -212,7 +212,7 @@ use super::job::{ Freshness::{Dirty, Fresh}, Job, Work, }; -use super::{BuildContext, Context, FileFlavor, Kind, Unit}; +use super::{BuildContext, CompileMode, Context, FileFlavor, Kind, Unit}; /// Determines if a `unit` is up-to-date, and if not prepares necessary work to /// update the persisted fingerprint. @@ -478,9 +478,7 @@ enum LocalFingerprint { /// The `dep_info` file, when present, also lists a number of other files /// for us to look at. If any of those files are newer than this file then /// we need to recompile. - CheckDepInfo { - dep_info: PathBuf, - }, + CheckDepInfo { dep_info: PathBuf }, /// This represents a nonempty set of `rerun-if-changed` annotations printed /// out by a build script. The `output` file is a arelative file anchored at @@ -500,10 +498,7 @@ enum LocalFingerprint { /// build script. The exact env var and value are hashed here. There's no /// filesystem dependence here, and if the values are changed the hash will /// change forcing a recompile. - RerunIfEnvChanged { - var: String, - val: Option, - }, + RerunIfEnvChanged { var: String, val: Option }, } enum StaleFile { @@ -899,7 +894,16 @@ impl DepFingerprint { dep: &Unit<'a>, ) -> CargoResult { let fingerprint = calculate(cx, dep)?; - let name = cx.bcx.extern_crate_name(parent, dep)?; + let order_only = cx + .order_only_dependencies + .get(parent) + .map(|s| s.contains(dep)) + .unwrap_or(false); + let name = if order_only { + String::new() + } else { + cx.bcx.extern_crate_name(parent, dep)? + }; // We need to be careful about what we hash here. We have a goal of // supporting renaming a project directory and not rebuilding @@ -1013,7 +1017,12 @@ fn calculate_normal<'a, 'cfg>( // get bland fingerprints because they don't change without their // `PackageId` changing. let target_root = target_root(cx, unit); - let local = if use_dep_info(unit) { + let local = if cx.pipelined_units.contains(unit) { + // If we're a "pipelined" unit then our fingerprint information is used + // and checked in the rmeta dependency that we depend on, so nothing new + // here. + Vec::new() + } else if use_dep_info(unit) { let dep_info = dep_info_loc(cx, unit); let dep_info = dep_info.strip_prefix(&target_root).unwrap().to_path_buf(); vec![LocalFingerprint::CheckDepInfo { dep_info }] @@ -1307,9 +1316,14 @@ pub fn prepare_init<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> Ca /// Returns the location that the dep-info file will show up at for the `unit` /// specified. pub fn dep_info_loc<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> PathBuf { + // If `unit` is a pipelined unit, or one that doesn't actually do any work + // because it's happening elsewhere, then we want to switch to the actual + // `rmeta` unit that does the work which will generate dep info. Otherwise + // the `unit` will produce its own dep info. + let unit = cx.rmeta_unit_if_pipelined(unit).unwrap_or(*unit); cx.files() - .fingerprint_dir(unit) - .join(&format!("dep-{}", filename(cx, unit))) + .fingerprint_dir(&unit) + .join(&format!("dep-{}", filename(cx, &unit))) } /// Returns an absolute path that the `unit`'s outputs should always be relative @@ -1453,14 +1467,15 @@ fn filename<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> String { // even if the package is fresh, we'll still link the fresh target let file_stem = cx.files().file_stem(unit); let kind = unit.target.kind().description(); - let flavor = if unit.mode.is_any_test() { - "test-" - } else if unit.mode.is_doc() { - "doc-" - } else if unit.mode.is_run_custom_build() { - "run-" - } else { - "" + let flavor = match unit.mode { + CompileMode::Test + | CompileMode::Bench + | CompileMode::Check { test: true } + | CompileMode::Doctest => "test-", + CompileMode::Doc { .. } => "doc-", + CompileMode::RunCustomBuild => "run-", + CompileMode::BuildRmeta => "rmeta-", + CompileMode::Check { test: false } | CompileMode::Build => "", }; format!("{}{}-{}", flavor, kind, file_stem) } diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 9c9f6533b92..9d265521886 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -15,7 +15,7 @@ use std::env; use std::ffi::{OsStr, OsString}; use std::fs; use std::io::{self, Write}; -use std::path::{self, Path, PathBuf}; +use std::path::{Path, PathBuf}; use std::sync::Arc; use failure::Error; @@ -155,7 +155,11 @@ fn compile<'a, 'cfg: 'a>( let force = exec.force_rebuild(unit) || force_rebuild; let mut job = fingerprint::prepare_target(cx, unit, force)?; job.before(if job.freshness() == Freshness::Dirty { - let work = if unit.mode.is_doc() { + let work = if cx.pipelined_units.contains(unit) { + // If we're a pipelined unit then we're just a phantom + // dependency node so there's no actual work for us to do. + Work::new(|_| Ok(())) + } else if unit.mode.is_doc() { rustdoc(cx, unit)? } else { rustc(cx, unit, exec)? @@ -789,7 +793,7 @@ fn build_base_args<'a, 'cfg>( if unit.mode.is_check() { cmd.arg("--emit=dep-info,metadata"); } else { - cmd.arg("--emit=dep-info,link"); + cmd.arg("--emit=dep-info,metadata,link"); } let prefer_dynamic = (unit.target.for_host() && !unit.target.is_custom_build()) @@ -984,6 +988,17 @@ fn build_deps_args<'a, 'cfg>( dep: &Unit<'a>, ) -> CargoResult<()> { let bcx = cx.bcx; + + // If this dependency edge was "order only" then we explicitly don't + // want to pass `--extern` because there's no actual dependency and it + // would accidentally let the crate use apis it shouldn't have access + // to. + if let Some(set) = cx.order_only_dependencies.get(current) { + if set.contains(dep) { + return Ok(()); + } + } + for output in cx.outputs(dep)?.iter() { if output.flavor != FileFlavor::Linkable { continue; @@ -992,9 +1007,7 @@ fn build_deps_args<'a, 'cfg>( let name = bcx.extern_crate_name(current, dep)?; v.push(name); v.push("="); - v.push(cx.files().out_dir(dep)); - v.push(&path::MAIN_SEPARATOR.to_string()); - v.push(&output.path.file_name().unwrap()); + v.push(&output.path); cmd.arg("--extern").arg(&v); } Ok(()) diff --git a/src/cargo/core/compiler/output_depinfo.rs b/src/cargo/core/compiler/output_depinfo.rs index b09f5344c58..3f7e042c11c 100644 --- a/src/cargo/core/compiler/output_depinfo.rs +++ b/src/cargo/core/compiler/output_depinfo.rs @@ -45,9 +45,10 @@ fn add_deps_for_unit<'a, 'b>( } } else { debug!( - "can't find dep_info for {:?} {}", + "can't find dep_info for {:?} {} at {:?}", unit.pkg.package_id(), - unit.target + unit.target, + dep_info_loc, ); return Err(internal("dep_info missing")); } diff --git a/src/cargo/core/compiler/unit.rs b/src/cargo/core/compiler/unit.rs index bf7d6f0871c..251823ee806 100644 --- a/src/cargo/core/compiler/unit.rs +++ b/src/cargo/core/compiler/unit.rs @@ -54,6 +54,12 @@ impl<'a> Unit<'a> { pub fn buildkey(&self) -> String { format!("{}-{}", self.pkg.name(), short_hash(self)) } + + /// Returns a new `Unit` with all the same fields as this one except with a + /// different `mode` + pub fn with_mode(&self, mode: CompileMode, units: &'a UnitInterner<'a>) -> Unit<'a> { + units.intern(self.pkg, self.target, self.profile, self.kind, mode) + } } // Just hash the pointer for fast hashing diff --git a/src/cargo/core/manifest.rs b/src/cargo/core/manifest.rs index 3cb9481680e..5f44fa0cf3c 100644 --- a/src/cargo/core/manifest.rs +++ b/src/cargo/core/manifest.rs @@ -120,6 +120,19 @@ impl LibKind { LibKind::Other(..) => false, } } + + pub fn requires_upstream_objects(&self) -> bool { + match *self { + // "lib" == "rlib" and is a compilation that doesn't actually + // require upstream object files to exist, only upstream etadata + // files. As a result, it doesn't require upstream artifacts + LibKind::Lib | LibKind::Rlib => false, + + // Everything else, however, is some form of "linkable output" or + // something that requires upstream object files. + _ => true, + } + } } impl fmt::Debug for LibKind { @@ -795,6 +808,10 @@ impl Target { }) } + /// Returns whether this target produces an artifact which can be linked + /// into a Rust crate. + /// + /// This only returns true for certain kinds of libraries. pub fn linkable(&self) -> bool { match self.kind { TargetKind::Lib(ref kinds) => kinds.iter().any(|k| k.linkable()), @@ -802,6 +819,20 @@ impl Target { } } + /// Returns whether production of this artifact requires the object files + /// from dependencies to be available. + /// + /// This only returns `false` when all we're producing is an rlib, otherwise + /// it will return `true`. + pub fn requires_upstream_objects(&self) -> bool { + match &self.kind { + TargetKind::Lib(kinds) | TargetKind::ExampleLib(kinds) => { + kinds.iter().any(|k| k.requires_upstream_objects()) + } + _ => true, + } + } + pub fn is_bin(&self) -> bool { self.kind == TargetKind::Bin } diff --git a/src/cargo/core/profiles.rs b/src/cargo/core/profiles.rs index 8cf142981c8..16a7bab89ff 100644 --- a/src/cargo/core/profiles.rs +++ b/src/cargo/core/profiles.rs @@ -93,6 +93,7 @@ impl Profiles { } } CompileMode::Build + | CompileMode::BuildRmeta | CompileMode::Check { .. } | CompileMode::Doctest | CompileMode::RunCustomBuild => { diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index 3d1719dfc34..749e9d048d7 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -271,6 +271,7 @@ pub fn compile_ws<'a>( match build_config.mode { CompileMode::Test | CompileMode::Build + | CompileMode::BuildRmeta | CompileMode::Check { .. } | CompileMode::Bench | CompileMode::RunCustomBuild => { @@ -502,8 +503,10 @@ impl CompileFilter { pub fn need_dev_deps(&self, mode: CompileMode) -> bool { match mode { CompileMode::Test | CompileMode::Doctest | CompileMode::Bench => true, - CompileMode::Build | CompileMode::Doc { .. } | CompileMode::Check { .. } => match *self - { + CompileMode::Build + | CompileMode::BuildRmeta + | CompileMode::Doc { .. } + | CompileMode::Check { .. } => match *self { CompileFilter::Default { .. } => false, CompileFilter::Only { ref examples, @@ -845,7 +848,7 @@ fn filter_default_targets(targets: &[Target], mode: CompileMode) -> Vec<&Target> .iter() .filter(|t| t.tested() || t.is_example()) .collect(), - CompileMode::Build | CompileMode::Check { .. } => targets + CompileMode::Build | CompileMode::BuildRmeta | CompileMode::Check { .. } => targets .iter() .filter(|t| t.is_bin() || t.is_lib()) .collect(), diff --git a/tests/testsuite/build.rs b/tests/testsuite/build.rs index cb7d021254a..efb810ad36c 100644 --- a/tests/testsuite/build.rs +++ b/tests/testsuite/build.rs @@ -1451,27 +1451,25 @@ fn cargo_default_env_metadata_env_var() { // No metadata on libbar since it's a dylib path dependency p.cargo("build -v") - .with_stderr(&format!( + .with_stderr( "\ [COMPILING] bar v0.0.1 ([CWD]/bar) [RUNNING] `rustc --crate-name bar bar/src/lib.rs --color never --crate-type dylib \ - --emit=dep-info,link \ + --emit=[..]link \ -C prefer-dynamic -C debuginfo=2 \ -C metadata=[..] \ --out-dir [..] \ -L dependency=[CWD]/target/debug/deps` [COMPILING] foo v0.0.1 ([CWD]) [RUNNING] `rustc --crate-name foo src/lib.rs --color never --crate-type lib \ - --emit=dep-info,link -C debuginfo=2 \ + --emit=[..]link -C debuginfo=2 \ -C metadata=[..] \ -C extra-filename=[..] \ --out-dir [..] \ -L dependency=[CWD]/target/debug/deps \ - --extern bar=[CWD]/target/debug/deps/{prefix}bar{suffix}` + --extern bar=[CWD]/target/debug/deps/libbar[..]` [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]", - prefix = env::consts::DLL_PREFIX, - suffix = env::consts::DLL_SUFFIX, - )) + ) .run(); p.cargo("clean").run(); @@ -1479,28 +1477,26 @@ fn cargo_default_env_metadata_env_var() { // If you set the env-var, then we expect metadata on libbar p.cargo("build -v") .env("__CARGO_DEFAULT_LIB_METADATA", "stable") - .with_stderr(&format!( + .with_stderr( "\ [COMPILING] bar v0.0.1 ([CWD]/bar) [RUNNING] `rustc --crate-name bar bar/src/lib.rs --color never --crate-type dylib \ - --emit=dep-info,link \ + --emit=[..]link \ -C prefer-dynamic -C debuginfo=2 \ -C metadata=[..] \ --out-dir [..] \ -L dependency=[CWD]/target/debug/deps` [COMPILING] foo v0.0.1 ([CWD]) [RUNNING] `rustc --crate-name foo src/lib.rs --color never --crate-type lib \ - --emit=dep-info,link -C debuginfo=2 \ + --emit=[..]link -C debuginfo=2 \ -C metadata=[..] \ -C extra-filename=[..] \ --out-dir [..] \ -L dependency=[CWD]/target/debug/deps \ - --extern bar=[CWD]/target/debug/deps/{prefix}bar-[..]{suffix}` + --extern bar=[CWD]/target/debug/deps/libbar-[..]` [FINISHED] dev [unoptimized + debuginfo] target(s) in [..] ", - prefix = env::consts::DLL_PREFIX, - suffix = env::consts::DLL_SUFFIX, - )) + ) .run(); } @@ -1864,7 +1860,7 @@ fn lto_build() { "\ [COMPILING] test v0.0.0 ([CWD]) [RUNNING] `rustc --crate-name test src/main.rs --color never --crate-type bin \ - --emit=dep-info,link \ + --emit=[..]link \ -C opt-level=3 \ -C lto \ -C metadata=[..] \ @@ -1884,7 +1880,7 @@ fn verbose_build() { "\ [COMPILING] foo v0.0.1 ([CWD]) [RUNNING] `rustc --crate-name foo src/lib.rs --color never --crate-type lib \ - --emit=dep-info,link -C debuginfo=2 \ + --emit=[..]link -C debuginfo=2 \ -C metadata=[..] \ --out-dir [..] \ -L dependency=[CWD]/target/debug/deps` @@ -1902,7 +1898,7 @@ fn verbose_release_build() { "\ [COMPILING] foo v0.0.1 ([CWD]) [RUNNING] `rustc --crate-name foo src/lib.rs --color never --crate-type lib \ - --emit=dep-info,link \ + --emit=[..]link \ -C opt-level=3 \ -C metadata=[..] \ --out-dir [..] \ @@ -1925,6 +1921,9 @@ fn verbose_release_build_deps() { version = "0.0.0" authors = [] + [lib] + crate-type = ['cdylib'] + [dependencies.foo] path = "foo" "#, @@ -1952,15 +1951,15 @@ fn verbose_release_build_deps() { [COMPILING] foo v0.0.0 ([CWD]/foo) [RUNNING] `rustc --crate-name foo foo/src/lib.rs --color never \ --crate-type dylib --crate-type rlib \ - --emit=dep-info,link \ + --emit=[..]link \ -C prefer-dynamic \ -C opt-level=3 \ -C metadata=[..] \ --out-dir [..] \ -L dependency=[CWD]/target/release/deps` [COMPILING] test v0.0.0 ([CWD]) -[RUNNING] `rustc --crate-name test src/lib.rs --color never --crate-type lib \ - --emit=dep-info,link \ +[RUNNING] `rustc --crate-name test src/lib.rs --color never --crate-type cdylib \ + --emit=[..]link \ -C opt-level=3 \ -C metadata=[..] \ --out-dir [..] \ @@ -3349,9 +3348,8 @@ fn compiler_json_error_format() { .file("bar/src/lib.rs", r#"fn dead() {}"#) .build(); - // Use `jobs=1` to ensure that the order of messages is consistent. - p.cargo("build -v --message-format=json --jobs=1") - .with_json( + p.cargo("build -v --message-format=json") + .with_json_contains_unordered( r#" { "reason":"compiler-artifact", @@ -3462,8 +3460,8 @@ fn compiler_json_error_format() { // With fresh build, we should repeat the artifacts, // but omit compiler warnings. - p.cargo("build -v --message-format=json --jobs=1") - .with_json( + p.cargo("build -v --message-format=json") + .with_json_contains_unordered( r#" { "reason":"compiler-artifact", @@ -4497,11 +4495,11 @@ fn build_filter_infer_profile() { p.cargo("build -v") .with_stderr_contains( "[RUNNING] `rustc --crate-name foo src/lib.rs --color never --crate-type lib \ - --emit=dep-info,link[..]", + --emit=[..]link[..]", ) .with_stderr_contains( "[RUNNING] `rustc --crate-name foo src/main.rs --color never --crate-type bin \ - --emit=dep-info,link[..]", + --emit=[..]link[..]", ) .run(); @@ -4509,15 +4507,15 @@ fn build_filter_infer_profile() { p.cargo("build -v --test=t1") .with_stderr_contains( "[RUNNING] `rustc --crate-name foo src/lib.rs --color never --crate-type lib \ - --emit=dep-info,link -C debuginfo=2 [..]", + --emit=[..]link -C debuginfo=2 [..]", ) .with_stderr_contains( - "[RUNNING] `rustc --crate-name t1 tests/t1.rs --color never --emit=dep-info,link \ + "[RUNNING] `rustc --crate-name t1 tests/t1.rs --color never --emit=[..]link \ -C debuginfo=2 [..]", ) .with_stderr_contains( "[RUNNING] `rustc --crate-name foo src/main.rs --color never --crate-type bin \ - --emit=dep-info,link -C debuginfo=2 [..]", + --emit=[..]link -C debuginfo=2 [..]", ) .run(); @@ -4526,16 +4524,16 @@ fn build_filter_infer_profile() { p.cargo("build -v --bench=b1") .with_stderr_contains( "[RUNNING] `rustc --crate-name foo src/lib.rs --color never --crate-type lib \ - --emit=dep-info,link -C debuginfo=2 [..]", + --emit=[..]link -C debuginfo=2 [..]", ) .with_stderr_contains( - "[RUNNING] `rustc --crate-name b1 benches/b1.rs --color never --emit=dep-info,link \ + "[RUNNING] `rustc --crate-name b1 benches/b1.rs --color never --emit=[..]link \ -C debuginfo=2 [..]", ) .with_stderr_does_not_contain("opt-level") .with_stderr_contains( "[RUNNING] `rustc --crate-name foo src/main.rs --color never --crate-type bin \ - --emit=dep-info,link -C debuginfo=2 [..]", + --emit=[..]link -C debuginfo=2 [..]", ) .run(); } @@ -4548,18 +4546,18 @@ fn targets_selected_default() { .with_stderr_contains( "\ [RUNNING] `rustc --crate-name foo src/main.rs --color never --crate-type bin \ - --emit=dep-info,link[..]", + --emit=[..]link[..]", ) // Benchmarks. .with_stderr_does_not_contain( "\ - [RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=dep-info,link \ + [RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=[..]link \ -C opt-level=3 --test [..]", ) // Unit tests. .with_stderr_does_not_contain( "\ - [RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=dep-info,link \ + [RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=[..]link \ -C debuginfo=2 --test [..]", ) .run(); @@ -4573,12 +4571,12 @@ fn targets_selected_all() { .with_stderr_contains( "\ [RUNNING] `rustc --crate-name foo src/main.rs --color never --crate-type bin \ - --emit=dep-info,link[..]", + --emit=[..]link[..]", ) // Unit tests. .with_stderr_contains( "\ - [RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=dep-info,link \ + [RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=[..]link \ -C debuginfo=2 --test [..]", ) .run(); @@ -4592,12 +4590,12 @@ fn all_targets_no_lib() { .with_stderr_contains( "\ [RUNNING] `rustc --crate-name foo src/main.rs --color never --crate-type bin \ - --emit=dep-info,link[..]", + --emit=[..]link[..]", ) // Unit tests. .with_stderr_contains( "\ - [RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=dep-info,link \ + [RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=[..]link \ -C debuginfo=2 --test [..]", ) .run(); diff --git a/tests/testsuite/build_lib.rs b/tests/testsuite/build_lib.rs index 00c256b610f..05627fe0552 100644 --- a/tests/testsuite/build_lib.rs +++ b/tests/testsuite/build_lib.rs @@ -12,7 +12,7 @@ fn build_lib_only() { "\ [COMPILING] foo v0.0.1 ([CWD]) [RUNNING] `rustc --crate-name foo src/lib.rs --color never --crate-type lib \ - --emit=dep-info,link -C debuginfo=2 \ + --emit=[..]link -C debuginfo=2 \ -C metadata=[..] \ --out-dir [..] \ -L dependency=[CWD]/target/debug/deps` diff --git a/tests/testsuite/build_script.rs b/tests/testsuite/build_script.rs index 3303327fea9..db2bf4a0982 100644 --- a/tests/testsuite/build_script.rs +++ b/tests/testsuite/build_script.rs @@ -241,7 +241,7 @@ fn custom_build_script_rustc_flags() { -C metadata=[..] \ -C extra-filename=-[..] \ --out-dir [CWD]/target \ - --emit=dep-info,link \ + --emit=[..]link \ -L [CWD]/target \ -L [CWD]/target/deps` ", @@ -1015,19 +1015,19 @@ fn build_cmd_with_a_build_cmd() { [RUNNING] `rustc [..] a/build.rs [..] --extern b=[..]` [RUNNING] `[..]/a-[..]/build-script-build` [RUNNING] `rustc --crate-name a [..]lib.rs --color never --crate-type lib \ - --emit=dep-info,link -C debuginfo=2 \ + --emit=[..]link -C debuginfo=2 \ -C metadata=[..] \ --out-dir [..]target/debug/deps \ -L [..]target/debug/deps` [COMPILING] foo v0.5.0 ([CWD]) [RUNNING] `rustc --crate-name build_script_build build.rs --color never --crate-type bin \ - --emit=dep-info,link \ + --emit=[..]link \ -C debuginfo=2 -C metadata=[..] --out-dir [..] \ -L [..]target/debug/deps \ --extern a=[..]liba[..].rlib` [RUNNING] `[..]/foo-[..]/build-script-build` [RUNNING] `rustc --crate-name foo [..]lib.rs --color never --crate-type lib \ - --emit=dep-info,link -C debuginfo=2 \ + --emit=[..]link -C debuginfo=2 \ -C metadata=[..] \ --out-dir [..] \ -L [..]target/debug/deps` @@ -2228,7 +2228,7 @@ fn diamond_passes_args_only_once() { [COMPILING] a v0.5.0 ([..] [RUNNING] `rustc [..]` [COMPILING] foo v0.5.0 ([..] -[RUNNING] `[..]rlib -L native=test` +[RUNNING] `[..]rmeta -L native=test` [FINISHED] dev [unoptimized + debuginfo] target(s) in [..] ", ) diff --git a/tests/testsuite/cfg.rs b/tests/testsuite/cfg.rs index 36866cc27d8..09b0d18c5d6 100644 --- a/tests/testsuite/cfg.rs +++ b/tests/testsuite/cfg.rs @@ -409,7 +409,9 @@ fn any_ok() { .file("b/Cargo.toml", &basic_manifest("b", "0.0.1")) .file("b/src/lib.rs", "") .build(); - p.cargo("build -v").run(); + p.cargo("build -v") + .env("RUST_LOG", "cargo") + .run(); } // https://github.com/rust-lang/cargo/issues/5313 diff --git a/tests/testsuite/clean.rs b/tests/testsuite/clean.rs index a0ec3affcfb..23e822986d7 100644 --- a/tests/testsuite/clean.rs +++ b/tests/testsuite/clean.rs @@ -289,6 +289,7 @@ fn clean_verbose() { "\ [REMOVING] [..] [REMOVING] [..] +[REMOVING] [..] ", ) .run(); diff --git a/tests/testsuite/cross_compile.rs b/tests/testsuite/cross_compile.rs index 6e9623aba21..e98d0b04456 100644 --- a/tests/testsuite/cross_compile.rs +++ b/tests/testsuite/cross_compile.rs @@ -379,7 +379,7 @@ fn linker_and_ar() { "\ [COMPILING] foo v0.5.0 ([CWD]) [RUNNING] `rustc --crate-name foo src/foo.rs --color never --crate-type bin \ - --emit=dep-info,link -C debuginfo=2 \ + --emit=[..]link -C debuginfo=2 \ -C metadata=[..] \ --out-dir [CWD]/target/{target}/debug/deps \ --target {target} \ diff --git a/tests/testsuite/dep_info.rs b/tests/testsuite/dep_info.rs index 2f8b910f8ba..8959c4e4920 100644 --- a/tests/testsuite/dep_info.rs +++ b/tests/testsuite/dep_info.rs @@ -60,7 +60,10 @@ fn build_dep_info_rlib() { .file("examples/ex.rs", "") .build(); - p.cargo("build --example=ex").run(); + p.cargo("build --example=ex") + .stream() + .env("RUST_LOG", "cargo") + .run(); assert!(p.example_lib("ex", "rlib").with_extension("d").is_file()); } diff --git a/tests/testsuite/freshness.rs b/tests/testsuite/freshness.rs index 76c10a71655..8a076a8dbd0 100644 --- a/tests/testsuite/freshness.rs +++ b/tests/testsuite/freshness.rs @@ -1439,8 +1439,8 @@ fn reuse_panic_pm() { .with_stderr_unordered( "\ [COMPILING] bar [..] -[RUNNING] `rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C debuginfo=2 [..] -[RUNNING] `rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C panic=abort -C debuginfo=2 [..] +[RUNNING] `rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C debuginfo=2 [..] +[RUNNING] `rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C panic=abort -C debuginfo=2 [..] [COMPILING] somepm [..] [RUNNING] `rustc --crate-name somepm [..] [COMPILING] foo [..] diff --git a/tests/testsuite/profile_overrides.rs b/tests/testsuite/profile_overrides.rs index 09bfd7dba48..141a709402a 100644 --- a/tests/testsuite/profile_overrides.rs +++ b/tests/testsuite/profile_overrides.rs @@ -321,17 +321,17 @@ fn profile_override_hierarchy() { p.cargo("build -v").masquerade_as_nightly_cargo().with_stderr_unordered("\ [COMPILING] m3 [..] [COMPILING] dep [..] -[RUNNING] `rustc --crate-name m3 m3/src/lib.rs --color never --crate-type lib --emit=dep-info,link -C codegen-units=4 [..] -[RUNNING] `rustc --crate-name dep [..]dep/src/lib.rs --color never --crate-type lib --emit=dep-info,link -C codegen-units=3 [..] -[RUNNING] `rustc --crate-name m3 m3/src/lib.rs --color never --crate-type lib --emit=dep-info,link -C codegen-units=1 [..] -[RUNNING] `rustc --crate-name build_script_build m1/build.rs --color never --crate-type bin --emit=dep-info,link -C codegen-units=4 [..] +[RUNNING] `rustc --crate-name m3 m3/src/lib.rs --color never --crate-type lib --emit=[..]link -C codegen-units=4 [..] +[RUNNING] `rustc --crate-name dep [..]dep/src/lib.rs --color never --crate-type lib --emit=[..]link -C codegen-units=3 [..] +[RUNNING] `rustc --crate-name m3 m3/src/lib.rs --color never --crate-type lib --emit=[..]link -C codegen-units=1 [..] +[RUNNING] `rustc --crate-name build_script_build m1/build.rs --color never --crate-type bin --emit=[..]link -C codegen-units=4 [..] [COMPILING] m2 [..] -[RUNNING] `rustc --crate-name build_script_build m2/build.rs --color never --crate-type bin --emit=dep-info,link -C codegen-units=2 [..] +[RUNNING] `rustc --crate-name build_script_build m2/build.rs --color never --crate-type bin --emit=[..]link -C codegen-units=2 [..] [RUNNING] `[..]/m1-[..]/build-script-build` [RUNNING] `[..]/m2-[..]/build-script-build` -[RUNNING] `rustc --crate-name m2 m2/src/lib.rs --color never --crate-type lib --emit=dep-info,link -C codegen-units=2 [..] +[RUNNING] `rustc --crate-name m2 m2/src/lib.rs --color never --crate-type lib --emit=[..]link -C codegen-units=2 [..] [COMPILING] m1 [..] -[RUNNING] `rustc --crate-name m1 m1/src/lib.rs --color never --crate-type lib --emit=dep-info,link -C codegen-units=1 [..] +[RUNNING] `rustc --crate-name m1 m1/src/lib.rs --color never --crate-type lib --emit=[..]link -C codegen-units=1 [..] [FINISHED] dev [unoptimized + debuginfo] [..] ", ) diff --git a/tests/testsuite/profile_targets.rs b/tests/testsuite/profile_targets.rs index f9de30d1acf..e1f5f8b510f 100644 --- a/tests/testsuite/profile_targets.rs +++ b/tests/testsuite/profile_targets.rs @@ -78,16 +78,16 @@ fn profile_selection_build() { // - build_script_build is built without panic because it thinks `build.rs` is a plugin. p.cargo("build -vv").with_stderr_unordered("\ [COMPILING] bar [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C codegen-units=1 -C debuginfo=2 [..] [COMPILING] bdep [..] -[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=[..]link -C codegen-units=1 -C debuginfo=2 [..] [COMPILING] foo [..] -[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=[..]link -C codegen-units=1 -C debuginfo=2 [..] [RUNNING] `[..]/target/debug/build/foo-[..]/build-script-build` [foo 0.0.1] foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0 -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=dep-info,link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] -[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--crate-type bin --emit=dep-info,link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=[..]link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--crate-type bin --emit=[..]link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] [FINISHED] dev [unoptimized + debuginfo] [..] ").run(); p.cargo("build -vv") @@ -109,16 +109,16 @@ fn profile_selection_build_release() { // `build --release` p.cargo("build --release -vv").with_stderr_unordered("\ [COMPILING] bar [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C opt-level=3 -C panic=abort -C codegen-units=2 [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C codegen-units=2 [..] [COMPILING] bdep [..] -[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C codegen-units=2 [..] [COMPILING] foo [..] -[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=[..]link -C opt-level=3 -C codegen-units=2 [..] [RUNNING] `[..]/target/release/build/foo-[..]/build-script-build` [foo 0.0.1] foo custom build PROFILE=release DEBUG=false OPT_LEVEL=3 -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=dep-info,link -C opt-level=3 -C panic=abort -C codegen-units=2 [..] -[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--crate-type bin --emit=dep-info,link -C opt-level=3 -C panic=abort -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--crate-type bin --emit=[..]link -C opt-level=3 -C panic=abort -C codegen-units=2 [..] [FINISHED] release [optimized] [..] ").run(); p.cargo("build --release -vv") @@ -165,22 +165,22 @@ fn profile_selection_build_all_targets() { // example dev build p.cargo("build --all-targets -vv").with_stderr_unordered("\ [COMPILING] bar [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] [COMPILING] bdep [..] -[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=[..]link -C codegen-units=1 -C debuginfo=2 [..] [COMPILING] foo [..] -[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=[..]link -C codegen-units=1 -C debuginfo=2 [..] [RUNNING] `[..]/target/debug/build/foo-[..]/build-script-build` [foo 0.0.1] foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0 -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=dep-info,link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..]` -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--emit=dep-info,link -C codegen-units=3 -C debuginfo=2 --test [..]` -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]` -[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--emit=dep-info,link -C codegen-units=3 -C debuginfo=2 --test [..]` -[RUNNING] `[..] rustc --crate-name test1 tests/test1.rs [..]--emit=dep-info,link -C codegen-units=3 -C debuginfo=2 --test [..]` -[RUNNING] `[..] rustc --crate-name bench1 benches/bench1.rs [..]--emit=dep-info,link -C codegen-units=3 -C debuginfo=2 --test [..]` -[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--crate-type bin --emit=dep-info,link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..]` -[RUNNING] `[..] rustc --crate-name ex1 examples/ex1.rs [..]--crate-type bin --emit=dep-info,link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..]` +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=[..]link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..]` +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--emit=[..]link -C codegen-units=3 -C debuginfo=2 --test [..]` +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=[..]link -C codegen-units=1 -C debuginfo=2 [..]` +[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--emit=[..]link -C codegen-units=3 -C debuginfo=2 --test [..]` +[RUNNING] `[..] rustc --crate-name test1 tests/test1.rs [..]--emit=[..]link -C codegen-units=3 -C debuginfo=2 --test [..]` +[RUNNING] `[..] rustc --crate-name bench1 benches/bench1.rs [..]--emit=[..]link -C codegen-units=3 -C debuginfo=2 --test [..]` +[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--crate-type bin --emit=[..]link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..]` +[RUNNING] `[..] rustc --crate-name ex1 examples/ex1.rs [..]--crate-type bin --emit=[..]link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..]` [FINISHED] dev [unoptimized + debuginfo] [..] ").run(); p.cargo("build -vv") @@ -230,22 +230,22 @@ fn profile_selection_build_all_targets_release() { // example release build p.cargo("build --all-targets --release -vv").with_stderr_unordered("\ [COMPILING] bar [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C opt-level=3 -C panic=abort -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort -C codegen-units=2 [..] [COMPILING] bdep [..] -[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C codegen-units=2 [..] [COMPILING] foo [..] -[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=[..]link -C opt-level=3 -C codegen-units=2 [..] [RUNNING] `[..]/target/release/build/foo-[..]/build-script-build` [foo 0.0.1] foo custom build PROFILE=release DEBUG=false OPT_LEVEL=3 -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=dep-info,link -C opt-level=3 -C panic=abort -C codegen-units=2 [..]` -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..]` -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..]` -[RUNNING] `[..] rustc --crate-name test1 tests/test1.rs [..]--emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..]` -[RUNNING] `[..] rustc --crate-name bench1 benches/bench1.rs [..]--emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..]` -[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..]` -[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--crate-type bin --emit=dep-info,link -C opt-level=3 -C panic=abort -C codegen-units=2 [..]` -[RUNNING] `[..] rustc --crate-name ex1 examples/ex1.rs [..]--crate-type bin --emit=dep-info,link -C opt-level=3 -C panic=abort -C codegen-units=2 [..]` +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort -C codegen-units=2 [..]` +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--emit=[..]link -C opt-level=3 -C codegen-units=4 --test [..]` +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C codegen-units=2 [..]` +[RUNNING] `[..] rustc --crate-name test1 tests/test1.rs [..]--emit=[..]link -C opt-level=3 -C codegen-units=4 --test [..]` +[RUNNING] `[..] rustc --crate-name bench1 benches/bench1.rs [..]--emit=[..]link -C opt-level=3 -C codegen-units=4 --test [..]` +[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--emit=[..]link -C opt-level=3 -C codegen-units=4 --test [..]` +[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--crate-type bin --emit=[..]link -C opt-level=3 -C panic=abort -C codegen-units=2 [..]` +[RUNNING] `[..] rustc --crate-name ex1 examples/ex1.rs [..]--crate-type bin --emit=[..]link -C opt-level=3 -C panic=abort -C codegen-units=2 [..]` [FINISHED] release [optimized] [..] ").run(); p.cargo("build --all-targets --release -vv") @@ -286,21 +286,21 @@ fn profile_selection_test() { // p.cargo("test -vv").with_stderr_unordered("\ [COMPILING] bar [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] [COMPILING] bdep [..] -[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=[..]link -C codegen-units=1 -C debuginfo=2 [..] [COMPILING] foo [..] -[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=[..]link -C codegen-units=1 -C debuginfo=2 [..] [RUNNING] `[..]/target/debug/build/foo-[..]/build-script-build` [foo 0.0.1] foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0 -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=dep-info,link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..] -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--emit=dep-info,link -C codegen-units=3 -C debuginfo=2 --test [..] -[RUNNING] `[..] rustc --crate-name test1 tests/test1.rs [..]--emit=dep-info,link -C codegen-units=3 -C debuginfo=2 --test [..] -[RUNNING] `[..] rustc --crate-name ex1 examples/ex1.rs [..]--crate-type bin --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..] -[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--emit=dep-info,link -C codegen-units=3 -C debuginfo=2 --test [..] -[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--crate-type bin --emit=dep-info,link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=[..]link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=[..]link -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--emit=[..]link -C codegen-units=3 -C debuginfo=2 --test [..] +[RUNNING] `[..] rustc --crate-name test1 tests/test1.rs [..]--emit=[..]link -C codegen-units=3 -C debuginfo=2 --test [..] +[RUNNING] `[..] rustc --crate-name ex1 examples/ex1.rs [..]--crate-type bin --emit=[..]link -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--emit=[..]link -C codegen-units=3 -C debuginfo=2 --test [..] +[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--crate-type bin --emit=[..]link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] [FINISHED] dev [unoptimized + debuginfo] [..] [RUNNING] `[..]/deps/foo-[..]` [RUNNING] `[..]/deps/foo-[..]` @@ -351,21 +351,21 @@ fn profile_selection_test_release() { // p.cargo("test --release -vv").with_stderr_unordered("\ [COMPILING] bar [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C opt-level=3 -C panic=abort -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort -C codegen-units=2 [..] [COMPILING] bdep [..] -[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C codegen-units=2 [..] [COMPILING] foo [..] -[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=[..]link -C opt-level=3 -C codegen-units=2 [..] [RUNNING] `[..]/target/release/build/foo-[..]/build-script-build` [foo 0.0.1] foo custom build PROFILE=release DEBUG=false OPT_LEVEL=3 -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=dep-info,link -C opt-level=3 -C panic=abort -C codegen-units=2 [..] -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..] -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..] -[RUNNING] `[..] rustc --crate-name test1 tests/test1.rs [..]--emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..] -[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..] -[RUNNING] `[..] rustc --crate-name ex1 examples/ex1.rs [..]--crate-type bin --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..] -[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--crate-type bin --emit=dep-info,link -C opt-level=3 -C panic=abort -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--emit=[..]link -C opt-level=3 -C codegen-units=4 --test [..] +[RUNNING] `[..] rustc --crate-name test1 tests/test1.rs [..]--emit=[..]link -C opt-level=3 -C codegen-units=4 --test [..] +[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--emit=[..]link -C opt-level=3 -C codegen-units=4 --test [..] +[RUNNING] `[..] rustc --crate-name ex1 examples/ex1.rs [..]--crate-type bin --emit=[..]link -C opt-level=3 -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--crate-type bin --emit=[..]link -C opt-level=3 -C panic=abort -C codegen-units=2 [..] [FINISHED] release [optimized] [..] [RUNNING] `[..]/deps/foo-[..]` [RUNNING] `[..]/deps/foo-[..]` @@ -416,20 +416,20 @@ fn profile_selection_bench() { // p.cargo("bench -vv").with_stderr_unordered("\ [COMPILING] bar [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C opt-level=3 -C panic=abort -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort -C codegen-units=2 [..] [COMPILING] bdep [..] -[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C codegen-units=2 [..] [COMPILING] foo [..] -[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=[..]link -C opt-level=3 -C codegen-units=2 [..] [RUNNING] `[..]target/release/build/foo-[..]/build-script-build` [foo 0.0.1] foo custom build PROFILE=release DEBUG=false OPT_LEVEL=3 -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=dep-info,link -C opt-level=3 -C panic=abort -C codegen-units=2 [..] -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..] -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..] -[RUNNING] `[..] rustc --crate-name bench1 benches/bench1.rs [..]--emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..] -[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..] -[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--crate-type bin --emit=dep-info,link -C opt-level=3 -C panic=abort -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--emit=[..]link -C opt-level=3 -C codegen-units=4 --test [..] +[RUNNING] `[..] rustc --crate-name bench1 benches/bench1.rs [..]--emit=[..]link -C opt-level=3 -C codegen-units=4 --test [..] +[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--emit=[..]link -C opt-level=3 -C codegen-units=4 --test [..] +[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--crate-type bin --emit=[..]link -C opt-level=3 -C panic=abort -C codegen-units=2 [..] [FINISHED] release [optimized] [..] [RUNNING] `[..]/deps/foo-[..] --bench` [RUNNING] `[..]/deps/foo-[..] --bench` @@ -480,23 +480,23 @@ fn profile_selection_check_all_targets() { // p.cargo("check --all-targets -vv").with_stderr_unordered("\ [COMPILING] bar [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,metadata -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]metadata -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]metadata -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] [COMPILING] bdep[..] -[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=[..]link -C codegen-units=1 -C debuginfo=2 [..] [COMPILING] foo [..] -[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=[..]link -C codegen-units=1 -C debuginfo=2 [..] [RUNNING] `[..]target/debug/build/foo-[..]/build-script-build` [foo 0.0.1] foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0 -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=dep-info,metadata -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 [..] -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..] -[RUNNING] `[..] rustc --crate-name test1 tests/test1.rs [..]--emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..] -[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..] -[RUNNING] `[..] rustc --crate-name bench1 benches/bench1.rs [..]--emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..] -[RUNNING] `[..] rustc --crate-name ex1 examples/ex1.rs [..]--crate-type bin --emit=dep-info,metadata -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] -[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--crate-type bin --emit=dep-info,metadata -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=[..]metadata -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=[..]metadata -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--emit=[..]metadata -C codegen-units=1 -C debuginfo=2 --test [..] +[RUNNING] `[..] rustc --crate-name test1 tests/test1.rs [..]--emit=[..]metadata -C codegen-units=1 -C debuginfo=2 --test [..] +[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--emit=[..]metadata -C codegen-units=1 -C debuginfo=2 --test [..] +[RUNNING] `[..] rustc --crate-name bench1 benches/bench1.rs [..]--emit=[..]metadata -C codegen-units=1 -C debuginfo=2 --test [..] +[RUNNING] `[..] rustc --crate-name ex1 examples/ex1.rs [..]--crate-type bin --emit=[..]metadata -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--crate-type bin --emit=[..]metadata -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] [FINISHED] dev [unoptimized + debuginfo] [..] ").run(); // Starting with Rust 1.27, rustc emits `rmeta` files for bins, so @@ -525,23 +525,23 @@ fn profile_selection_check_all_targets_release() { // `dev` for all targets. p.cargo("check --all-targets --release -vv").with_stderr_unordered("\ [COMPILING] bar [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,metadata -C opt-level=3 -C codegen-units=2 [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,metadata -C opt-level=3 -C panic=abort -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]metadata -C opt-level=3 -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]metadata -C opt-level=3 -C panic=abort -C codegen-units=2 [..] [COMPILING] bdep[..] -[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C codegen-units=2 [..] [COMPILING] foo [..] -[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=dep-info,link -C opt-level=3 -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=[..]link -C opt-level=3 -C codegen-units=2 [..] [RUNNING] `[..]target/release/build/foo-[..]/build-script-build` [foo 0.0.1] foo custom build PROFILE=release DEBUG=false OPT_LEVEL=3 -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=dep-info,metadata -C opt-level=3 -C panic=abort -C codegen-units=2 [..] -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=dep-info,metadata -C opt-level=3 -C codegen-units=2 [..] -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--emit=dep-info,metadata -C opt-level=3 -C codegen-units=2 --test [..] -[RUNNING] `[..] rustc --crate-name test1 tests/test1.rs [..]--emit=dep-info,metadata -C opt-level=3 -C codegen-units=2 --test [..] -[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--emit=dep-info,metadata -C opt-level=3 -C codegen-units=2 --test [..] -[RUNNING] `[..] rustc --crate-name bench1 benches/bench1.rs [..]--emit=dep-info,metadata -C opt-level=3 -C codegen-units=2 --test [..] -[RUNNING] `[..] rustc --crate-name ex1 examples/ex1.rs [..]--crate-type bin --emit=dep-info,metadata -C opt-level=3 -C panic=abort -C codegen-units=2 [..] -[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--crate-type bin --emit=dep-info,metadata -C opt-level=3 -C panic=abort -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=[..]metadata -C opt-level=3 -C panic=abort -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=[..]metadata -C opt-level=3 -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--emit=[..]metadata -C opt-level=3 -C codegen-units=2 --test [..] +[RUNNING] `[..] rustc --crate-name test1 tests/test1.rs [..]--emit=[..]metadata -C opt-level=3 -C codegen-units=2 --test [..] +[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--emit=[..]metadata -C opt-level=3 -C codegen-units=2 --test [..] +[RUNNING] `[..] rustc --crate-name bench1 benches/bench1.rs [..]--emit=[..]metadata -C opt-level=3 -C codegen-units=2 --test [..] +[RUNNING] `[..] rustc --crate-name ex1 examples/ex1.rs [..]--crate-type bin --emit=[..]metadata -C opt-level=3 -C panic=abort -C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--crate-type bin --emit=[..]metadata -C opt-level=3 -C panic=abort -C codegen-units=2 [..] [FINISHED] release [optimized] [..] ").run(); @@ -586,20 +586,20 @@ fn profile_selection_check_all_targets_test() { // p.cargo("check --all-targets --profile=test -vv").with_stderr_unordered("\ [COMPILING] bar [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]metadata -C codegen-units=1 -C debuginfo=2 [..] [COMPILING] bdep[..] -[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=[..]link -C codegen-units=1 -C debuginfo=2 [..] [COMPILING] foo [..] -[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=[..]link -C codegen-units=1 -C debuginfo=2 [..] [RUNNING] `[..]target/debug/build/foo-[..]/build-script-build` [foo 0.0.1] foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0 -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 [..] -[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..] -[RUNNING] `[..] rustc --crate-name test1 tests/test1.rs [..]--emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..] -[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..] -[RUNNING] `[..] rustc --crate-name bench1 benches/bench1.rs [..]--emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..] -[RUNNING] `[..] rustc --crate-name ex1 examples/ex1.rs [..]--emit=dep-info,metadata -C codegen-units=1 -C debuginfo=2 --test [..] +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=[..]metadata -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name foo src/lib.rs [..]--emit=[..]metadata -C codegen-units=1 -C debuginfo=2 --test [..] +[RUNNING] `[..] rustc --crate-name test1 tests/test1.rs [..]--emit=[..]metadata -C codegen-units=1 -C debuginfo=2 --test [..] +[RUNNING] `[..] rustc --crate-name foo src/main.rs [..]--emit=[..]metadata -C codegen-units=1 -C debuginfo=2 --test [..] +[RUNNING] `[..] rustc --crate-name bench1 benches/bench1.rs [..]--emit=[..]metadata -C codegen-units=1 -C debuginfo=2 --test [..] +[RUNNING] `[..] rustc --crate-name ex1 examples/ex1.rs [..]--emit=[..]metadata -C codegen-units=1 -C debuginfo=2 --test [..] [FINISHED] dev [unoptimized + debuginfo] [..] ").run(); @@ -632,13 +632,13 @@ fn profile_selection_doc() { p.cargo("doc -vv").with_stderr_unordered("\ [COMPILING] bar [..] [DOCUMENTING] bar [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C codegen-units=1 -C debuginfo=2 [..] [RUNNING] `rustdoc --crate-name bar bar/src/lib.rs [..] -[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=dep-info,metadata -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name bar bar/src/lib.rs [..]--crate-type lib --emit=[..]metadata -C panic=abort -C codegen-units=1 -C debuginfo=2 [..] [COMPILING] bdep [..] -[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name bdep bdep/src/lib.rs [..]--crate-type lib --emit=[..]link -C codegen-units=1 -C debuginfo=2 [..] [COMPILING] foo [..] -[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=[..]link -C codegen-units=1 -C debuginfo=2 [..] [RUNNING] `[..]target/debug/build/foo-[..]/build-script-build` [foo 0.0.1] foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0 [DOCUMENTING] foo [..] diff --git a/tests/testsuite/profiles.rs b/tests/testsuite/profiles.rs index dd5608a0573..a139399b823 100644 --- a/tests/testsuite/profiles.rs +++ b/tests/testsuite/profiles.rs @@ -27,7 +27,7 @@ fn profile_overrides() { "\ [COMPILING] test v0.0.0 ([CWD]) [RUNNING] `rustc --crate-name test src/lib.rs --color never --crate-type lib \ - --emit=dep-info,link \ + --emit=[..]link \ -C opt-level=1 \ -C debug-assertions=on \ -C metadata=[..] \ @@ -63,7 +63,7 @@ fn opt_level_override_0() { "\ [COMPILING] test v0.0.0 ([CWD]) [RUNNING] `rustc --crate-name test src/lib.rs --color never --crate-type lib \ - --emit=dep-info,link \ + --emit=[..]link \ -C debuginfo=2 \ -C metadata=[..] \ --out-dir [..] \ @@ -96,7 +96,7 @@ fn debug_override_1() { "\ [COMPILING] test v0.0.0 ([CWD]) [RUNNING] `rustc --crate-name test src/lib.rs --color never --crate-type lib \ - --emit=dep-info,link \ + --emit=[..]link \ -C debuginfo=1 \ -C metadata=[..] \ --out-dir [..] \ @@ -132,7 +132,7 @@ fn check_opt_level_override(profile_level: &str, rustc_level: &str) { "\ [COMPILING] test v0.0.0 ([CWD]) [RUNNING] `rustc --crate-name test src/lib.rs --color never --crate-type lib \ - --emit=dep-info,link \ + --emit=[..]link \ -C opt-level={level} \ -C debuginfo=2 \ -C debug-assertions=on \ @@ -171,6 +171,9 @@ fn top_level_overrides_deps() { version = "0.0.0" authors = [] + [lib] + crate-type = ['cdylib'] + [profile.release] opt-level = 1 debug = true @@ -206,7 +209,7 @@ fn top_level_overrides_deps() { [COMPILING] foo v0.0.0 ([CWD]/foo) [RUNNING] `rustc --crate-name foo foo/src/lib.rs --color never \ --crate-type dylib --crate-type rlib \ - --emit=dep-info,link \ + --emit=[..]link \ -C prefer-dynamic \ -C opt-level=1 \ -C debuginfo=2 \ @@ -214,8 +217,8 @@ fn top_level_overrides_deps() { --out-dir [CWD]/target/release/deps \ -L dependency=[CWD]/target/release/deps` [COMPILING] test v0.0.0 ([CWD]) -[RUNNING] `rustc --crate-name test src/lib.rs --color never --crate-type lib \ - --emit=dep-info,link \ +[RUNNING] `rustc --crate-name test src/lib.rs --color never --crate-type cdylib \ + --emit=[..]link \ -C opt-level=1 \ -C debuginfo=2 \ -C metadata=[..] \ diff --git a/tests/testsuite/run.rs b/tests/testsuite/run.rs index 25494a51cc4..70e938dd09c 100644 --- a/tests/testsuite/run.rs +++ b/tests/testsuite/run.rs @@ -697,14 +697,14 @@ fn example_with_release_flag() { "\ [COMPILING] bar v0.5.0 ([CWD]/bar) [RUNNING] `rustc --crate-name bar bar/src/bar.rs --color never --crate-type lib \ - --emit=dep-info,link \ + --emit=[..]link \ -C opt-level=3 \ -C metadata=[..] \ --out-dir [CWD]/target/release/deps \ -L dependency=[CWD]/target/release/deps` [COMPILING] foo v0.0.1 ([CWD]) [RUNNING] `rustc --crate-name a examples/a.rs --color never --crate-type bin \ - --emit=dep-info,link \ + --emit=[..]link \ -C opt-level=3 \ -C metadata=[..] \ --out-dir [CWD]/target/release/examples \ @@ -726,14 +726,14 @@ fast2", "\ [COMPILING] bar v0.5.0 ([CWD]/bar) [RUNNING] `rustc --crate-name bar bar/src/bar.rs --color never --crate-type lib \ - --emit=dep-info,link \ + --emit=[..]link \ -C debuginfo=2 \ -C metadata=[..] \ --out-dir [CWD]/target/debug/deps \ -L dependency=[CWD]/target/debug/deps` [COMPILING] foo v0.0.1 ([CWD]) [RUNNING] `rustc --crate-name a examples/a.rs --color never --crate-type bin \ - --emit=dep-info,link \ + --emit=[..]link \ -C debuginfo=2 \ -C metadata=[..] \ --out-dir [CWD]/target/debug/examples \ diff --git a/tests/testsuite/rustc.rs b/tests/testsuite/rustc.rs index 8fef310b173..7674afdb62d 100644 --- a/tests/testsuite/rustc.rs +++ b/tests/testsuite/rustc.rs @@ -16,7 +16,7 @@ fn build_lib_for_foo() { "\ [COMPILING] foo v0.0.1 ([CWD]) [RUNNING] `rustc --crate-name foo src/lib.rs --color never --crate-type lib \ - --emit=dep-info,link -C debuginfo=2 \ + --emit=[..]link -C debuginfo=2 \ -C metadata=[..] \ --out-dir [..] \ -L dependency=[CWD]/target/debug/deps` @@ -38,7 +38,7 @@ fn lib() { "\ [COMPILING] foo v0.0.1 ([CWD]) [RUNNING] `rustc --crate-name foo src/lib.rs --color never --crate-type lib \ - --emit=dep-info,link -C debuginfo=2 \ + --emit=[..]link -C debuginfo=2 \ -C debug-assertions=off \ -C metadata=[..] \ --out-dir [..] \ @@ -61,12 +61,12 @@ fn build_main_and_allow_unstable_options() { "\ [COMPILING] {name} v{version} ([CWD]) [RUNNING] `rustc --crate-name {name} src/lib.rs --color never --crate-type lib \ - --emit=dep-info,link -C debuginfo=2 \ + --emit=[..]link -C debuginfo=2 \ -C metadata=[..] \ --out-dir [..] \ -L dependency=[CWD]/target/debug/deps` [RUNNING] `rustc --crate-name {name} src/main.rs --color never --crate-type bin \ - --emit=dep-info,link -C debuginfo=2 \ + --emit=[..]link -C debuginfo=2 \ -C debug-assertions \ -C metadata=[..] \ --out-dir [..] \ @@ -106,10 +106,10 @@ fn build_with_args_to_one_of_multiple_binaries() { .with_stderr( "\ [COMPILING] foo v0.0.1 ([CWD]) -[RUNNING] `rustc --crate-name foo src/lib.rs --color never --crate-type lib --emit=dep-info,link \ +[RUNNING] `rustc --crate-name foo src/lib.rs --color never --crate-type lib --emit=[..]link \ -C debuginfo=2 -C metadata=[..] \ --out-dir [..]` -[RUNNING] `rustc --crate-name bar src/bin/bar.rs --color never --crate-type bin --emit=dep-info,link \ +[RUNNING] `rustc --crate-name bar src/bin/bar.rs --color never --crate-type bin --emit=[..]link \ -C debuginfo=2 -C debug-assertions [..]` [FINISHED] dev [unoptimized + debuginfo] target(s) in [..] ", @@ -144,10 +144,10 @@ fn build_with_args_to_one_of_multiple_tests() { .with_stderr( "\ [COMPILING] foo v0.0.1 ([CWD]) -[RUNNING] `rustc --crate-name foo src/lib.rs --color never --crate-type lib --emit=dep-info,link \ +[RUNNING] `rustc --crate-name foo src/lib.rs --color never --crate-type lib --emit=[..]link \ -C debuginfo=2 -C metadata=[..] \ --out-dir [..]` -[RUNNING] `rustc --crate-name bar tests/bar.rs --color never --emit=dep-info,link -C debuginfo=2 \ +[RUNNING] `rustc --crate-name bar tests/bar.rs --color never --emit=[..]link -C debuginfo=2 \ -C debug-assertions [..]--test[..]` [FINISHED] dev [unoptimized + debuginfo] target(s) in [..] ", @@ -233,18 +233,18 @@ fn targets_selected_default() { .with_stderr_contains( "\ [RUNNING] `rustc --crate-name foo src/main.rs --color never --crate-type bin \ - --emit=dep-info,link[..]", + --emit=[..]link[..]", ) // bench .with_stderr_does_not_contain( "\ - [RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=dep-info,link \ + [RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=[..]link \ -C opt-level=3 --test [..]", ) // unit test .with_stderr_does_not_contain( "\ - [RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=dep-info,link \ + [RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=[..]link \ -C debuginfo=2 --test [..]", ) .run(); @@ -258,12 +258,12 @@ fn targets_selected_all() { .with_stderr_contains( "\ [RUNNING] `rustc --crate-name foo src/main.rs --color never --crate-type bin \ - --emit=dep-info,link[..]", + --emit=[..]link[..]", ) // unit test .with_stderr_contains( "\ - [RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=dep-info,link \ + [RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=[..]link \ -C debuginfo=2 --test [..]", ) .run(); From 2114c5dc924f44c9d415a6ae61efd4140ec8b160 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 19 Apr 2019 13:03:16 -0700 Subject: [PATCH 2/2] Implement `JobQueue` support for pipelining This commit adds support to Cargo's internal `JobQueue` to execute pipelined rlib compilations actually in a pipelined fashion. This internally invovled some refactoring to ensure we juggled the right jobs into the right places, ensuring that as soon as an rmeta file is produce we can start subsequent compilations but still synchronize with the finished result of a `Build` unit. Internally this continues to still not actually pipeline anything in the sense that rustc doesn't support pipelining, but it's in theory all the groundwork necessary to read a signal from rustc that a metadata file is ready to go and then plumb that into Cargo's job scheduler. --- src/cargo/core/compiler/build_config.rs | 4 + .../compiler/context/unit_dependencies.rs | 2 +- src/cargo/core/compiler/job_queue.rs | 249 ++++++++++++++++-- src/cargo/core/compiler/mod.rs | 33 ++- src/cargo/core/manifest.rs | 2 +- src/cargo/util/dependency_queue.rs | 13 + tests/testsuite/build.rs | 25 +- tests/testsuite/dep_info.rs | 1 - 8 files changed, 285 insertions(+), 44 deletions(-) diff --git a/src/cargo/core/compiler/build_config.rs b/src/cargo/core/compiler/build_config.rs index 0999a76faa8..b87641ab87a 100644 --- a/src/cargo/core/compiler/build_config.rs +++ b/src/cargo/core/compiler/build_config.rs @@ -127,6 +127,10 @@ pub enum CompileMode { Test, /// Building a target with `rustc` (lib or bin). Build, + /// Building just the metadata of an rlib with `rustc` + /// + /// This is somewhat of a special mode, and for more information see the + /// documentation in `job_queue.rs` BuildRmeta, /// Building a target with `rustc` to emit `rmeta` metadata only. If /// `test` is true, then it is also compiled with `--test` to check it like diff --git a/src/cargo/core/compiler/context/unit_dependencies.rs b/src/cargo/core/compiler/context/unit_dependencies.rs index 6218ca069ec..e566dab205b 100644 --- a/src/cargo/core/compiler/context/unit_dependencies.rs +++ b/src/cargo/core/compiler/context/unit_dependencies.rs @@ -660,7 +660,7 @@ fn pipeline_compilations(state: &mut State<'_, '_, '_>) -> CargoResult<()> { debug_assert_eq!(build_rmeta_unit.mode, CompileMode::BuildRmeta); debug_assert_eq!(build_unit.mode, CompileMode::Build); - // There may be multiple paths to the root of the depenency graph as we + // There may be multiple paths to the root of the dependency graph as we // walk upwards, but we don't want to add units more than once. Use a // visited set to guard against this. if !updated.insert((*build_unit, *build_rmeta_unit)) { diff --git a/src/cargo/core/compiler/job_queue.rs b/src/cargo/core/compiler/job_queue.rs index f7a6a6f7e45..e40b8e374c6 100644 --- a/src/cargo/core/compiler/job_queue.rs +++ b/src/cargo/core/compiler/job_queue.rs @@ -1,3 +1,67 @@ +//! A job queue for executing Cargo's dependency graph +//! +//! This module primarily contains a `JobQueue` type which is the source of +//! executing Cargo's jobs in parallel. This is the module where we actually +//! execute rustc and the job graph. The internal `DependencyQueue` is +//! constructed elsewhere in Cargo, and the job of this module is to simply +//! execute what's described internally in the `DependencyQueue` as fast as it +//! can (using configured parallelism settings). +//! +//! Note that this is also the primary module where jobserver management comes +//! into play because that governs how many jobs we can execute in parallel. +//! Additionally of note is that everything here is using blocking/synchronous +//! I/O and such. We spawn a thread per rustc instance and it all coordinates +//! back to the main Cargo thread which coordinates everything. Perhaps one day +//! we can use async I/O, but it's not super pressing right now. +//! +//! ## Pipelining +//! +//! Another major feature of this module is the execution of a pipelined job +//! graph. The term "pipelining" here refers to executing rustc in an overlapped +//! fashion. We can build rlibs, for example, as soon as their dependencies have +//! metadata files available. No need to wait for codegen! +//! +//! Pipelined execution is modeled in Cargo with a few properties: +//! +//! * The `DependencyQueue` dependency graph has two nodes for each rlib. One +//! node is a `BuildRmeta` node while the other is a `Build` node (which +//! depends on `BuildRmeta`). This is prepared elsewhere. +//! +//! * Each node in a `DependencyQueue` is associated with a unit of work to +//! complete that node. In the case of pipelined compilation the `BuildRmeta` +//! node's work actually performs the full compile for both `BuildRmeta` and +//! `Build`. The work associated with `Build` is just some bookkeeping that +//! doesn't do any actual work. +//! +//! * The execution of a `BuildRmeta` unit will, before the end of the work, +//! send a message through `JobState` that the metadata file is ready. Later, +//! when it's fully finished, it will flag that the `Build` work is ready. +//! +//! All of this is somewhat wonky and doesn't fit perfectly into the +//! `JobQueue`'s management of all other sorts of jobs, but it looks like it +//! generally works ok below. The strategy is that we specially handle pipelined +//! units in the `run` and `finish` methods, but ideally not many other places. +//! +//! When a `BuildRmeta` unit is executed we'll arrange for the the correct +//! messages to be sent. A `Finish` for the `BuildRmeta` will be sent ASAP as +//! the work indicates, and then `Finish` for the `Build` will be sent +//! afterwards. This means that running a `BuildRmeta` unit allocates some +//! metadata for the `Build` unit as well. +//! +//! When a `BuildRmeta` unit finishes we try hard to make sure the `Build` unit +//! doesn't leak into the standard paths elsewhere because it's, well, not very +//! standard. To handle this we immediately remove the `Build` from the +//! dependency graph and specially handle it. It's internally flagged as an +//! active unit which allocates a jobserver token, and then execution proceeds +//! as usual. +//! +//! When the original work queued with the `BuildRmeta` completes it will send a +//! `Finish` notification for the `Build` unit. When this happens we catch this +//! happening and run the deferred `Job` we found during the completion of the +//! `BuildRmeta`. This should handle everything in theory and add up to a +//! working system! + +use std::cell::Cell; use std::collections::{HashMap, HashSet}; use std::io; use std::marker; @@ -29,20 +93,59 @@ use crate::util::{Progress, ProgressStyle}; /// actual compilation step of each package. Packages enqueue units of work and /// then later on the entire graph is processed and compiled. pub struct JobQueue<'a, 'cfg> { + // An instance of a dependency queue which keeps track of all units and jobs + // associated to execute with them. This is built up over time while we're + // preparing a `JobQueue` and is then used to dynamically track what work is + // ready to execute as work finishes. queue: DependencyQueue, Job>, + + // A cross-thread channel used to send messages to the main reactor thread + // which spawns off work. tx: Sender, rx: Receiver, + + // All work items that are currently executing. Maps from a unique ID + // assigned in a monotonically increasing fashion (allocated from `next_id`) + // to the `Unit` that is being executed. `Finish` messages will contain + // these ids and allow mapping back to the original `Unit`. active: HashMap>, + next_id: u32, + + // Metadata information used to keep track of what we're printing on the + // console. This ensures we don't print messages more than once and we print + // them at reasonable-ish times. compiled: HashSet, documented: HashSet, counts: HashMap, is_release: bool, progress: Progress<'cfg>, - next_id: u32, + + // Auxiliary tables to track the status of pipelined units. A `Unit` with a + // `BuildRmeta` mode will actually perform the work of a `Build` unit that + // depends on it, so we need to track that information here to ensure that + // we execute all the callbacks and finish units at the right time. + // + // The `pipelined` map keeps track of `BuildRmeta` units to their + // corresponding `Build` unit along with a preallocated id for the `Build` + // unit. This is created during `self.run`, and then consumed later during + // `self.finish` for the `BuildRmeta` unit. + // + // The `deferred` map keeps track of a mapping of the id of the `Build` unit + // to the `Job` that should execute when it's finished. The `Job` should + // always be a quick noop. + pipelined: HashMap, (Unit<'a>, u32)>, + deferred: HashMap, } pub struct JobState<'a> { + // Communication channel back to the main coordination thread. tx: Sender, + + // If this job is executing as part of a pipelined compilation this will + // list the id of the rmeta job. This is mutated to `None` once we send a + // message saying that the rmeta if finished. + rmeta_id: Cell>, + // Historical versions of Cargo made use of the `'a` argument here, so to // leave the door open to future refactorings keep it here. _marker: marker::PhantomData<&'a ()>, @@ -93,6 +196,19 @@ impl<'a> JobState<'a> { capture_output, ) } + + /// A method to only be used when rustc is being executed to compile an + /// rlib. As soon as the job learns that a metadata file is available this + /// method is called to send a notification back to the job queue that + /// metadata is ready to go and work that only depends on the metadata + /// should be executed ASAP. + /// + /// This will panic if executed twice or outside of a unit that's not for an + /// rlib. + pub fn finish_rmeta(&self) { + let id = self.rmeta_id.replace(None).unwrap(); + self.tx.send(Message::Finish(id, Ok(()))).unwrap(); + } } impl<'a, 'cfg> JobQueue<'a, 'cfg> { @@ -110,6 +226,8 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> { is_release: bcx.build_config.release, progress, next_id: 0, + deferred: Default::default(), + pipelined: Default::default(), } } @@ -119,18 +237,25 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> { unit: &Unit<'a>, job: Job, ) -> CargoResult<()> { + // Binaries aren't actually needed to *compile* tests, just to run + // them, so we don't include this dependency edge in the job graph. let dependencies = cx.dep_targets(unit); let dependencies = dependencies .iter() - .filter(|unit| { - // Binaries aren't actually needed to *compile* tests, just to run - // them, so we don't include this dependency edge in the job graph. - !unit.target.is_test() || !unit.target.is_bin() - }) + .filter(|unit| !unit.target.is_test() || !unit.target.is_bin()) .cloned() .collect::>(); self.queue.queue(unit, job, &dependencies); - *self.counts.entry(unit.pkg.package_id()).or_insert(0) += 1; + + // Keep track of how many work items we have for each package. This'll + // help us later print whether a package is "fresh" or not if all of its + // component units are indeed fresh. + // + // Note that we skip pipelined units since they don't make their way + // into `run` below. + if !cx.pipelined_units.contains(unit) { + *self.counts.entry(unit.pkg.package_id()).or_insert(0) += 1; + } Ok(()) } @@ -139,7 +264,7 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> { /// This function will spawn off `config.jobs()` workers to build all of the /// necessary dependencies, in order. Freshness is propagated as far as /// possible along each dependency chain. - pub fn execute(&mut self, cx: &mut Context<'_, '_>, plan: &mut BuildPlan) -> CargoResult<()> { + pub fn execute(&mut self, cx: &mut Context<'a, 'cfg>, plan: &mut BuildPlan) -> CargoResult<()> { let _p = profile::start("executing the job graph"); self.queue.queue_finished(); @@ -176,7 +301,7 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> { fn drain_the_queue( &mut self, - cx: &mut Context<'_, '_>, + cx: &mut Context<'a, 'cfg>, plan: &mut BuildPlan, scope: &Scope<'a>, jobserver_helper: &HelperThread, @@ -265,15 +390,11 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> { print.print(&msg)?; } Message::Finish(id, result) => { + trace!("end id {}", id); let unit = self.active.remove(&id).unwrap(); info!("end: {:?}", unit); - - if !self.active.is_empty() { - assert!(!tokens.is_empty()); - drop(tokens.pop()); - } match result { - Ok(()) => self.finish(&unit, cx)?, + Ok(()) => self.finish(&unit, id, cx)?, Err(e) => { let msg = "The following warnings were emitted during compilation:"; self.emit_warnings(Some(msg), &unit, cx)?; @@ -376,24 +497,71 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> { &mut self, unit: &Unit<'a>, job: Job, - cx: &Context<'_, '_>, + cx: &Context<'a, 'cfg>, scope: &Scope<'a>, ) -> CargoResult<()> { - info!("start: {:?}", unit); + // This unit should never run with a unit which has been pipelined. + // These units are handled specially in `finish` below so just assert we + // don't handle those here. + assert!(cx.rmeta_unit_if_pipelined(unit).is_none()); - let id = self.next_id; - self.next_id = id.checked_add(1).unwrap(); + let id = self.next_id(); + info!("start: {} {:?}", id, unit); assert!(self.active.insert(id, *unit).is_none()); *self.counts.get_mut(&unit.pkg.package_id()).unwrap() -= 1; - let my_tx = self.tx.clone(); + // If we're the rmeta component of a build then our work will actually + // produce the `Build` unit as well. Allocate a `build_id` for that unit + // here and prepare some internal state to know about how this unit is + // pipelined with another `Build` unit. This will also configure what + // messages are sent back to the coordination thread to ensure that we + // finish the `BuildRmeta` unit first and then the `Build` unit. let fresh = job.freshness(); + let (rmeta_id, last_id) = if unit.mode == CompileMode::BuildRmeta { + log::debug!("preparing state to pipeline next unit"); + let build_id = self.next_id(); + let build_unit = unit.with_mode(CompileMode::Build, cx.bcx.units); + assert!(self + .pipelined + .insert(*unit, (build_unit, build_id)) + .is_none()); + (Some(id), build_id) + } else { + (None, id) + }; + + let my_tx = self.tx.clone(); let doit = move || { - let res = job.run(&JobState { + let state = JobState { tx: my_tx.clone(), _marker: marker::PhantomData, - }); - my_tx.send(Message::Finish(id, res)).unwrap(); + rmeta_id: Cell::new(rmeta_id), + }; + let res = job.run(&state); + + // If the `rmeta_id` wasn't consumed but it was set previously, then + // we either have: + // + // 1. The `job` didn't do anything because it was "fresh". + // 2. The `job` returned an error and didn't reach the point where + // it called `finish_rmeta`. + // 3. We forgot to call `finish_rmeta` and there's a bug in Cargo. + // + // Ruling out the third, the other two are pretty common and we just need + // to say that both the `BuildRmeta` and `Build` (which we're + // responsible for) are finished. If an error happens we don't + // finish `Build` because it didn't actually complete. + if let Some(rmeta_id) = state.rmeta_id.replace(None) { + let ok = res.is_ok(); + my_tx.send(Message::Finish(rmeta_id, res)).unwrap(); + if ok { + my_tx.send(Message::Finish(last_id, Ok(()))).unwrap(); + } + } else { + // ... otherwise if we don't have anything to do with pipelining + // this is business as usual... + my_tx.send(Message::Finish(last_id, res)).unwrap(); + } }; if !cx.bcx.build_config.build_plan { @@ -411,6 +579,12 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> { Ok(()) } + fn next_id(&mut self) -> u32 { + let ret = self.next_id; + self.next_id = ret.checked_add(1).unwrap(); + return ret; + } + fn emit_warnings( &mut self, msg: Option<&str>, @@ -439,11 +613,38 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> { Ok(()) } - fn finish(&mut self, unit: &Unit<'a>, cx: &mut Context<'_, '_>) -> CargoResult<()> { + fn finish(&mut self, unit: &Unit<'a>, id: u32, cx: &mut Context<'_, '_>) -> CargoResult<()> { if unit.mode.is_run_custom_build() && cx.bcx.show_warnings(unit.pkg.package_id()) { self.emit_warnings(None, unit, cx)?; } self.queue.finish(unit); + + // Specially handled pipelined units here. If we're finishing the + // metadata component of a pipelined unit then we have an invariant that + // the `Build` unit is always ready to go. Forcibly dequeue that from + // the dependency queue and save off the work it would otherwise do. + // Along the way we also update the `active` map which should transition + // the jobserver token we were previously using to this unit. + // + // If we're finishing a `Build` unit then the whole pipeline is now + // finished, so we need to actually run the work we deferred earlier + // which should complete quickly. + if unit.mode == CompileMode::BuildRmeta { + log::debug!("first of a pipelined unit finished"); + let (build_unit, build_id) = self.pipelined[unit]; + assert!(self.active.insert(build_id, build_unit).is_none()); + let job = self.queue.dequeue_key(&build_unit); + assert!(self.deferred.insert(build_id, job).is_none()); + } else if cx.pipelined_units.contains(unit) { + log::debug!("completing the work of a pipelined unit"); + let job = self.deferred.remove(&id).unwrap(); + job.run(&JobState { + tx: self.tx.clone(), + _marker: marker::PhantomData, + rmeta_id: Cell::new(None), + })?; + } + Ok(()) } diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 9d265521886..7650f83b841 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -244,6 +244,7 @@ fn rustc<'a, 'cfg>( .unwrap_or_else(|| cx.bcx.config.cwd()) .to_path_buf(); let fingerprint_dir = cx.files().fingerprint_dir(unit); + let is_build_rmeta = unit.mode == CompileMode::BuildRmeta; return Ok(Work::new(move |state| { // Only at runtime have we discovered what the extra -L and -l @@ -315,6 +316,25 @@ fn rustc<'a, 'cfg>( .chain_err(|| format!("Could not compile `{}`.", name))?; } + // FIXME(rust-lang/rust#58465): this is the whole point of "pipelined + // compilation" in Cargo. We want to, here in this unit, call + // `finish_rmeta` as soon as we can which indicates that the metadata + // file is emitted by rustc and ready to go. This will start dependency + // compilations as soon as possible. + // + // The compiler doesn't currently actually implement the ability to let + // us know, however, when the metadata file is ready to go. It actually + // today produces the file very late in compilation, far later than it + // would otherwise be able to do! + // + // In any case this is all covered by the issue above. This is just a + // marker for "yes we unconditionally do this today but tomorrow we + // should actually read what rustc is doing and execute this at an + // appropriate time, ideally long before rustc finishes completely". + if is_build_rmeta { + state.finish_rmeta(); + } + if do_rename && real_name != crate_name { let dst = &outputs[0].path; let src = dst.with_file_name( @@ -790,11 +810,14 @@ fn build_base_args<'a, 'cfg>( } } - if unit.mode.is_check() { - cmd.arg("--emit=dep-info,metadata"); - } else { - cmd.arg("--emit=dep-info,metadata,link"); - } + cmd.arg(match unit.mode { + CompileMode::Build | CompileMode::Test | CompileMode::Bench => "--emit=dep-info,link", + CompileMode::BuildRmeta => "--emit=dep-info,metadata,link", + CompileMode::Check { .. } => "--emit=dep-info,metadata", + CompileMode::Doc { .. } | CompileMode::Doctest | CompileMode::RunCustomBuild => { + unreachable!() + } + }); let prefer_dynamic = (unit.target.for_host() && !unit.target.is_custom_build()) || (crate_types.contains(&"dylib") && bcx.ws.members().any(|p| p != unit.pkg)); diff --git a/src/cargo/core/manifest.rs b/src/cargo/core/manifest.rs index 5f44fa0cf3c..0272a200c15 100644 --- a/src/cargo/core/manifest.rs +++ b/src/cargo/core/manifest.rs @@ -124,7 +124,7 @@ impl LibKind { pub fn requires_upstream_objects(&self) -> bool { match *self { // "lib" == "rlib" and is a compilation that doesn't actually - // require upstream object files to exist, only upstream etadata + // require upstream object files to exist, only upstream metadata // files. As a result, it doesn't require upstream artifacts LibKind::Lib | LibKind::Rlib => false, diff --git a/src/cargo/util/dependency_queue.rs b/src/cargo/util/dependency_queue.rs index 9df373ee4f0..55da8e22eab 100644 --- a/src/cargo/util/dependency_queue.rs +++ b/src/cargo/util/dependency_queue.rs @@ -132,6 +132,19 @@ impl DependencyQueue { Some((key, data)) } + /// Forcibly dequeues a particular key from the dependency queue. + /// + /// # Panics + /// + /// Panics if `key`'s dependencies haven't finished yet or if `key` isn't in + /// the dependency queue. + pub fn dequeue_key(&mut self, key: &K) -> V { + let (deps, data) = self.dep_map.remove(&key).unwrap(); + assert!(deps.is_empty()); + self.pending.insert(key.clone()); + return data; + } + /// Returns `true` if there are remaining packages to be built. pub fn is_empty(&self) -> bool { self.dep_map.is_empty() && self.pending.is_empty() diff --git a/tests/testsuite/build.rs b/tests/testsuite/build.rs index efb810ad36c..6d7b868af34 100644 --- a/tests/testsuite/build.rs +++ b/tests/testsuite/build.rs @@ -1451,11 +1451,11 @@ fn cargo_default_env_metadata_env_var() { // No metadata on libbar since it's a dylib path dependency p.cargo("build -v") - .with_stderr( + .with_stderr(&format!( "\ [COMPILING] bar v0.0.1 ([CWD]/bar) [RUNNING] `rustc --crate-name bar bar/src/lib.rs --color never --crate-type dylib \ - --emit=[..]link \ + --emit=dep-info,link \ -C prefer-dynamic -C debuginfo=2 \ -C metadata=[..] \ --out-dir [..] \ @@ -1467,9 +1467,11 @@ fn cargo_default_env_metadata_env_var() { -C extra-filename=[..] \ --out-dir [..] \ -L dependency=[CWD]/target/debug/deps \ - --extern bar=[CWD]/target/debug/deps/libbar[..]` + --extern bar=[CWD]/target/debug/deps/{prefix}bar{suffix}` [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]", - ) + prefix = env::consts::DLL_PREFIX, + suffix = env::consts::DLL_SUFFIX, + )) .run(); p.cargo("clean").run(); @@ -1477,11 +1479,11 @@ fn cargo_default_env_metadata_env_var() { // If you set the env-var, then we expect metadata on libbar p.cargo("build -v") .env("__CARGO_DEFAULT_LIB_METADATA", "stable") - .with_stderr( + .with_stderr(&format!( "\ [COMPILING] bar v0.0.1 ([CWD]/bar) [RUNNING] `rustc --crate-name bar bar/src/lib.rs --color never --crate-type dylib \ - --emit=[..]link \ + --emit=dep-info,link \ -C prefer-dynamic -C debuginfo=2 \ -C metadata=[..] \ --out-dir [..] \ @@ -1493,10 +1495,12 @@ fn cargo_default_env_metadata_env_var() { -C extra-filename=[..] \ --out-dir [..] \ -L dependency=[CWD]/target/debug/deps \ - --extern bar=[CWD]/target/debug/deps/libbar-[..]` + --extern bar=[CWD]/target/debug/deps/{prefix}bar-[..]{suffix}` [FINISHED] dev [unoptimized + debuginfo] target(s) in [..] ", - ) + prefix = env::consts::DLL_PREFIX, + suffix = env::consts::DLL_SUFFIX, + )) .run(); } @@ -1921,9 +1925,6 @@ fn verbose_release_build_deps() { version = "0.0.0" authors = [] - [lib] - crate-type = ['cdylib'] - [dependencies.foo] path = "foo" "#, @@ -1958,7 +1959,7 @@ fn verbose_release_build_deps() { --out-dir [..] \ -L dependency=[CWD]/target/release/deps` [COMPILING] test v0.0.0 ([CWD]) -[RUNNING] `rustc --crate-name test src/lib.rs --color never --crate-type cdylib \ +[RUNNING] `rustc --crate-name test src/lib.rs --color never --crate-type lib \ --emit=[..]link \ -C opt-level=3 \ -C metadata=[..] \ diff --git a/tests/testsuite/dep_info.rs b/tests/testsuite/dep_info.rs index 8959c4e4920..4e228e86535 100644 --- a/tests/testsuite/dep_info.rs +++ b/tests/testsuite/dep_info.rs @@ -61,7 +61,6 @@ fn build_dep_info_rlib() { .build(); p.cargo("build --example=ex") - .stream() .env("RUST_LOG", "cargo") .run(); assert!(p.example_lib("ex", "rlib").with_extension("d").is_file());