Skip to content

Commit fbcd9bb

Browse files
committed
Auto merge of #14464 - linyihai:issue-14194, r=weihanglo
fix: avoid inserting duplicate `dylib_path_envvar` when calling `cargo run` recursively ### What does this PR try to resolve? If the current program started by `cargo run` recursively call into `cargo run`, the second `cargo run` will insert `search_path` into `dylib_path_envvar` again. Fixes #14194 ### How should we test and review this PR? The first commit adds the test to reflect the issue. The first call to `cargo run` stores the dylib search path env var to a file. Subsequent calls verify that env var remains the same. The second commit fixes the behavior by checking if env vars in `search_path` are a prefix of the slice of env vars in `dylib_path_envvar`.
2 parents 2e309bd + 54dbc2b commit fbcd9bb

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed

src/cargo/core/compiler/compilation.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,11 @@ impl<'gctx> Compilation<'gctx> {
323323

324324
let dylib_path = paths::dylib_path();
325325
let dylib_path_is_empty = dylib_path.is_empty();
326-
search_path.extend(dylib_path.into_iter());
326+
if dylib_path.starts_with(&search_path) {
327+
search_path = dylib_path;
328+
} else {
329+
search_path.extend(dylib_path.into_iter());
330+
}
327331
if cfg!(target_os = "macos") && dylib_path_is_empty {
328332
// These are the defaults when DYLD_FALLBACK_LIBRARY_PATH isn't
329333
// set or set to an empty string. Since Cargo is explicitly setting

tests/testsuite/build.rs

+60
Original file line numberDiff line numberDiff line change
@@ -2154,6 +2154,66 @@ fn crate_library_path_env_var() {
21542154
setenv_for_removing_empty_component(p.cargo("run")).run();
21552155
}
21562156

2157+
// See https://github.com/rust-lang/cargo/issues/14194
2158+
#[cargo_test]
2159+
fn issue_14194_deduplicate_library_path_env_var() {
2160+
let p = project()
2161+
.file(
2162+
"src/main.rs",
2163+
&format!(
2164+
r#"
2165+
use std::process::Command;
2166+
fn main() {{
2167+
let level: i32 = std::env::args().nth(1).unwrap().parse().unwrap();
2168+
let txt = "var.txt";
2169+
let lib_path = std::env::var("{}").unwrap();
2170+
2171+
// Make sure we really have something in dylib search path.
2172+
let count = std::env::split_paths(&lib_path).count();
2173+
assert!(count > 0);
2174+
2175+
if level >= 3 {{
2176+
std::fs::write(txt, &lib_path).unwrap();
2177+
}} else {{
2178+
let prev_lib_path = std::fs::read_to_string(txt).unwrap();
2179+
// Ensure no duplicate insertion to dylib search paths
2180+
// when calling `cargo run` recursively.
2181+
assert_eq!(lib_path, prev_lib_path);
2182+
}}
2183+
2184+
if level == 0 {{
2185+
return;
2186+
}}
2187+
2188+
let _ = Command::new(std::env!("CARGO"))
2189+
.arg("run")
2190+
.arg("--")
2191+
.arg((level - 1).to_string())
2192+
.status()
2193+
.unwrap();
2194+
}}
2195+
"#,
2196+
dylib_path_envvar(),
2197+
),
2198+
)
2199+
.build();
2200+
2201+
setenv_for_removing_empty_component(p.cargo("run -- 3"))
2202+
.with_stderr_data(str![[r#"
2203+
[COMPILING] foo v0.0.1 ([ROOT]/foo)
2204+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
2205+
[RUNNING] `target/debug/foo[EXE] 3`
2206+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
2207+
[RUNNING] `target/debug/foo[EXE] 2`
2208+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
2209+
[RUNNING] `target/debug/foo[EXE] 1`
2210+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
2211+
[RUNNING] `target/debug/foo[EXE] 0`
2212+
2213+
"#]])
2214+
.run();
2215+
}
2216+
21572217
// Regression test for #4277
21582218
#[cargo_test]
21592219
fn build_with_fake_libc_not_loading() {

0 commit comments

Comments
 (0)