Allow multiple and non-default crate_types
authorCarl Lerche + Yehuda Katz <engineering@tilde.io>
Fri, 13 Jun 2014 00:49:10 +0000 (17:49 -0700)
committerTim Carey-Smith <tim@spork.in>
Fri, 13 Jun 2014 00:49:10 +0000 (17:49 -0700)
Note that at present there is no good error handling for fat-fingering
the crate type. This is a TODO.

src/cargo/core/manifest.rs
src/cargo/ops/cargo_rustc.rs
src/cargo/sources/git/source.rs
src/cargo/util/toml.rs

index d5d459c6b43edafb5e08507f435a11c11b4340de..6b9d1b57b1b17e45354e03c4a6d8145a81fbfbd8 100644 (file)
@@ -1,3 +1,4 @@
+use std::result;
 use std::fmt;
 use std::fmt::{Show,Formatter};
 use semver::Version;
@@ -9,6 +10,7 @@ use core::{
     Summary
 };
 use core::dependency::SerializedDependency;
+use util::{CargoResult,simple_human};
 
 #[deriving(PartialEq,Clone)]
 pub struct Manifest {
@@ -48,9 +50,42 @@ impl<E, S: Encoder<E>> Encodable<S, E> for Manifest {
     }
 }
 
+#[deriving(Show,Clone,PartialEq,Encodable)]
+pub enum LibKind {
+    Lib,
+    Rlib,
+    Dylib,
+    StaticLib
+}
+
+impl LibKind {
+    pub fn from_str(string: &str) -> CargoResult<LibKind> {
+        match string {
+            "lib" => Ok(Lib),
+            "rlib" => Ok(Rlib),
+            "dylib" => Ok(Dylib),
+            "staticlib" => Ok(StaticLib),
+            _ => Err(simple_human(format!("{} was not one of lib|rlib|dylib|staticlib", string)))
+        }
+    }
+
+    pub fn from_strs<S: Str>(strings: Vec<S>) -> CargoResult<Vec<LibKind>> {
+        result::collect(strings.iter().map(|s| LibKind::from_str(s.as_slice())))
+    }
+
+    pub fn crate_type(&self) -> &'static str {
+        match *self {
+            Lib => "lib",
+            Rlib => "rlib",
+            Dylib => "dylib",
+            StaticLib => "staticlib"
+        }
+    }
+}
+
 #[deriving(Show,Clone,PartialEq,Encodable)]
 pub enum TargetKind {
-    LibTarget,
+    LibTarget(Vec<LibKind>),
     BinTarget
 }
 
