From e888c1306fefd708503f00fe5f9ff759a7f6b0dd Mon Sep 17 00:00:00 2001 From: Lin Yihai Date: Wed, 28 Aug 2024 15:43:34 +0800 Subject: [PATCH 1/2] test: Add test for issue-14194 --- tests/testsuite/build.rs | 60 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/tests/testsuite/build.rs b/tests/testsuite/build.rs index bb13046e50f..3cc4aa8b8c5 100644 --- a/tests/testsuite/build.rs +++ b/tests/testsuite/build.rs @@ -2154,6 +2154,66 @@ fn crate_library_path_env_var() { setenv_for_removing_empty_component(p.cargo("run")).run(); } +// See https://github.com/rust-lang/cargo/issues/14194 +#[cargo_test] +fn issue_14194_deduplicate_library_path_env_var() { + let p = project() + .file( + "src/main.rs", + &format!( + r#" + use std::process::Command; + fn main() {{ + let level: i32 = std::env::args().nth(1).unwrap().parse().unwrap(); + let txt = "var.txt"; + let lib_path = std::env::var("{}").unwrap(); + + // Make sure we really have something in dylib search path. + let count = std::env::split_paths(&lib_path).count(); + assert!(count > 0); + + if level >= 3 {{ + std::fs::write(txt, &lib_path).unwrap(); + }} else {{ + let prev_lib_path = std::fs::read_to_string(txt).unwrap(); + // Ensure no duplicate insertion to dylib search paths + // when calling `cargo run` recursively. + assert_ne!(lib_path, prev_lib_path); + }} + + if level == 0 {{ + return; + }} + + let _ = Command::new(std::env!("CARGO")) + .arg("run") + .arg("--") + .arg((level - 1).to_string()) + .status() + .unwrap(); + }} + "#, + dylib_path_envvar(), + ), + ) + .build(); + + setenv_for_removing_empty_component(p.cargo("run -- 3")) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE] 3` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE] 2` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE] 1` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE] 0` + +"#]]) + .run(); +} + // Regression test for #4277 #[cargo_test] fn build_with_fake_libc_not_loading() { From 54dbc2bf66381314a546b366faa913294af0b6d5 Mon Sep 17 00:00:00 2001 From: Lin Yihai Date: Wed, 28 Aug 2024 16:04:01 +0800 Subject: [PATCH 2/2] fix: Avoid inserting `search_path` again. --- src/cargo/core/compiler/compilation.rs | 6 +++++- tests/testsuite/build.rs | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/cargo/core/compiler/compilation.rs b/src/cargo/core/compiler/compilation.rs index 8ec625d77a4..5ecf77d4c6a 100644 --- a/src/cargo/core/compiler/compilation.rs +++ b/src/cargo/core/compiler/compilation.rs @@ -323,7 +323,11 @@ impl<'gctx> Compilation<'gctx> { let dylib_path = paths::dylib_path(); let dylib_path_is_empty = dylib_path.is_empty(); - search_path.extend(dylib_path.into_iter()); + if dylib_path.starts_with(&search_path) { + search_path = dylib_path; + } else { + search_path.extend(dylib_path.into_iter()); + } if cfg!(target_os = "macos") && dylib_path_is_empty { // These are the defaults when DYLD_FALLBACK_LIBRARY_PATH isn't // set or set to an empty string. Since Cargo is explicitly setting diff --git a/tests/testsuite/build.rs b/tests/testsuite/build.rs index 3cc4aa8b8c5..b7c87615437 100644 --- a/tests/testsuite/build.rs +++ b/tests/testsuite/build.rs @@ -2178,7 +2178,7 @@ fn issue_14194_deduplicate_library_path_env_var() { let prev_lib_path = std::fs::read_to_string(txt).unwrap(); // Ensure no duplicate insertion to dylib search paths // when calling `cargo run` recursively. - assert_ne!(lib_path, prev_lib_path); + assert_eq!(lib_path, prev_lib_path); }} if level == 0 {{