Invoke rustc only once for multiple crate types
authorAlex Crichton <alex@alexcrichton.com>
Thu, 19 Jun 2014 22:21:00 +0000 (15:21 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Fri, 20 Jun 2014 02:44:45 +0000 (19:44 -0700)
src/cargo/ops/cargo_rustc.rs
tests/test_cargo_compile.rs

index d89b389add95fcaf0c0bbc04edb42a761590ad31..82f0492afcd096d77e2c4e88743ee92a89740809 100644 (file)
@@ -75,28 +75,26 @@ fn rustc(root: &Path, target: &Target, dest: &Path, deps: &Path,
 
     let crate_types = target.rustc_crate_types();
 
-    for crate_type in crate_types.iter() {
-        log!(5, "root={}; target={}; crate_type={}; dest={}; deps={}; verbose={}",
-             root.display(), target, crate_type, dest.display(), deps.display(),
-             verbose);
+    log!(5, "root={}; target={}; crate_types={}; dest={}; deps={}; verbose={}",
+         root.display(), target, crate_types, dest.display(), deps.display(),
+         verbose);
 
-        let rustc = prepare_rustc(root, target, *crate_type, dest, deps);
+    let rustc = prepare_rustc(root, target, crate_types, dest, deps);
 
-        try!(if verbose {
-            rustc.exec().map_err(|err| human(err.to_str()))
-        } else {
-            rustc.exec_with_output().and(Ok(())).map_err(|err| human(err.to_str()))
-        });
-    }
+    try!(if verbose {
+        rustc.exec().map_err(|err| human(err.to_str()))
+    } else {
+        rustc.exec_with_output().and(Ok(())).map_err(|err| human(err.to_str()))
+    });
 
     Ok(())
 }
 
-fn prepare_rustc(root: &Path, target: &Target, crate_type: &'static str,
+fn prepare_rustc(root: &Path, target: &Target, crate_types: Vec<&str>,
                  dest: &Path, deps: &Path) -> ProcessBuilder {
     let mut args = Vec::new();
 
-    build_base_args(&mut args, target, crate_type, dest);
+    build_base_args(&mut args, target, crate_types, dest);
     build_deps_args(&mut args, dest, deps);
 
     util::process("rustc")
@@ -105,12 +103,14 @@ fn prepare_rustc(root: &Path, target: &Target, crate_type: &'static str,
         .env("RUST_LOG", None) // rustc is way too noisy
 }
 
-fn build_base_args(into: &mut Args, target: &Target, crate_type: &'static str,
+fn build_base_args(into: &mut Args, target: &Target, crate_types: Vec<&str>,
                    dest: &Path) {
     // TODO: Handle errors in converting paths into args
     into.push(target.get_path().display().to_str());
-    into.push("--crate-type".to_str());
-    into.push(crate_type.to_str());
+    for crate_type in crate_types.iter() {
+        into.push("--crate-type".to_str());
+        into.push(crate_type.to_str());
+    }
     into.push("--out-dir".to_str());
     into.push(dest.display().to_str());
 }
index 62f4e1190d13b7bd563d6a4c4dd95d31e0d6d82d..9dd6e3014e0ac2b1539535f3a05a5a27eb8d2039 100644 (file)
@@ -1,3 +1,6 @@
+use std::io::fs;
+use std::os;
+
 use support::{ResultTest,project,execs,main_file};
 use hamcrest::{assert_that,existing_file};
 use cargo;
@@ -488,3 +491,39 @@ test!(custom_build_in_dependency {
     assert_that(p.cargo_process("cargo-compile"),
                 execs().with_status(0));
 })
+
+test!(many_crate_types {
+    let mut p = project("foo");
+    p = p
+        .file("Cargo.toml", r#"
+            [project]
+
+            name = "foo"
+            version = "0.5.0"
+            authors = ["wycats@example.com"]
+
+            [[lib]]
+
+            name = "foo"
+            crate_type = ["rlib", "dylib"]
+        "#)
+        .file("src/foo.rs", r#"
+            pub fn foo() {}
+        "#);
+    assert_that(p.cargo_process("cargo-compile"),
+                execs().with_status(0));
+
+    let files = fs::readdir(&p.root().join("target")).assert();
+    let mut files: Vec<String> = files.iter().filter_map(|f| {
+        match f.filename_str().unwrap() {
+            "deps" => None,
+            s => Some(s.to_str())
+        }
+    }).collect();
+    files.sort();
+    let file0 = files.get(0).as_slice();
+    let file1 = files.get(1).as_slice();
+    assert!(file0.ends_with(".rlib") || file1.ends_with(".rlib"));
+    assert!(file0.ends_with(os::consts::DLL_SUFFIX) ||
+            file1.ends_with(os::consts::DLL_SUFFIX));
+})