@@ -63,7 +98,7 @@ pub struct Target {
 
 #[deriving(Encodable)]
 pub struct SerializedTarget {
-    kind: &'static str,
+    kind: Vec<&'static str>,
     name: String,
     path: String
 }
@@ -71,8 +106,8 @@ pub struct SerializedTarget {
 impl<E, S: Encoder<E>> Encodable<S, E> for Target {
     fn encode(&self, s: &mut S) -> Result<(), E> {
         let kind = match self.kind {
-            LibTarget => "lib",
-            BinTarget => "bin"
+            LibTarget(ref kinds) => kinds.iter().map(|k| k.crate_type()).collect(),
+            BinTarget => vec!("bin")
         };
 
         SerializedTarget {
@@ -138,9 +173,9 @@ impl Manifest {
 }
 
 impl Target {
-    pub fn lib_target(name: &str, path: &Path) -> Target {
+    pub fn lib_target(name: &str, crate_targets: Vec<LibKind>, path: &Path) -> Target {
         Target {
-            kind: LibTarget,
+            kind: LibTarget(crate_targets),
             name: name.to_str(),
             path: path.clone()
         }
@@ -160,7 +195,7 @@ impl Target {
 
     pub fn is_lib(&self) -> bool {
         match self.kind {
-            LibTarget => true,
+            LibTarget(_) => true,
             _ => false
         }
     }
@@ -172,10 +207,12 @@ impl Target {
         }
     }
 
-    pub fn rustc_crate_type(&self) -> &'static str {
+    pub fn rustc_crate_types(&self) -> Vec<&'static str> {
         match self.kind {
-            LibTarget => "lib",
-            BinTarget => "bin"
+            LibTarget(ref kinds) => {
+                kinds.iter().map(|kind| kind.crate_type()).collect()
+            },
+            BinTarget => vec!("bin")
         }
     }
 }
index 957302f7d7490aaecaef0ab3fc74059cbf433ad6..2d38610c5a8f252b2cfa0286336080c867fae07b 100644 (file)
@@ -52,23 +52,29 @@ fn mk_target(target: &Path) -> CargoResult<()> {
 }
 
 fn rustc(root: &Path, target: &Target, dest: &Path, deps: &Path, verbose: bool) -> CargoResult<()> {
-    log!(5, "root={}; target={}; dest={}; deps={}; verbose={}", root.display(), target, dest.display(), deps.display(), verbose);
 
-    let rustc = prepare_rustc(root, target, dest, deps);
+    let crate_types = target.rustc_crate_types();
 
-    try!((if verbose {
-        rustc.exec()
-    } else {
-        rustc.exec_with_output().and(Ok(()))
-    }).map_err(|e| rustc_to_cargo_err(rustc.get_args().as_slice(), root, e)));
+    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);
+
+        let rustc = prepare_rustc(root, target, *crate_type, dest, deps);
+
+        try!((if verbose {
+            rustc.exec()
+        } else {
+            rustc.exec_with_output().and(Ok(()))
+        }).map_err(|e| rustc_to_cargo_err(rustc.get_args().as_slice(), root, e)));
+    }
 
     Ok(())
 }
 
-fn prepare_rustc(root: &Path, target: &Target, dest: &Path, deps: &Path) -> ProcessBuilder {
+fn prepare_rustc(root: &Path, target: &Target, crate_type: &'static str, dest: &Path, deps: &Path) -> ProcessBuilder {
     let mut args = Vec::new();
 
-    build_base_args(&mut args, target, dest);
+    build_base_args(&mut args, target, crate_type, dest);
     build_deps_args(&mut args, deps);
 
     util::process("rustc")
@@ -77,11 +83,11 @@ fn prepare_rustc(root: &Path, target: &Target, dest: &Path, deps: &Path) -> Proc
         .env("RUST_LOG", None) // rustc is way too noisy
 }
 
-fn build_base_args(into: &mut Args, target: &Target, dest: &Path) {
+fn build_base_args(into: &mut Args, target: &Target, crate_type: &'static 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(target.rustc_crate_type().to_str());
+    into.push(crate_type.to_str());
     into.push("--out-dir".to_str());
     into.push(dest.display().to_str());
 }
index a3872be8e17223fdaf2fcba25b30f1939100da0c..12c68af8bc865f78e09856f1fac9e6dcdb96146a 100644 (file)
@@ -37,6 +37,7 @@ impl Show for GitSource {
 
 impl Source for GitSource {
     fn update(&self) -> CargoResult<()> {
+        println!("Updating git repository `{}`", self.remote.get_url());
         log!(5, "updating git source `{}`", self.remote);
         let repo = try!(self.remote.checkout(&self.db_path));
         try!(repo.copy_to(self.reference.as_slice(), &self.checkout_path));
index bb05837cfac52261aa1a2e5dd57f1ddd03fb6393..57f1f67b173135ad3d166fbd0fcea834ca04bc0c 100644 (file)
@@ -5,6 +5,7 @@ use std::collections::HashMap;
 use serialize::Decodable;
 
 use core::source::{SourceId,GitKind};
+use core::manifest::{LibKind,Lib};
 use core::{Summary,Manifest,Target,Dependency,PackageId};
 use util::{CargoResult,Require,simple_human,toml_error};
 
@@ -159,6 +160,7 @@ impl TomlManifest {
 #[deriving(Decodable,Encodable,PartialEq,Clone,Show)]
 struct TomlTarget {
     name: String,
+    crate_type: Option<Vec<String>>,
     path: Option<String>
 }
 
@@ -168,7 +170,8 @@ fn normalize(lib: Option<&[TomlLibTarget]>, bin: Option<&[TomlBinTarget]>) -> Ve
     fn lib_targets(dst: &mut Vec<Target>, libs: &[TomlLibTarget]) {
         let l = &libs[0];
         let path = l.path.clone().unwrap_or_else(|| format!("src/{}.rs", l.name));
-        dst.push(Target::lib_target(l.name.as_slice(), &Path::new(path)));
+        let crate_types = l.crate_type.clone().and_then(|kinds| LibKind::from_strs(kinds).ok()).unwrap_or_else(|| vec!(Lib));
+        dst.push(Target::lib_target(l.name.as_slice(), crate_types, &Path::new(path)));
     }
 
     fn bin_targets(dst: &mut Vec<Target>, bins: &[TomlBinTarget], default: |&TomlBinTarget| -> String) {