Skip to content

Commit 9bf9bdd

Browse files
committed
Auto merge of #3974 - mcgoo:build_rs_native_path, r=alexcrichton
fix dynamic search path for build scripts fixes #3957
2 parents a232aef + b8158cf commit 9bf9bdd

File tree

6 files changed

+93
-50
lines changed

6 files changed

+93
-50
lines changed

src/cargo/ops/cargo_rustc/compilation.rs

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -100,32 +100,9 @@ impl<'cfg> Compilation<'cfg> {
100100
let mut search_path = if is_host {
101101
vec![self.plugins_dylib_path.clone()]
102102
} else {
103-
let mut search_path = vec![];
104-
105-
// Add -L arguments, after stripping off prefixes like "native="
106-
// or "framework=" and filtering out directories *not* inside our
107-
// output directory, since they are likely spurious and can cause
108-
// clashes with system shared libraries (issue #3366).
109-
for dir in self.native_dirs.iter() {
110-
let dir = match dir.to_str() {
111-
Some(s) => {
112-
let mut parts = s.splitn(2, '=');
113-
match (parts.next(), parts.next()) {
114-
(Some("native"), Some(path)) |
115-
(Some("crate"), Some(path)) |
116-
(Some("dependency"), Some(path)) |
117-
(Some("framework"), Some(path)) |
118-
(Some("all"), Some(path)) => path.into(),
119-
_ => dir.clone(),
120-
}
121-
}
122-
None => dir.clone(),
123-
};
124-
125-
if dir.starts_with(&self.root_output) {
126-
search_path.push(dir);
127-
}
128-
}
103+
let mut search_path =
104+
super::filter_dynamic_search_path(self.native_dirs.iter(),
105+
&self.root_output);
129106
search_path.push(self.root_output.clone());
130107
search_path.push(self.deps_output.clone());
131108
search_path

src/cargo/ops/cargo_rustc/context.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,11 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
336336
self.host.deps()
337337
}
338338

339+
/// Return the root of the build output tree
340+
pub fn target_root(&self) -> &Path {
341+
self.host.dest()
342+
}
343+
339344
/// Returns the appropriate output directory for the specified package and
340345
/// target.
341346
pub fn out_dir(&mut self, unit: &Unit) -> PathBuf {

src/cargo/ops/cargo_rustc/custom_build.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>)
181181
fs::create_dir_all(&script_output)?;
182182
fs::create_dir_all(&build_output)?;
183183

184+
let root_output = cx.target_root().to_path_buf();
185+
184186
// Prepare the unit of "dirty work" which will actually run the custom build
185187
// command.
186188
//
@@ -218,7 +220,8 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>)
218220
}
219221
if let Some(build_scripts) = build_scripts {
220222
super::add_plugin_deps(&mut cmd, &build_state,
221-
&build_scripts)?;
223+
&build_scripts,
224+
&root_output)?;
222225
}
223226
}
224227

src/cargo/ops/cargo_rustc/mod.rs

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,8 @@ fn rustc(cx: &mut Context, unit: &Unit, exec: Arc<Executor>) -> CargoResult<Work
297297
exec.init(cx);
298298
let exec = exec.clone();
299299

