From 6f2173dc9f61074a7277c599fd1f3047b1aad9dd Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 28 Jul 2014 17:08:46 -0700 Subject: [PATCH] Fix some dep errors with cross-compiled plugins * Make sure plugins link to plugin dependencies, not target dependencies. Previously the --extern flag was being passed incorrectly but the dependency was being picked up by -L anyway. * Fix a type and actually put the host dep directory into LD_LIBRARY_PATH, not the target directory. A test was added for this change. --- src/cargo/ops/cargo_rustc/mod.rs | 23 ++++++----- tests/test_cargo_cross_compile.rs | 64 +++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 9 deletions(-) diff --git a/src/cargo/ops/cargo_rustc/mod.rs b/src/cargo/ops/cargo_rustc/mod.rs index 9c5535b15..1b94648d8 100644 --- a/src/cargo/ops/cargo_rustc/mod.rs +++ b/src/cargo/ops/cargo_rustc/mod.rs @@ -335,6 +335,8 @@ fn build_plugin_args(mut cmd: ProcessBuilder, cx: &Context, fn build_deps_args(mut cmd: ProcessBuilder, target: &Target, package: &Package, cx: &Context, plugin: bool) -> ProcessBuilder { + enum LinkReason { Dependency, LocalLib } + let layout = cx.layout(plugin); cmd = cmd.arg("-L").arg(layout.root()); cmd = cmd.arg("-L").arg(layout.deps()); @@ -344,7 +346,7 @@ fn build_deps_args(mut cmd: ProcessBuilder, target: &Target, package: &Package, cmd = push_native_dirs(cmd, &layout, package, cx, &mut HashSet::new()); for &(_, target) in cx.dep_targets(package).iter() { - cmd = link_to(cmd, target, cx, true); + cmd = link_to(cmd, target, cx, plugin, Dependency); } let mut targets = package.get_targets().iter().filter(|target| { @@ -353,23 +355,26 @@ fn build_deps_args(mut cmd: ProcessBuilder, target: &Target, package: &Package, if target.is_bin() { for target in targets { - cmd = link_to(cmd, target, cx, false); + cmd = link_to(cmd, target, cx, plugin, LocalLib); } } return cmd; fn link_to(mut cmd: ProcessBuilder, target: &Target, - cx: &Context, is_dep_lib: bool) -> ProcessBuilder { - let layout = cx.layout(target.get_profile().is_plugin()); + cx: &Context, plugin: bool, reason: LinkReason) -> ProcessBuilder { + // If this target is itself a plugin *or* if it's being linked to a + // plugin, then we want the plugin directory. Otherwise we want the + // target directory (hence the || here). + let layout = cx.layout(plugin || target.get_profile().is_plugin()); + for filename in cx.target_filenames(target).iter() { let mut v = Vec::new(); v.push_all(target.get_name().as_bytes()); v.push(b'='); - if is_dep_lib { - v.push_all(layout.deps().as_vec()); - } else { - v.push_all(layout.root().as_vec()); + match reason { + Dependency => v.push_all(layout.deps().as_vec()), + LocalLib => v.push_all(layout.root().as_vec()), } v.push(b'/'); v.push_all(filename.as_bytes()); @@ -403,7 +408,7 @@ pub fn process(cmd: T, pkg: &Package, cx: &Context) -> ProcessBuilder // When invoking a tool, we need the *host* deps directory in the dynamic // library search path for plugins and such which have dynamic dependencies. let mut search_path = DynamicLibrary::search_path(); - search_path.push(cx.layout(false).deps().clone()); + search_path.push(cx.layout(true).deps().clone()); let search_path = os::join_paths(search_path.as_slice()).unwrap(); util::process(cmd) diff --git a/tests/test_cargo_cross_compile.rs b/tests/test_cargo_cross_compile.rs index e7978e2a1..7e2fe4d7e 100644 --- a/tests/test_cargo_cross_compile.rs +++ b/tests/test_cargo_cross_compile.rs @@ -268,3 +268,67 @@ test!(linker_and_ar { sep = path::SEP, ).as_slice())); }) + +test!(plugin_with_extra_dylib_dep { + let foo = project("foo") + .file("Cargo.toml", r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + + [dependencies.bar] + path = "../bar" + "#) + .file("src/main.rs", r#" + #![feature(phase)] + #[phase(plugin)] extern crate bar; + + fn main() {} + "#); + let bar = project("bar") + .file("Cargo.toml", r#" + [package] + name = "bar" + version = "0.0.1" + authors = [] + + [[lib]] + name = "bar" + plugin = true + + [dependencies.baz] + path = "../baz" + "#) + .file("src/lib.rs", r#" + #![feature(plugin_registrar)] + + extern crate rustc; + extern crate baz; + + use rustc::plugin::Registry; + + #[plugin_registrar] + pub fn foo(reg: &mut Registry) { + println!("{}", baz::baz()); + } + "#); + let baz = project("baz") + .file("Cargo.toml", r#" + [package] + name = "baz" + version = "0.0.1" + authors = [] + + [[lib]] + name = "baz" + crate_type = ["dylib"] + "#) + .file("src/lib.rs", "pub fn baz() -> int { 1 }"); + bar.build(); + baz.build(); + + let target = alternate(); + assert_that(foo.cargo_process("cargo-build").arg("--target").arg(target), + execs().with_status(0)); +})