]> git.lizzy.rs Git - rust.git/commitdiff
Pass -fPIC to native compiles on 32-bit
authorAlex Crichton <alex@alexcrichton.com>
Sat, 4 Feb 2017 06:18:32 +0000 (22:18 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Sat, 4 Feb 2017 06:18:32 +0000 (22:18 -0800)
This is apparently a regression from 1.14.0 to 1.15.0. Previously we
passed `-fPIC` to C compilers on i686 targets, but the `gcc` crate
apparently [explicitly] didn't do this. I don't recall why that was
avoided but it was [previously passed by the makefiles][mk] and this
seems to have [caused a regression][regression] in Firefox, so this
commit reverts back to passing `-fPIC`.

[explicitly]: https://github.com/alexcrichton/gcc-rs/commit/362bdf20
[mk]: https://github.com/rust-lang/rust/blob/c781fc4a/mk/cfg/i686-unknown-linux-gnu.mk#L11
[regression]: https://bugzilla.mozilla.org/show_bug.cgi?id=1336155

12 files changed:
src/Cargo.lock
src/vendor/gcc/.cargo-checksum.json
src/vendor/gcc/.gitignore
src/vendor/gcc/.travis.yml
src/vendor/gcc/Cargo.toml
src/vendor/gcc/README.md
src/vendor/gcc/src/bin/gcc-shim.rs
src/vendor/gcc/src/lib.rs
src/vendor/gcc/src/registry.rs
src/vendor/gcc/src/windows_registry.rs
src/vendor/gcc/tests/support/mod.rs
src/vendor/gcc/tests/test.rs

index 95b963f6a78ebc8e72e7131d354f835a5841956e..288a8b658335f5245b319659ef42a27b7ca4050f 100644 (file)
@@ -19,7 +19,7 @@ version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
  "core 0.0.0",
- "gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.0.0",
 ]
 