300+
let root_output = cx.target_root().to_path_buf();
301+
300302
return Ok(Work::new(move |state| {
301303
// Only at runtime have we discovered what the extra -L and -l
302304
// arguments are for native libraries, so we process those here. We
@@ -307,7 +309,8 @@ fn rustc(cx: &mut Context, unit: &Unit, exec: Arc<Executor>) -> CargoResult<Work
307309
let build_state = build_state.outputs.lock().unwrap();
308310
add_native_deps(&mut rustc, &build_state, &build_deps,
309311
pass_l_flag, &current_id)?;
310-
add_plugin_deps(&mut rustc, &build_state, &build_deps)?;
312+
add_plugin_deps(&mut rustc, &build_state, &build_deps,
313+
&root_output)?;
311314
}
312315

313316
// FIXME(rust-lang/rust#18913): we probably shouldn't have to do
@@ -492,7 +495,8 @@ fn load_build_deps(cx: &Context, unit: &Unit) -> Option<Arc<BuildScripts>> {
492495
// execute.
493496
fn add_plugin_deps(rustc: &mut ProcessBuilder,
494497
build_state: &BuildMap,
495-
build_scripts: &BuildScripts)
498+
build_scripts: &BuildScripts,
499+
root_output: &PathBuf)
496500
-> CargoResult<()> {
497501
let var = util::dylib_path_envvar();
498502
let search_path = rustc.get_env(var).unwrap_or(OsString::new());
@@ -502,15 +506,47 @@ fn add_plugin_deps(rustc: &mut ProcessBuilder,
502506
let output = build_state.get(&key).chain_error(|| {
503507
internal(format!("couldn't find libs for plugin dep {}", id))
504508
})?;
505-
for path in output.library_paths.iter() {
506-
search_path.push(path.clone());
507-
}
509+
search_path.append(&mut filter_dynamic_search_path(output.library_paths.iter(),
510+
root_output));
508511
}
509512
let search_path = join_paths(&search_path, var)?;
510513
rustc.env(var, &search_path);
511514
Ok(())
512515
}
513516

517+
// Determine paths to add to the dynamic search path from -L entries
518+
//
519+
// Strip off prefixes like "native=" or "framework=" and filter out directories
520+
// *not* inside our output directory since they are likely spurious and can cause
521+
// clashes with system shared libraries (issue #3366).
522+
fn filter_dynamic_search_path<'a, I>(paths :I, root_output: &PathBuf) -> Vec<PathBuf>
523+
where I: Iterator<Item=&'a PathBuf> {
524+
let mut search_path = vec![];
525+
for dir in paths {
526+
let dir = match dir.to_str() {
527+
Some(s) => {
528+
let mut parts = s.splitn(2, '=');
529+
match (parts.next(), parts.next()) {
530+
(Some("native"), Some(path)) |
531+
(Some("crate"), Some(path)) |
532+
(Some("dependency"), Some(path)) |
533+
(Some("framework"), Some(path)) |
534+
(Some("all"), Some(path)) => path.into(),
535+
_ => dir.clone(),
536+
}
537+
}
538+
None => dir.clone(),
539+
};
540+
if dir.starts_with(&root_output) {
541+
search_path.push(dir);
542+
} else {
543+
debug!("Not including path {} in runtime library search path because it is \
544+
outside target root {}", dir.display(), root_output.display());
545+
}
546+
}
547+
search_path
548+
}
549+
514550
fn prepare_rustc(cx: &mut Context,
515551
crate_types: Vec<&str>,
516552
unit: &Unit) -> CargoResult<ProcessBuilder> {

tests/build-script.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,7 +1131,15 @@ fn test_dev_dep_build_script() {
11311131

11321132
#[test]
11331133
fn build_script_with_dynamic_native_dependency() {
1134-
let build = project("builder")
1134+
1135+
let workspace = project("ws")
1136+
.file("Cargo.toml", r#"
1137+
[workspace]
1138+
members = ["builder", "foo"]
1139+
"#);
1140+
workspace.build();
1141+
1142+
let build = project("ws/builder")
11351143
.file("Cargo.toml", r#"
11361144
[package]
11371145
name = "builder"
@@ -1147,11 +1155,9 @@ fn build_script_with_dynamic_native_dependency() {
11471155
#[no_mangle]
11481156
pub extern fn foo() {}
11491157
"#);
1150-
assert_that(build.cargo_process("build").arg("-v")
1151-
.env("RUST_LOG", "cargo::ops::cargo_rustc"),
1152-
execs().with_status(0));
1158+
build.build();
11531159

1154-
let foo = project("foo")
1160+
let foo = project("ws/foo")
11551161
.file("Cargo.toml", r#"
11561162
[package]
11571163
name = "foo"
@@ -1180,7 +1186,7 @@ fn build_script_with_dynamic_native_dependency() {
11801186
11811187
fn main() {
11821188
let src = PathBuf::from(env::var("SRC").unwrap());
1183-
println!("cargo:rustc-link-search={}/target/debug/deps",
1189+
println!("cargo:rustc-link-search=native={}/target/debug/deps",
11841190
src.display());
11851191
}
11861192
"#)
@@ -1192,8 +1198,13 @@ fn build_script_with_dynamic_native_dependency() {
11921198
unsafe { foo() }
11931199
}
11941200
"#);
1201+
foo.build();
1202+
1203+
assert_that(build.cargo("build").arg("-v")
1204+
.env("RUST_LOG", "cargo::ops::cargo_rustc"),
1205+
execs().with_status(0));
11951206

1196-
assert_that(foo.cargo_process("build").arg("-v").env("SRC", build.root())
1207+
assert_that(foo.cargo("build").arg("-v").env("SRC", build.root())
11971208
.env("RUST_LOG", "cargo::ops::cargo_rustc"),
11981209
execs().with_status(0));
11991210
}

tests/plugins.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,14 @@ fn plugin_to_the_max() {
9090
fn plugin_with_dynamic_native_dependency() {
9191
if !is_nightly() { return }
9292

93-
let build = project("builder")
93+
let workspace = project("ws")
94+
.file("Cargo.toml", r#"
95+
[workspace]
96+
members = ["builder", "foo"]
97+
"#);
98+
workspace.build();
99+
100+
let build = project("ws/builder")
94101
.file("Cargo.toml", r#"
95102
[package]
96103
name = "builder"
@@ -105,16 +112,9 @@ fn plugin_with_dynamic_native_dependency() {
105112
#[no_mangle]
106113
pub extern fn foo() {}
107114
"#);
108-
assert_that(build.cargo_process("build"),
109-
execs().with_status(0));
110-
let src = build.root().join("target/debug");
111-
let lib = fs::read_dir(&src).unwrap().map(|s| s.unwrap().path()).find(|lib| {
112-
let lib = lib.file_name().unwrap().to_str().unwrap();
113-
lib.starts_with(env::consts::DLL_PREFIX) &&
114-
lib.ends_with(env::consts::DLL_SUFFIX)
115-
}).unwrap();
115+
build.build();
116116

117-
let foo = project("foo")
117+
let foo = project("ws/foo")
118118
.file("Cargo.toml", r#"
119119
[package]
120120
name = "foo"
@@ -165,8 +165,19 @@ fn plugin_with_dynamic_native_dependency() {
165165
unsafe { foo() }
166166
}
167167
"#);
168+
foo.build();
169+
170+
assert_that(build.cargo("build"),
171+
execs().with_status(0));
172+
173+
let src = workspace.root().join("target/debug");
174+
let lib = fs::read_dir(&src).unwrap().map(|s| s.unwrap().path()).find(|lib| {
175+
let lib = lib.file_name().unwrap().to_str().unwrap();
176+
lib.starts_with(env::consts::DLL_PREFIX) &&
177+
lib.ends_with(env::consts::DLL_SUFFIX)
178+
}).unwrap();
168179

169-
assert_that(foo.cargo_process("build").env("SRC", &lib).arg("-v"),
180+
assert_that(foo.cargo("build").env("SRC", &lib).arg("-v"),
170181
execs().with_status(0));
171182
}
172183

0 commit comments

Comments
 (0)