bug 1409276 - vendor a newer version of the cc crate. r=mbrubreck
authorTed Mielczarek <ted@mielczarek.org>
Wed, 11 Jul 2018 07:21:48 -0400
changeset 487028 ee4bd7464329a1b284d484554e22fdc1ee6fb954
parent 487027 5f20a8a55268a579911b0494243a34311e836ec6
child 487029 43eacc8458b87a83278cb6aed42d88c9409a73c7
push id1815
push userffxbld-merge
push dateMon, 15 Oct 2018 10:40:45 +0000
treeherdermozilla-release@18d4c09e9378 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmbrubreck
bugs1409276
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 1409276 - vendor a newer version of the cc crate. r=mbrubreck The cc crate had a bug where it would ignore compiler arguments in compilers specified in environment variables. We update to a copy with that issue fixed: https://github.com/alexcrichton/cc-rs/commit/9eaa56536ec420c7248cb52e10d3538568700d62 MozReview-Commit-ID: FE8AywUEMoc
Cargo.lock
third_party/rust/cc/.cargo-checksum.json
third_party/rust/cc/.travis.yml
third_party/rust/cc/Cargo.toml
third_party/rust/cc/src/lib.rs
third_party/rust/cc/src/windows_registry.rs
third_party/rust/cc/tests/test.rs
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -264,23 +264,23 @@ dependencies = [
  "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "bzip2-sys"
 version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cc"
-version = "1.0.9"
+version = "1.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "cexpr"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -325,17 +325,17 @@ dependencies = [
  "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cmake"
 version = "0.1.29"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cookie"
 version = "0.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1064,17 +1064,17 @@ name = "libc"
 version = "0.2.39"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "libloading"
 version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "libudev"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -1209,17 +1209,17 @@ dependencies = [
  "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "miniz_oxide_c_api"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
  "miniz_oxide 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "mio"
 version = "0.6.9"
@@ -2551,17 +2551,17 @@ dependencies = [
 "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
 "checksum bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "80b13e2ab064ff3aa0bdbf1eff533f9822dc37899821f5f98c67f263eab51707"
 "checksum boxfnonce 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8380105befe91099e6f69206164072c05bc92427ff6aa8a5171388317346dd75"
 "checksum build_const 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e90dc84f5e62d2ebe7676b83c22d33b6db8bd27340fb6ffbff0a364efa0cb9c9"
 "checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
 "checksum bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d828f97b58cc5de3e40c421d0cf2132d6b2da4ee0e11b8632fa838f0f9333ad6"
 "checksum bzip2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3eafc42c44e0d827de6b1c131175098fe7fb53b8ce8a47e65cb3ea94688be24"
 "checksum bzip2-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2c5162604199bbb17690ede847eaa6120a3f33d5ab4dcc8e7c25b16d849ae79b"
-"checksum cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2b4911e4bdcb4100c7680e7e854ff38e23f1b34d4d9e079efae3da2801341ffc"
+"checksum cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "2119ea4867bd2b8ed3aecab467709720b2d55b1bcfe09f772fd68066eaf15275"
 "checksum cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393a5f0088efbe41f9d1fcd062f24e83c278608420e62109feb2c8abee07de7d"
 "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
 "checksum chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00"
 "checksum clang-sys 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7f7c04e52c35222fffcc3a115b5daf5f7e2bfb71c13c4e2321afe1fc71859c2"
 "checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536"
 "checksum cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "56d741ea7a69e577f6d06b36b7dff4738f680593dc27a701ffa8506b73ce28bb"
 "checksum cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "746858cae4eae40fff37e1998320068df317bc247dc91a67c6cfa053afdc2abb"
 "checksum core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7caa6cb9e76ddddbea09a03266d6b3bc98cd41e9fb9b017c473e7cca593ec25"
--- a/third_party/rust/cc/.cargo-checksum.json
+++ b/third_party/rust/cc/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".travis.yml":"04e69a35c252b62a8b2a47c5bd2b8dcdfbfb97e9457fe78b2f310eb710a2a781","Cargo.toml":"8829f9474c56e0deb7279d19a303243130a46e2f0b46731c5fa68eddfa5824b1","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"186c5c8a62520cb7a3d90d77161c954b52ae8456fca0e0669bc3a5b889592a43","appveyor.yml":"ab45bfdcf2596f357225a54e730c34d518a8f3ad56c2ed33af682cfd45bddc02","src/bin/gcc-shim.rs":"d6be9137cb48b86891e7b263adbf492e1193ffe682db9ba4a88eb1079b874b58","src/com.rs":"8b9a54af5400c259f877126cc68ea63ada4fe66e84c9b840711c95e570b15774","src/lib.rs":"6e8cea99f5fc8e5982b1ea9a336ee2f9a6158a9498c8f0c36f1e8cee8c99716e","src/registry.rs":"3cc1b5a50879fa751572878ae1d0afbfc960c11665258492754b2c8bccb0ff5d","src/setup_config.rs":"f5c45afc99ad3b7c1311242bc4baf37e861d740ab81bf6ca90e2aa283672e65a","src/winapi.rs":"d7929b36130e33f1caa6bd444b378b83023b2b82d589c6e0ab38c4ff6c950da8","src/windows_registry.rs":"5caea0d9ff6513a1fa2908cf8f72906da981af8de8756bae3ca182d755bdf552","tests/cc_env.rs":"bf7b14aa52af04294f648b2934f0f1830c5a0bdac1676310b8aa1f61458e7782","tests/support/mod.rs":"80dc87e54025197104cfb62d1af7a3400a3a0ddf0f2d98ea4ef4111cb1f0c890","tests/test.rs":"42a771b1b6e1ed83b31204439b8ba5190b151ae93d5fa402a18851273df39cc0"},"package":"2b4911e4bdcb4100c7680e7e854ff38e23f1b34d4d9e079efae3da2801341ffc"}
\ No newline at end of file
+{"files":{".travis.yml":"26bcb4e14726789c4bdf8783f445820c012d82d623ea51beb985d4d4ec870733","Cargo.toml":"b921b2f55193e3c4b09fa93329734c5811fb1e5a08c5fb6f10b960147403564d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"186c5c8a62520cb7a3d90d77161c954b52ae8456fca0e0669bc3a5b889592a43","appveyor.yml":"ab45bfdcf2596f357225a54e730c34d518a8f3ad56c2ed33af682cfd45bddc02","src/bin/gcc-shim.rs":"d6be9137cb48b86891e7b263adbf492e1193ffe682db9ba4a88eb1079b874b58","src/com.rs":"8b9a54af5400c259f877126cc68ea63ada4fe66e84c9b840711c95e570b15774","src/lib.rs":"f0b231d2e1923d43cd987278ccf4f20d55a6da4e2959061f57434d87428f003d","src/registry.rs":"3cc1b5a50879fa751572878ae1d0afbfc960c11665258492754b2c8bccb0ff5d","src/setup_config.rs":"f5c45afc99ad3b7c1311242bc4baf37e861d740ab81bf6ca90e2aa283672e65a","src/winapi.rs":"d7929b36130e33f1caa6bd444b378b83023b2b82d589c6e0ab38c4ff6c950da8","src/windows_registry.rs":"e31ce7a3273d67f99387edf28c5a9b4d6efab8f03fe446079c2b1ede6a21ffdb","tests/cc_env.rs":"bf7b14aa52af04294f648b2934f0f1830c5a0bdac1676310b8aa1f61458e7782","tests/support/mod.rs":"80dc87e54025197104cfb62d1af7a3400a3a0ddf0f2d98ea4ef4111cb1f0c890","tests/test.rs":"a6f4fde55631b0a8726cfb026791759c92720a5ba890e6989e9405d5acf461db"},"package":"2119ea4867bd2b8ed3aecab467709720b2d55b1bcfe09f772fd68066eaf15275"}
\ No newline at end of file
--- a/third_party/rust/cc/.travis.yml
+++ b/third_party/rust/cc/.travis.yml
@@ -13,20 +13,16 @@ matrix:
     - os: osx
       env: TARGET=x86_64-apple-darwin NO_ADD=1
     - os: osx
       env: TARGET=aarch64-apple-ios NO_RUN=--no-run TARGET_SYSROOT=$(xcrun -sdk iphoneos --show-sdk-path)
     - rust: beta
       env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1
     - rust: nightly
       env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1
-    - install: rustup component add rustfmt-preview
-      script:
-        - cargo fmt -- --write-mode diff
-        - (cd cc-test && cargo fmt -- --write-mode diff)
 
     - rust: nightly
       before_script:
         - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH
       install:
       script:
         - cargo doc --no-deps --all-features
       after_success:
--- a/third_party/rust/cc/Cargo.toml
+++ b/third_party/rust/cc/Cargo.toml
@@ -7,17 +7,17 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "cc"
-version = "1.0.9"
+version = "1.0.18"
 authors = ["Alex Crichton <alex@alexcrichton.com>"]
 description = "A build-time dependency for Cargo build scripts to assist in invoking the native\nC compiler to compile native C code into a static archive to be linked into Rust\ncode.\n"
 homepage = "https://github.com/alexcrichton/cc-rs"
 documentation = "https://docs.rs/cc"
 readme = "README.md"
 keywords = ["build-dependencies"]
 categories = ["development-tools"]
 license = "MIT/Apache-2.0"
--- a/third_party/rust/cc/src/lib.rs
+++ b/third_party/rust/cc/src/lib.rs
@@ -112,16 +112,17 @@ pub struct Build {
     archiver: Option<PathBuf>,
     cargo_metadata: bool,
     pic: Option<bool>,
     static_crt: Option<bool>,
     shared_flag: Option<bool>,
     static_flag: Option<bool>,
     warnings_into_errors: bool,
     warnings: bool,
+    extra_warnings: bool,
 }
 
 /// Represents the types of errors that may occur while using cc-rs.
 #[derive(Clone, Debug)]
 enum ErrorKind {
     /// Error occurred while performing I/O.
     IOError,
     /// Invalid architecture supplied.
@@ -184,77 +185,82 @@ pub struct Tool {
 #[derive(Copy, Clone, Debug, PartialEq)]
 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,
+    Msvc { clang_cl: bool },
 }
 
 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::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::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::Msvc { .. } => "/E",
             ToolFamily::Gnu | ToolFamily::Clang => "-E",
         }
     }
 
     /// What the flags to enable all warnings
-    fn warnings_flags(&self) -> &'static [&'static str] {
-        static MSVC_FLAGS: &'static [&'static str] = &["/W4"];
-        static GNU_CLANG_FLAGS: &'static [&'static str] = &["-Wall", "-Wextra"];
+    fn warnings_flags(&self) -> &'static str {
+        match *self {
+            ToolFamily::Msvc { .. } => "/W4",
+            ToolFamily::Gnu | ToolFamily::Clang => "-Wall",
+        }
+    }
 
+    /// What the flags to enable extra warnings
+    fn extra_warnings_flags(&self) -> Option<&'static str> {
         match *self {
-            ToolFamily::Msvc => &MSVC_FLAGS,
-            ToolFamily::Gnu | ToolFamily::Clang => &GNU_CLANG_FLAGS,
+            ToolFamily::Msvc { .. } => None,
+            ToolFamily::Gnu | ToolFamily::Clang => Some("-Wextra"),
         }
     }
 
     /// What the flag to turn warning into errors
     fn warnings_to_errors_flag(&self) -> &'static str {
         match *self {
-            ToolFamily::Msvc => "/WX",
+            ToolFamily::Msvc { .. } => "/WX",
             ToolFamily::Gnu | ToolFamily::Clang => "-Werror",
         }
     }
 
     /// NVCC-specific. Device code debug info flag. This is separate from the
     /// debug info flag passed to the C++ compiler.
     fn nvcc_debug_flag(&self) -> &'static str {
         match *self {
-            ToolFamily::Msvc => unimplemented!(),
+            ToolFamily::Msvc { .. } => unimplemented!(),
             ToolFamily::Gnu | ToolFamily::Clang => "-G",
         }
     }
 
     /// NVCC-specific. Redirect the following flag to the underlying C++
     /// compiler.
     fn nvcc_redirect_flag(&self) -> &'static str {
         match *self {
-            ToolFamily::Msvc => unimplemented!(),
+            ToolFamily::Msvc { .. } => unimplemented!(),
             ToolFamily::Gnu | ToolFamily::Clang => "-Xcompiler",
         }
     }
 }
 
 /// Represents an object.
 ///
 /// This is a source file -> object file pair.
