Port the output-filename-collision message

This commit is contained in:
Joe Neeman 2025-10-16 11:41:52 -05:00
parent fb571ec028
commit bc389539a6
3 changed files with 95 additions and 108 deletions

View File

@ -9,6 +9,7 @@ use crate::core::compiler::compilation::{self, UnitOutput};
use crate::core::compiler::{self, Unit, artifact};
use crate::util::cache_lock::CacheLockMode;
use crate::util::errors::CargoResult;
use annotate_snippets::{Level, Message};
use anyhow::{Context as _, bail};
use cargo_util::paths;
use filetime::FileTime;
@ -515,58 +516,56 @@ impl<'a, 'gctx> BuildRunner<'a, 'gctx> {
#[tracing::instrument(skip_all)]
fn check_collisions(&self) -> CargoResult<()> {
let mut output_collisions = HashMap::new();
let describe_collision = |unit: &Unit, other_unit: &Unit, path: &PathBuf| -> String {
let describe_collision = |unit: &Unit, other_unit: &Unit| -> String {
format!(
"The {} target `{}` in package `{}` has the same output \
filename as the {} target `{}` in package `{}`.\n\
Colliding filename is: {}\n",
"the {} target `{}` in package `{}` has the same output filename as the {} target `{}` in package `{}`",
unit.target.kind().description(),
unit.target.name(),
unit.pkg.package_id(),
other_unit.target.kind().description(),
other_unit.target.name(),
other_unit.pkg.package_id(),
path.display()
)
};
let suggestion = "Consider changing their names to be unique or compiling them separately.\n\
This may become a hard error in the future; see \
<https://github.com/rust-lang/cargo/issues/6313>.";
let rustdoc_suggestion = "This is a known bug where multiple crates with the same name use\n\
the same path; see <https://github.com/rust-lang/cargo/issues/6313>.";
let suggestion = [
Level::NOTE.message("this may become a hard error in the future; see <https://github.com/rust-lang/cargo/issues/6313>"),
Level::HELP.message("consider changing their names to be unique or compiling them separately")
];
let rustdoc_suggestion = [
Level::NOTE.message("this is a known bug where multiple crates with the same name use the same path; see <https://github.com/rust-lang/cargo/issues/6313>")
];
let report_collision = |unit: &Unit,
other_unit: &Unit,
path: &PathBuf,
suggestion: &str|
messages: &[Message<'_>]|
-> CargoResult<()> {
if unit.target.name() == other_unit.target.name() {
self.bcx.gctx.shell().warn(format!(
"output filename collision.\n\
{}\
The targets should have unique names.\n\
{}",
describe_collision(unit, other_unit, path),
suggestion
))
self.bcx.gctx.shell().print_report(
&[Level::WARNING
.secondary_title(format!("output filename collision at {}", path.display()))
.elements(
[Level::NOTE.message(describe_collision(unit, other_unit))]
.into_iter()
.chain(messages.iter().cloned()),
)],
false,
)
} else {
self.bcx.gctx.shell().warn(format!(
"output filename collision.\n\
{}\
The output filenames should be unique.\n\
{}\n\
If this looks unexpected, it may be a bug in Cargo. Please file a bug report at\n\
https://github.com/rust-lang/cargo/issues/ with as much information as you\n\
can provide.\n\
cargo {} running on `{}` target `{}`\n\
First unit: {:?}\n\
Second unit: {:?}",
describe_collision(unit, other_unit, path),
suggestion,
crate::version(),
self.bcx.host_triple(),
self.bcx.target_data.short_name(&unit.kind),
unit,
other_unit))
self.bcx.gctx.shell().print_report(
&[Level::WARNING
.secondary_title(format!("output filename collision at {}", path.display()))
.elements([
Level::NOTE.message(describe_collision(unit, other_unit)),
Level::NOTE.message("if this looks unexpected, it may be a bug in Cargo. Please file a bug \
report at https://github.com/rust-lang/cargo/issues/ with as much information as you \
can provide."),
Level::NOTE.message(format!("cargo {} running on `{}` target `{}`",
crate::version(), self.bcx.host_triple(), self.bcx.target_data.short_name(&unit.kind))),
Level::NOTE.message(format!("first unit: {unit:?}")),
Level::NOTE.message(format!("second unit: {other_unit:?}")),
])],
false,
)
}
};
@ -623,26 +622,31 @@ impl<'a, 'gctx> BuildRunner<'a, 'gctx> {
if unit.mode.is_doc() {
// See https://github.com/rust-lang/rust/issues/56169
// and https://github.com/rust-lang/rust/issues/61378
report_collision(unit, other_unit, &output.path, rustdoc_suggestion)?;
report_collision(unit, other_unit, &output.path, &rustdoc_suggestion)?;
} else {
report_collision(unit, other_unit, &output.path, suggestion)?;
report_collision(unit, other_unit, &output.path, &suggestion)?;
}
}
if let Some(hardlink) = output.hardlink.as_ref() {
if let Some(other_unit) = output_collisions.insert(hardlink.clone(), unit) {
report_collision(unit, other_unit, hardlink, suggestion)?;
report_collision(unit, other_unit, hardlink, &suggestion)?;
}
}
if let Some(ref export_path) = output.export_path {
if let Some(other_unit) = output_collisions.insert(export_path.clone(), unit) {
self.bcx.gctx.shell().warn(format!(
"`--artifact-dir` filename collision.\n\
{}\
The exported filenames should be unique.\n\
{}",
describe_collision(unit, other_unit, export_path),
suggestion
))?;
self.bcx.gctx.shell().print_report(
&[Level::WARNING
.secondary_title(format!(
"`--artifact-dir` filename collision at {}",
export_path.display()
))
.elements(
[Level::NOTE.message(describe_collision(unit, other_unit))]
.into_iter()
.chain(suggestion.iter().cloned()),
)],
false,
)?;
}
}
}

View File

@ -55,12 +55,11 @@ fn collision_dylib() {
p.cargo("build -j=1")
.with_stderr_data(&format!("\
...
[WARNING] output filename collision.
The lib target `a` in package `b v1.0.0 ([ROOT]/foo/b)` has the same output filename as the lib target `a` in package `a v1.0.0 ([ROOT]/foo/a)`.
Colliding filename is: [ROOT]/foo/target/debug/deps/{}a{}
The targets should have unique names.
Consider changing their names to be unique or compiling them separately.
This may become a hard error in the future; see <https://github.com/rust-lang/cargo/issues/6313>.
[WARNING] output filename collision at [ROOT]/foo/target/debug/deps/{}a{}
|
= [NOTE] the lib target `a` in package `b v1.0.0 ([ROOT]/foo/b)` has the same output filename as the lib target `a` in package `a v1.0.0 ([ROOT]/foo/a)`
= [NOTE] this may become a hard error in the future; see <https://github.com/rust-lang/cargo/issues/6313>
= [HELP] consider changing their names to be unique or compiling them separately
...
", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX))
.run();
@ -88,12 +87,11 @@ fn collision_example() {
p.cargo("build --examples -j=1")
.with_stderr_data(str![[r#"
...
[WARNING] output filename collision.
The example target `ex1` in package `b v1.0.0 ([ROOT]/foo/b)` has the same output filename as the example target `ex1` in package `a v1.0.0 ([ROOT]/foo/a)`.
Colliding filename is: [ROOT]/foo/target/debug/examples/ex1[EXE]
The targets should have unique names.
Consider changing their names to be unique or compiling them separately.
This may become a hard error in the future; see <https://github.com/rust-lang/cargo/issues/6313>.
[WARNING] output filename collision at [ROOT]/foo/target/debug/examples/ex1[EXE]
|
= [NOTE] the example target `ex1` in package `b v1.0.0 ([ROOT]/foo/b)` has the same output filename as the example target `ex1` in package `a v1.0.0 ([ROOT]/foo/a)`
= [NOTE] this may become a hard error in the future; see <https://github.com/rust-lang/cargo/issues/6313>
= [HELP] consider changing their names to be unique or compiling them separately
...
"#]])
@ -119,12 +117,11 @@ fn collision_export() {
p.cargo("build -j1 --artifact-dir=out -Z unstable-options --bins --examples")
.masquerade_as_nightly_cargo(&["artifact-dir"])
.with_stderr_data(str![[r#"
[WARNING] `--artifact-dir` filename collision.
The example target `foo` in package `foo v1.0.0 ([ROOT]/foo)` has the same output filename as the bin target `foo` in package `foo v1.0.0 ([ROOT]/foo)`.
Colliding filename is: [ROOT]/foo/out/foo[EXE]
The exported filenames should be unique.
Consider changing their names to be unique or compiling them separately.
This may become a hard error in the future; see <https://github.com/rust-lang/cargo/issues/6313>.
[WARNING] `--artifact-dir` filename collision at [ROOT]/foo/out/foo[EXE]
|
= [NOTE] the example target `foo` in package `foo v1.0.0 ([ROOT]/foo)` has the same output filename as the bin target `foo` in package `foo v1.0.0 ([ROOT]/foo)`
= [NOTE] this may become a hard error in the future; see <https://github.com/rust-lang/cargo/issues/6313>
= [HELP] consider changing their names to be unique or compiling them separately
...
"#]])
@ -165,12 +162,10 @@ fn collision_doc() {
p.cargo("doc -j=1")
.with_stderr_data(str![[r#"
...
[WARNING] output filename collision.
The lib target `foo` in package `foo2 v0.1.0 ([ROOT]/foo/foo2)` has the same output filename as the lib target `foo` in package `foo v0.1.0 ([ROOT]/foo)`.
Colliding filename is: [ROOT]/foo/target/doc/foo/index.html
The targets should have unique names.
This is a known bug where multiple crates with the same name use
the same path; see <https://github.com/rust-lang/cargo/issues/6313>.
[WARNING] output filename collision at [ROOT]/foo/target/doc/foo/index.html
|
= [NOTE] the lib target `foo` in package `foo2 v0.1.0 ([ROOT]/foo/foo2)` has the same output filename as the lib target `foo` in package `foo v0.1.0 ([ROOT]/foo)`
= [NOTE] this is a known bug where multiple crates with the same name use the same path; see <https://github.com/rust-lang/cargo/issues/6313>
...
"#]])
@ -449,12 +444,10 @@ fn collision_doc_sources() {
[LOCKING] 2 packages to latest compatible versions
[DOWNLOADING] crates ...
[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)
[WARNING] output filename collision.
The lib target `bar` in package `bar v1.0.0` has the same output filename as the lib target `bar` in package `bar v1.0.0 ([ROOT]/foo/bar)`.
Colliding filename is: [ROOT]/foo/target/doc/bar/index.html
The targets should have unique names.
This is a known bug where multiple crates with the same name use
the same path; see <https://github.com/rust-lang/cargo/issues/6313>.
[WARNING] output filename collision at [ROOT]/foo/target/doc/bar/index.html
|
= [NOTE] the lib target `bar` in package `bar v1.0.0` has the same output filename as the lib target `bar` in package `bar v1.0.0 ([ROOT]/foo/bar)`
= [NOTE] this is a known bug where multiple crates with the same name use the same path; see <https://github.com/rust-lang/cargo/issues/6313>
[CHECKING] bar v1.0.0 ([ROOT]/foo/bar)
[DOCUMENTING] bar v1.0.0 ([ROOT]/foo/bar)
[DOCUMENTING] bar v1.0.0
@ -576,12 +569,10 @@ fn collision_with_root() {
[LOCKING] 1 package to latest compatible version
[DOWNLOADING] crates ...
[DOWNLOADED] foo-macro v1.0.0 (registry `dummy-registry`)
[WARNING] output filename collision.
The lib target `foo_macro` in package `foo-macro v1.0.0` has the same output filename as the lib target `foo_macro` in package `foo-macro v1.0.0 ([ROOT]/foo/foo-macro)`.
Colliding filename is: [ROOT]/foo/target/doc/foo_macro/index.html
The targets should have unique names.
This is a known bug where multiple crates with the same name use
the same path; see <https://github.com/rust-lang/cargo/issues/6313>.
[WARNING] output filename collision at [ROOT]/foo/target/doc/foo_macro/index.html
|
= [NOTE] the lib target `foo_macro` in package `foo-macro v1.0.0` has the same output filename as the lib target `foo_macro` in package `foo-macro v1.0.0 ([ROOT]/foo/foo-macro)`
= [NOTE] this is a known bug where multiple crates with the same name use the same path; see <https://github.com/rust-lang/cargo/issues/6313>
[CHECKING] foo-macro v1.0.0
[DOCUMENTING] foo-macro v1.0.0
[CHECKING] abc v1.0.0 ([ROOT]/foo/abc)

View File

@ -297,12 +297,10 @@ fn doc_multiple_targets_same_name() {
p.cargo("doc --workspace")
.with_stderr_data(str![[r#"
[WARNING] output filename collision.
The bin target `foo_lib` in package `foo v0.1.0 ([ROOT]/foo/foo)` has the same output filename as the lib target `foo_lib` in package `bar v0.1.0 ([ROOT]/foo/bar)`.
Colliding filename is: [ROOT]/foo/target/doc/foo_lib/index.html
The targets should have unique names.
This is a known bug where multiple crates with the same name use
the same path; see <https://github.com/rust-lang/cargo/issues/6313>.
[WARNING] output filename collision at [ROOT]/foo/target/doc/foo_lib/index.html
|
= [NOTE] this is a known bug where multiple crates with the same name use the same path; see <https://github.com/rust-lang/cargo/issues/6313>
= [NOTE] the bin target `foo_lib` in package `foo v0.1.0 ([ROOT]/foo/foo)` has the same output filename as the lib target `foo_lib` in package `bar v0.1.0 ([ROOT]/foo/bar)`
[DOCUMENTING] bar v0.1.0 ([ROOT]/foo/bar)
[DOCUMENTING] foo v0.1.0 ([ROOT]/foo/foo)
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
@ -513,12 +511,10 @@ fn doc_lib_bin_same_name_documents_named_bin_when_requested() {
// The checking/documenting lines are sometimes swapped since they run
// concurrently.
.with_stderr_data(str![[r#"
[WARNING] output filename collision.
The bin target `foo` in package `foo v0.0.1 ([ROOT]/foo)` has the same output filename as the lib target `foo` in package `foo v0.0.1 ([ROOT]/foo)`.
Colliding filename is: [ROOT]/foo/target/doc/foo/index.html
The targets should have unique names.
This is a known bug where multiple crates with the same name use
the same path; see <https://github.com/rust-lang/cargo/issues/6313>.
[WARNING] output filename collision at [ROOT]/foo/target/doc/foo/index.html
|
= [NOTE] the bin target `foo` in package `foo v0.0.1 ([ROOT]/foo)` has the same output filename as the lib target `foo` in package `foo v0.0.1 ([ROOT]/foo)`
= [NOTE] this is a known bug where multiple crates with the same name use the same path; see <https://github.com/rust-lang/cargo/issues/6313>
[CHECKING] foo v0.0.1 ([ROOT]/foo)
[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
@ -557,12 +553,10 @@ fn doc_lib_bin_same_name_documents_bins_when_requested() {
// The checking/documenting lines are sometimes swapped since they run
// concurrently.
.with_stderr_data(str![[r#"
[WARNING] output filename collision.
The bin target `foo` in package `foo v0.0.1 ([ROOT]/foo)` has the same output filename as the lib target `foo` in package `foo v0.0.1 ([ROOT]/foo)`.
Colliding filename is: [ROOT]/foo/target/doc/foo/index.html
The targets should have unique names.
This is a known bug where multiple crates with the same name use
the same path; see <https://github.com/rust-lang/cargo/issues/6313>.
[WARNING] output filename collision at [ROOT]/foo/target/doc/foo/index.html
|
= [NOTE] the bin target `foo` in package `foo v0.0.1 ([ROOT]/foo)` has the same output filename as the lib target `foo` in package `foo v0.0.1 ([ROOT]/foo)`
= [NOTE] this is a known bug where multiple crates with the same name use the same path; see <https://github.com/rust-lang/cargo/issues/6313>
[CHECKING] foo v0.0.1 ([ROOT]/foo)
[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
@ -1408,12 +1402,10 @@ fn doc_all_member_dependency_same_name() {
[LOCKING] 1 package to latest compatible version
[DOWNLOADING] crates ...
[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)
[WARNING] output filename collision.
The lib target `bar` in package `bar v0.1.0` has the same output filename as the lib target `bar` in package `bar v0.1.0 ([ROOT]/foo/bar)`.
Colliding filename is: [ROOT]/foo/target/doc/bar/index.html
The targets should have unique names.
This is a known bug where multiple crates with the same name use
the same path; see <https://github.com/rust-lang/cargo/issues/6313>.
[WARNING] output filename collision at [ROOT]/foo/target/doc/bar/index.html
|
= [NOTE] the lib target `bar` in package `bar v0.1.0` has the same output filename as the lib target `bar` in package `bar v0.1.0 ([ROOT]/foo/bar)`
= [NOTE] this is a known bug where multiple crates with the same name use the same path; see <https://github.com/rust-lang/cargo/issues/6313>
[DOCUMENTING] bar v0.1.0
[CHECKING] bar v0.1.0
[DOCUMENTING] bar v0.1.0 ([ROOT]/foo/bar)