From eac3b66bd457c6beb4295b077871300e290b2448 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 5 May 2020 14:20:56 -0700 Subject: [PATCH] Rework how Cargo computes the rustc file outputs. --- src/cargo/core/compiler/build_context/mod.rs | 2 +- .../compiler/build_context/target_info.rs | 241 ++++++++--- .../compiler/context/compilation_files.rs | 383 +++++++----------- src/cargo/core/compiler/context/mod.rs | 4 +- src/cargo/core/compiler/crate_type.rs | 97 +++++ src/cargo/core/compiler/fingerprint.rs | 18 +- src/cargo/core/compiler/layout.rs | 7 +- src/cargo/core/compiler/mod.rs | 54 +-- src/cargo/core/compiler/output_depinfo.rs | 2 +- src/cargo/core/manifest.rs | 29 +- src/cargo/ops/mod.rs | 2 +- tests/testsuite/bench.rs | 2 +- tests/testsuite/build_plan.rs | 4 +- tests/testsuite/cache_messages.rs | 20 + tests/testsuite/dep_info.rs | 16 +- tests/testsuite/metabuild.rs | 6 +- tests/testsuite/out_dir.rs | 4 +- tests/testsuite/test.rs | 2 +- 18 files changed, 516 insertions(+), 377 deletions(-) create mode 100644 src/cargo/core/compiler/crate_type.rs diff --git a/src/cargo/core/compiler/build_context/mod.rs b/src/cargo/core/compiler/build_context/mod.rs index 8dac81cffd2..ac7d6eca295 100644 --- a/src/cargo/core/compiler/build_context/mod.rs +++ b/src/cargo/core/compiler/build_context/mod.rs @@ -10,7 +10,7 @@ use std::collections::HashMap; use std::path::PathBuf; mod target_info; -pub use self::target_info::{FileFlavor, RustcTargetData, TargetInfo}; +pub use self::target_info::{FileFlavor, FileType, RustcTargetData, TargetInfo}; /// The build context, containing all information about a build task. /// diff --git a/src/cargo/core/compiler/build_context/target_info.rs b/src/cargo/core/compiler/build_context/target_info.rs index 698a9e4080f..d3bab3365bf 100644 --- a/src/cargo/core/compiler/build_context/target_info.rs +++ b/src/cargo/core/compiler/build_context/target_info.rs @@ -1,5 +1,5 @@ -use crate::core::compiler::{BuildOutput, CompileKind, CompileTarget, CrateType}; -use crate::core::{Dependency, TargetKind, Workspace}; +use crate::core::compiler::{BuildOutput, CompileKind, CompileMode, CompileTarget, CrateType}; +use crate::core::{Dependency, Target, TargetKind, Workspace}; use crate::util::config::{Config, StringList, TargetConfig}; use crate::util::{CargoResult, CargoResultExt, ProcessBuilder, Rustc}; use cargo_platform::{Cfg, CfgExpr}; @@ -49,41 +49,73 @@ pub struct TargetInfo { pub enum FileFlavor { /// Not a special file type. Normal, - /// Like `Normal`, but not directly executable + /// Like `Normal`, but not directly executable. + /// For example, a `.wasm` file paired with the "normal" `.js` file. Auxiliary, /// Something you can link against (e.g., a library). - Linkable { rmeta: bool }, + Linkable, + /// An `.rmeta` Rust metadata file. + Rmeta, /// Piece of external debug information (e.g., `.dSYM`/`.pdb` file). DebugInfo, } /// Type of each file generated by a Unit. +#[derive(Debug)] pub struct FileType { /// The kind of file. pub flavor: FileFlavor, + /// The crate-type that generates this file. + /// + /// `None` for things that aren't associated with a specific crate type, + /// for example `rmeta` files. + pub crate_type: Option, /// The suffix for the file (for example, `.rlib`). /// This is an empty string for executables on Unix-like platforms. suffix: String, /// The prefix for the file (for example, `lib`). /// This is an empty string for things like executables. prefix: String, - /// Flag to convert hyphen to underscore. - /// - /// wasm bin targets will generate two files in deps such as - /// "web-stuff.js" and "web_stuff.wasm". Note the different usages of "-" - /// and "_". This flag indicates that the stem "web-stuff" should be - /// converted to "web_stuff". + /// Flag to convert hyphen to underscore when uplifting. should_replace_hyphens: bool, } impl FileType { - pub fn filename(&self, stem: &str) -> String { - let stem = if self.should_replace_hyphens { - stem.replace("-", "_") + /// The filename for this FileType crated by rustc. + pub fn output_filename(&self, target: &Target, metadata: Option<&str>) -> String { + match metadata { + Some(metadata) => format!( + "{}{}-{}{}", + self.prefix, + target.crate_name(), + metadata, + self.suffix + ), + None => format!("{}{}{}", self.prefix, target.crate_name(), self.suffix), + } + } + + /// The filename for this FileType that Cargo should use when "uplifting" + /// it to the destination directory. + pub fn uplift_filename(&self, target: &Target) -> String { + let name = if self.should_replace_hyphens { + target.crate_name() } else { - stem.to_string() + target.name().to_string() }; - format!("{}{}{}", self.prefix, stem, self.suffix) + format!("{}{}{}", self.prefix, name, self.suffix) + } + + /// Creates a new instance representing a `.rmeta` file. + pub fn new_rmeta() -> FileType { + // Note that even binaries use the `lib` prefix. + FileType { + flavor: FileFlavor::Rmeta, + crate_type: None, + suffix: ".rmeta".to_string(), + prefix: "lib".to_string(), + should_replace_hyphens: true, + } } } @@ -232,11 +264,10 @@ impl TargetInfo { /// Returns the list of file types generated by the given crate type. /// /// Returns `None` if the target does not support the given crate type. - pub fn file_types( + fn file_types( &self, crate_type: &CrateType, flavor: FileFlavor, - kind: &TargetKind, target_triple: &str, ) -> CargoResult>> { let crate_type = if *crate_type == CrateType::Lib { @@ -262,58 +293,95 @@ impl TargetInfo { suffix: suffix.clone(), prefix: prefix.clone(), flavor, - should_replace_hyphens: false, + crate_type: Some(crate_type.clone()), + should_replace_hyphens: crate_type != CrateType::Bin, }]; - // See rust-lang/cargo#4500. - if target_triple.ends_with("-windows-msvc") - && (crate_type == CrateType::Dylib || crate_type == CrateType::Cdylib) - && suffix == ".dll" - { - ret.push(FileType { - suffix: ".dll.lib".to_string(), - prefix: prefix.clone(), - flavor: FileFlavor::Normal, - should_replace_hyphens: false, - }) - } else if target_triple.ends_with("windows-gnu") - && (crate_type == CrateType::Dylib || crate_type == CrateType::Cdylib) - && suffix == ".dll" - { - // LD can link DLL directly, but LLD requires the import library. - ret.push(FileType { - suffix: ".dll.a".to_string(), - prefix: "lib".to_string(), - flavor: FileFlavor::Normal, - should_replace_hyphens: false, - }) + // Window shared library import/export files. + if crate_type.is_dynamic() { + if target_triple.ends_with("-windows-msvc") { + assert!(suffix == ".dll"); + // See https://docs.microsoft.com/en-us/cpp/build/reference/working-with-import-libraries-and-export-files + // for more information about DLL import/export files. + ret.push(FileType { + suffix: ".dll.lib".to_string(), + prefix: prefix.clone(), + flavor: FileFlavor::Auxiliary, + crate_type: Some(crate_type.clone()), + should_replace_hyphens: true, + }); + // NOTE: lld does not produce these + ret.push(FileType { + suffix: ".dll.exp".to_string(), + prefix: prefix.clone(), + flavor: FileFlavor::Auxiliary, + crate_type: Some(crate_type.clone()), + should_replace_hyphens: true, + }); + } else if target_triple.ends_with("windows-gnu") { + assert!(suffix == ".dll"); + // See https://cygwin.com/cygwin-ug-net/dll.html for more + // information about GNU import libraries. + // LD can link DLL directly, but LLD requires the import library. + ret.push(FileType { + suffix: ".dll.a".to_string(), + prefix: "lib".to_string(), + flavor: FileFlavor::Auxiliary, + crate_type: Some(crate_type.clone()), + should_replace_hyphens: true, + }) + } } - // See rust-lang/cargo#4535. if target_triple.starts_with("wasm32-") && crate_type == CrateType::Bin && suffix == ".js" { + // emscripten binaries generate a .js file, which loads a .wasm + // file. ret.push(FileType { suffix: ".wasm".to_string(), prefix: prefix.clone(), flavor: FileFlavor::Auxiliary, + crate_type: Some(crate_type.clone()), + // Name `foo-bar` will generate a `foo_bar.js` and + // `foo_bar.wasm`. Cargo will translate the underscore and + // copy `foo_bar.js` to `foo-bar.js`. However, the wasm + // filename is embedded in the .js file with an underscore, so + // it should not contain hyphens. should_replace_hyphens: true, - }) + }); + // And a map file for debugging. This is only emitted with debug=2 + // (-g4 for emcc). + ret.push(FileType { + suffix: ".wasm.map".to_string(), + prefix: prefix.clone(), + flavor: FileFlavor::DebugInfo, + crate_type: Some(crate_type.clone()), + should_replace_hyphens: true, + }); } - // See rust-lang/cargo#4490, rust-lang/cargo#4960. - // Only uplift debuginfo for binaries. - // - Tests are run directly from `target/debug/deps/` with the - // metadata hash still in the filename. - // - Examples are only uplifted for apple because the symbol file - // needs to match the executable file name to be found (i.e., it - // needs to remove the hash in the filename). On Windows, the path - // to the .pdb with the hash is embedded in the executable. + // Handle separate debug files. let is_apple = target_triple.contains("-apple-"); - if *kind == TargetKind::Bin || (*kind == TargetKind::ExampleBin && is_apple) { + if matches!( + crate_type, + CrateType::Bin | CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro + ) { if is_apple { + let suffix = if crate_type == CrateType::Bin { + ".dSYM".to_string() + } else { + ".dylib.dSYM".to_string() + }; ret.push(FileType { - suffix: ".dSYM".to_string(), + suffix, prefix: prefix.clone(), flavor: FileFlavor::DebugInfo, + crate_type: Some(crate_type.clone()), + // macOS tools like lldb use all sorts of magic to locate + // dSYM files. See https://lldb.llvm.org/use/symbols.html + // for some details. It seems like a `.dSYM` located next + // to the executable with the same name is one method. The + // dSYM should have the same hyphens as the executable for + // the names to match. should_replace_hyphens: false, }) } else if target_triple.ends_with("-msvc") { @@ -321,8 +389,13 @@ impl TargetInfo { suffix: ".pdb".to_string(), prefix: prefix.clone(), flavor: FileFlavor::DebugInfo, - // rustc calls the linker with underscores, and the - // filename is embedded in the executable. + crate_type: Some(crate_type.clone()), + // The absolute path to the pdb file is embedded in the + // executable. If the exe/pdb pair is moved to another + // machine, then debuggers will look in the same directory + // of the exe with the original pdb filename. Since the + // original name contains underscores, they need to be + // preserved. should_replace_hyphens: true, }) } @@ -353,6 +426,62 @@ impl TargetInfo { &mut output.lines(), )?) } + + /// Returns all the file types generated by rustc for the given mode/target_kind. + /// + /// The first value is a Vec of file types generated, the second value is + /// a list of CrateTypes that are not supported by the given target. + pub fn rustc_outputs( + &self, + mode: CompileMode, + target_kind: &TargetKind, + target_triple: &str, + ) -> CargoResult<(Vec, Vec)> { + match mode { + CompileMode::Build => self.calc_rustc_outputs(target_kind, target_triple), + CompileMode::Test | CompileMode::Bench => { + match self.file_types(&CrateType::Bin, FileFlavor::Normal, target_triple)? { + Some(fts) => Ok((fts, Vec::new())), + None => Ok((Vec::new(), vec![CrateType::Bin])), + } + } + CompileMode::Check { .. } => Ok((vec![FileType::new_rmeta()], Vec::new())), + CompileMode::Doc { .. } | CompileMode::Doctest | CompileMode::RunCustomBuild => { + panic!("asked for rustc output for non-rustc mode") + } + } + } + + fn calc_rustc_outputs( + &self, + target_kind: &TargetKind, + target_triple: &str, + ) -> CargoResult<(Vec, Vec)> { + let mut unsupported = Vec::new(); + let mut result = Vec::new(); + let crate_types = target_kind.rustc_crate_types(); + for crate_type in &crate_types { + let flavor = if crate_type.is_linkable() { + FileFlavor::Linkable + } else { + FileFlavor::Normal + }; + let file_types = self.file_types(&crate_type, flavor, target_triple)?; + match file_types { + Some(types) => { + result.extend(types); + } + None => { + unsupported.push(crate_type.clone()); + } + } + } + if !result.is_empty() && !crate_types.iter().any(|ct| ct.requires_upstream_objects()) { + // Only add rmeta if pipelining. + result.push(FileType::new_rmeta()); + } + Ok((result, unsupported)) + } } /// Takes rustc output (using specialized command line args), and calculates the file prefix and @@ -537,9 +666,7 @@ pub struct RustcTargetData { host_info: TargetInfo, /// Build information for targets that we're building for. This will be - /// empty if the `--target` flag is not passed, and currently also only ever - /// has at most one entry, but eventually we'd like to support multi-target - /// builds with Cargo. + /// empty if the `--target` flag is not passed. target_config: HashMap, target_info: HashMap, } diff --git a/src/cargo/core/compiler/context/compilation_files.rs b/src/cargo/core/compiler/context/compilation_files.rs index b2c48d4d7cd..09a8bf0587b 100644 --- a/src/cargo/core/compiler/context/compilation_files.rs +++ b/src/cargo/core/compiler/context/compilation_files.rs @@ -9,7 +9,7 @@ use lazycell::LazyCell; use log::info; use super::{BuildContext, CompileKind, Context, FileFlavor, Layout}; -use crate::core::compiler::{CompileMode, CompileTarget, CrateType, Unit}; +use crate::core::compiler::{CompileMode, CompileTarget, CrateType, FileType, Unit}; use crate::core::{Target, TargetKind, Workspace}; use crate::util::{self, CargoResult}; @@ -85,10 +85,7 @@ pub struct CompilationFiles<'a, 'cfg> { roots: Vec, ws: &'a Workspace<'cfg>, /// Metadata hash to use for each unit. - /// - /// `None` if the unit should not use a metadata data hash (like rustdoc, - /// or some dylibs). - metas: HashMap>, + metas: HashMap, /// For each Unit, a list all files produced. outputs: HashMap>>>, } @@ -151,15 +148,18 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> { } } - /// Gets the metadata for a target in a specific profile. - /// We build to the path `"{filename}-{target_metadata}"`. - /// We use a linking step to link/copy to a predictable filename - /// like `target/debug/libfoo.{a,so,rlib}` and such. + /// Gets the metadata for the given unit. + /// + /// See module docs for more details. /// - /// Returns `None` if the unit should not use a metadata data hash (like + /// Returns `None` if the unit should not use a metadata hash (like /// rustdoc, or some dylibs). - pub fn metadata(&self, unit: &Unit) -> Option { - self.metas[unit] + pub fn metadata(&self, bcx: &BuildContext<'_, '_>, unit: &Unit) -> Option { + if should_use_metadata(bcx, unit) { + Some(self.metas[unit]) + } else { + None + } } /// Gets the short hash based only on the `PackageId`. @@ -169,8 +169,8 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> { util::short_hash(&hashable) } - /// Returns the appropriate output directory for the specified package and - /// target. + /// Returns the directory where the artifacts for the given unit are + /// initially created. pub fn out_dir(&self, unit: &Unit) -> PathBuf { if unit.mode.is_doc() { self.layout(unit.kind).doc().to_path_buf() @@ -191,12 +191,11 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> { } /// Directory name to use for a package in the form `NAME-HASH`. + /// + /// The hash is unique per Unit. pub fn pkg_dir(&self, unit: &Unit) -> String { let name = unit.pkg.package_id().name(); - match self.metas[unit] { - Some(ref meta) => format!("{}-{}", name, meta), - None => format!("{}-{}", name, self.target_short_hash(unit)), - } + format!("{}-{}", name, self.metas[unit]) } /// Returns the root of the build output tree for the host @@ -252,14 +251,6 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> { self.build_script_run_dir(unit).join("out") } - /// Returns the file stem for a given target/profile combo (with metadata). - pub fn file_stem(&self, unit: &Unit) -> String { - match self.metas[unit] { - Some(ref metadata) => format!("{}-{}", unit.target.crate_name(), metadata), - None => self.bin_stem(unit), - } - } - /// Returns the path to the executable binary for the given bin target. /// /// This should only to be used when a `Unit` is not available. @@ -272,13 +263,12 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> { assert!(target.is_bin()); let dest = self.layout(kind).dest(); let info = bcx.target_data.info(kind); - let file_types = info - .file_types( - &CrateType::Bin, - FileFlavor::Normal, + let (file_types, _) = info + .rustc_outputs( + CompileMode::Build, &TargetKind::Bin, bcx.target_data.short_name(&kind), - )? + ) .expect("target must support `bin`"); let file_type = file_types @@ -286,10 +276,12 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> { .find(|file_type| file_type.flavor == FileFlavor::Normal) .expect("target must support `bin`"); - Ok(dest.join(file_type.filename(target.name()))) + Ok(dest.join(file_type.uplift_filename(target))) } /// Returns the filenames that the given unit will generate. + /// + /// Note: It is not guaranteed that all of the files will be generated. pub(super) fn outputs( &self, unit: &Unit, @@ -300,57 +292,50 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> { .map(Arc::clone) } - /// Returns the bin filename for a given target, without extension and metadata. - fn bin_stem(&self, unit: &Unit) -> String { - if unit.target.allows_dashes() { - unit.target.name().to_string() - } else { - unit.target.crate_name() + /// Returns the path where the output for the given unit and FileType + /// should be uplifted to. + /// + /// Returns `None` if the unit shouldn't be uplifted (for example, a + /// dependent rlib). + fn uplift_to(&self, unit: &Unit, file_type: &FileType, from_path: &Path) -> Option { + // Tests, check, doc, etc. should not be uplifted. + if unit.mode != CompileMode::Build || file_type.flavor == FileFlavor::Rmeta { + return None; + } + // Only uplift: + // - Binaries: The user always wants to see these, even if they are + // implicitly built (for example for integration tests). + // - dylibs: This ensures that the dynamic linker pulls in all the + // latest copies (even if the dylib was built from a previous cargo + // build). There are complex reasons for this, see #8139, #6167, #6162. + // - Things directly requested from the command-line (the "roots"). + // This one is a little questionable for rlibs (see #6131), but is + // historically how Cargo has operated. This is primarily useful to + // give the user access to staticlibs and cdylibs. + if !unit.target.is_bin() + && !unit.target.is_custom_build() + && file_type.crate_type != Some(CrateType::Dylib) + && !self.roots.contains(unit) + { + return None; } - } - /// Returns a tuple `(hard_link_dir, filename_stem)` for the primary - /// output file for the given unit. - /// - /// `hard_link_dir` is the directory where the file should be hard-linked - /// ("uplifted") to. For example, `/path/to/project/target`. - /// - /// `filename_stem` is the base filename without an extension. - /// - /// This function returns it in two parts so the caller can add - /// prefix/suffix to filename separately. - /// - /// Returns an `Option` because in some cases we don't want to link - /// (eg a dependent lib). - fn link_stem(&self, unit: &Unit) -> Option<(PathBuf, String)> { - let out_dir = self.out_dir(unit); - let bin_stem = self.bin_stem(unit); // Stem without metadata. - let file_stem = self.file_stem(unit); // Stem with metadata. - - // We currently only lift files up from the `deps` directory. If - // it was compiled into something like `example/` or `doc/` then - // we don't want to link it up. - if out_dir.ends_with("deps") { - // Don't lift up library dependencies. - if unit.target.is_bin() || self.roots.contains(unit) || unit.target.is_dylib() { - Some(( - out_dir.parent().unwrap().to_owned(), - if unit.mode.is_any_test() { - file_stem - } else { - bin_stem - }, - )) - } else { - None - } - } else if bin_stem == file_stem { - None - } else if out_dir.ends_with("examples") || out_dir.parent().unwrap().ends_with("build") { - Some((out_dir, bin_stem)) + let filename = file_type.uplift_filename(&unit.target); + let uplift_path = if unit.target.is_example() { + // Examples live in their own little world. + self.layout(unit.kind).examples().join(filename) + } else if unit.target.is_custom_build() { + self.build_script_dir(unit).join(filename) } else { - None + self.layout(unit.kind).dest().join(filename) + }; + if from_path == uplift_path { + // This can happen with things like examples that reside in the + // same directory, do not have a metadata hash (like on Windows), + // and do not have hyphens. + return None; } + Some(uplift_path) } fn calc_outputs( @@ -359,18 +344,6 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> { bcx: &BuildContext<'a, 'cfg>, ) -> CargoResult>> { let ret = match unit.mode { - CompileMode::Check { .. } => { - // This may be confusing. rustc outputs a file named `lib*.rmeta` - // for both libraries and binaries. - let file_stem = self.file_stem(unit); - let path = self.out_dir(unit).join(format!("lib{}.rmeta", file_stem)); - vec![OutputFile { - path, - hardlink: None, - export_path: None, - flavor: FileFlavor::Linkable { rmeta: false }, - }] - } CompileMode::Doc { .. } => { let path = self .out_dir(unit) @@ -394,131 +367,77 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> { // but Cargo does not know about that. vec![] } - CompileMode::Test | CompileMode::Build | CompileMode::Bench => { - self.calc_outputs_rustc(unit, bcx)? - } + CompileMode::Test + | CompileMode::Build + | CompileMode::Bench + | CompileMode::Check { .. } => self.calc_outputs_rustc(unit, bcx)?, }; info!("Target filenames: {:?}", ret); Ok(Arc::new(ret)) } + /// Computes the actual, full pathnames for all the files generated by rustc. + /// + /// The `OutputFile` also contains the paths where those files should be + /// "uplifted" to. fn calc_outputs_rustc( &self, unit: &Unit, bcx: &BuildContext<'a, 'cfg>, ) -> CargoResult> { - let mut ret = Vec::new(); - let mut unsupported = Vec::new(); - let out_dir = self.out_dir(unit); - let link_stem = self.link_stem(unit); + let info = bcx.target_data.info(unit.kind); - let file_stem = self.file_stem(unit); - - let mut add = |crate_type: &CrateType, flavor: FileFlavor| -> CargoResult<()> { - let file_types = info.file_types( - crate_type, - flavor, - unit.target.kind(), - bcx.target_data.short_name(&unit.kind), - )?; - - match file_types { - Some(types) => { - for file_type in types { - let path = out_dir.join(file_type.filename(&file_stem)); - // Don't create hardlink for tests - let hardlink = if unit.mode.is_any_test() { - None - } else { - 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() - .map(|hardlink| export_dir.join(hardlink.file_name().unwrap())) - }) - }; - ret.push(OutputFile { - path, - hardlink, - export_path, - flavor: file_type.flavor, - }); - } - } - // Not supported; don't worry about it. - None => { - unsupported.push(crate_type.to_string()); - } - } - Ok(()) - }; - match unit.target.kind() { - TargetKind::Bin - | TargetKind::CustomBuild - | TargetKind::ExampleBin - | TargetKind::Bench - | TargetKind::Test => { - add(&CrateType::Bin, FileFlavor::Normal)?; - } - TargetKind::Lib(..) | TargetKind::ExampleLib(..) if unit.mode.is_any_test() => { - add(&CrateType::Bin, FileFlavor::Normal)?; - } - TargetKind::ExampleLib(crate_types) | TargetKind::Lib(crate_types) => { - for crate_type in crate_types { - add( - crate_type, - if crate_type.is_linkable() { - FileFlavor::Linkable { rmeta: false } - } else { - FileFlavor::Normal - }, - )?; - } - let path = out_dir.join(format!("lib{}.rmeta", file_stem)); - if !unit.requires_upstream_objects() { - ret.push(OutputFile { - path, - hardlink: None, - export_path: None, - flavor: FileFlavor::Linkable { rmeta: true }, - }); - } - } - } - if ret.is_empty() { + let triple = bcx.target_data.short_name(&unit.kind); + let (file_types, unsupported) = + info.rustc_outputs(unit.mode, unit.target.kind(), triple)?; + if file_types.is_empty() { if !unsupported.is_empty() { + let unsupported_strs: Vec<_> = unsupported.iter().map(|ct| ct.as_str()).collect(); anyhow::bail!( "cannot produce {} for `{}` as the target `{}` \ does not support these crate types", - unsupported.join(", "), + unsupported_strs.join(", "), unit.pkg, - bcx.target_data.short_name(&unit.kind), + triple, ) } anyhow::bail!( "cannot compile `{}` as the target `{}` does not \ support any of the output crate types", unit.pkg, - bcx.target_data.short_name(&unit.kind), + triple, ); } - Ok(ret) + + // Convert FileType to OutputFile. + let mut outputs = Vec::new(); + for file_type in file_types { + let meta = self.metadata(bcx, unit).map(|m| m.to_string()); + let path = out_dir.join(file_type.output_filename(&unit.target, meta.as_deref())); + let hardlink = self.uplift_to(unit, &file_type, &path); + let export_path = if unit.target.is_custom_build() { + None + } else { + self.export_dir.as_ref().and_then(|export_dir| { + hardlink + .as_ref() + .map(|hardlink| export_dir.join(hardlink.file_name().unwrap())) + }) + }; + outputs.push(OutputFile { + path, + hardlink, + export_path, + flavor: file_type.flavor, + }); + } + Ok(outputs) } } -fn metadata_of( - unit: &Unit, - cx: &Context<'_, '_>, - metas: &mut HashMap>, -) -> Option { +fn metadata_of(unit: &Unit, cx: &Context<'_, '_>, metas: &mut HashMap) -> Metadata { if !metas.contains_key(unit) { let meta = compute_metadata(unit, cx, metas); metas.insert(unit.clone(), meta); @@ -532,48 +451,9 @@ fn metadata_of( fn compute_metadata( unit: &Unit, cx: &Context<'_, '_>, - metas: &mut HashMap>, -) -> Option { - if unit.mode.is_doc_test() { - // Doc tests do not have metadata. - return None; - } - // 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. - // - // No metadata for bin because of an issue: - // - wasm32 rustc/emcc encodes the `.wasm` name in the `.js` (rust-lang/cargo#4535). - // - msvc: The path to the PDB is embedded in the executable, and we don't - // want the PDB path to include the hash in it. - // - // Two exceptions: - // 1) Upstream dependencies (we aren't exporting + need to resolve name conflict), - // 2) `__CARGO_DEFAULT_LIB_METADATA` env var. - // - // Note, however, that the compiler's build system at least wants - // path dependencies (eg libstd) to have hashes in filenames. To account for - // that we have an extra hack here which reads the - // `__CARGO_DEFAULT_LIB_METADATA` environment variable and creates a - // hash in the filename if that's present. - // - // This environment variable should not be relied on! It's - // just here for rustbuild. We need a more principled method - // doing this eventually. + metas: &mut HashMap, +) -> Metadata { let bcx = &cx.bcx; - let __cargo_default_lib_metadata = env::var("__CARGO_DEFAULT_LIB_METADATA"); - let short_name = bcx.target_data.short_name(&unit.kind); - if !(unit.mode.is_any_test() || unit.mode.is_check()) - && (unit.target.is_dylib() - || unit.target.is_cdylib() - || (unit.target.is_executable() && short_name.starts_with("wasm32-")) - || (unit.target.is_executable() && short_name.contains("msvc"))) - && unit.pkg.package_id().source_id().is_path() - && __cargo_default_lib_metadata.is_err() - { - return None; - } - let mut hasher = SipHasher::new(); // This is a generic version number that can be changed to make @@ -633,7 +513,7 @@ fn compute_metadata( // Seed the contents of `__CARGO_DEFAULT_LIB_METADATA` to the hasher if present. // This should be the release channel, to get a different hash for each channel. - if let Ok(ref channel) = __cargo_default_lib_metadata { + if let Ok(ref channel) = env::var("__CARGO_DEFAULT_LIB_METADATA") { channel.hash(&mut hasher); } @@ -646,7 +526,7 @@ fn compute_metadata( // with user dependencies. unit.is_std.hash(&mut hasher); - Some(Metadata(hasher.finish())) + Metadata(hasher.finish()) } fn hash_rustc_version(bcx: &BuildContext<'_, '_>, hasher: &mut SipHasher) { @@ -680,3 +560,46 @@ fn hash_rustc_version(bcx: &BuildContext<'_, '_>, hasher: &mut SipHasher) { // the future when cranelift sees more use, and people want to switch // between different backends without recompiling. } + +/// Returns whether or not this unit should use a metadata hash. +fn should_use_metadata(bcx: &BuildContext<'_, '_>, unit: &Unit) -> bool { + if unit.mode.is_doc_test() { + // Doc tests do not have metadata. + return false; + } + if unit.mode.is_any_test() || unit.mode.is_check() { + // These always use metadata. + return true; + } + // No metadata in these cases: + // + // - dylibs: + // - macOS encodes the dylib name in the executable, so it can't be renamed. + // - TODO: Are there other good reasons? If not, maybe this should be macos specific? + // - Windows MSVC executables: The path to the PDB is embedded in the + // executable, and we don't want the PDB path to include the hash in it. + // - wasm32 executables: When using emscripten, the path to the .wasm file + // is embedded in the .js file, so we don't want the hash in there. + // TODO: Is this necessary for wasm32-unknown-unknown? + // + // This is only done for local packages, as we don't expect to export + // dependencies. + // + // The __CARGO_DEFAULT_LIB_METADATA env var is used to override this to + // force metadata in the hash. This is only used for building libstd. For + // example, if libstd is placed in a common location, we don't want a file + // named /usr/lib/libstd.so which could conflict with other rustc + // installs. TODO: Is this still a realistic concern? + // See https://github.com/rust-lang/cargo/issues/3005 + let short_name = bcx.target_data.short_name(&unit.kind); + if (unit.target.is_dylib() + || unit.target.is_cdylib() + || (unit.target.is_executable() && short_name.starts_with("wasm32-")) + || (unit.target.is_executable() && short_name.contains("msvc"))) + && unit.pkg.package_id().source_id().is_path() + && env::var("__CARGO_DEFAULT_LIB_METADATA").is_err() + { + return false; + } + true +} diff --git a/src/cargo/core/compiler/context/mod.rs b/src/cargo/core/compiler/context/mod.rs index ae5c1382947..318dc8655b4 100644 --- a/src/cargo/core/compiler/context/mod.rs +++ b/src/cargo/core/compiler/context/mod.rs @@ -262,7 +262,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> { /// Returns the executable for the specified unit (if any). pub fn get_executable(&mut self, unit: &Unit) -> CargoResult> { for output in self.outputs(unit)?.iter() { - if output.flavor == FileFlavor::DebugInfo { + if output.flavor != FileFlavor::Normal { continue; } @@ -377,7 +377,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> { pub fn get_run_build_script_metadata(&self, unit: &Unit) -> Metadata { assert!(unit.mode.is_run_custom_build()); self.files() - .metadata(unit) + .metadata(self.bcx, unit) .expect("build script should always have hash") } diff --git a/src/cargo/core/compiler/crate_type.rs b/src/cargo/core/compiler/crate_type.rs new file mode 100644 index 00000000000..fd0126cbe83 --- /dev/null +++ b/src/cargo/core/compiler/crate_type.rs @@ -0,0 +1,97 @@ +use std::fmt; + +#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub enum CrateType { + Bin, + Lib, + Rlib, + Dylib, + Cdylib, + Staticlib, + ProcMacro, + Other(String), +} + +impl CrateType { + pub fn as_str(&self) -> &str { + match self { + CrateType::Bin => "bin", + CrateType::Lib => "lib", + CrateType::Rlib => "rlib", + CrateType::Dylib => "dylib", + CrateType::Cdylib => "cdylib", + CrateType::Staticlib => "staticlib", + CrateType::ProcMacro => "proc-macro", + CrateType::Other(s) => s, + } + } + + pub fn is_linkable(&self) -> bool { + match self { + CrateType::Lib | CrateType::Rlib | CrateType::Dylib | CrateType::ProcMacro => true, + CrateType::Bin | CrateType::Cdylib | CrateType::Staticlib | CrateType::Other(..) => { + false + } + } + } + + pub fn is_dynamic(&self) -> bool { + match self { + CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro => true, + CrateType::Lib + | CrateType::Rlib + | CrateType::Bin + | CrateType::Staticlib + | CrateType::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 metadata + // files. As a result, it doesn't require upstream artifacts + CrateType::Lib | CrateType::Rlib => false, + + // Everything else, however, is some form of "linkable output" or + // something that requires upstream object files. + _ => true, + } + } +} + +impl fmt::Display for CrateType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.as_str().fmt(f) + } +} + +impl<'a> From<&'a String> for CrateType { + fn from(s: &'a String) -> Self { + match s.as_str() { + "bin" => CrateType::Bin, + "lib" => CrateType::Lib, + "rlib" => CrateType::Rlib, + "dylib" => CrateType::Dylib, + "cdylib" => CrateType::Cdylib, + "staticlib" => CrateType::Staticlib, + "procmacro" => CrateType::ProcMacro, + _ => CrateType::Other(s.clone()), + } + } +} + +impl fmt::Debug for CrateType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.to_string().fmt(f) + } +} + +impl serde::Serialize for CrateType { + fn serialize(&self, s: S) -> Result + where + S: serde::ser::Serializer, + { + self.to_string().serialize(s) + } +} diff --git a/src/cargo/core/compiler/fingerprint.rs b/src/cargo/core/compiler/fingerprint.rs index 598abdec8e1..eaf88e2ee5c 100644 --- a/src/cargo/core/compiler/fingerprint.rs +++ b/src/cargo/core/compiler/fingerprint.rs @@ -104,8 +104,9 @@ //! - A "dep-info" file which contains a list of source filenames for the //! target. See below for details. //! - An `invoked.timestamp` file whose filesystem mtime is updated every time -//! the Unit is built. This is an experimental feature used for cleaning -//! unused artifacts. +//! the Unit is built. This is used for capturing the time when the build +//! starts, to detect if files are changed in the middle of the build. See +//! below for more details. //! //! Note that some units are a little different. A Unit for *running* a build //! script or for `rustdoc` does not have a dep-info file (it's not @@ -352,7 +353,7 @@ pub fn prepare_target(cx: &mut Context<'_, '_>, unit: &Unit, force: bool) -> Car )); let bcx = cx.bcx; let new = cx.files().fingerprint_dir(unit); - let loc = new.join(&filename(cx, unit)); + let loc = new.join(&filename(unit)); debug!("fingerprint at: {}", loc.display()); @@ -1523,7 +1524,7 @@ pub fn prepare_init(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<()> { pub fn dep_info_loc(cx: &mut Context<'_, '_>, unit: &Unit) -> PathBuf { cx.files() .fingerprint_dir(unit) - .join(&format!("dep-{}", filename(cx, unit))) + .join(&format!("dep-{}", filename(unit))) } /// Returns an absolute path that target directory. @@ -1679,11 +1680,8 @@ where None } -fn filename(cx: &mut Context<'_, '_>, unit: &Unit) -> String { - // file_stem includes metadata hash. Thus we have a different - // fingerprint for every metadata hash version. This works because - // even if the package is fresh, we'll still link the fresh target - let file_stem = cx.files().file_stem(unit); +/// Returns the filename used for the fingerprint file. +fn filename(unit: &Unit) -> String { let kind = unit.target.kind().description(); let flavor = if unit.mode.is_any_test() { "test-" @@ -1694,7 +1692,7 @@ fn filename(cx: &mut Context<'_, '_>, unit: &Unit) -> String { } else { "" }; - format!("{}{}-{}", flavor, kind, file_stem) + format!("{}{}-{}", flavor, kind, unit.target.name()) } #[repr(u8)] diff --git a/src/cargo/core/compiler/layout.rs b/src/cargo/core/compiler/layout.rs index a896d5be38b..c9f8fcedff0 100644 --- a/src/cargo/core/compiler/layout.rs +++ b/src/cargo/core/compiler/layout.rs @@ -26,16 +26,17 @@ //! # packages //! .fingerprint/ //! # Each package is in a separate directory. +//! # Note that different target kinds have different filename prefixes. //! $pkgname-$META/ //! # Set of source filenames for this package. -//! dep-lib-$pkgname-$META +//! dep-lib-$targetname //! # Timestamp when this package was last built. //! invoked.timestamp //! # The fingerprint hash. -//! lib-$pkgname-$META +//! lib-$targetname //! # Detailed information used for logging the reason why //! # something is being recompiled. -//! lib-$pkgname-$META.json +//! lib-$targetname.json //! # The console output from the compiler. This is cached //! # so that warnings can be redisplayed for "fresh" units. //! output diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index a24aaf0ab9b..ef404c5e989 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -31,7 +31,7 @@ use lazycell::LazyCell; use log::debug; pub use self::build_config::{BuildConfig, CompileMode, MessageFormat}; -pub use self::build_context::{BuildContext, FileFlavor, RustcTargetData, TargetInfo}; +pub use self::build_context::{BuildContext, FileFlavor, FileType, RustcTargetData, TargetInfo}; use self::build_plan::BuildPlan; pub use self::compilation::{Compilation, Doctest}; pub use self::compile_kind::{CompileKind, CompileTarget}; @@ -192,17 +192,12 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc) -> Car // don't pass the `-l` flags. let pass_l_flag = unit.target.is_lib() || !unit.pkg.targets().iter().any(|t| t.is_lib()); let pass_cdylib_link_args = unit.target.is_cdylib(); - let do_rename = unit.target.allows_dashes() && !unit.mode.is_any_test(); - let real_name = unit.target.name().to_string(); - let crate_name = unit.target.crate_name(); - // Rely on `target_filenames` iterator as source of truth rather than rederiving filestem. - let rustc_dep_info_loc = if do_rename && cx.files().metadata(unit).is_none() { - root.join(&crate_name) - } else { - root.join(&cx.files().file_stem(unit)) - } - .with_extension("d"); + let dep_info_name = match cx.files().metadata(cx.bcx, unit) { + Some(metadata) => format!("{}-{}.d", unit.target.crate_name(), metadata), + None => format!("{}.d", unit.target.crate_name()), + }; + let rustc_dep_info_loc = root.join(dep_info_name); let dep_info_loc = fingerprint::dep_info_loc(cx, unit); rustc.args(cx.bcx.rustflags_args(unit)); @@ -294,20 +289,6 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc) -> Car .chain_err(|| format!("could not compile `{}`.", name))?; } - if do_rename && real_name != crate_name { - let dst = &outputs[0].path; - let src = dst.with_file_name( - dst.file_name() - .unwrap() - .to_str() - .unwrap() - .replace(&real_name, &crate_name), - ); - if src.exists() && src.file_name() != dst.file_name() { - fs::rename(&src, &dst).chain_err(|| format!("could not rename crate {:?}", src))?; - } - } - if rustc_dep_info_loc.exists() { fingerprint::translate_dep_info( &rustc_dep_info_loc, @@ -888,7 +869,7 @@ fn build_base_args( cmd.arg("--cfg").arg(&format!("feature=\"{}\"", feat)); } - match cx.files().metadata(unit) { + match cx.files().metadata(cx.bcx, unit) { Some(m) => { cmd.arg("-C").arg(&format!("metadata={}", m)); cmd.arg("-C").arg(&format!("extra-filename=-{}", m)); @@ -1069,19 +1050,18 @@ pub fn extern_args( }; let outputs = cx.outputs(&dep.unit)?; - let mut outputs = outputs.iter().filter_map(|output| match output.flavor { - FileFlavor::Linkable { rmeta } => Some((output, rmeta)), - _ => None, - }); - - if cx.only_requires_rmeta(unit, &dep.unit) { - let (output, _rmeta) = outputs - .find(|(_output, rmeta)| *rmeta) - .expect("failed to find rlib dep for pipelined dep"); + + if cx.only_requires_rmeta(unit, &dep.unit) || dep.unit.mode.is_check() { + // Example: rlib dependency for an rlib, rmeta is all that is required. + let output = outputs + .iter() + .find(|output| output.flavor == FileFlavor::Rmeta) + .expect("failed to find rmeta dep for pipelined dep"); pass(&output.path); } else { - for (output, rmeta) in outputs { - if !rmeta { + // Example: a bin needs `rlib` for dependencies, it cannot use rmeta. + for output in outputs.iter() { + if output.flavor == FileFlavor::Linkable { pass(&output.path); } } diff --git a/src/cargo/core/compiler/output_depinfo.rs b/src/cargo/core/compiler/output_depinfo.rs index 284cb338cd5..3a9fac2c6d4 100644 --- a/src/cargo/core/compiler/output_depinfo.rs +++ b/src/cargo/core/compiler/output_depinfo.rs @@ -132,7 +132,7 @@ pub fn output_depinfo(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<()> for output in cx .outputs(unit)? .iter() - .filter(|o| o.flavor != FileFlavor::DebugInfo) + .filter(|o| !matches!(o.flavor, FileFlavor::DebugInfo | FileFlavor::Auxiliary)) { if let Some(ref link_dst) = output.hardlink { let output_path = link_dst.with_extension("d"); diff --git a/src/cargo/core/manifest.rs b/src/cargo/core/manifest.rs index 6e96cdf4c3d..994603aca57 100644 --- a/src/cargo/core/manifest.rs +++ b/src/cargo/core/manifest.rs @@ -164,6 +164,18 @@ impl TargetKind { _ => true, } } + + /// Returns the arguments suitable for `--crate-type` to pass to rustc. + pub fn rustc_crate_types(&self) -> Vec { + match self { + TargetKind::Lib(kinds) | TargetKind::ExampleLib(kinds) => kinds.clone(), + TargetKind::CustomBuild + | TargetKind::Bench + | TargetKind::Test + | TargetKind::ExampleBin + | TargetKind::Bin => vec![CrateType::Bin], + } + } } /// Information about a binary, a library, an example, etc. that is part of the @@ -757,14 +769,6 @@ impl Target { } } - /// Whether or not this target allows dashes in its filename. - /// - /// Rustc will always emit filenames with underscores, and Cargo will - /// rename them back to dashes if this is true. - pub fn allows_dashes(&self) -> bool { - self.is_bin() || self.is_example() || self.is_custom_build() - } - pub fn is_lib(&self) -> bool { match self.kind() { TargetKind::Lib(_) => true, @@ -835,14 +839,7 @@ impl Target { /// Returns the arguments suitable for `--crate-type` to pass to rustc. pub fn rustc_crate_types(&self) -> Vec { - match self.kind() { - TargetKind::Lib(kinds) | TargetKind::ExampleLib(kinds) => kinds.clone(), - TargetKind::CustomBuild - | TargetKind::Bench - | TargetKind::Test - | TargetKind::ExampleBin - | TargetKind::Bin => vec![CrateType::Bin], - } + self.kind().rustc_crate_types() } pub fn can_lto(&self) -> bool { diff --git a/src/cargo/ops/mod.rs b/src/cargo/ops/mod.rs index eed36c7867f..dc45fc41dcb 100644 --- a/src/cargo/ops/mod.rs +++ b/src/cargo/ops/mod.rs @@ -1,6 +1,6 @@ pub use self::cargo_clean::{clean, CleanOptions}; pub use self::cargo_compile::{ - compile, compile_with_exec, compile_ws, resolve_all_features, CompileOptions, + compile, compile_with_exec, compile_ws, create_bcx, resolve_all_features, CompileOptions, }; pub use self::cargo_compile::{CompileFilter, FilterRule, LibRule, Packages}; pub use self::cargo_doc::{doc, DocOptions}; diff --git a/tests/testsuite/bench.rs b/tests/testsuite/bench.rs index 225d5c9625e..b4d7de19aa8 100644 --- a/tests/testsuite/bench.rs +++ b/tests/testsuite/bench.rs @@ -1614,7 +1614,7 @@ fn json_artifact_includes_executable_for_benchmark() { { "executable": "[..]/foo/target/release/deps/benchmark-[..][EXE]", "features": [], - "filenames": [ "[..]/foo/target/release/deps/benchmark-[..][EXE]" ], + "filenames": "{...}", "fresh": false, "package_id": "foo 0.0.1 ([..])", "profile": "{...}", diff --git a/tests/testsuite/build_plan.rs b/tests/testsuite/build_plan.rs index 092ff90e637..a6e8eaac8dd 100644 --- a/tests/testsuite/build_plan.rs +++ b/tests/testsuite/build_plan.rs @@ -154,9 +154,7 @@ fn cargo_build_plan_build_script() { "env": "{...}", "kind": null, "links": "{...}", - "outputs": [ - "[..]/foo/target/debug/build/[..]/build_script_build-[..]" - ], + "outputs": "{...}", "package_name": "foo", "package_version": "0.5.0", "program": "rustc", diff --git a/tests/testsuite/cache_messages.rs b/tests/testsuite/cache_messages.rs index 0503306b943..feaeff7e62a 100644 --- a/tests/testsuite/cache_messages.rs +++ b/tests/testsuite/cache_messages.rs @@ -491,3 +491,23 @@ fn rustc_workspace_wrapper() { .with_stdout_does_not_contain("WRAPPER CALLED: rustc --crate-name foo src/lib.rs [..]") .run(); } + +#[cargo_test] +fn wacky_hashless_fingerprint() { + // On Windows, executables don't have hashes. This checks for a bad + // assumption that caused bad caching. + let p = project() + .file("src/bin/a.rs", "fn main() { let unused = 1; }") + .file("src/bin/b.rs", "fn main() {}") + .build(); + p.cargo("build --bin b") + .with_stderr_does_not_contain("[..]unused[..]") + .run(); + p.cargo("build --bin a") + .with_stderr_contains("[..]unused[..]") + .run(); + // This should not pick up the cache from `a`. + p.cargo("build --bin b") + .with_stderr_does_not_contain("[..]unused[..]") + .run(); +} diff --git a/tests/testsuite/dep_info.rs b/tests/testsuite/dep_info.rs index 886ef862cc4..4223fb31198 100644 --- a/tests/testsuite/dep_info.rs +++ b/tests/testsuite/dep_info.rs @@ -272,13 +272,13 @@ fn relative_depinfo_paths_ws() { assert_deps_contains( &p, - "target/debug/.fingerprint/pm-*/dep-lib-pm-*", + "target/debug/.fingerprint/pm-*/dep-lib-pm", &[(1, "src/lib.rs"), (2, "debug/deps/libpmdep-*.rlib")], ); assert_deps_contains( &p, - &format!("target/{}/debug/.fingerprint/foo-*/dep-bin-foo*", host), + &format!("target/{}/debug/.fingerprint/foo-*/dep-bin-foo", host), &[ (1, "src/main.rs"), ( @@ -296,7 +296,7 @@ fn relative_depinfo_paths_ws() { assert_deps_contains( &p, - "target/debug/.fingerprint/foo-*/dep-build-script-build_script_build-*", + "target/debug/.fingerprint/foo-*/dep-build-script-build-script-build", &[(1, "build.rs"), (2, "debug/deps/libbdep-*.rlib")], ); @@ -400,13 +400,13 @@ fn relative_depinfo_paths_no_ws() { assert_deps_contains( &p, - "target/debug/.fingerprint/pm-*/dep-lib-pm-*", + "target/debug/.fingerprint/pm-*/dep-lib-pm", &[(1, "src/lib.rs"), (2, "debug/deps/libpmdep-*.rlib")], ); assert_deps_contains( &p, - "target/debug/.fingerprint/foo-*/dep-bin-foo*", + "target/debug/.fingerprint/foo-*/dep-bin-foo", &[ (1, "src/main.rs"), ( @@ -424,7 +424,7 @@ fn relative_depinfo_paths_no_ws() { assert_deps_contains( &p, - "target/debug/.fingerprint/foo-*/dep-build-script-build_script_build-*", + "target/debug/.fingerprint/foo-*/dep-build-script-build-script-build", &[(1, "build.rs"), (2, "debug/deps/libbdep-*.rlib")], ); @@ -461,7 +461,7 @@ fn reg_dep_source_not_tracked() { assert_deps( &p, - "target/debug/.fingerprint/regdep-*/dep-lib-regdep-*", + "target/debug/.fingerprint/regdep-*/dep-lib-regdep", |info_path, entries| { for (kind, path) in entries { if *kind == 1 { @@ -513,7 +513,7 @@ fn canonical_path() { assert_deps_contains( &p, - "target/debug/.fingerprint/foo-*/dep-lib-foo-*", + "target/debug/.fingerprint/foo-*/dep-lib-foo", &[(1, "src/lib.rs"), (2, "debug/deps/libregdep-*.rmeta")], ); } diff --git a/tests/testsuite/metabuild.rs b/tests/testsuite/metabuild.rs index ece3c7aece8..77f4843aa3a 100644 --- a/tests/testsuite/metabuild.rs +++ b/tests/testsuite/metabuild.rs @@ -497,7 +497,7 @@ fn metabuild_build_plan() { "compile_mode": "build", "kind": null, "deps": [0, 1], - "outputs": ["[..]/target/debug/build/foo-[..]/metabuild_foo-[..][EXE]"], + "outputs": "{...}", "links": "{...}", "program": "rustc", "args": "{...}", @@ -686,9 +686,7 @@ fn metabuild_json_artifact() { { "executable": null, "features": [], - "filenames": [ - "[..]/foo/target/debug/build/foo-[..]/metabuild-foo[EXE]" - ], + "filenames": "{...}", "fresh": false, "package_id": "foo [..]", "profile": "{...}", diff --git a/tests/testsuite/out_dir.rs b/tests/testsuite/out_dir.rs index 15b26f61980..91365137c9a 100644 --- a/tests/testsuite/out_dir.rs +++ b/tests/testsuite/out_dir.rs @@ -90,8 +90,8 @@ fn dynamic_library_with_debug() { check_dir_contents( &p.root().join("out"), &["libfoo.so"], - &["libfoo.dylib"], - &["foo.dll", "foo.dll.lib"], + &["libfoo.dylib", "libfoo.dylib.dSYM"], + &["foo.dll", "foo.dll.exp", "foo.dll.lib", "foo.pdb"], &["foo.dll", "libfoo.dll.a"], ); } diff --git a/tests/testsuite/test.rs b/tests/testsuite/test.rs index 7f1561e3372..68fb5bc8182 100644 --- a/tests/testsuite/test.rs +++ b/tests/testsuite/test.rs @@ -3360,7 +3360,7 @@ fn json_artifact_includes_test_flag() { "name":"foo", "src_path":"[..]lib.rs" }, - "filenames":["[..]/foo-[..]"], + "filenames":"{...}", "fresh": false }