]> git.proxmox.com Git - cargo.git/commitdiff
Support for multiple and cleaner build commands
authorTomaka17 <pierre.krieger1708@gmail.com>
Mon, 7 Jul 2014 16:33:45 +0000 (18:33 +0200)
committerTomaka17 <pierre.krieger1708@gmail.com>
Mon, 7 Jul 2014 20:12:26 +0000 (22:12 +0200)
src/cargo/core/manifest.rs
src/cargo/ops/cargo_rustc.rs
src/cargo/util/toml.rs
tests/test_cargo_compile.rs

index ffd1e6eee988a5cf33aa5afad3581ec24a9cee31..88fd29e7ab2381c8efdf593ccd5c811ed2f60ddc 100644 (file)
@@ -19,7 +19,7 @@ pub struct Manifest {
     targets: Vec<Target>,
     target_dir: Path,
     sources: Vec<SourceId>,
-    build: Option<String>,
+    build: Vec<String>,
     unused_keys: Vec<String>,
 }
 
@@ -40,7 +40,7 @@ pub struct SerializedManifest {
     authors: Vec<String>,
     targets: Vec<Target>,
     target_dir: String,
-    build: Option<String>,
+    build: Option<Vec<String>>,
 }
 
 impl<E, S: Encoder<E>> Encodable<S, E> for Manifest {
@@ -54,7 +54,7 @@ impl<E, S: Encoder<E>> Encodable<S, E> for Manifest {
             authors: self.authors.clone(),
             targets: self.targets.clone(),
             target_dir: self.target_dir.display().to_str(),
-            build: self.build.clone(),
+            build: if self.build.len() == 0 { None } else { Some(self.build.clone()) },
         }.encode(s)
     }
 }
@@ -185,7 +185,7 @@ impl Show for Target {
 impl Manifest {
     pub fn new(summary: &Summary, targets: &[Target],
                target_dir: &Path, sources: Vec<SourceId>,
-               build: Option<String>) -> Manifest {
+               build: Vec<String>) -> Manifest {
         Manifest {
             summary: summary.clone(),
             authors: Vec::new(),
@@ -233,8 +233,8 @@ impl Manifest {
         self.sources.as_slice()
     }
 
-    pub fn get_build<'a>(&'a self) -> Option<&'a str> {
-        self.build.as_ref().map(|s| s.as_slice())
+    pub fn get_build<'a>(&'a self) -> &'a [String] {
+        self.build.as_slice()
     }
 
     pub fn add_unused_key(&mut self, s: String) {
index 6c6218cf15da9ecdc5939278c0fc062e7c730bec..5832d883030cb01537c83fed2a7c2b362bd31889 100644 (file)
@@ -109,9 +109,8 @@ fn compile(targets: &[&Target], pkg: &Package,
     let mut cmds = Vec::new();
 
     // TODO: Should this be on the target or the package?
-    match pkg.get_manifest().get_build() {
-        Some(cmd) => cmds.push(compile_custom(pkg, cmd, cx)),
-        None => {}
+    for build_cmd in pkg.get_manifest().get_build().iter() {
+        cmds.push(compile_custom(pkg, build_cmd.as_slice(), cx));
     }
 
     // After the custom command has run, execute rustc for all targets of our
index 15a4e11d561d7d0f8323d23de97b3f9b65137593..f04821eb3dd23d66664364db614dea97a1a943d6 100644 (file)
@@ -119,7 +119,13 @@ pub struct TomlProject {
     // FIXME #54: should be a Version to be able to be Decodable'd directly.
     pub version: String,
     pub authors: Vec<String>,
-    build: Option<String>,
+    build: Option<TomlBuildCommandsList>,
+}
+
+#[deriving(Encodable,Decodable,PartialEq,Clone,Show)]
+pub enum TomlBuildCommandsList {
+    SingleBuildCommand(String),
+    MultipleBuildCommands(Vec<String>)
 }
 
 impl TomlProject {
@@ -178,7 +184,11 @@ impl TomlManifest {
                 targets.as_slice(),
                 &Path::new("target"),
                 sources,
-                project.build.clone()),
+                match project.build {
+                    Some(SingleBuildCommand(ref cmd)) => vec!(cmd.clone()),
+                    Some(MultipleBuildCommands(ref cmd)) => cmd.clone(),
+                    None => Vec::new()
+                }),
            nested_paths))
     }
 }