@@ -299,16 +305,17 @@ impl Build {
             debug: None,
             env: Vec::new(),
             compiler: None,
             archiver: None,
             cargo_metadata: true,
             pic: None,
             static_crt: None,
             warnings: true,
+            extra_warnings: true,
             warnings_into_errors: false,
         }
     }
 
     /// Add a directory to the `-I` or include path for headers
     ///
     /// # Example
     ///
@@ -401,21 +408,22 @@ impl Build {
         if let Some(is_supported) = known_status.get(flag).cloned() {
             return Ok(is_supported);
         }
 
         let out_dir = self.get_out_dir()?;
         let src = self.ensure_check_file()?;
         let obj = out_dir.join("flag_check");
         let target = self.get_target()?;
+        let host = self.get_host()?;
         let mut cfg = Build::new();
         cfg.flag(flag)
             .target(&target)
             .opt_level(0)
-            .host(&target)
+            .host(&host)
             .debug(false)
             .cpp(self.cpp)
             .cuda(self.cuda);
         let compiler = cfg.try_get_compiler()?;
         let mut cmd = compiler.to_command();
         let is_arm = target.contains("aarch64") || target.contains("arm");
         command_add_output_file(&mut cmd, &obj, target.contains("msvc"), false, is_arm);
 
@@ -568,25 +576,50 @@ impl Build {
     /// ```no_run
     /// cc::Build::new()
     ///     .file("src/foo.c")
     ///     .warnings(false)
     ///     .compile("libfoo.a");
     /// ```
     pub fn warnings(&mut self, warnings: bool) -> &mut Build {
         self.warnings = warnings;
+        self.extra_warnings = warnings;
+        self
+    }
+
+    /// Set extra warnings flags.
+    ///
+    /// Adds some flags:
+    /// - nothing for MSVC.
+    /// - "-Wextra" for GNU and Clang.
+    ///
+    /// Enabled by default.
+    ///
+    /// # Example
+    ///
+    /// ```no_run
+    /// // Disables -Wextra, -Wall remains enabled:
+    /// cc::Build::new()
+    ///     .file("src/foo.c")
+    ///     .extra_warnings(false)
+    ///     .compile("libfoo.a");
+    /// ```
+    pub fn extra_warnings(&mut self, warnings: bool) -> &mut Build {
+        self.extra_warnings = warnings;
         self
     }
 
     /// Set the standard library to link against when compiling with C++
     /// support.
     ///
     /// The default value of this property depends on the current target: On
     /// OS X `Some("c++")` is used, when compiling for a Visual Studio based
     /// target `None` is used and for other targets `Some("stdc++")` is used.
+    /// If the `CXXSTDLIB` environment variable is set, its value will
+    /// override the default value.
     ///
     /// A value of `None` indicates that no automatic linking should happen,
     /// otherwise cargo will link against the specified library.
     ///
     /// The given library name must not contain the `lib` prefix.
     ///
     /// Common values:
     /// - `stdc++` for GNU
@@ -1022,17 +1055,17 @@ impl Build {
         let opt_level = self.get_opt_level()?;
         let target = self.get_target()?;
 
         let mut cmd = self.get_base_compiler()?;
 
         // Non-target flags
         // If the flag is not conditioned on target variable, it belongs here :)
         match cmd.family {
-            ToolFamily::Msvc => {
+            ToolFamily::Msvc { .. } => {
                 assert!(!self.cuda,
                     "CUDA C++ compilation not supported for MSVC, yet... but you are welcome to implement it :)");
 
                 cmd.args.push("/nologo".into());
 
                 let crt_flag = match self.static_crt {
                     Some(true) => "/MT",
                     Some(false) => "/MD",
@@ -1087,48 +1120,70 @@ impl Build {
             cmd.push_cc_arg(debug_flag);
         }
 
         // Target flags
         match cmd.family {
             ToolFamily::Clang => {
                 cmd.args.push(format!("--target={}", target).into());
             }
-            ToolFamily::Msvc => {
-                if target.contains("i586") {
-                    cmd.args.push("/ARCH:IA32".into());
+            ToolFamily::Msvc { clang_cl } => {
+                if clang_cl {
+                    if target.contains("x86_64") {
+                        cmd.args.push("-m64".into());
+                    } else if target.contains("i586") {
+                        cmd.args.push("-m32".into());
+                        cmd.args.push("/arch:IA32".into());
+                    } else {
+                        cmd.args.push("-m32".into());
+                    }
+                } else {
+                    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 == "x86_64-unknown-linux-gnux32" {
                     cmd.args.push("-mx32".into());
                 } else if target.contains("x86_64") || target.contains("powerpc64") {
                     cmd.args.push("-m64".into());
                 }
 
-                if self.static_flag.is_none() && target.contains("musl") {
-                    cmd.args.push("-static".into());
+                if self.static_flag.is_none() {
+                    let features = env::var("CARGO_CFG_TARGET_FEATURE").unwrap_or(String::new());
+                    if features.contains("crt-static") {
+                        cmd.args.push("-static".into());
+                    }
                 }
 
                 // armv7 targets get to use armv7 instructions
-                if target.starts_with("armv7-") && target.contains("-linux-") {
+                if (target.starts_with("armv7") || target.starts_with("thumbv7")) && target.contains("-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());
+                // (x86 Android doesn't say "eabi")
+                if target.contains("-androideabi") && target.contains("v7") {
+                    // -march=armv7-a handled above
                     cmd.args.push("-mthumb".into());
-                    cmd.args.push("-mfpu=vfpv3-d16".into());
+                    if !target.contains("neon") {
+                        // On android we can guarantee some extra float instructions
+                        // (specified in the android spec online)
+                        // NEON guarantees even more; see below.
+                        cmd.args.push("-mfpu=vfpv3-d16".into());
+                    }
                     cmd.args.push("-mfloat-abi=softfp".into());
                 }
 
+                if target.contains("neon") {
+                    cmd.args.push("-mfpu=neon-vfpv4".into());
+                }
+
                 if target.starts_with("armv4t-unknown-linux-") {
                     cmd.args.push("-march=armv4t".into());
                     cmd.args.push("-marm".into());
                     cmd.args.push("-mfloat-abi=soft".into());
                 }
 
                 if target.starts_with("armv5te-unknown-linux-") {
                     cmd.args.push("-march=armv5te".into());
@@ -1223,33 +1278,38 @@ impl Build {
         }
 
         for directory in self.include_directories.iter() {
             cmd.args.push(cmd.family.include_flag().into());
             cmd.args.push(directory.into());
         }
 
         if self.warnings {
-            for flag in cmd.family.warnings_flags().iter() {
-                cmd.push_cc_arg(flag.into());
+            let wflags = cmd.family.warnings_flags().into();
+            cmd.push_cc_arg(wflags);
+        }
+
+        if self.extra_warnings {
+            if let Some(wflags) = cmd.family.extra_warnings_flags() {
+                cmd.push_cc_arg(wflags.into());
             }
         }
 
         for flag in self.flags.iter() {
             cmd.args.push(flag.into());
         }
 
         for flag in self.flags_supported.iter() {
             if self.is_flag_supported(flag).unwrap_or(false) {
                 cmd.push_cc_arg(flag.into());
             }
         }
 
         for &(ref key, ref value) in self.definitions.iter() {
-            let lead = if let ToolFamily::Msvc = cmd.family {
+            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 {
                 cmd.args.push(format!("{}D{}", lead, key).into());
@@ -1485,16 +1545,18 @@ impl Build {
 
         // On Solaris, c++/cc unlikely to exist or be correct.
         let default = if host.contains("solaris") {
             gnu
         } else {
             traditional
         };
 
+        let cl_exe = windows_registry::find_tool(&target, "cl.exe");
+
         let tool_opt: Option<Tool> = self.env_tool(env)
             .map(|(tool, cc, args)| {
                 // chop off leading/trailing whitespace to work around
                 // semi-buggy build scripts which are shared in
                 // makefiles/configure scripts (where spaces are far more
                 // lenient)
                 let mut t = Tool::new(PathBuf::from(tool.trim()));
                 if let Some(cc) = cc {
@@ -1516,29 +1578,37 @@ impl Build {
                         Some(t)
                     } else {
                         Some(Tool::new(PathBuf::from(tool)))
                     }
                 } else {
                     None
                 }
             })
-            .or_else(|| windows_registry::find_tool(&target, "cl.exe"));
+            .or_else(|| cl_exe.clone());
 
         let tool = match tool_opt {
             Some(t) => t,
             None => {
                 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)
+                    format!(
+                        "{}-{}",
+                        target
+                            .replace("armv7", "arm")
+                            .replace("armv7neon", "arm")
+                            .replace("thumbv7", "arm")
+                            .replace("thumbv7neon", "arm"),
+                        gnu
+                    )
                 } else if target.contains("cloudabi") {
                     format!("{}-{}", target, traditional)
                 } 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"),
@@ -1549,16 +1619,22 @@ impl Build {
                         "arm-frc-linux-gnueabi" => Some("arm-frc-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-netbsd-eabi" => Some("arm--netbsdelf-eabi"),
                         "armv6-unknown-netbsd-eabihf" => Some("armv6--netbsdelf-eabihf"),
                         "armv7-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"),
                         "armv7-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"),
+                        "armv7neon-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"),
+                        "armv7neon-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"),
+                        "thumbv7-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"),
+                        "thumbv7-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"),
+                        "thumbv7neon-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"),
+                        "thumbv7neon-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"),
                         "armv7-unknown-netbsd-eabihf" => Some("armv7--netbsdelf-eabihf"),
                         "i586-unknown-linux-musl" => Some("musl"),
                         "i686-pc-windows-gnu" => Some("i686-w64-mingw32"),
                         "i686-unknown-linux-musl" => Some("musl"),
                         "i686-unknown-netbsd" => 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"),
@@ -1589,17 +1665,17 @@ impl Build {
                     }
                 } else {
                     default.to_string()
                 };
                 Tool::new(PathBuf::from(compiler))
             }
         };
 
-        let tool = if self.cuda {
+        let mut tool = if self.cuda {
             assert!(
                 tool.args.is_empty(),
                 "CUDA compilation currently assumes empty pre-existing args"
             );
             let nvcc = match self.get_var("NVCC") {
                 Err(_) => "nvcc".into(),
                 Ok(nvcc) => nvcc,
             };
@@ -1607,16 +1683,37 @@ impl Build {
             nvcc_tool
                 .args
                 .push(format!("-ccbin={}", tool.path.display()).into());
             nvcc_tool
         } else {
             tool
         };
 
+        // If we found `cl.exe` in our environment, the tool we're returning is
+        // an MSVC-like tool, *and* no env vars were set then set env vars for
+        // the tool that we're returning.
+        //
+        // Env vars are needed for things like `link.exe` being put into PATH as
+        // well as header include paths sometimes. These paths are automatically
+        // included by default but if the `CC` or `CXX` env vars are set these
+        // won't be used. This'll ensure that when the env vars are used to
+        // configure for invocations like `clang-cl` we still get a "works out
+        // of the box" experience.
+        if let Some(cl_exe) = cl_exe {
+            if tool.family == (ToolFamily::Msvc { clang_cl: true }) &&
+                tool.env.len() == 0 &&
+                target.contains("msvc")
+            {
+                for &(ref k, ref v) in cl_exe.env.iter() {
+                    tool.env.push((k.to_owned(), v.to_owned()));
+                }
+            }
+        }
+
         Ok(tool)
     }
 
     fn get_var(&self, var_base: &str) -> Result<String, Error> {
         let target = self.get_target()?;
         let host = self.get_host()?;
         let kind = if host == target { "HOST" } else { "TARGET" };
         let target_u = target.replace("-", "_");
@@ -1708,27 +1805,35 @@ impl Build {
     }
 
     /// Returns the default C++ standard library for the current target: `libc++`
     /// for OS X and `libstdc++` for anything else.
     fn get_cpp_link_stdlib(&self) -> Result<Option<String>, Error> {
         match self.cpp_link_stdlib.clone() {
             Some(s) => Ok(s),
             None => {
-                let target = self.get_target()?;
-                if target.contains("msvc") {
-                    Ok(None)
-                } else if target.contains("apple") {
-                    Ok(Some("c++".to_string()))
-                } else if target.contains("freebsd") {
-                    Ok(Some("c++".to_string()))
-                } else if target.contains("openbsd") {
-                    Ok(Some("c++".to_string()))
+                if let Ok(stdlib) = self.get_var("CXXSTDLIB") {
+                    if stdlib.is_empty() {
+                        Ok(None)
+                    } else {
+                        Ok(Some(stdlib))
+                    }
                 } else {
-                    Ok(Some("stdc++".to_string()))
+                    let target = self.get_target()?;
+                    if target.contains("msvc") {
+                        Ok(None)
+                    } else if target.contains("apple") {
+                        Ok(Some("c++".to_string()))
+                    } else if target.contains("freebsd") {
+                        Ok(Some("c++".to_string()))
+                    } else if target.contains("openbsd") {
+                        Ok(Some("c++".to_string()))
+                    } else {
+                        Ok(Some("stdc++".to_string()))
+                    }
                 }
             }
         }
     }
 
     fn get_ar(&self) -> Result<(Command, String), Error> {
         if let Some(ref p) = self.archiver {
             let name = p.file_name().and_then(|s| s.to_str()).unwrap_or("ar");
@@ -1826,22 +1931,25 @@ impl Default for Build {
 impl Tool {
     fn new(path: PathBuf) -> Tool {
         Tool::with_features(path, false)
     }
 
     fn with_features(path: PathBuf, cuda: bool) -> 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") {
+            if fname.contains("clang-cl") {
+                ToolFamily::Msvc { clang_cl: true }
+            } else if fname.contains("cl") &&
+                !fname.contains("cloudabi") &&
+                !fname.contains("uclibc") &&
+                !fname.contains("clang") {
+                ToolFamily::Msvc { clang_cl: false }
+            } else if fname.contains("clang") {
                 ToolFamily::Clang
-            } else if fname.contains("cl") && !fname.contains("cloudabi")
-                && !fname.contains("uclibc")
-            {
-                ToolFamily::Msvc
             } else {
                 ToolFamily::Gnu
             }
         } else {
             ToolFamily::Gnu
         };
         Tool {
             path: path,
@@ -1871,21 +1979,21 @@ impl Tool {
     /// This is useful for when the compiler needs to be executed and the
     /// command returned will already have the initial arguments and environment
     /// variables configured.
     pub fn to_command(&self) -> Command {
         let mut cmd = match self.cc_wrapper_path {
             Some(ref cc_wrapper_path) => {
                 let mut cmd = Command::new(&cc_wrapper_path);
                 cmd.arg(&self.path);
-                cmd.args(&self.cc_wrapper_args);
                 cmd
             }
             None => Command::new(&self.path),
         };
+        cmd.args(&self.cc_wrapper_args);
         cmd.args(&self.args);
         for &(ref k, ref v) in self.env.iter() {
             cmd.env(k, v);
         }
         cmd
     }
 
     /// Returns the path for this compiler.
@@ -1951,17 +2059,20 @@ impl Tool {
 
     /// Whether the tool is Clang-like.
     pub fn is_like_clang(&self) -> bool {
         self.family == ToolFamily::Clang
     }
 
     /// Whether the tool is MSVC-like.
     pub fn is_like_msvc(&self) -> bool {
-        self.family == ToolFamily::Msvc
+        match self.family {
+            ToolFamily::Msvc { .. } => true,
+            _ => false,
+        }
     }
 }
 
 fn run(cmd: &mut Command, program: &str) -> Result<(), Error> {
     let (mut child, print) = spawn(cmd, program)?;
     let status = match child.wait() {
         Ok(s) => s,
         Err(_) => {
--- a/third_party/rust/cc/src/windows_registry.rs
+++ b/third_party/rust/cc/src/windows_registry.rs
@@ -60,16 +60,20 @@ pub fn find_tool(target: &str, tool: &st
 
     // 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 impl_::find_msbuild(target);
     }
 
+    if tool.contains("devenv") {
+        return impl_::find_devenv(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())
@@ -320,16 +324,17 @@ mod impl_ {
         tool.libs.push(ucrt_lib.join("ucrt").join(sub));
 
         if let Some((sdk, version)) = get_sdk10_dir() {
             tool.path.push(sdk.join("bin").join(sub));
             let sdk_lib = sdk.join("lib").join(&version);
             tool.libs.push(sdk_lib.join("um").join(sub));
             let sdk_include = sdk.join("include").join(&version);
             tool.include.push(sdk_include.join("um"));
+            tool.include.push(sdk_include.join("cppwinrt"));
             tool.include.push(sdk_include.join("winrt"));
             tool.include.push(sdk_include.join("shared"));
         } else if let Some(sdk) = get_sdk81_dir() {
             tool.path.push(sdk.join("bin").join(sub));
             let sdk_lib = sdk.join("lib").join("winv6.3");
             tool.libs.push(sdk_lib.join("um").join(sub));
             let sdk_include = sdk.join("include");
             tool.include.push(sdk_include.join("um"));
@@ -616,16 +621,36 @@ mod impl_ {
                     "SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\{}",
                     version
                 )))
                 .is_ok(),
             _ => false,
         }
     }
 
+    pub fn find_devenv(target: &str) -> Option<Tool> {
+        find_devenv_vs15(&target)
+    }
+
+    fn find_devenv_vs15(target: &str) -> Option<Tool> {
+        let key = r"SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7";
+        LOCAL_MACHINE
+            .open(key.as_ref())
+            .ok()
+            .and_then(|key| key.query_str("15.0").ok())
+            .map(|path| {
+                let path = PathBuf::from(path).join(r"Common7\IDE\devenv.exe");
+                let mut tool = Tool::new(path);
+                if target.contains("x86_64") {
+                    tool.env.push(("Platform".into(), "X64".into()));
+                }
+                tool
+            })
+    }
+
     // see http://stackoverflow.com/questions/328017/path-to-msbuild
     pub fn find_msbuild(target: &str) -> Option<Tool> {
         // VS 15 (2017) changed how to locate msbuild
         if let Some(r) = find_msbuild_vs15(target) {
             return Some(r);
         } else {
             find_old_msbuild(target)
         }
--- a/third_party/rust/cc/tests/test.rs
+++ b/third_party/rust/cc/tests/test.rs
@@ -67,16 +67,42 @@ fn gnu_warnings() {
         .flag("-Wno-missing-field-initializers")
         .file("foo.c")
         .compile("foo");
 
     test.cmd(0).must_have("-Wall").must_have("-Wextra");
 }
 
 #[test]
+fn gnu_extra_warnings0() {
+    let test = Test::gnu();
+    test.gcc()
+        .warnings(true)
+        .extra_warnings(false)
+        .flag("-Wno-missing-field-initializers")
+        .file("foo.c")
+        .compile("foo");
+
+    test.cmd(0).must_have("-Wall").must_not_have("-Wextra");
+}
+
+#[test]
+fn gnu_extra_warnings1() {
+    let test = Test::gnu();
+    test.gcc()
+        .warnings(false)
+        .extra_warnings(true)
+        .flag("-Wno-missing-field-initializers")
+        .file("foo.c")
+        .compile("foo");
+
+    test.cmd(0).must_not_have("-Wall").must_have("-Wextra");
+}
+
+#[test]
 fn gnu_warnings_overridable() {
     let test = Test::gnu();
     test.gcc()
         .warnings(true)
         .flag("-Wno-missing-field-initializers")
         .file("foo.c")
         .compile("foo");