mirror of
https://github.com/rust-lang/cargo.git
synced 2025-10-01 11:30:39 +00:00
Auto merge of #9418 - ehuss:always-meta, r=alexcrichton
Always use full metadata hash for -C metadata. This changes it so that cargo always uses the full metadata hash for `-C metadata`. This ensures that even if a unit isn't using `-C extra-filename` that the symbol hashing uses all the fields used in the other cases. This fixes an issue on macOS where a combination of split-debuginfo and incremental caused the same `.o` filenames to be used, which caused corruption in the incremental cache (see issue for details). Fixes #9353.
This commit is contained in:
commit
52a0ca5cc3
@ -80,6 +80,17 @@ impl fmt::Debug for Metadata {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Information about the metadata hashes used for a `Unit`.
|
||||||
|
struct MetaInfo {
|
||||||
|
/// The symbol hash to use.
|
||||||
|
meta_hash: Metadata,
|
||||||
|
/// Whether or not the `-C extra-filename` flag is used to generate unique
|
||||||
|
/// output filenames for this `Unit`.
|
||||||
|
///
|
||||||
|
/// If this is `true`, the `meta_hash` is used for the filename.
|
||||||
|
use_extra_filename: bool,
|
||||||
|
}
|
||||||
|
|
||||||
/// Collection of information about the files emitted by the compiler, and the
|
/// Collection of information about the files emitted by the compiler, and the
|
||||||
/// output directory structure.
|
/// output directory structure.
|
||||||
pub struct CompilationFiles<'a, 'cfg> {
|
pub struct CompilationFiles<'a, 'cfg> {
|
||||||
@ -94,7 +105,7 @@ pub struct CompilationFiles<'a, 'cfg> {
|
|||||||
roots: Vec<Unit>,
|
roots: Vec<Unit>,
|
||||||
ws: &'a Workspace<'cfg>,
|
ws: &'a Workspace<'cfg>,
|
||||||
/// Metadata hash to use for each unit.
|
/// Metadata hash to use for each unit.
|
||||||
metas: HashMap<Unit, Option<Metadata>>,
|
metas: HashMap<Unit, MetaInfo>,
|
||||||
/// For each Unit, a list all files produced.
|
/// For each Unit, a list all files produced.
|
||||||
outputs: HashMap<Unit, LazyCell<Arc<Vec<OutputFile>>>>,
|
outputs: HashMap<Unit, LazyCell<Arc<Vec<OutputFile>>>>,
|
||||||
}
|
}
|
||||||
@ -160,11 +171,14 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
|
|||||||
/// Gets the metadata for the given unit.
|
/// Gets the metadata for the given unit.
|
||||||
///
|
///
|
||||||
/// See module docs for more details.
|
/// See module docs for more details.
|
||||||
///
|
pub fn metadata(&self, unit: &Unit) -> Metadata {
|
||||||
/// Returns `None` if the unit should not use a metadata hash (like
|
self.metas[unit].meta_hash
|
||||||
/// rustdoc, or some dylibs).
|
}
|
||||||
pub fn metadata(&self, unit: &Unit) -> Option<Metadata> {
|
|
||||||
self.metas[unit]
|
/// Returns whether or not `-C extra-filename` is used to extend the
|
||||||
|
/// output filenames to make them unique.
|
||||||
|
pub fn use_extra_filename(&self, unit: &Unit) -> bool {
|
||||||
|
self.metas[unit].use_extra_filename
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the short hash based only on the `PackageId`.
|
/// Gets the short hash based only on the `PackageId`.
|
||||||
@ -201,9 +215,11 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
|
|||||||
/// taken in those cases!
|
/// taken in those cases!
|
||||||
fn pkg_dir(&self, unit: &Unit) -> String {
|
fn pkg_dir(&self, unit: &Unit) -> String {
|
||||||
let name = unit.pkg.package_id().name();
|
let name = unit.pkg.package_id().name();
|
||||||
match self.metas[unit] {
|
let meta = &self.metas[unit];
|
||||||
Some(ref meta) => format!("{}-{}", name, meta),
|
if meta.use_extra_filename {
|
||||||
None => format!("{}-{}", name, self.target_short_hash(unit)),
|
format!("{}-{}", name, meta.meta_hash)
|
||||||
|
} else {
|
||||||
|
format!("{}-{}", name, self.target_short_hash(unit))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,8 +464,9 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
|
|||||||
// Convert FileType to OutputFile.
|
// Convert FileType to OutputFile.
|
||||||
let mut outputs = Vec::new();
|
let mut outputs = Vec::new();
|
||||||
for file_type in file_types {
|
for file_type in file_types {
|
||||||
let meta = self.metadata(unit).map(|m| m.to_string());
|
let meta = &self.metas[unit];
|
||||||
let path = out_dir.join(file_type.output_filename(&unit.target, meta.as_deref()));
|
let meta_opt = meta.use_extra_filename.then(|| meta.meta_hash.to_string());
|
||||||
|
let path = out_dir.join(file_type.output_filename(&unit.target, meta_opt.as_deref()));
|
||||||
let hardlink = self.uplift_to(unit, &file_type, &path);
|
let hardlink = self.uplift_to(unit, &file_type, &path);
|
||||||
let export_path = if unit.target.is_custom_build() {
|
let export_path = if unit.target.is_custom_build() {
|
||||||
None
|
None
|
||||||
@ -471,11 +488,11 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn metadata_of(
|
fn metadata_of<'a>(
|
||||||
unit: &Unit,
|
unit: &Unit,
|
||||||
cx: &Context<'_, '_>,
|
cx: &Context<'_, '_>,
|
||||||
metas: &mut HashMap<Unit, Option<Metadata>>,
|
metas: &'a mut HashMap<Unit, MetaInfo>,
|
||||||
) -> Option<Metadata> {
|
) -> &'a MetaInfo {
|
||||||
if !metas.contains_key(unit) {
|
if !metas.contains_key(unit) {
|
||||||
let meta = compute_metadata(unit, cx, metas);
|
let meta = compute_metadata(unit, cx, metas);
|
||||||
metas.insert(unit.clone(), meta);
|
metas.insert(unit.clone(), meta);
|
||||||
@ -483,18 +500,15 @@ fn metadata_of(
|
|||||||
metadata_of(&dep.unit, cx, metas);
|
metadata_of(&dep.unit, cx, metas);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
metas[unit]
|
&metas[unit]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_metadata(
|
fn compute_metadata(
|
||||||
unit: &Unit,
|
unit: &Unit,
|
||||||
cx: &Context<'_, '_>,
|
cx: &Context<'_, '_>,
|
||||||
metas: &mut HashMap<Unit, Option<Metadata>>,
|
metas: &mut HashMap<Unit, MetaInfo>,
|
||||||
) -> Option<Metadata> {
|
) -> MetaInfo {
|
||||||
let bcx = &cx.bcx;
|
let bcx = &cx.bcx;
|
||||||
if !should_use_metadata(bcx, unit) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let mut hasher = StableHasher::new();
|
let mut hasher = StableHasher::new();
|
||||||
|
|
||||||
METADATA_VERSION.hash(&mut hasher);
|
METADATA_VERSION.hash(&mut hasher);
|
||||||
@ -514,7 +528,7 @@ fn compute_metadata(
|
|||||||
let mut deps_metadata = cx
|
let mut deps_metadata = cx
|
||||||
.unit_deps(unit)
|
.unit_deps(unit)
|
||||||
.iter()
|
.iter()
|
||||||
.map(|dep| metadata_of(&dep.unit, cx, metas))
|
.map(|dep| metadata_of(&dep.unit, cx, metas).meta_hash)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
deps_metadata.sort();
|
deps_metadata.sort();
|
||||||
deps_metadata.hash(&mut hasher);
|
deps_metadata.hash(&mut hasher);
|
||||||
@ -561,7 +575,10 @@ fn compute_metadata(
|
|||||||
// with user dependencies.
|
// with user dependencies.
|
||||||
unit.is_std.hash(&mut hasher);
|
unit.is_std.hash(&mut hasher);
|
||||||
|
|
||||||
Some(Metadata(hasher.finish()))
|
MetaInfo {
|
||||||
|
meta_hash: Metadata(hasher.finish()),
|
||||||
|
use_extra_filename: should_use_metadata(bcx, unit),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hash_rustc_version(bcx: &BuildContext<'_, '_>, hasher: &mut StableHasher) {
|
fn hash_rustc_version(bcx: &BuildContext<'_, '_>, hasher: &mut StableHasher) {
|
||||||
|
@ -391,9 +391,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
|
|||||||
/// Returns the metadata hash for a RunCustomBuild unit.
|
/// Returns the metadata hash for a RunCustomBuild unit.
|
||||||
pub fn get_run_build_script_metadata(&self, unit: &Unit) -> Metadata {
|
pub fn get_run_build_script_metadata(&self, unit: &Unit) -> Metadata {
|
||||||
assert!(unit.mode.is_run_custom_build());
|
assert!(unit.mode.is_run_custom_build());
|
||||||
self.files()
|
self.files().metadata(unit)
|
||||||
.metadata(unit)
|
|
||||||
.expect("build script should always have hash")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_primary_package(&self, unit: &Unit) -> bool {
|
pub fn is_primary_package(&self, unit: &Unit) -> bool {
|
||||||
|
@ -229,9 +229,14 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc<dyn Executor>) -> Car
|
|||||||
let pass_l_flag = unit.target.is_lib() || !unit.pkg.targets().iter().any(|t| t.is_lib());
|
let pass_l_flag = unit.target.is_lib() || !unit.pkg.targets().iter().any(|t| t.is_lib());
|
||||||
let link_type = (&unit.target).into();
|
let link_type = (&unit.target).into();
|
||||||
|
|
||||||
let dep_info_name = match cx.files().metadata(unit) {
|
let dep_info_name = if cx.files().use_extra_filename(unit) {
|
||||||
Some(metadata) => format!("{}-{}.d", unit.target.crate_name(), metadata),
|
format!(
|
||||||
None => format!("{}.d", unit.target.crate_name()),
|
"{}-{}.d",
|
||||||
|
unit.target.crate_name(),
|
||||||
|
cx.files().metadata(unit)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
format!("{}.d", unit.target.crate_name())
|
||||||
};
|
};
|
||||||
let rustc_dep_info_loc = root.join(dep_info_name);
|
let rustc_dep_info_loc = root.join(dep_info_name);
|
||||||
let dep_info_loc = fingerprint::dep_info_loc(cx, unit);
|
let dep_info_loc = fingerprint::dep_info_loc(cx, unit);
|
||||||
@ -881,15 +886,10 @@ fn build_base_args(
|
|||||||
cmd.arg("--cfg").arg(&format!("feature=\"{}\"", feat));
|
cmd.arg("--cfg").arg(&format!("feature=\"{}\"", feat));
|
||||||
}
|
}
|
||||||
|
|
||||||
match cx.files().metadata(unit) {
|
let meta = cx.files().metadata(unit);
|
||||||
Some(m) => {
|
cmd.arg("-C").arg(&format!("metadata={}", meta));
|
||||||
cmd.arg("-C").arg(&format!("metadata={}", m));
|
if cx.files().use_extra_filename(unit) {
|
||||||
cmd.arg("-C").arg(&format!("extra-filename=-{}", m));
|
cmd.arg("-C").arg(&format!("extra-filename=-{}", meta));
|
||||||
}
|
|
||||||
None => {
|
|
||||||
cmd.arg("-C")
|
|
||||||
.arg(&format!("metadata={}", cx.files().target_short_hash(unit)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if rpath {
|
if rpath {
|
||||||
|
@ -587,3 +587,60 @@ foo v0.1.0 [..]
|
|||||||
)
|
)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cargo_test]
|
||||||
|
#[ignore]
|
||||||
|
fn avoids_split_debuginfo_collision() {
|
||||||
|
// Checks for a bug where .o files were being incorrectly shared between
|
||||||
|
// different toolchains using incremental and split-debuginfo on macOS.
|
||||||
|
let p = project()
|
||||||
|
.file(
|
||||||
|
"Cargo.toml",
|
||||||
|
r#"
|
||||||
|
[package]
|
||||||
|
name = "foo"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
split-debuginfo = "unpacked"
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.file("src/main.rs", "fn main() {}")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
execs()
|
||||||
|
.with_process_builder(tc_process("cargo", "stable"))
|
||||||
|
.arg("build")
|
||||||
|
.env("CARGO_INCREMENTAL", "1")
|
||||||
|
.cwd(p.root())
|
||||||
|
.with_stderr(
|
||||||
|
"\
|
||||||
|
[COMPILING] foo v0.1.0 [..]
|
||||||
|
[FINISHED] [..]
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.run();
|
||||||
|
|
||||||
|
p.cargo("build")
|
||||||
|
.env("CARGO_INCREMENTAL", "1")
|
||||||
|
.with_stderr(
|
||||||
|
"\
|
||||||
|
[COMPILING] foo v0.1.0 [..]
|
||||||
|
[FINISHED] [..]
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.run();
|
||||||
|
|
||||||
|
execs()
|
||||||
|
.with_process_builder(tc_process("cargo", "stable"))
|
||||||
|
.arg("build")
|
||||||
|
.env("CARGO_INCREMENTAL", "1")
|
||||||
|
.cwd(p.root())
|
||||||
|
.with_stderr(
|
||||||
|
"\
|
||||||
|
[COMPILING] foo v0.1.0 [..]
|
||||||
|
[FINISHED] [..]
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user