index 9fa6a8aa8b1b0e4e29014fc8a4ebb232d2fc7067..6ba32c5bce5e3b352be15a1e46d51f1b2da99718 100644 (file)
@@ -369,6 +369,70 @@ test!(custom_build {
                        .with_stderr(""));
 })
 
+test!(custom_multiple_build {
+    let mut build1 = project("builder1");
+    build1 = build1
+        .file("Cargo.toml", r#"
+            [project]
+
+            name = "foo"
+            version = "0.5.0"
+            authors = ["wycats@example.com"]
+
+            [[bin]] name = "foo"
+        "#)
+        .file("src/foo.rs", r#"
+            fn main() {
+                let args = ::std::os::args();
+                assert_eq!(args.get(1), &"hello".to_string());
+                assert_eq!(args.get(2), &"world".to_string());
+            }
+        "#);
+    assert_that(build1.cargo_process("cargo-build"),
+                execs().with_status(0));
+
+    let mut build2 = project("builder2");
+    build2 = build2
+        .file("Cargo.toml", r#"
+            [project]
+
+            name = "bar"
+            version = "0.5.0"
+            authors = ["wycats@example.com"]
+
+            [[bin]] name = "bar"
+        "#)
+        .file("src/bar.rs", r#"
+            fn main() {
+                let args = ::std::os::args();
+                assert_eq!(args.get(1), &"cargo".to_string());
+            }
+        "#);
+    assert_that(build2.cargo_process("cargo-build"),
+                execs().with_status(0));
+
+    let mut p = project("foo");
+    p = p
+        .file("Cargo.toml", format!(r#"
+            [project]
+
+            name = "foo"
+            version = "0.5.0"
+            authors = ["wycats@example.com"]
+            build = [ "{} hello world", "{} cargo" ]
+
+            [[bin]] name = "foo"
+        "#, escape_path(&build1.bin("foo")), escape_path(&build2.bin("bar"))))
+        .file("src/foo.rs", r#"
+            fn main() {}
+        "#);
+    assert_that(p.cargo_process("cargo-build"),
+                execs().with_status(0)
+                       .with_stdout(format!("   Compiling foo v0.5.0 (file:{})\n",
+                                            p.root().display()))
+                       .with_stderr(""));
+})
+
 test!(custom_build_failure {
     let mut build = project("builder");
     build = build
@@ -413,6 +477,67 @@ task '<main>' failed at 'nope', {filename}:2\n\
 ", build.bin("foo").display(), filename = format!("src{}foo.rs", path::SEP))));
 })
 
+test!(custom_second_build_failure {
+    let mut build1 = project("builder1");
+    build1 = build1
+        .file("Cargo.toml", r#"
+            [project]
+
+            name = "foo"
+            version = "0.5.0"
+            authors = ["wycats@example.com"]
+
+            [[bin]] name = "foo"
+        "#)
+        .file("src/foo.rs", r#"
+            fn main() { println!("Hello!"); }
+        "#);
+    assert_that(build1.cargo_process("cargo-build"),
+                execs().with_status(0));
+
+    let mut build2 = project("builder2");
+    build2 = build2
+        .file("Cargo.toml", r#"
+            [project]
+
+            name = "bar"
+            version = "0.5.0"
+            authors = ["wycats@example.com"]
+
+            [[bin]]
+            name = "bar"
+        "#)
+        .file("src/bar.rs", r#"
+            fn main() { fail!("nope") }
+        "#);
+    assert_that(build2.cargo_process("cargo-build"), execs().with_status(0));
+
+
+    let mut p = project("foo");
+    p = p
+        .file("Cargo.toml", format!(r#"
+            [project]
+
+            name = "foo"
+            version = "0.5.0"
+            authors = ["wycats@example.com"]
+            build = [ "{}", "{}" ]
+
+            [[bin]]
+            name = "foo"
+        "#, escape_path(&build1.bin("foo")), escape_path(&build2.bin("bar"))))
+        .file("src/foo.rs", r#"
+            fn main() {}
+        "#);
+    assert_that(p.cargo_process("cargo-build"),
+                execs().with_status(101).with_stderr(format!("\
+Could not execute process `{}` (status=101)\n\
+--- stderr\n\
+task '<main>' failed at 'nope', {filename}:2\n\
+\n\
+", build2.bin("bar").display(), filename = format!("src{}bar.rs", path::SEP))));
+})
+
 test!(custom_build_env_vars {
     let mut p = project("foo");
     let mut build = project("builder");