@@ -42,7 +42,7 @@ dependencies = [
  "build_helper 0.1.0",
  "cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -74,7 +74,7 @@ name = "cmake"
 version = "0.1.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -91,7 +91,7 @@ name = "compiler_builtins"
 version = "0.0.0"
 dependencies = [
  "core 0.0.0",
- "gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -132,7 +132,7 @@ name = "flate"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -141,7 +141,7 @@ version = "0.0.0"
 
 [[package]]
 name = "gcc"
-version = "0.3.40"
+version = "0.3.43"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -396,7 +396,7 @@ name = "rustc_llvm"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_bitflags 0.0.0",
 ]
 
@@ -539,7 +539,7 @@ version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
  "build_helper 0.1.0",
- "gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.0.0",
  "rustc 0.0.0",
  "rustc_back 0.0.0",
@@ -571,7 +571,7 @@ dependencies = [
  "collections 0.0.0",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
- "gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.0.0",
  "panic_abort 0.0.0",
  "panic_unwind 0.0.0",
@@ -661,7 +661,7 @@ dependencies = [
 "checksum cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0e5bcf27e097a184c1df4437654ed98df3d7a516e8508a6ba45d8b092bbdf283"
 "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
 "checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922"
-"checksum gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "872db9e59486ef2b14f8e8c10e9ef02de2bccef6363d7f34835dedb386b3d950"
+"checksum gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)" = "c07c758b972368e703a562686adb39125707cc1ef3399da8c019fc6c2498a75d"
 "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
 "checksum libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "044d1360593a78f5c8e5e710beccdc24ab71d1f01bc19a29bcacdba22e8475d8"
 "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
index e85f4b2181357350e038b5142d739f400349c923..69e2a953a176d45606baf48182ad85c5c2529e8c 100644 (file)
@@ -1 +1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"f9b1ca6ae27d1c18215265024629a8960c31379f206d9ed20f64e0b2dcf79805",".travis.yml":"675ffe583db77282d010306f29e6d81e5070ab081deddd0300137dfbd2cb83de","Cargo.toml":"19bb617b74de761515ef5d087fd0e30912fda1d7c22fd04fa211236dab99a509","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"ecb2d93f4c81edbd48d8742ff7887dc0a4530a5890967839090bbc972d49bebe","appveyor.yml":"46c77d913eaa45871296942c2cd96ef092c9dcaf19201cb5c500a5107faeb06f","src/bin/gcc-shim.rs":"11edfe1fc6f932bd42ffffda5145833302bc163e0b87dc0d54f4bd0997ad4708","src/lib.rs":"7e7c60beccfdd145e876da81bb07dd09c5248dab0b26d93190bab4242799d51a","src/registry.rs":"3e2a42581ebb82e325dd5600c6571cef937b35003b2927dc618967f5238a2058","src/windows_registry.rs":"1f4211caec5a192b5f05c8a47efb27aa6a0ab976c659b9318a0cf603a28d6746","tests/cc_env.rs":"d92c5e3d3d43ac244e63b2cd2c93a521fcf124bf1ccf8d4c6bfa7f8333d88976","tests/support/mod.rs":"f4dad5a8133c3dd6678d9a3de057b82e624ef547b9b3e4ac9508a48962fc387b","tests/test.rs":"164220f11be2eebc20315826513999970660a82feff8cc4b15b4e9d73d98324e"},"package":"872db9e59486ef2b14f8e8c10e9ef02de2bccef6363d7f34835dedb386b3d950"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"4cc6445feac7e9a1f8f1e1c51cc3afd0cf7bb931e3c5a6f18c41258401652702",".travis.yml":"e68f9d10a8e367890cf734239c39952ee480cf0e8da9520b377df4a2b8ccc9e8","Cargo.toml":"4c5eb683d4c57fff819ebf564a8db93b5c87284993def6bc066ba1e311d5b090","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"b1a639560fd536f2c3ab708a8e1066b675edd4d018dfa4e5e18d0d7327d81c15","appveyor.yml":"46c77d913eaa45871296942c2cd96ef092c9dcaf19201cb5c500a5107faeb06f","src/bin/gcc-shim.rs":"d6be9137cb48b86891e7b263adbf492e1193ffe682db9ba4a88eb1079b874b58","src/lib.rs":"eb4ca086dd2ffa5e30f022f556d0def6d1142160da392afb328393b3f435e8f7","src/registry.rs":"3876ef9573e3bbc050aef41a684b9a510cc1a91b15ae874fe032cf4377b4d116","src/windows_registry.rs":"36c6a7f8322407faff2dcfd4789d0876d034885944bc0340ac7c1f7cbfc307f1","tests/cc_env.rs":"d92c5e3d3d43ac244e63b2cd2c93a521fcf124bf1ccf8d4c6bfa7f8333d88976","tests/support/mod.rs":"56bcfd1e2ff5ae8e581c71229444a3d96094bf689808808dd80e315bd6632083","tests/test.rs":"b63e74d571e7d585edc53693bcf0caae88fc040613ace91e32437d4a62cddb6a"},"package":"c07c758b972368e703a562686adb39125707cc1ef3399da8c019fc6c2498a75d"}
\ No newline at end of file
index a9d37c560c6ab8d4afbf47eda643e8c42e857716..3b874ca574de0550d0ee2608988aeb9655940377 100644 (file)
@@ -1,2 +1,4 @@
 target
 Cargo.lock
+.idea
+*.iml
index bf55f49173dcc894eae82fa48fc7f4ade5a2f513..10d3d13d876bcee206e5c1171d5038537bf0dd22 100644 (file)
@@ -3,6 +3,13 @@ rust:
   - stable
   - beta
   - nightly
+matrix:
+  include:
+    # Minimum version supported
+    - rust: 1.6.0
+      install:
+      script: cargo build
+
 sudo: false
 install:
   - if [ "$TRAVIS_OS_NAME" = "linux" ]; then OS=unknown-linux-gnu; else OS=apple-darwin; fi
index 7efdbf9b4b3808ef6ce3593deced1e07e7cdf22e..9fee7788cefc85ef8c593130cc080729563efda4 100644 (file)
@@ -1,11 +1,11 @@
 [package]
 
 name = "gcc"
-version = "0.3.40"
+version = "0.3.43"
 authors = ["Alex Crichton <alex@alexcrichton.com>"]
 license = "MIT/Apache-2.0"
 repository = "https://github.com/alexcrichton/gcc-rs"
-documentation = "http://alexcrichton.com/gcc-rs"
+documentation = "https://docs.rs/gcc"
 description = """
 A build-time dependency for Cargo build scripts to assist in invoking the native
 C compiler to compile native C code into a static archive to be linked into Rust
@@ -13,8 +13,12 @@ code.
 """
 keywords = ["build-dependencies"]
 
+[badges]
+travis-ci = { repository = "alexcrichton/gcc-rs" }
+appveyor = { repository = "alexcrichton/gcc-rs" }
+
 [dependencies]
-rayon = { version = "0.4", optional = true }
+rayon = { version = "0.6", optional = true }
 
 [features]
 parallel = ["rayon"]
index ecc79c6735266dbfc64b510ecbcfb10e5bc3dd58..2d3e5ed7387549a5fb81b5caea6c0b3931866f1a 100644 (file)
@@ -5,7 +5,7 @@ A library to compile C/C++ code into a Rust library/application.
 [![Build Status](https://travis-ci.org/alexcrichton/gcc-rs.svg?branch=master)](https://travis-ci.org/alexcrichton/gcc-rs)
 [![Build status](https://ci.appveyor.com/api/projects/status/onu270iw98h81nwv?svg=true)](https://ci.appveyor.com/project/alexcrichton/gcc-rs)
 
-[Documentation](http://alexcrichton.com/gcc-rs)
+[Documentation](https://docs.rs/gcc)
 
 A simple library meant to be used as a build dependency with Cargo packages in
 order to build a set of C/C++ files into a static archive. Note that while this
@@ -106,7 +106,9 @@ gcc = { version = "0.3", features = ["parallel"] }
 ```
 
 By default gcc-rs will limit parallelism to `$NUM_JOBS`, or if not present it
-will limit it to the number of cpus on the machine.
+will limit it to the number of cpus on the machine. If you are using cargo,
+use `-jN` option of `build`, `test` and `run` commands as `$NUM_JOBS`
+is supplied by cargo.
 
 ## Compile-time Requirements
 
index 43fd811d3615b6728937c202df53e17307ff08d8..7fd0ea8fa84b72bbf8da4aeb92d4a91021f46514 100644 (file)
@@ -10,7 +10,7 @@ fn main() {
     for i in 0.. {
         let candidate = out_dir.join(format!("out{}", i));
         if candidate.exists() {
-            continue
+            continue;
         }
         let mut f = File::create(candidate).unwrap();
         for arg in env::args().skip(1) {
@@ -18,6 +18,6 @@ fn main() {
         }
 
         File::create(out_dir.join("libfoo.a")).unwrap();
-        break
+        break;
     }
 }
index 43cc371117f018564c6d124564156d5e3feed388..f2d9da7f694218d8016fdb0787c4b8510e99887f 100644 (file)
@@ -42,7 +42,7 @@
 //! }
 //! ```
 
-#![doc(html_root_url = "http://alexcrichton.com/gcc-rs")]
+#![doc(html_root_url = "https://docs.rs/gcc/0.3")]
 #![cfg_attr(test, deny(warnings))]
 #![deny(missing_docs)]
 
 use std::env;
 use std::ffi::{OsString, OsStr};
 use std::fs;
-use std::io;
 use std::path::{PathBuf, Path};
 use std::process::{Command, Stdio};
-use std::io::{BufReader, BufRead, Write};
+use std::io::{self, BufReader, BufRead, Read, Write};
+use std::thread;
 
 #[cfg(windows)]
 mod registry;
@@ -94,6 +94,52 @@ pub struct Tool {
     path: PathBuf,
     args: Vec<OsString>,
     env: Vec<(OsString, OsString)>,
+    family: ToolFamily
+}
+
+/// Represents the family of tools this tool belongs to.
+///
+/// Each family of tools differs in how and what arguments they accept.
+///
+/// Detection of a family is done on best-effort basis and may not accurately reflect the tool.
+#[derive(Copy, Clone, Debug)]
+enum ToolFamily {
+    /// Tool is GNU Compiler Collection-like.
+    Gnu,
+    /// Tool is Clang-like. It differs from the GCC in a sense that it accepts superset of flags
+    /// and its cross-compilation approach is different.
+    Clang,
+    /// Tool is the MSVC cl.exe.
+    Msvc,
+}
+
+impl ToolFamily {
+    /// What the flag to request debug info for this family of tools look like
+    fn debug_flag(&self) -> &'static str {
+        match *self {
+            ToolFamily::Msvc => "/Z7",
+            ToolFamily::Gnu |
+            ToolFamily::Clang => "-g",
+        }
+    }
+
+    /// What the flag to include directories into header search path looks like
+    fn include_flag(&self) -> &'static str {
+        match *self {
+            ToolFamily::Msvc => "/I",
+            ToolFamily::Gnu |
+            ToolFamily::Clang => "-I",
+        }
+    }
+
+    /// What the flag to request macro-expanded source output looks like
+    fn expand_flag(&self) -> &'static str {
+        match *self {
+            ToolFamily::Msvc => "/E",
+            ToolFamily::Gnu |
+            ToolFamily::Clang => "-E",
+        }
+    }
 }
 
 /// Compile a library from the given set of input C files.
@@ -114,7 +160,7 @@ pub fn compile_library(output: &str, files: &[&str]) {
     for f in files.iter() {
         c.file(*f);
     }
-    c.compile(output)
+    c.compile(output);
 }
 
 impl Config {
@@ -194,8 +240,7 @@ pub fn cpp(&mut self, cpp: bool) -> &mut Config {
     /// otherwise cargo will link against the specified library.
     ///
     /// The given library name must not contain the `lib` prefix.
-    pub fn cpp_link_stdlib(&mut self, cpp_link_stdlib: Option<&str>)
-                           -> &mut Config {
+    pub fn cpp_link_stdlib(&mut self, cpp_link_stdlib: Option<&str>) -> &mut Config {
         self.cpp_link_stdlib = Some(cpp_link_stdlib.map(|s| s.into()));
         self
     }
@@ -220,8 +265,7 @@ pub fn cpp_link_stdlib(&mut self, cpp_link_stdlib: Option<&str>)
     /// be used, otherwise `-stdlib` is added to the compile invocation.
     ///
     /// The given library name must not contain the `lib` prefix.
-    pub fn cpp_set_stdlib(&mut self, cpp_set_stdlib: Option<&str>)
-                          -> &mut Config {
+    pub fn cpp_set_stdlib(&mut self, cpp_set_stdlib: Option<&str>) -> &mut Config {
         self.cpp_set_stdlib = cpp_set_stdlib.map(|s| s.into());
         self.cpp_link_stdlib(cpp_set_stdlib);
         self
@@ -322,7 +366,8 @@ pub fn pic(&mut self, pic: bool) -> &mut Config {
 
     #[doc(hidden)]
     pub fn __set_env<A, B>(&mut self, a: A, b: B) -> &mut Config
-        where A: AsRef<OsStr>, B: AsRef<OsStr>
+        where A: AsRef<OsStr>,
+              B: AsRef<OsStr>
     {
         self.env.push((a.as_ref().to_owned(), b.as_ref().to_owned()));
         self
@@ -355,18 +400,18 @@ pub fn compile(&self, output: &str) {
 
         if self.get_target().contains("msvc") {
             let compiler = self.get_base_compiler();
-            let atlmfc_lib = compiler.env().iter().find(|&&(ref var, _)| {
-                var == OsStr::new("LIB")
-            }).and_then(|&(_, ref lib_paths)| {
-                env::split_paths(lib_paths).find(|path| {
-                    let sub = Path::new("atlmfc/lib");
-                    path.ends_with(sub) || path.parent().map_or(false, |p| p.ends_with(sub))
-                })
-            });
+            let atlmfc_lib = compiler.env()
+                .iter()
+                .find(|&&(ref var, _)| var.as_os_str() == OsStr::new("LIB"))
+                .and_then(|&(_, ref lib_paths)| {
+                    env::split_paths(lib_paths).find(|path| {
+                        let sub = Path::new("atlmfc/lib");
+                        path.ends_with(sub) || path.parent().map_or(false, |p| p.ends_with(sub))
+                    })
+                });
 
             if let Some(atlmfc_lib) = atlmfc_lib {
-                self.print(&format!("cargo:rustc-link-search=native={}",
-                                    atlmfc_lib.display()));
+                self.print(&format!("cargo:rustc-link-search=native={}", atlmfc_lib.display()));
             }
         }
 
@@ -394,9 +439,7 @@ fn compile_objects(&self, objs: &[(PathBuf, PathBuf)]) {
         }
         drop(rayon::initialize(cfg));
 
-        objs.par_iter().weight_max().for_each(|&(ref src, ref dst)| {
-            self.compile_object(src, dst)
-        })
+        objs.par_iter().weight_max().for_each(|&(ref src, ref dst)| self.compile_object(src, dst));
     }
 
     #[cfg(not(feature = "parallel"))]
@@ -417,8 +460,12 @@ fn compile_object(&self, file: &Path, dst: &Path) {
             for &(ref a, ref b) in self.env.iter() {
                 cmd.env(a, b);
             }
-            (cmd, compiler.path.file_name().unwrap()
-                          .to_string_lossy().into_owned())
+            (cmd,
+             compiler.path
+                 .file_name()
+                 .unwrap()
+                 .to_string_lossy()
+                 .into_owned())
         };
         if msvc && is_asm {
             cmd.arg("/Fo").arg(dst);
@@ -429,12 +476,35 @@ fn compile_object(&self, file: &Path, dst: &Path) {
         } else {
             cmd.arg("-o").arg(&dst);
         }
-        cmd.arg(if msvc {"/c"} else {"-c"});
+        cmd.arg(if msvc { "/c" } else { "-c" });
         cmd.arg(file);
 
         run(&mut cmd, &name);
     }
 
+    /// Run the compiler, returning the macro-expanded version of the input files.
+    ///
+    /// This is only relevant for C and C++ files.
+    pub fn expand(&self) -> Vec<u8> {
+        let compiler = self.get_compiler();
+        let mut cmd = compiler.to_command();
+        for &(ref a, ref b) in self.env.iter() {
+            cmd.env(a, b);
+        }
+        cmd.arg(compiler.family.expand_flag());
+        for file in self.files.iter() {
+            cmd.arg(file);
+        }
+
+        let name = compiler.path
+            .file_name()
+            .unwrap()
+            .to_string_lossy()
+            .into_owned();
+
+        run(&mut cmd, &name)
+    }
+
     /// Get the compiler that's in use for this configuration.
     ///
     /// This function will return a `Tool` which represents the culmination
@@ -451,136 +521,159 @@ fn compile_object(&self, file: &Path, dst: &Path) {
     /// falling back to the default configuration.
     pub fn get_compiler(&self) -> Tool {
         let opt_level = self.get_opt_level();
-        let debug = self.get_debug();
         let target = self.get_target();
-        let msvc = target.contains("msvc");
-        self.print(&format!("debug={} opt-level={}", debug, opt_level));
 
         let mut cmd = self.get_base_compiler();
-        let nvcc = cmd.path.to_str()
-            .map(|path| path.contains("nvcc"))
+        let nvcc = cmd.path.file_name()
+            .and_then(|p| p.to_str()).map(|p| p.contains("nvcc"))
             .unwrap_or(false);
 
-        if msvc {
-            cmd.args.push("/nologo".into());
-            let features = env::var("CARGO_CFG_TARGET_FEATURE")
-                              .unwrap_or(String::new());
-            if features.contains("crt-static") {
-                cmd.args.push("/MT".into());
-            } else {
-                cmd.args.push("/MD".into());
-            }
-            match &opt_level[..] {
-                "z" | "s" => cmd.args.push("/Os".into()),
-                "2" => cmd.args.push("/O2".into()),
-                "1" => cmd.args.push("/O1".into()),
-                _ => {}
+        // Non-target flags
+        // If the flag is not conditioned on target variable, it belongs here :)
+        match cmd.family {
+            ToolFamily::Msvc => {
+                cmd.args.push("/nologo".into());
+                let features = env::var("CARGO_CFG_TARGET_FEATURE")
+                                  .unwrap_or(String::new());
+                if features.contains("crt-static") {
+                    cmd.args.push("/MT".into());
+                } else {
+                    cmd.args.push("/MD".into());
+                }
+                match &opt_level[..] {
+                    "z" | "s" => cmd.args.push("/Os".into()),
+                    "1" => cmd.args.push("/O1".into()),
+                    // -O3 is a valid value for gcc and clang compilers, but not msvc. Cap to /O2.
+                    "2" | "3" => cmd.args.push("/O2".into()),
+                    _ => {}
+                }
             }
-            if target.contains("i586") {
-                cmd.args.push("/ARCH:IA32".into());
+            ToolFamily::Gnu |
+            ToolFamily::Clang => {
+                cmd.args.push(format!("-O{}", opt_level).into());
+                if !nvcc {
+                    cmd.args.push("-ffunction-sections".into());
+                    cmd.args.push("-fdata-sections".into());
+                    if self.pic.unwrap_or(!target.contains("windows-gnu")) {
+                        cmd.args.push("-fPIC".into());
+                    }
+                } else if self.pic.unwrap_or(false) {
+                    cmd.args.push("-Xcompiler".into());
+                    cmd.args.push("\'-fPIC\'".into());
+                }
             }
-        } else if nvcc {
-            cmd.args.push(format!("-O{}", opt_level).into());
-        } else {
-            cmd.args.push(format!("-O{}", opt_level).into());
-            cmd.args.push("-ffunction-sections".into());
-            cmd.args.push("-fdata-sections".into());
         }
         for arg in self.envflags(if self.cpp {"CXXFLAGS"} else {"CFLAGS"}) {
             cmd.args.push(arg.into());
         }
 
-        if debug {
-            cmd.args.push(if msvc {"/Z7"} else {"-g"}.into());
+        if self.get_debug() {
+            cmd.args.push(cmd.family.debug_flag().into());
         }
 
-        if target.contains("-ios") {
-            self.ios_flags(&mut cmd);
-        } else if !msvc {
-            if target.contains("i686") || target.contains("i586") {
-                cmd.args.push("-m32".into());
-            } else if target.contains("x86_64") || target.contains("powerpc64") {
-                cmd.args.push("-m64".into());
+        // Target flags
+        match cmd.family {
+            ToolFamily::Clang => {
+                cmd.args.push(format!("--target={}", target).into());
             }
-
-            if !nvcc && self.pic.unwrap_or(!target.contains("i686") && !target.contains("windows-gnu")) {
-                cmd.args.push("-fPIC".into());
-            } else if nvcc && self.pic.unwrap_or(false) {
-                cmd.args.push("-Xcompiler".into());
-                cmd.args.push("\'-fPIC\'".into());
+            ToolFamily::Msvc => {
+                if target.contains("i586") {
+                    cmd.args.push("/ARCH:IA32".into());
+                }
             }
+            ToolFamily::Gnu => {
+                if target.contains("i686") || target.contains("i586") {
+                    cmd.args.push("-m32".into());
+                } else if target.contains("x86_64") || target.contains("powerpc64") {
+                    cmd.args.push("-m64".into());
+                }
 
-            if target.contains("musl") {
-                cmd.args.push("-static".into());
-            }
+                if target.contains("musl") {
+                    cmd.args.push("-static".into());
+                }
 
-            // armv7 targets get to use armv7 instructions
-            if target.starts_with("armv7-unknown-linux-") {
-                cmd.args.push("-march=armv7-a".into());
-            }
+                // armv7 targets get to use armv7 instructions
+                if target.starts_with("armv7-unknown-linux-") {
+                    cmd.args.push("-march=armv7-a".into());
+                }
 
-            // On android we can guarantee some extra float instructions
-            // (specified in the android spec online)
-            if target.starts_with("armv7-linux-androideabi") {
-                cmd.args.push("-march=armv7-a".into());
-                cmd.args.push("-mfpu=vfpv3-d16".into());
-            }
+                // On android we can guarantee some extra float instructions
+                // (specified in the android spec online)
+                if target.starts_with("armv7-linux-androideabi") {
+                    cmd.args.push("-march=armv7-a".into());
+                    cmd.args.push("-mfpu=vfpv3-d16".into());
+                }
 
-            // For us arm == armv6 by default
-            if target.starts_with("arm-unknown-linux-") {
-                cmd.args.push("-march=armv6".into());
-                cmd.args.push("-marm".into());
-            }
+                // For us arm == armv6 by default
+                if target.starts_with("arm-unknown-linux-") {
+                    cmd.args.push("-march=armv6".into());
+                    cmd.args.push("-marm".into());
+                }
 
-            // Turn codegen down on i586 to avoid some instructions.
-            if target.starts_with("i586-unknown-linux-") {
-                cmd.args.push("-march=pentium".into());
-            }
+                // Turn codegen down on i586 to avoid some instructions.
+                if target.starts_with("i586-unknown-linux-") {
+                    cmd.args.push("-march=pentium".into());
+                }
 
-            // Set codegen level for i686 correctly
-            if target.starts_with("i686-unknown-linux-") {
-                cmd.args.push("-march=i686".into());
-            }
+                // Set codegen level for i686 correctly
+                if target.starts_with("i686-unknown-linux-") {
+                    cmd.args.push("-march=i686".into());
+                }
 
-            // Looks like `musl-gcc` makes is hard for `-m32` to make its way
-            // all the way to the linker, so we need to actually instruct the
-            // linker that we're generating 32-bit executables as well. This'll
-            // typically only be used for build scripts which transitively use
-            // these flags that try to compile executables.
-            if target == "i686-unknown-linux-musl" {
-                cmd.args.push("-Wl,-melf_i386".into());
-            }
+                // Looks like `musl-gcc` makes is hard for `-m32` to make its way
+                // all the way to the linker, so we need to actually instruct the
+                // linker that we're generating 32-bit executables as well. This'll
+                // typically only be used for build scripts which transitively use
+                // these flags that try to compile executables.
+                if target == "i686-unknown-linux-musl" {
+                    cmd.args.push("-Wl,-melf_i386".into());
+                }
 
-            if target.starts_with("thumb") {
-                cmd.args.push("-mthumb".into());
+                if target.starts_with("thumb") {
+                    cmd.args.push("-mthumb".into());
 
-                if target.ends_with("eabihf") {
-                    cmd.args.push("-mfloat-abi=hard".into())
+                    if target.ends_with("eabihf") {
+                        cmd.args.push("-mfloat-abi=hard".into())
+                    }
                 }
-            }
-            if target.starts_with("thumbv6m") {
-                cmd.args.push("-march=armv6s-m".into());
-            }
-            if target.starts_with("thumbv7em") {
-                cmd.args.push("-march=armv7e-m".into());
+                if target.starts_with("thumbv6m") {
+                    cmd.args.push("-march=armv6s-m".into());
+                }
+                if target.starts_with("thumbv7em") {
+                    cmd.args.push("-march=armv7e-m".into());
 
-                if target.ends_with("eabihf") {
-                    cmd.args.push("-mfpu=fpv4-sp-d16".into())
+                    if target.ends_with("eabihf") {
+                        cmd.args.push("-mfpu=fpv4-sp-d16".into())
+                    }
+                }
+                if target.starts_with("thumbv7m") {
+                    cmd.args.push("-march=armv7-m".into());
                 }
             }
-            if target.starts_with("thumbv7m") {
-                cmd.args.push("-march=armv7-m".into());
-            }
         }
 
-        if self.cpp && !msvc {
-            if let Some(ref stdlib) = self.cpp_set_stdlib {
-                cmd.args.push(format!("-stdlib=lib{}", stdlib).into());
+        if target.contains("-ios") {
+            // FIXME: potential bug. iOS is always compiled with Clang, but Gcc compiler may be
+            // detected instead.
+            self.ios_flags(&mut cmd);
+        }
+
+        if self.cpp {
+            match (self.cpp_set_stdlib.as_ref(), cmd.family) {
+                (None, _) => { }
+                (Some(stdlib), ToolFamily::Gnu) |
+                (Some(stdlib), ToolFamily::Clang) => {
+                    cmd.args.push(format!("-stdlib=lib{}", stdlib).into());
+                }
+                _ => {
+                    println!("cargo:warning=cpp_set_stdlib is specified, but the {:?} compiler \
+                              does not support this option, ignored", cmd.family);
+                }
             }
         }
 
         for directory in self.include_directories.iter() {
-            cmd.args.push(if msvc {"/I"} else {"-I"}.into());
+            cmd.args.push(cmd.family.include_flag().into());
             cmd.args.push(directory.into());
         }
 
@@ -589,7 +682,7 @@ pub fn get_compiler(&self) -> Tool {
         }
 
         for &(ref key, ref value) in self.definitions.iter() {
-            let lead = if msvc {"/"} else {"-"};
+            let lead = if let ToolFamily::Msvc = cmd.family {"/"} else {"-"};
             if let &Some(ref value) = value {
                 cmd.args.push(format!("{}D{}={}", lead, key, value).into());
             } else {
@@ -601,10 +694,12 @@ pub fn get_compiler(&self) -> Tool {
 
     fn msvc_macro_assembler(&self) -> (Command, String) {
         let target = self.get_target();
-        let tool = if target.contains("x86_64") {"ml64.exe"} else {"ml.exe"};
-        let mut cmd = windows_registry::find(&target, tool).unwrap_or_else(|| {
-            self.cmd(tool)
-        });
+        let tool = if target.contains("x86_64") {
+            "ml64.exe"
+        } else {
+            "ml.exe"
+        };
+        let mut cmd = windows_registry::find(&target, tool).unwrap_or_else(|| self.cmd(tool));
         for directory in self.include_directories.iter() {
             cmd.arg("/I").arg(directory);
         }
@@ -635,31 +730,37 @@ fn assemble(&self, lib_name: &str, dst: &Path, objects: &[PathBuf]) {
         if target.contains("msvc") {
             let mut cmd = match self.archiver {
                 Some(ref s) => self.cmd(s),
-                None => windows_registry::find(&target, "lib.exe")
-                                         .unwrap_or(self.cmd("lib.exe")),
+                None => windows_registry::find(&target, "lib.exe").unwrap_or(self.cmd("lib.exe")),
             };
             let mut out = OsString::from("/OUT:");
             out.push(dst);
-            run(cmd.arg(out).arg("/nologo")
-                   .args(objects)
-                   .args(&self.objects), "lib.exe");
+            run(cmd.arg(out)
+                    .arg("/nologo")
+                    .args(objects)
+                    .args(&self.objects),
+                "lib.exe");
 
             // The Rust compiler will look for libfoo.a and foo.lib, but the
             // MSVC linker will also be passed foo.lib, so be sure that both
             // exist for now.
             let lib_dst = dst.with_file_name(format!("{}.lib", lib_name));
             let _ = fs::remove_file(&lib_dst);
-            fs::hard_link(&dst, &lib_dst).or_else(|_| {
-                //if hard-link fails, just copy (ignoring the number of bytes written)
-                fs::copy(&dst, &lib_dst).map(|_| ())
-            }).ok().expect("Copying from {:?} to {:?} failed.");;
+            fs::hard_link(&dst, &lib_dst)
+                .or_else(|_| {
+                    // if hard-link fails, just copy (ignoring the number of bytes written)
+                    fs::copy(&dst, &lib_dst).map(|_| ())
+                })
+                .ok()
+                .expect("Copying from {:?} to {:?} failed.");;
         } else {
             let ar = self.get_ar();
             let cmd = ar.file_name().unwrap().to_string_lossy();
-            run(self.cmd(&ar).arg("crs")
-                                 .arg(dst)
-                                 .args(objects)
-                                 .args(&self.objects), &cmd);
+            run(self.cmd(&ar)
+                    .arg("crs")
+                    .arg(dst)
+                    .args(objects)
+                    .args(&self.objects),
+                &cmd);
         }
     }
 
@@ -677,7 +778,7 @@ enum ArchSpec {
             "arm64" | "aarch64" => ArchSpec::Device("arm64"),
             "i386" | "i686" => ArchSpec::Simulator("-m32"),
             "x86_64" => ArchSpec::Simulator("-m64"),
-            _ => fail("Unknown arch for iOS target")
+            _ => fail("Unknown arch for iOS target"),
         };
 
         let sdk = match arch {
@@ -686,7 +787,7 @@ enum ArchSpec {
                 cmd.args.push(arch.into());
                 cmd.args.push("-miphoneos-version-min=7.0".into());
                 "iphoneos"
-            },
+            }
             ArchSpec::Simulator(arch) => {
                 cmd.args.push(arch.into());
                 cmd.args.push("-mios-simulator-version-min=7.0".into());
@@ -715,12 +816,12 @@ fn cmd<P: AsRef<OsStr>>(&self, prog: P) -> Command {
         for &(ref a, ref b) in self.env.iter() {
             cmd.env(a, b);
         }
-        return cmd
+        return cmd;
     }
 
     fn get_base_compiler(&self) -> Tool {
         if let Some(ref c) = self.compiler {
-            return Tool::new(c.clone())
+            return Tool::new(c.clone());
         }
         let host = self.get_host();
         let target = self.get_target();
@@ -729,87 +830,88 @@ fn get_base_compiler(&self) -> Tool {
         } else {
             ("CC", "cl.exe", "gcc", "cc")
         };
-        self.env_tool(env).map(|(tool, args)| {
-            let mut t = Tool::new(PathBuf::from(tool));
-            for arg in args {
-                t.args.push(arg.into());
-            }
-            return t
-        }).or_else(|| {
-            if target.contains("emscripten") {
-                if self.cpp {
-                    Some(Tool::new(PathBuf::from("em++")))
-                } else {
-                    Some(Tool::new(PathBuf::from("emcc")))
+        self.env_tool(env)
+            .map(|(tool, args)| {
+                let mut t = Tool::new(PathBuf::from(tool));
+                for arg in args {
+                    t.args.push(arg.into());
                 }
-            } else {
-                None
-            }
-        }).or_else(|| {
-            windows_registry::find_tool(&target, "cl.exe")
-        }).unwrap_or_else(|| {
-            let compiler = if host.contains("windows") &&
-                              target.contains("windows") {
-                if target.contains("msvc") {
-                    msvc.to_string()
+                return t;
+            })
+            .or_else(|| {
+                if target.contains("emscripten") {
+                    if self.cpp {
+                        Some(Tool::new(PathBuf::from("em++")))
+                    } else {
+                        Some(Tool::new(PathBuf::from("emcc")))
+                    }
                 } else {
-                    format!("{}.exe", gnu)
+                    None
                 }
-            } else if target.contains("android") {
-                format!("{}-{}", target, gnu)
-            } else if self.get_host() != target {
-                // CROSS_COMPILE is of the form: "arm-linux-gnueabi-"
-                let cc_env = self.getenv("CROSS_COMPILE");
-                let cross_compile = cc_env.as_ref().map(|s| s.trim_right_matches('-'));
-                let prefix = cross_compile.or(match &target[..] {
-                    "aarch64-unknown-linux-gnu" => Some("aarch64-linux-gnu"),
-                    "arm-unknown-linux-gnueabi" => Some("arm-linux-gnueabi"),
-                    "arm-unknown-linux-gnueabihf"  => Some("arm-linux-gnueabihf"),
-                    "arm-unknown-linux-musleabi" => Some("arm-linux-musleabi"),
-                    "arm-unknown-linux-musleabihf"  => Some("arm-linux-musleabihf"),
-                    "arm-unknown-netbsdelf-eabi" => Some("arm--netbsdelf-eabi"),
-                    "armv6-unknown-netbsdelf-eabihf" => Some("armv6--netbsdelf-eabihf"),
-                    "armv7-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"),
-                    "armv7-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"),
-                    "armv7-unknown-netbsdelf-eabihf" => Some("armv7--netbsdelf-eabihf"),
-                    "i686-pc-windows-gnu" => Some("i686-w64-mingw32"),
-                    "i686-unknown-linux-musl" => Some("musl"),
-                    "i686-unknown-netbsdelf" => Some("i486--netbsdelf"),
-                    "mips-unknown-linux-gnu" => Some("mips-linux-gnu"),
-                    "mipsel-unknown-linux-gnu" => Some("mipsel-linux-gnu"),
-                    "mips64-unknown-linux-gnuabi64" => Some("mips64-linux-gnuabi64"),
-                    "mips64el-unknown-linux-gnuabi64" => Some("mips64el-linux-gnuabi64"),
-                    "powerpc-unknown-linux-gnu" => Some("powerpc-linux-gnu"),
-                    "powerpc-unknown-netbsd" => Some("powerpc--netbsd"),
-                    "powerpc64-unknown-linux-gnu" => Some("powerpc-linux-gnu"),
-                    "powerpc64le-unknown-linux-gnu" => Some("powerpc64le-linux-gnu"),
-                    "s390x-unknown-linux-gnu" => Some("s390x-linux-gnu"),
-                    "sparc64-unknown-netbsd" => Some("sparc64--netbsd"),
-                    "thumbv6m-none-eabi" => Some("arm-none-eabi"),
-                    "thumbv7em-none-eabi" => Some("arm-none-eabi"),
-                    "thumbv7em-none-eabihf" => Some("arm-none-eabi"),
-                    "thumbv7m-none-eabi" => Some("arm-none-eabi"),
-                    "x86_64-pc-windows-gnu" => Some("x86_64-w64-mingw32"),
-                    "x86_64-rumprun-netbsd" => Some("x86_64-rumprun-netbsd"),
-                    "x86_64-unknown-linux-musl" => Some("musl"),
-                    "x86_64-unknown-netbsd" => Some("x86_64--netbsd"),
-                    _ => None,
-                });
-                match prefix {
-                    Some(prefix) => format!("{}-{}", prefix, gnu),
-                    None => default.to_string(),
-                }
-            } else {
-                default.to_string()
-            };
-            Tool::new(PathBuf::from(compiler))
-        })
+            })
+            .or_else(|| windows_registry::find_tool(&target, "cl.exe"))
+            .unwrap_or_else(|| {
+                let compiler = if host.contains("windows") && target.contains("windows") {
+                    if target.contains("msvc") {
+                        msvc.to_string()
+                    } else {
+                        format!("{}.exe", gnu)
+                    }
+                } else if target.contains("android") {
+                    format!("{}-{}", target.replace("armv7", "arm"), gnu)
+                } else if self.get_host() != target {
+                    // CROSS_COMPILE is of the form: "arm-linux-gnueabi-"
+                    let cc_env = self.getenv("CROSS_COMPILE");
+                    let cross_compile = cc_env.as_ref().map(|s| s.trim_right_matches('-'));
+                    let prefix = cross_compile.or(match &target[..] {
+                        "aarch64-unknown-linux-gnu" => Some("aarch64-linux-gnu"),
+                        "arm-unknown-linux-gnueabi" => Some("arm-linux-gnueabi"),
+                        "arm-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"),
+                        "arm-unknown-linux-musleabi" => Some("arm-linux-musleabi"),
+                        "arm-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"),
+                        "arm-unknown-netbsdelf-eabi" => Some("arm--netbsdelf-eabi"),
+                        "armv6-unknown-netbsdelf-eabihf" => Some("armv6--netbsdelf-eabihf"),
+                        "armv7-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"),
+                        "armv7-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"),
+                        "armv7-unknown-netbsdelf-eabihf" => Some("armv7--netbsdelf-eabihf"),
+                        "i686-pc-windows-gnu" => Some("i686-w64-mingw32"),
+                        "i686-unknown-linux-musl" => Some("musl"),
+                        "i686-unknown-netbsdelf" => Some("i486--netbsdelf"),
+                        "mips-unknown-linux-gnu" => Some("mips-linux-gnu"),
+                        "mipsel-unknown-linux-gnu" => Some("mipsel-linux-gnu"),
+                        "mips64-unknown-linux-gnuabi64" => Some("mips64-linux-gnuabi64"),
+                        "mips64el-unknown-linux-gnuabi64" => Some("mips64el-linux-gnuabi64"),
+                        "powerpc-unknown-linux-gnu" => Some("powerpc-linux-gnu"),
+                        "powerpc-unknown-netbsd" => Some("powerpc--netbsd"),
+                        "powerpc64-unknown-linux-gnu" => Some("powerpc-linux-gnu"),
+                        "powerpc64le-unknown-linux-gnu" => Some("powerpc64le-linux-gnu"),
+                        "s390x-unknown-linux-gnu" => Some("s390x-linux-gnu"),
+                        "sparc64-unknown-netbsd" => Some("sparc64--netbsd"),
+                        "thumbv6m-none-eabi" => Some("arm-none-eabi"),
+                        "thumbv7em-none-eabi" => Some("arm-none-eabi"),
+                        "thumbv7em-none-eabihf" => Some("arm-none-eabi"),
+                        "thumbv7m-none-eabi" => Some("arm-none-eabi"),
+                        "x86_64-pc-windows-gnu" => Some("x86_64-w64-mingw32"),
+                        "x86_64-rumprun-netbsd" => Some("x86_64-rumprun-netbsd"),
+                        "x86_64-unknown-linux-musl" => Some("musl"),
+                        "x86_64-unknown-netbsd" => Some("x86_64--netbsd"),
+                        _ => None,
+                    });
+                    match prefix {
+                        Some(prefix) => format!("{}-{}", prefix, gnu),
+                        None => default.to_string(),
+                    }
+                } else {
+                    default.to_string()
+                };
+                Tool::new(PathBuf::from(compiler))
+            })
     }
 
     fn get_var(&self, var_base: &str) -> Result<String, String> {
         let target = self.get_target();
         let host = self.get_host();
-        let kind = if host == target {"HOST"} else {"TARGET"};
+        let kind = if host == target { "HOST" } else { "TARGET" };
         let target_u = target.replace("-", "_");
         let res = self.getenv(&format!("{}_{}", var_base, target))
             .or_else(|| self.getenv(&format!("{}_{}", var_base, target_u)))
@@ -823,8 +925,10 @@ fn get_var(&self, var_base: &str) -> Result<String, String> {
     }
 
     fn envflags(&self, name: &str) -> Vec<String> {
-        self.get_var(name).unwrap_or(String::new())
-            .split(|c: char| c.is_whitespace()).filter(|s| !s.is_empty())
+        self.get_var(name)
+            .unwrap_or(String::new())
+            .split(|c: char| c.is_whitespace())
+            .filter(|s| !s.is_empty())
             .map(|s| s.to_string())
             .collect()
     }
@@ -834,8 +938,7 @@ fn env_tool(&self, name: &str) -> Option<(String, Vec<String>)> {
             let whitelist = ["ccache", "distcc"];
             for t in whitelist.iter() {
                 if tool.starts_with(t) && tool[t.len()..].starts_with(" ") {
-                    return (t.to_string(),
-                            vec![tool[t.len()..].trim_left().to_string()])
+                    return (t.to_string(), vec![tool[t.len()..].trim_left().to_string()]);
                 }
             }
             (tool, Vec::new())
@@ -860,17 +963,18 @@ fn get_cpp_link_stdlib(&self) -> Option<String> {
     }
 
     fn get_ar(&self) -> PathBuf {
-        self.archiver.clone().or_else(|| {
-            self.get_var("AR").map(PathBuf::from).ok()
-        }).unwrap_or_else(|| {
-            if self.get_target().contains("android") {
-                PathBuf::from(format!("{}-ar", self.get_target()))
-            } else if self.get_target().contains("emscripten") {
-                PathBuf::from("emar")
-            } else {
-                PathBuf::from("ar")
-            }
-        })
+        self.archiver
+            .clone()
+            .or_else(|| self.get_var("AR").map(PathBuf::from).ok())
+            .unwrap_or_else(|| {
+                if self.get_target().contains("android") {
+                    PathBuf::from(format!("{}-ar", self.get_target().replace("armv7", "arm")))
+                } else if self.get_target().contains("emscripten") {
+                    PathBuf::from("emar")
+                } else {
+                    PathBuf::from("ar")
+                }
+            })
     }
 
     fn get_target(&self) -> String {
@@ -882,9 +986,7 @@ fn get_host(&self) -> String {
     }
 
     fn get_opt_level(&self) -> String {
-        self.opt_level.as_ref().cloned().unwrap_or_else(|| {
-            self.getenv_unwrap("OPT_LEVEL")
-        })
+        self.opt_level.as_ref().cloned().unwrap_or_else(|| self.getenv_unwrap("OPT_LEVEL"))
     }
 
     fn get_debug(&self) -> bool {
@@ -892,9 +994,7 @@ fn get_debug(&self) -> bool {
     }
 
     fn get_out_dir(&self) -> PathBuf {
-        self.out_dir.clone().unwrap_or_else(|| {
-            env::var_os("OUT_DIR").map(PathBuf::from).unwrap()
-        })
+        self.out_dir.clone().unwrap_or_else(|| env::var_os("OUT_DIR").map(PathBuf::from).unwrap())
     }
 
     fn getenv(&self, v: &str) -> Option<String> {
@@ -919,10 +1019,23 @@ fn print(&self, s: &str) {
 
 impl Tool {
     fn new(path: PathBuf) -> Tool {
+        // Try to detect family of the tool from its name, falling back to Gnu.
+        let family = if let Some(fname) = path.file_name().and_then(|p| p.to_str()) {
+            if fname.contains("clang") {
+                ToolFamily::Clang
+            } else if fname.contains("cl") {
+                ToolFamily::Msvc
+            } else {
+                ToolFamily::Gnu
+            }
+        } else {
+            ToolFamily::Gnu
+        };
         Tool {
             path: path,
             args: Vec::new(),
             env: Vec::new(),
+            family: family
         }
     }
 
@@ -937,7 +1050,7 @@ pub fn to_command(&self) -> Command {
         for &(ref k, ref v) in self.env.iter() {
             cmd.env(k, v);
         }
-        return cmd
+        cmd
     }
 
     /// Returns the path for this compiler.
@@ -963,23 +1076,27 @@ pub fn env(&self) -> &[(OsString, OsString)] {
     }
 }
 
-fn run(cmd: &mut Command, program: &str) {
+fn run(cmd: &mut Command, program: &str) -> Vec<u8> {
     println!("running: {:?}", cmd);
     // Capture the standard error coming from these programs, and write it out
     // with cargo:warning= prefixes. Note that this is a bit wonky to avoid
     // requiring the output to be UTF-8, we instead just ship bytes from one
     // location to another.
-    let spawn_result = match cmd.stderr(Stdio::piped()).spawn() {
+    let (spawn_result, stdout) = match cmd.stdout(Stdio::piped()).stderr(Stdio::piped()).spawn() {
         Ok(mut child) => {
             let stderr = BufReader::new(child.stderr.take().unwrap());
-            for line in stderr.split(b'\n').filter_map(|l| l.ok()) {
-                print!("cargo:warning=");
-                std::io::stdout().write_all(&line).unwrap();
-                println!("");
-            }
-            child.wait()
+            thread::spawn(move || {
+                for line in stderr.split(b'\n').filter_map(|l| l.ok()) {
+                    print!("cargo:warning=");
+                    std::io::stdout().write_all(&line).unwrap();
+                    println!("");
+                }
+            });
+            let mut stdout = vec![];
+            child.stdout.take().unwrap().read_to_end(&mut stdout).unwrap();
+            (child.wait(), stdout)
         }
-        Err(e) => Err(e),
+        Err(e) => (Err(e), vec![]),
     };
     let status = match spawn_result {
         Ok(status) => status,
@@ -991,7 +1108,10 @@ fn run(cmd: &mut Command, program: &str) {
                 ""
             };
             fail(&format!("failed to execute command: {}\nIs `{}` \
-                           not installed?{}", e, program, extra));
+                           not installed?{}",
+                          e,
+                          program,
+                          extra));
         }
         Err(e) => fail(&format!("failed to execute command: {}", e)),
     };
@@ -999,6 +1119,7 @@ fn run(cmd: &mut Command, program: &str) {
     if !status.success() {
         fail(&format!("command did not execute successfully, got: {}", status));
     }
+    stdout
 }
 
 fn fail(s: &str) -> ! {
index d871cd21f3c06d69e40a3c332e91fd97323b1d8b..a45272344db403c87e1005a7315e14a755f47804 100644 (file)
@@ -40,7 +40,8 @@ fn RegOpenKeyExW(key: HKEY,
                      lpSubKey: LPCWSTR,
                      ulOptions: DWORD,
                      samDesired: REGSAM,
-                     phkResult: PHKEY) -> LONG;
+                     phkResult: PHKEY)
+                     -> LONG;
     fn RegEnumKeyExW(key: HKEY,
                      dwIndex: DWORD,
                      lpName: LPWSTR,
@@ -48,13 +49,15 @@ fn RegEnumKeyExW(key: HKEY,
                      lpReserved: LPDWORD,
                      lpClass: LPWSTR,
                      lpcClass: LPDWORD,
-                     lpftLastWriteTime: PFILETIME) -> LONG;
+                     lpftLastWriteTime: PFILETIME)
+                     -> LONG;
     fn RegQueryValueExW(hKey: HKEY,
                         lpValueName: LPCWSTR,
                         lpReserved: LPDWORD,
                         lpType: LPDWORD,
                         lpData: LPBYTE,
-                        lpcbData: LPDWORD) -> LONG;
+                        lpcbData: LPDWORD)
+                        -> LONG;
     fn RegCloseKey(hKey: HKEY) -> LONG;
 }
 
@@ -73,8 +76,7 @@ pub struct Iter<'a> {
 unsafe impl Sync for Repr {}
 unsafe impl Send for Repr {}
 
-pub static LOCAL_MACHINE: RegistryKey =
-    RegistryKey(Repr::Const(HKEY_LOCAL_MACHINE));
+pub static LOCAL_MACHINE: RegistryKey = RegistryKey(Repr::Const(HKEY_LOCAL_MACHINE));
 
 impl RegistryKey {
     fn raw(&self) -> HKEY {
@@ -88,8 +90,11 @@ pub fn open(&self, key: &OsStr) -> io::Result<RegistryKey> {
         let key = key.encode_wide().chain(Some(0)).collect::<Vec<_>>();
         let mut ret = 0 as *mut _;
         let err = unsafe {
-            RegOpenKeyExW(self.raw(), key.as_ptr(), 0,
-                          KEY_READ | KEY_WOW64_32KEY, &mut ret)
+            RegOpenKeyExW(self.raw(),
+                          key.as_ptr(),
+                          0,
+                          KEY_READ | KEY_WOW64_32KEY,
+                          &mut ret)
         };
         if err == ERROR_SUCCESS as LONG {
             Ok(RegistryKey(Repr::Owned(OwnedKey(ret))))
@@ -99,7 +104,10 @@ pub fn open(&self, key: &OsStr) -> io::Result<RegistryKey> {
     }
 
     pub fn iter(&self) -> Iter {
-        Iter { idx: 0.., key: self }
+        Iter {
+            idx: 0..,
+            key: self,
+        }
     }
 
     pub fn query_str(&self, name: &str) -> io::Result<OsString> {
@@ -108,25 +116,31 @@ pub fn query_str(&self, name: &str) -> io::Result<OsString> {
         let mut len = 0;
         let mut kind = 0;
         unsafe {
-            let err = RegQueryValueExW(self.raw(), name.as_ptr(), 0 as *mut _,
-                                       &mut kind, 0 as *mut _, &mut len);
+            let err = RegQueryValueExW(self.raw(),
+                                       name.as_ptr(),
+                                       0 as *mut _,
+                                       &mut kind,
+                                       0 as *mut _,
+                                       &mut len);
             if err != ERROR_SUCCESS as LONG {
-                return Err(io::Error::from_raw_os_error(err as i32))
+                return Err(io::Error::from_raw_os_error(err as i32));
             }
             if kind != REG_SZ {
-                return Err(io::Error::new(io::ErrorKind::Other,
-                                          "registry key wasn't a string"))
+                return Err(io::Error::new(io::ErrorKind::Other, "registry key wasn't a string"));
             }
 
             // The length here is the length in bytes, but we're using wide
             // characters so we need to be sure to halve it for the capacity
             // passed in.
             let mut v = Vec::with_capacity(len as usize / 2);
-            let err = RegQueryValueExW(self.raw(), name.as_ptr(), 0 as *mut _,
-                                       0 as *mut _, v.as_mut_ptr() as *mut _,
+            let err = RegQueryValueExW(self.raw(),
+                                       name.as_ptr(),
+                                       0 as *mut _,
+                                       0 as *mut _,
+                                       v.as_mut_ptr() as *mut _,
                                        &mut len);
             if err != ERROR_SUCCESS as LONG {
-                return Err(io::Error::from_raw_os_error(err as i32))
+                return Err(io::Error::from_raw_os_error(err as i32));
             }
             v.set_len(len as usize / 2);
 
@@ -142,7 +156,9 @@ pub fn query_str(&self, name: &str) -> io::Result<OsString> {
 
 impl Drop for OwnedKey {
     fn drop(&mut self) {
-        unsafe { RegCloseKey(self.0); }
+        unsafe {
+            RegCloseKey(self.0);
+        }
     }
 }
 
@@ -153,8 +169,13 @@ fn next(&mut self) -> Option<io::Result<OsString>> {
         self.idx.next().and_then(|i| unsafe {
             let mut v = Vec::with_capacity(256);
             let mut len = v.capacity() as DWORD;
-            let ret = RegEnumKeyExW(self.key.raw(), i, v.as_mut_ptr(), &mut len,
-                                    0 as *mut _, 0 as *mut _, 0 as *mut _,
+            let ret = RegEnumKeyExW(self.key.raw(),
+                                    i,
+                                    v.as_mut_ptr(),
+                                    &mut len,
+                                    0 as *mut _,
+                                    0 as *mut _,
+                                    0 as *mut _,
                                     0 as *mut _);
             if ret == ERROR_NO_MORE_ITEMS as LONG {
                 None
index e16a33f24647884b6559990a1ab73d4fc7328b87..08b1df5f9b24af3926861ae5f2b05cb97c2e3204 100644 (file)
@@ -78,31 +78,29 @@ fn into_tool(self) -> Tool {
             add_env(&mut tool, "LIB", libs);
             add_env(&mut tool, "PATH", path);
             add_env(&mut tool, "INCLUDE", include);
-            return tool
+            tool
         }
     }
 
     // This logic is all tailored for MSVC, if we're not that then bail out
     // early.
     if !target.contains("msvc") {
-        return None
+        return None;
     }
 
     // Looks like msbuild isn't located in the same location as other tools like
     // cl.exe and lib.exe. To handle this we probe for it manually with
     // dedicated registry keys.
     if tool.contains("msbuild") {
-        return find_msbuild(target)
+        return find_msbuild(target);
     }
 
     // If VCINSTALLDIR is set, then someone's probably already run vcvars and we
     // should just find whatever that indicates.
     if env::var_os("VCINSTALLDIR").is_some() {
-        return env::var_os("PATH").and_then(|path| {
-            env::split_paths(&path).map(|p| p.join(tool)).find(|p| p.exists())
-        }).map(|path| {
-            Tool::new(path.into())
-        })
+        return env::var_os("PATH")
+            .and_then(|path| env::split_paths(&path).map(|p| p.join(tool)).find(|p| p.exists()))
+            .map(|path| Tool::new(path.into()));
     }
 
     // Ok, if we're here, now comes the fun part of the probing. Default shells
@@ -112,13 +110,10 @@ fn into_tool(self) -> Tool {
     // environment variables like `LIB`, `INCLUDE`, and `PATH` to ensure that
     // the tool is actually usable.
 
-    return find_msvc_latest(tool, target, "15.0").or_else(|| {
-        find_msvc_latest(tool, target, "14.0")
-    }).or_else(|| {
-        find_msvc_12(tool, target)
-    }).or_else(|| {
-        find_msvc_11(tool, target)
-    });
+    return find_msvc_latest(tool, target, "15.0")
+        .or_else(|| find_msvc_latest(tool, target, "14.0"))
+        .or_else(|| find_msvc_12(tool, target))
+        .or_else(|| find_msvc_11(tool, target));
 
     // For MSVC 14 or newer we need to find the Universal CRT as well as either
     // the Windows 10 SDK or Windows 8.1 SDK.
@@ -151,7 +146,7 @@ fn find_msvc_latest(tool: &str, target: &str, ver: &str) -> Option<Tool> {
             tool.include.push(sdk_include.join("winrt"));
             tool.include.push(sdk_include.join("shared"));
         } else {
-            return None
+            return None;
         }
         Some(tool.into_tool())
     }
@@ -198,26 +193,27 @@ fn add_env(tool: &mut Tool, env: &str, paths: Vec<PathBuf>) {
     // Given a possible MSVC installation directory, we look for the linker and
     // then add the MSVC library path.
     fn get_tool(tool: &str, path: &Path, target: &str) -> Option<MsvcTool> {
-        bin_subdir(target).into_iter().map(|(sub, host)| {
-            (path.join("bin").join(sub).join(tool),
-             path.join("bin").join(host))
-        }).filter(|&(ref path, _)| {
-            path.is_file()
-        }).map(|(path, host)| {
-            let mut tool = MsvcTool::new(path);
-            tool.path.push(host);
-            tool
-        }).filter_map(|mut tool| {
-            let sub = otry!(vc_lib_subdir(target));
-            tool.libs.push(path.join("lib").join(sub));
-            tool.include.push(path.join("include"));
-            let atlmfc_path = path.join("atlmfc");
-            if atlmfc_path.exists() {
-                tool.libs.push(atlmfc_path.join("lib").join(sub));
-                tool.include.push(atlmfc_path.join("include"));
-            }
-            Some(tool)
-        }).next()
+        bin_subdir(target)
+            .into_iter()
+            .map(|(sub, host)| (path.join("bin").join(sub).join(tool), path.join("bin").join(host)))
+            .filter(|&(ref path, _)| path.is_file())
+            .map(|(path, host)| {
+                let mut tool = MsvcTool::new(path);
+                tool.path.push(host);
+                tool
+            })
+            .filter_map(|mut tool| {
+                let sub = otry!(vc_lib_subdir(target));
+                tool.libs.push(path.join("lib").join(sub));
+                tool.include.push(path.join("include"));
+                let atlmfc_path = path.join("atlmfc");
+                if atlmfc_path.exists() {
+                    tool.libs.push(atlmfc_path.join("lib").join(sub));
+                    tool.include.push(atlmfc_path.join("include"));
+                }
+                Some(tool)
+            })
+            .next()
     }
 
     // To find MSVC we look in a specific registry key for the version we are
@@ -240,17 +236,16 @@ fn get_ucrt_dir() -> Option<(PathBuf, String)> {
         let key = otry!(LOCAL_MACHINE.open(key.as_ref()).ok());
         let root = otry!(key.query_str("KitsRoot10").ok());
         let readdir = otry!(Path::new(&root).join("lib").read_dir().ok());
-        let max_libdir = otry!(readdir.filter_map(|dir| {
-            dir.ok()
-        }).map(|dir| {
-            dir.path()
-        }).filter(|dir| {
-            dir.components().last().and_then(|c| {
-                c.as_os_str().to_str()
-            }).map(|c| {
-                c.starts_with("10.") && dir.join("ucrt").is_dir()
-            }).unwrap_or(false)
-        }).max());
+        let max_libdir = otry!(readdir.filter_map(|dir| dir.ok())
+            .map(|dir| dir.path())
+            .filter(|dir| {
+                dir.components()
+                    .last()
+                    .and_then(|c| c.as_os_str().to_str())
+                    .map(|c| c.starts_with("10.") && dir.join("ucrt").is_dir())
+                    .unwrap_or(false)
+            })
+            .max());
         let version = max_libdir.components().last().unwrap();
         let version = version.as_os_str().to_str().unwrap().to_string();
         Some((root.into(), version))
@@ -270,12 +265,13 @@ fn get_sdk10_dir() -> Option<(PathBuf, String)> {
         let root = otry!(key.query_str("InstallationFolder").ok());
         let readdir = otry!(Path::new(&root).join("lib").read_dir().ok());
         let mut dirs = readdir.filter_map(|dir| dir.ok())
-                              .map(|dir| dir.path())
-                              .collect::<Vec<_>>();
+            .map(|dir| dir.path())
+            .collect::<Vec<_>>();
         dirs.sort();
-        let dir = otry!(dirs.into_iter().rev().filter(|dir| {
-            dir.join("um").join("x64").join("kernel32.lib").is_file()
-        }).next());
+        let dir = otry!(dirs.into_iter()
+            .rev()
+            .filter(|dir| dir.join("um").join("x64").join("kernel32.lib").is_file())
+            .next());
         let version = dir.components().last().unwrap();
         let version = version.as_os_str().to_str().unwrap().to_string();
         Some((root.into(), version))
@@ -319,10 +315,8 @@ fn get_sdk8_dir() -> Option<PathBuf> {
     fn bin_subdir(target: &str) -> Vec<(&'static str, &'static str)> {
         let arch = target.split('-').next().unwrap();
         match (arch, host_arch()) {
-            ("i586", X86) |
-            ("i686", X86) => vec![("", "")],
-            ("i586", X86_64) |
-            ("i686", X86_64) => vec![("amd64_x86", "amd64"), ("", "")],
+            ("i586", X86) | ("i686", X86) => vec![("", "")],
+            ("i586", X86_64) | ("i686", X86_64) => vec![("amd64_x86", "amd64"), ("", "")],
             ("x86_64", X86) => vec![("x86_amd64", "")],
             ("x86_64", X86_64) => vec![("amd64", "amd64"), ("x86_amd64", "")],
             ("arm", X86) => vec![("x86_arm", "")],
@@ -393,9 +387,8 @@ fn max_version(key: &RegistryKey) -> Option<(OsString, RegistryKey)> {
         let mut max_vers = 0;
         let mut max_key = None;
         for subkey in key.iter().filter_map(|k| k.ok()) {
-            let val = subkey.to_str().and_then(|s| {
-                s.trim_left_matches("v").replace(".", "").parse().ok()
-            });
+            let val = subkey.to_str()
+                .and_then(|s| s.trim_left_matches("v").replace(".", "").parse().ok());
             let val = match val {
                 Some(s) => s,
                 None => continue,
@@ -407,24 +400,25 @@ fn max_version(key: &RegistryKey) -> Option<(OsString, RegistryKey)> {
                 }
             }
         }
-        return max_key
+        max_key
     }
 
     // see http://stackoverflow.com/questions/328017/path-to-msbuild
     fn find_msbuild(target: &str) -> Option<Tool> {
         let key = r"SOFTWARE\Microsoft\MSBuild\ToolsVersions";
-        LOCAL_MACHINE.open(key.as_ref()).ok().and_then(|key| {
-            max_version(&key).and_then(|(_vers, key)| {
-                key.query_str("MSBuildToolsPath").ok()
+        LOCAL_MACHINE.open(key.as_ref())
+            .ok()
+            .and_then(|key| {
+                max_version(&key).and_then(|(_vers, key)| key.query_str("MSBuildToolsPath").ok())
+            })
+            .map(|path| {
+                let mut path = PathBuf::from(path);
+                path.push("MSBuild.exe");
+                let mut tool = Tool::new(path);
+                if target.contains("x86_64") {
+                    tool.env.push(("Platform".into(), "X64".into()));
+                }
+                tool
             })
-        }).map(|path| {
-            let mut path = PathBuf::from(path);
-            path.push("MSBuild.exe");
-            let mut tool = Tool::new(path);
-            if target.contains("x86_64") {
-                tool.env.push(("Platform".into(), "X64".into()));
-            }
-            tool
-        })
     }
 }
index 5c40984eb6a0999f27ba3195f7827324620957b4..135a6635b5935ae206759a2c8dcd49e77829b1fe 100644 (file)
@@ -37,28 +37,27 @@ pub fn new() -> Test {
     pub fn gnu() -> Test {
         let t = Test::new();
         t.shim("cc").shim("ar");
-        return t
+        t
     }
 
     pub fn msvc() -> Test {
         let mut t = Test::new();
         t.shim("cl").shim("lib.exe");
         t.msvc = true;
-        return t
+        t
     }
 
     pub fn shim(&self, name: &str) -> &Test {
         let fname = format!("{}{}", name, env::consts::EXE_SUFFIX);
-        fs::hard_link(&self.gcc, self.td.path().join(&fname)).or_else(|_| {
-            fs::copy(&self.gcc, self.td.path().join(&fname)).map(|_| ())
-        }).unwrap();
+        fs::hard_link(&self.gcc, self.td.path().join(&fname))
+            .or_else(|_| fs::copy(&self.gcc, self.td.path().join(&fname)).map(|_| ()))
+            .unwrap();
         self
     }
 
     pub fn gcc(&self) -> gcc::Config {
         let mut cfg = gcc::Config::new();
-        let mut path = env::split_paths(&env::var_os("PATH").unwrap())
-                           .collect::<Vec<_>>();
+        let mut path = env::split_paths(&env::var_os("PATH").unwrap()).collect::<Vec<_>>();
         path.insert(0, self.td.path().to_owned());
         let target = if self.msvc {
             "x86_64-pc-windows-msvc"
@@ -66,26 +65,27 @@ pub fn gcc(&self) -> gcc::Config {
             "x86_64-unknown-linux-gnu"
         };
 
-        cfg.target(target).host(target)
-           .opt_level(2)
-           .debug(false)
-           .out_dir(self.td.path())
-           .__set_env("PATH", env::join_paths(path).unwrap())
-           .__set_env("GCCTEST_OUT_DIR", self.td.path());
+        cfg.target(target)
+            .host(target)
+            .opt_level(2)
+            .debug(false)
+            .out_dir(self.td.path())
+            .__set_env("PATH", env::join_paths(path).unwrap())
+            .__set_env("GCCTEST_OUT_DIR", self.td.path());
         if self.msvc {
             cfg.compiler(self.td.path().join("cl"));
             cfg.archiver(self.td.path().join("lib.exe"));
         }
-        return cfg
+        cfg
     }
 
     pub fn cmd(&self, i: u32) -> Execution {
         let mut s = String::new();
-        File::open(self.td.path().join(format!("out{}", i))).unwrap()
-             .read_to_string(&mut s).unwrap();
-        Execution {
-            args: s.lines().map(|s| s.to_string()).collect(),
-        }
+        File::open(self.td.path().join(format!("out{}", i)))
+            .unwrap()
+            .read_to_string(&mut s)
+            .unwrap();
+        Execution { args: s.lines().map(|s| s.to_string()).collect() }
     }
 }
 
@@ -107,8 +107,6 @@ pub fn must_not_have<P: AsRef<OsStr>>(&self, p: P) -> &Execution {
     }
 
     pub fn has(&self, p: &OsStr) -> bool {
-        self.args.iter().any(|arg| {
-            OsStr::new(arg) == p
-        })
+        self.args.iter().any(|arg| OsStr::new(arg) == p)
     }
 }
index 1b6a0bd0d10a6b92cfc8c68f0dac89724d19ee90..5a034ff347b240de930e3a28ab5cb60bfa5d211a 100644 (file)
@@ -9,14 +9,16 @@
 fn gnu_smoke() {
     let test = Test::gnu();
     test.gcc()
-        .file("foo.c").compile("libfoo.a");
-
-    test.cmd(0).must_have("-O2")
-               .must_have("foo.c")
-               .must_not_have("-g")
-               .must_have("-c")
-               .must_have("-ffunction-sections")
-               .must_have("-fdata-sections");
+        .file("foo.c")
+        .compile("libfoo.a");
+
+    test.cmd(0)
+        .must_have("-O2")
+        .must_have("foo.c")
+        .must_not_have("-g")
+        .must_have("-c")
+        .must_have("-ffunction-sections")
+        .must_have("-fdata-sections");
     test.cmd(1).must_have(test.td.path().join("foo.o"));
 }
 
@@ -25,10 +27,12 @@ fn gnu_opt_level_1() {
     let test = Test::gnu();
     test.gcc()
         .opt_level(1)
-        .file("foo.c").compile("libfoo.a");
+        .file("foo.c")
+        .compile("libfoo.a");
 
-    test.cmd(0).must_have("-O1")
-               .must_not_have("-O2");
+    test.cmd(0)
+        .must_have("-O1")
+        .must_not_have("-O2");
 }
 
 #[test]
@@ -36,13 +40,15 @@ fn gnu_opt_level_s() {
     let test = Test::gnu();
     test.gcc()
         .opt_level_str("s")
-        .file("foo.c").compile("libfoo.a");
+        .file("foo.c")
+        .compile("libfoo.a");
 
-    test.cmd(0).must_have("-Os")
-               .must_not_have("-O1")
-               .must_not_have("-O2")
-               .must_not_have("-O3")
-               .must_not_have("-Oz");
+    test.cmd(0)
+        .must_have("-Os")
+        .must_not_have("-O1")
+        .must_not_have("-O2")
+        .must_not_have("-O3")
+        .must_not_have("-Oz");
 }
 
 #[test]
@@ -50,7 +56,8 @@ fn gnu_debug() {
     let test = Test::gnu();
     test.gcc()
         .debug(true)
-        .file("foo.c").compile("libfoo.a");
+        .file("foo.c")
+        .compile("libfoo.a");
     test.cmd(0).must_have("-g");
 }
 
@@ -62,10 +69,12 @@ fn gnu_x86_64() {
         test.gcc()
             .target(&target)
             .host(&target)
-            .file("foo.c").compile("libfoo.a");
+            .file("foo.c")
+            .compile("libfoo.a");
 
-        test.cmd(0).must_have("-fPIC")
-                   .must_have("-m64");
+        test.cmd(0)
+            .must_have("-fPIC")
+            .must_have("-m64");
     }
 }
 
@@ -78,7 +87,8 @@ fn gnu_x86_64_no_pic() {
             .pic(false)
             .target(&target)
             .host(&target)
-            .file("foo.c").compile("libfoo.a");
+            .file("foo.c")
+            .compile("libfoo.a");
 
         test.cmd(0).must_not_have("-fPIC");
     }
@@ -92,10 +102,12 @@ fn gnu_i686() {
         test.gcc()
             .target(&target)
             .host(&target)
-            .file("foo.c").compile("libfoo.a");
+            .file("foo.c")
+            .compile("libfoo.a");
 
-        test.cmd(0).must_not_have("-fPIC")
-                   .must_have("-m32");
+        test.cmd(0)
+            .must_not_have("-fPIC")
+            .must_have("-m32");
     }
 }
 
@@ -108,7 +120,8 @@ fn gnu_i686_pic() {
             .pic(true)
             .target(&target)
             .host(&target)
-            .file("foo.c").compile("libfoo.a");
+            .file("foo.c")
+            .compile("libfoo.a");
 
         test.cmd(0).must_have("-fPIC");
     }
@@ -119,7 +132,8 @@ fn gnu_set_stdlib() {
     let test = Test::gnu();
     test.gcc()
         .cpp_set_stdlib(Some("foo"))
-        .file("foo.c").compile("libfoo.a");
+        .file("foo.c")
+        .compile("libfoo.a");
 
     test.cmd(0).must_not_have("-stdlib=foo");
 }
@@ -129,7 +143,8 @@ fn gnu_include() {
     let test = Test::gnu();
     test.gcc()
         .include("foo/bar")
-        .file("foo.c").compile("libfoo.a");
+        .file("foo.c")
+        .compile("libfoo.a");
 
     test.cmd(0).must_have("-I").must_have("foo/bar");
 }
@@ -140,7 +155,8 @@ fn gnu_define() {
     test.gcc()
         .define("FOO", Some("bar"))
         .define("BAR", None)
-        .file("foo.c").compile("libfoo.a");
+        .file("foo.c")
+        .compile("libfoo.a");
 
     test.cmd(0).must_have("-DFOO=bar").must_have("-DBAR");
 }
@@ -149,7 +165,8 @@ fn gnu_define() {
 fn gnu_compile_assembly() {
     let test = Test::gnu();
     test.gcc()
-        .file("foo.S").compile("libfoo.a");
+        .file("foo.S")
+        .compile("libfoo.a");
     test.cmd(0).must_have("foo.S");
 }
 
@@ -157,12 +174,14 @@ fn gnu_compile_assembly() {
 fn msvc_smoke() {
     let test = Test::msvc();
     test.gcc()
-        .file("foo.c").compile("libfoo.a");
-
-    test.cmd(0).must_have("/O2")
-               .must_have("foo.c")
-               .must_not_have("/Z7")
-               .must_have("/c");
+        .file("foo.c")
+        .compile("libfoo.a");
+
+    test.cmd(0)
+        .must_have("/O2")
+        .must_have("foo.c")
+        .must_not_have("/Z7")
+        .must_have("/c");
     test.cmd(1).must_have(test.td.path().join("foo.o"));
 }
 
@@ -171,7 +190,8 @@ fn msvc_opt_level_0() {
     let test = Test::msvc();
     test.gcc()
         .opt_level(0)
-        .file("foo.c").compile("libfoo.a");
+        .file("foo.c")
+        .compile("libfoo.a");
 
     test.cmd(0).must_not_have("/O2");
 }
@@ -181,7 +201,8 @@ fn msvc_debug() {
     let test = Test::msvc();
     test.gcc()
         .debug(true)
-        .file("foo.c").compile("libfoo.a");
+        .file("foo.c")
+        .compile("libfoo.a");
     test.cmd(0).must_have("/Z7");
 }
 
@@ -190,7 +211,8 @@ fn msvc_include() {
     let test = Test::msvc();
     test.gcc()
         .include("foo/bar")
-        .file("foo.c").compile("libfoo.a");
+        .file("foo.c")
+        .compile("libfoo.a");
 
     test.cmd(0).must_have("/I").must_have("foo/bar");
 }
@@ -201,7 +223,8 @@ fn msvc_define() {
     test.gcc()
         .define("FOO", Some("bar"))
         .define("BAR", None)
-        .file("foo.c").compile("libfoo.a");
+        .file("foo.c")
+        .compile("libfoo.a");
 
     test.cmd(0).must_have("/DFOO=bar").must_have("/DBAR");
 }