diff --git a/src/cargo/ops/cargo_rustc/context.rs b/src/cargo/ops/cargo_rustc/context.rs index 6ee234b2a9b..35714b16384 100644 --- a/src/cargo/ops/cargo_rustc/context.rs +++ b/src/cargo/ops/cargo_rustc/context.rs @@ -3,6 +3,7 @@ use std::str; use core::{SourceMap, Package, PackageId, PackageSet, Resolve, Target}; use util::{mod, CargoResult, ChainError, internal, Config, profile, Require}; +use util::human; use super::{Kind, KindPlugin, KindTarget, Compilation}; use super::layout::{Layout, LayoutProxy}; @@ -26,9 +27,10 @@ pub struct Context<'a, 'b> { host: Layout, target: Option, target_triple: String, - host_dylib: (String, String), + host_triple: String, + host_dylib: Option<(String, String)>, package_set: &'a PackageSet, - target_dylib: (String, String), + target_dylib: Option<(String, String)>, target_exe: String, requirements: HashMap<(&'a PackageId, &'a str), PlatformRequirement>, } @@ -48,10 +50,11 @@ impl<'a, 'b> Context<'a, 'b> { }; let (rustc_version, rustc_host) = try!(Context::rustc_version()); let target_triple = config.target().map(|s| s.to_string()); - let target_triple = target_triple.unwrap_or(rustc_host); + let target_triple = target_triple.unwrap_or(rustc_host.clone()); Ok(Context { rustc_version: rustc_version, target_triple: target_triple, + host_triple: rustc_host, env: env, host: host, target: target, @@ -93,7 +96,7 @@ impl<'a, 'b> Context<'a, 'b> { /// Run `rustc` to discover the dylib prefix/suffix for the target /// specified as well as the exe suffix fn filename_parts(target: Option<&str>) - -> CargoResult<((String, String), String)> { + -> CargoResult<(Option<(String, String)>, String)> { let process = util::process("rustc") .arg("-") .arg("--crate-name").arg("-") @@ -106,17 +109,22 @@ impl<'a, 'b> Context<'a, 'b> { }; let output = try!(process.exec_with_output()); + let error = str::from_utf8(output.error.as_slice()).unwrap(); let output = str::from_utf8(output.output.as_slice()).unwrap(); let mut lines = output.lines(); - let dylib_parts: Vec<&str> = lines.next().unwrap().trim() - .split('-').collect(); - assert!(dylib_parts.len() == 2, - "rustc --print-file-name output has changed"); + let dylib = if error.contains("dropping unsupported crate type `dylib`") { + None + } else { + let dylib_parts: Vec<&str> = lines.next().unwrap().trim() + .split('-').collect(); + assert!(dylib_parts.len() == 2, + "rustc --print-file-name output has changed"); + Some((dylib_parts[0].to_string(), dylib_parts[1].to_string())) + }; + let exe_suffix = lines.next().unwrap().trim() .split('-').skip(1).next().unwrap().to_string(); - - Ok(((dylib_parts[0].to_string(), dylib_parts[1].to_string()), - exe_suffix.to_string())) + Ok((dylib, exe_suffix.to_string())) } /// Prepare this context, ensuring that all filesystem directories are in @@ -193,9 +201,17 @@ impl<'a, 'b> Context<'a, 'b> { /// /// If `plugin` is true, the pair corresponds to the host platform, /// otherwise it corresponds to the target platform. - fn dylib(&self, kind: Kind) -> (&str, &str) { - let pair = if kind == KindPlugin {&self.host_dylib} else {&self.target_dylib}; - (pair.ref0().as_slice(), pair.ref1().as_slice()) + fn dylib(&self, kind: Kind) -> CargoResult<(&str, &str)> { + let (triple, pair) = if kind == KindPlugin { + (&self.host_triple, &self.host_dylib) + } else { + (&self.target_triple, &self.target_dylib) + }; + match *pair { + None => return Err(human(format!("dylib outputs are not supported \ + for {}", triple))), + Some((ref s1, ref s2)) => Ok((s1.as_slice(), s2.as_slice())), + } } /// Return the target triple which this context is targeting. @@ -204,7 +220,7 @@ impl<'a, 'b> Context<'a, 'b> { } /// Return the exact filename of the target. - pub fn target_filenames(&self, target: &Target) -> Vec { + pub fn target_filenames(&self, target: &Target) -> CargoResult> { let stem = target.file_stem(); let mut ret = Vec::new(); @@ -214,7 +230,7 @@ impl<'a, 'b> Context<'a, 'b> { if target.is_dylib() { let plugin = target.get_profile().is_plugin(); let kind = if plugin {KindPlugin} else {KindTarget}; - let (prefix, suffix) = self.dylib(kind); + let (prefix, suffix) = try!(self.dylib(kind)); ret.push(format!("{}{}{}", prefix, stem, suffix)); } if target.is_rlib() { @@ -225,7 +241,7 @@ impl<'a, 'b> Context<'a, 'b> { } } assert!(ret.len() > 0); - return ret; + return Ok(ret); } /// For a package, return all targets which are registered as dependencies diff --git a/src/cargo/ops/cargo_rustc/fingerprint.rs b/src/cargo/ops/cargo_rustc/fingerprint.rs index 323150f0129..aebb93ff60c 100644 --- a/src/cargo/ops/cargo_rustc/fingerprint.rs +++ b/src/cargo/ops/cargo_rustc/fingerprint.rs @@ -73,7 +73,7 @@ pub fn prepare_target(cx: &mut Context, pkg: &Package, target: &Target, if !target.get_profile().is_doc() { pairs.push((old_dep_info, new_dep_info)); - for filename in cx.target_filenames(target).iter() { + for filename in try!(cx.target_filenames(target)).iter() { let filename = filename.as_slice(); let dst = root.join(filename); pairs.push((old_root.join(filename), root.join(filename))); diff --git a/src/cargo/ops/cargo_rustc/mod.rs b/src/cargo/ops/cargo_rustc/mod.rs index 6b725426738..93510285390 100644 --- a/src/cargo/ops/cargo_rustc/mod.rs +++ b/src/cargo/ops/cargo_rustc/mod.rs @@ -135,10 +135,10 @@ fn compile<'a, 'b>(targets: &[&'a Target], pkg: &'a Package, let (mut libs, mut bins) = (Vec::new(), Vec::new()); for &target in targets.iter() { let work = if target.get_profile().is_doc() { - vec![(rustdoc(pkg, target, cx), KindTarget)] + vec![(try!(rustdoc(pkg, target, cx)), KindTarget)] } else { let req = cx.get_requirement(pkg, target); - rustc(pkg, target, cx, req) + try!(rustc(pkg, target, cx, req)) }; let dst = if target.is_lib() {&mut libs} else {&mut bins}; @@ -188,7 +188,8 @@ fn compile_custom(pkg: &Package, cmd: &str, } fn rustc(package: &Package, target: &Target, - cx: &mut Context, req: PlatformRequirement) -> Vec<(Work, Kind)> { + cx: &mut Context, req: PlatformRequirement) + -> CargoResult >{ let crate_types = target.rustc_crate_types(); let root = package.get_root(); @@ -196,7 +197,7 @@ fn rustc(package: &Package, target: &Target, root.display(), target, crate_types, cx.primary, req); let primary = cx.primary; - let rustcs = prepare_rustc(package, target, crate_types, cx, req); + let rustcs = try!(prepare_rustc(package, target, crate_types, cx, req)); let _ = cx.config.shell().verbose(|shell| { for &(ref rustc, _) in rustcs.iter() { @@ -205,7 +206,7 @@ fn rustc(package: &Package, target: &Target, Ok(()) }); - rustcs.move_iter().map(|(rustc, kind)| { + Ok(rustcs.move_iter().map(|(rustc, kind)| { let name = package.get_name().to_string(); (proc() { @@ -223,32 +224,35 @@ fn rustc(package: &Package, target: &Target, } Ok(()) }, kind) - }).collect() + }).collect()) } fn prepare_rustc(package: &Package, target: &Target, crate_types: Vec<&str>, cx: &Context, req: PlatformRequirement) - -> Vec<(ProcessBuilder, Kind)> { + -> CargoResult> { let base = process("rustc", package, cx); let base = build_base_args(base, target, crate_types.as_slice()); let target_cmd = build_plugin_args(base.clone(), cx, package, target, KindTarget); let plugin_cmd = build_plugin_args(base, cx, package, target, KindPlugin); - let target_cmd = build_deps_args(target_cmd, target, package, cx, KindTarget); - let plugin_cmd = build_deps_args(plugin_cmd, target, package, cx, KindPlugin); + let target_cmd = try!(build_deps_args(target_cmd, target, package, cx, + KindTarget)); + let plugin_cmd = try!(build_deps_args(plugin_cmd, target, package, cx, + KindPlugin)); - match req { + Ok(match req { Target => vec![(target_cmd, KindTarget)], Plugin => vec![(plugin_cmd, KindPlugin)], PluginAndTarget if cx.config.target().is_none() => vec![(target_cmd, KindTarget)], PluginAndTarget => vec![(target_cmd, KindTarget), (plugin_cmd, KindPlugin)], - } + }) } -fn rustdoc(package: &Package, target: &Target, cx: &mut Context) -> Work { +fn rustdoc(package: &Package, target: &Target, + cx: &mut Context) -> CargoResult { let kind = KindTarget; let pkg_root = package.get_root(); let cx_root = cx.layout(kind).proxy().dest().join("doc"); @@ -256,7 +260,7 @@ fn rustdoc(package: &Package, target: &Target, cx: &mut Context) -> Work { let rustdoc = rustdoc.arg(target.get_src_path()) .arg("-o").arg(cx_root) .arg("--crate-name").arg(target.get_name()); - let rustdoc = build_deps_args(rustdoc, target, package, cx, kind); + let rustdoc = try!(build_deps_args(rustdoc, target, package, cx, kind)); log!(5, "commands={}", rustdoc); @@ -266,7 +270,7 @@ fn rustdoc(package: &Package, target: &Target, cx: &mut Context) -> Work { let primary = cx.primary; let name = package.get_name().to_string(); - proc() { + Ok(proc() { if primary { try!(rustdoc.exec().chain_error(|| { human(format!("Could not document `{}`.", name)) @@ -278,7 +282,7 @@ fn rustdoc(package: &Package, target: &Target, cx: &mut Context) -> Work { })) } Ok(()) - } + }) } fn build_base_args(mut cmd: ProcessBuilder, @@ -355,7 +359,8 @@ fn build_plugin_args(mut cmd: ProcessBuilder, cx: &Context, pkg: &Package, } fn build_deps_args(mut cmd: ProcessBuilder, target: &Target, package: &Package, - cx: &Context, kind: Kind) -> ProcessBuilder { + cx: &Context, + kind: Kind) -> CargoResult { enum LinkReason { Dependency, LocalLib } let layout = cx.layout(kind); @@ -367,7 +372,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, kind, Dependency); + cmd = try!(link_to(cmd, target, cx, kind, Dependency)); } let mut targets = package.get_targets().iter().filter(|target| { @@ -376,14 +381,15 @@ 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, kind, LocalLib); + cmd = try!(link_to(cmd, target, cx, kind, LocalLib)); } } - return cmd; + return Ok(cmd); fn link_to(mut cmd: ProcessBuilder, target: &Target, - cx: &Context, kind: Kind, reason: LinkReason) -> ProcessBuilder { + cx: &Context, kind: Kind, + reason: LinkReason) -> CargoResult { // 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). @@ -393,7 +399,7 @@ fn build_deps_args(mut cmd: ProcessBuilder, target: &Target, package: &Package, KindTarget => KindTarget, }); - for filename in cx.target_filenames(target).iter() { + for filename in try!(cx.target_filenames(target)).iter() { let mut v = Vec::new(); v.push_all(target.get_name().as_bytes()); v.push(b'='); @@ -405,7 +411,7 @@ fn build_deps_args(mut cmd: ProcessBuilder, target: &Target, package: &Package, v.push_all(filename.as_bytes()); cmd = cmd.arg("--extern").arg(v.as_slice()); } - return cmd; + return Ok(cmd); } fn push_native_dirs(mut cmd: ProcessBuilder, layout: &layout::LayoutProxy, diff --git a/tests/test_cargo_cross_compile.rs b/tests/test_cargo_cross_compile.rs index 35b702a8239..ab5c2ec5915 100644 --- a/tests/test_cargo_cross_compile.rs +++ b/tests/test_cargo_cross_compile.rs @@ -456,3 +456,22 @@ test!(simple_cargo_run { assert_that(p.cargo_process("run").arg("--target").arg(target), execs().with_status(0)); }) + +test!(cross_but_no_dylibs { + let p = project("foo") + .file("Cargo.toml", r#" + [package] + name = "foo" + version = "0.0.0" + authors = [] + + [lib] + name = "foo" + crate-type = ["dylib"] + "#) + .file("src/lib.rs", ""); + assert_that(p.cargo_process("build").arg("--target").arg("arm-apple-ios"), + execs().with_status(101) + .with_stderr("dylib outputs are not supported for \ + arm-apple-ios")); +})