Skip to content
Merged
15 changes: 10 additions & 5 deletions src/cargo/core/compiler/build_runner/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -483,13 +483,18 @@ impl<'a, 'gctx> BuildRunner<'a, 'gctx> {
}
if self.bcx.gctx.cli_unstable().build_dir_new_layout {
for (unit, _) in self.bcx.unit_graph.iter() {
if kind != unit.kind {
continue;
}
let dep_dir = self.files().deps_dir(unit);
paths::create_dir_all(&dep_dir)?;
self.compilation
.deps_output
.entry(kind)
.or_default()
.insert(dep_dir);
if unit.target.is_dylib() {
self.compilation
.deps_output
.entry(kind)
.or_default()
.insert(dep_dir);
}
}
} else {
self.compilation
Expand Down
8 changes: 6 additions & 2 deletions src/cargo/core/compiler/compilation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,9 @@ impl<'gctx> Compilation<'gctx> {
&self.root_output[&CompileKind::Host],
));
}
search_path.extend(self.deps_output[&CompileKind::Host].clone());
if let Some(paths) = self.deps_output.get(&CompileKind::Host) {
search_path.extend(paths.clone());
}
} else {
if let Some(path) = self.root_output.get(&kind) {
search_path.extend(super::filter_dynamic_search_path(
Expand All @@ -384,7 +386,9 @@ impl<'gctx> Compilation<'gctx> {
));
search_path.push(path.clone());
}
search_path.extend(self.deps_output[&kind].clone());
if let Some(paths) = self.deps_output.get(&kind) {
search_path.extend(paths.clone());
}
// For build-std, we don't want to accidentally pull in any shared
// libs from the sysroot that ships with rustc. This may not be
// required (at least I cannot craft a situation where it
Expand Down
13 changes: 8 additions & 5 deletions src/cargo/core/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1826,12 +1826,15 @@ fn add_dep_arg<'a, 'b: 'a>(
build_runner: &'b BuildRunner<'b, '_>,
unit: &'a Unit,
) {
if map.contains_key(&unit) {
return;
}
map.insert(&unit, build_runner.files().deps_dir(&unit));

for dep in build_runner.unit_deps(unit) {
// Don't include build script out dir in the args to reduce rustc command bloat.
if dep.unit.target.is_custom_build() {
continue;
}
if map.contains_key(&dep.unit) {
continue;
}
map.insert(&dep.unit, build_runner.files().deps_dir(&dep.unit));
add_dep_arg(map, build_runner, &dep.unit);
}
}
Expand Down
179 changes: 179 additions & 0 deletions tests/testsuite/build.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Tests for the `cargo build` command.

use std::env;
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
use std::fs;
use std::io::Read;
use std::process::Stdio;
Expand Down Expand Up @@ -6540,3 +6541,181 @@ fn no_embed_metadata_invalidate() {
"#]])
.run();
}

#[cargo_test]
fn should_not_include_current_build_unit_path_in_rustc_args() {
let p = project()
.file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#)
.file(
".cargo/config.toml",
r#"
[build]
target-dir = "target-dir"
build-dir = "build-dir"
"#,
)
.build();

p.cargo("-Zbuild-dir-new-layout -v build")
.masquerade_as_nightly_cargo(&["new build-dir layout"])
.enable_mac_dsym()
// Don't pass any `-L` args if there are no dependencies (including our own `out` dir)
.with_stderr_data(str![[r#"
[COMPILING] foo v0.0.1 ([ROOT]/foo)
[RUNNING] `rustc --crate-name foo [..] --out-dir [ROOT]/foo/build-dir/debug/build/foo/[HASH]/out --verbose`
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s

"#]])
.run();
}

#[cargo_test]
fn should_not_include_build_script_out_dir_path_in_rustc_args() {
let p = project()
.file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#)
.file("build.rs", r#"fn main() { }"#)
.file(
".cargo/config.toml",
r#"
[build]
target-dir = "target-dir"
build-dir = "build-dir"
"#,
)
.build();

p.cargo("-Zbuild-dir-new-layout -v build")
.masquerade_as_nightly_cargo(&["new build-dir layout"])
.enable_mac_dsym()
// Don't pass build script `out` dirs and avoid bloating the rustc command args which can
// lead to problems on Windows.
.with_stderr_data(str![[r#"
[COMPILING] foo v0.0.1 ([ROOT]/foo)
[RUNNING] `rustc --crate-name build_script_build [..]`
[RUNNING] `[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/build_script_build`
[RUNNING] `rustc --crate-name foo [..] --out-dir [ROOT]/foo/build-dir/debug/build/foo/[HASH]/out --verbose`
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s

"#]])
.run();
}

#[cargo_test(
nightly,
reason = "Depends on https://github.com/rust-lang/rust/pull/155439/changes/61f3e086acc1c187bb262ab43cac71f44018c397"
)]
fn should_only_include_dylibs_on_lib_search_path() {
let envvar = dylib_path_envvar();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.0"
edition = "2021"
authors = []
resolver = "2"

[dependencies]
bar = { path = "bar" }
baz = { path = "baz" }
qux = { path = "qux" }
"#,
)
.file(
"src/main.rs",
&format!(
r#"
fn main() {{
let search_path = std::env::var_os("{envvar}").unwrap();
let paths: Vec<_> = std::env::split_paths(&search_path).collect();

for (name, kind) in [("bar", "dylib"), ("baz", "rlib"), ("qux", "cdylib")] {{
let found = paths.iter().any(|dir| artifact_exists(dir, name, kind));
println!("{{name}} ({{kind}}) on search path: {{found}}");
}}
}}

fn artifact_exists(dir: &std::path::Path, name: &str, kind: &str) -> bool {{
let (prefix, suffix) = if kind == "rlib" {{
(format!("lib{{name}}-"), ".rlib".to_string())
}} else {{
(format!("{DLL_PREFIX}{{name}}"), "{DLL_SUFFIX}".to_string())
}};
std::fs::read_dir(dir)
.into_iter()
.flatten()
.flatten()
.any(|e| {{
let f = e.file_name();
let f = f.to_string_lossy();
f.starts_with(&prefix) && f.ends_with(&suffix)
}})
}}
"#
),
)
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.0"
edition = "2021"
authors = []

[lib]
crate-type = ["dylib"]
"#,
)
.file("bar/src/lib.rs", r#"pub fn bar_value() -> i32 { 100 }"#)
.file(
"baz/Cargo.toml",
r#"
[package]
name = "baz"
version = "0.1.0"
edition = "2021"
authors = []
"#,
)
.file("baz/src/lib.rs", r#"pub fn baz_value() -> i32 { 200 }"#)
.file(
"qux/Cargo.toml",
r#"
[package]
name = "qux"
version = "0.1.0"
edition = "2021"
authors = []

[lib]
crate-type = ["cdylib"]
"#,
)
.file("qux/src/lib.rs", r#"pub fn qux_value() -> i32 { 200 }"#)
.build();

p.cargo("-Zbuild-dir-new-layout -v run")
.masquerade_as_nightly_cargo(&["new build-dir layout"])
.enable_mac_dsym()
.with_stdout_data(str![[r#"
bar (dylib) on search path: true
baz (rlib) on search path: false
qux (cdylib) on search path: false

"#]])
.run();

// Legacy layout
p.cargo("-v run")
.enable_mac_dsym()
.with_stdout_data(str![[r#"
bar (dylib) on search path: true
baz (rlib) on search path: true
qux (cdylib) on search path: true

"#]])
.run();
}
99 changes: 99 additions & 0 deletions tests/testsuite/build_script.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Tests for build.rs scripts.

use std::env;
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
use std::fs;
use std::io;
use std::thread;
Expand All @@ -17,6 +18,7 @@ use cargo_test_support::registry::Package;
use cargo_test_support::str;
use cargo_test_support::{basic_manifest, cross_compile, is_coarse_mtime, project, project_in};
use cargo_test_support::{git, rustc_host, sleep_ms, slow_cpu_multiplier, symlink_supported};
use cargo_util::paths::dylib_path_envvar;
use cargo_util::paths::{self, remove_dir_all};

#[cargo_test]
Expand Down Expand Up @@ -6870,3 +6872,100 @@ fn target_linker_does_not_apply_to_build_script_with_host_config() {
"#]])
.run();
}

#[cargo_test(
nightly,
reason = "Depends on https://github.com/rust-lang/rust/pull/155439/changes/61f3e086acc1c187bb262ab43cac71f44018c397"
)]
fn build_script_dylib_search_path_excludes_target_dylibs() {
if cross_compile_disabled() {
return;
}

let envvar = dylib_path_envvar();
let target = cross_compile::alternate();

let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.0"
edition = "2021"
authors = []

[dependencies]
bar = { path = "bar" }

[build-dependencies]
hostbar = { path = "hostbar" }
"#,
)
.file(
"build.rs",
&format!(
r#"
fn main() {{
let search_path = std::env::var_os("{envvar}").unwrap();
let paths: Vec<_> = std::env::split_paths(&search_path).collect();

let found_hostbar = paths.iter()
.any(|dir| dir.join("{DLL_PREFIX}hostbar{DLL_SUFFIX}").exists());
assert!(
found_hostbar,
"hostbar (host-arch build-dependency dylib) should be on \
the build script's search path, but wasn't: {{:?}}",
paths
);

let found_bar = paths.iter()
.any(|dir| dir.join("{DLL_PREFIX}bar{DLL_SUFFIX}").exists());
assert!(
!found_bar,
"bar ({target}-arch regular dependency dylib) must NOT be on \
the host build script's search path, but was: {{:?}}",
paths
);
}}
"#
),
)
.file("src/main.rs", "fn main() {}")
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.0"
edition = "2021"
authors = []
[lib]
crate-type = ["dylib"]
"#,
)
.file("bar/src/lib.rs", "pub fn bar_value() -> i32 { 100 }")
.file(
"hostbar/Cargo.toml",
r#"
[package]
name = "hostbar"
version = "0.1.0"
edition = "2021"
authors = []
[lib]
crate-type = ["dylib"]
"#,
)
.file(
"hostbar/src/lib.rs",
"pub fn hostbar_value() -> i32 { 200 }",
)
.build();

p.cargo("build -Zbuild-dir-new-layout -v --target")
.arg(&target)
.masquerade_as_nightly_cargo(&["new build-dir layout"])
.enable_mac_dsym()
.run();
}
4 changes: 2 additions & 2 deletions tests/testsuite/min_publish_age.rs
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ fn report_rust_version_note_over_too_new_note() {
.publish();
// 2 days before `NOW`, and needs a newer Rust than the workspace.
Package::new("bar", "1.1.0")
.rust_version("1.99.0")
.rust_version("1.65535.0")
.pubtime("2006-08-06T00:00:00Z")
.publish();

Expand Down Expand Up @@ -517,7 +517,7 @@ fn report_rust_version_note_over_too_new_note() {
.with_stderr_data(str![[r#"
[UPDATING] `dummy-registry` index
[LOCKING] 1 package to latest compatible version
[ADDING] bar v1.1.0 (requires Rust 1.99.0)
[ADDING] bar v1.1.0 (requires Rust 1.65535.0)

"#]])
.run();
Expand Down