Bug 1537643 - update cc crate; r=glandium
authorNathan Froyd <froydnj@mozilla.com>
Wed, 03 Apr 2019 00:06:04 +0000
changeset 467750 1b9e5f4b0589a636233affb84666a469a4cc4ef5
parent 467749 88c2a60599669ee7899764812730b90ce98a1450
child 467751 2e3359dc72e8ae3cca9f3ce2300bed8d60540b50
push id112658
push useraciure@mozilla.com
push dateThu, 04 Apr 2019 04:41:45 +0000
treeherdermozilla-inbound@a36718c8163e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersglandium
bugs1537643
milestone68.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 1537643 - update cc crate; r=glandium This update from the official sources brings in the changes that we were using glandium's fork for, as well as changes enabling us to tweak more settings on Windows. Differential Revision: https://phabricator.services.mozilla.com/D25888
.cargo/config.in
Cargo.lock
Cargo.toml
third_party/rust/cc/.cargo-checksum.json
third_party/rust/cc/.travis.yml
third_party/rust/cc/Cargo.toml
third_party/rust/cc/README.md
third_party/rust/cc/appveyor.yml
third_party/rust/cc/azure-pipelines.yml
third_party/rust/cc/ci/azure-install-rust.yml
third_party/rust/cc/ci/azure-steps.yml
third_party/rust/cc/src/lib.rs
third_party/rust/cc/src/windows_registry.rs
third_party/rust/cc/tests/test.rs
--- a/.cargo/config.in
+++ b/.cargo/config.in
@@ -12,21 +12,16 @@ git = "https://github.com/servo/serde"
 branch = "deserialize_from_enums9"
 replace-with = "vendored-sources"
 
 [source."https://github.com/retep998/winapi-rs"]
 git = "https://github.com/froydnj/winapi-rs"
 branch = "aarch64"
 replace-with = "vendored-sources"
 
-[source."https://github.com/alexcrichton/cc-rs"]
-git = "https://github.com/glandium/cc-rs"
-branch = "1.0.23-clang-cl-aarch64"
-replace-with = "vendored-sources"
-
 [source."https://github.com/rust-lang-nursery/packed_simd"]
 git = "https://github.com/hsivonen/packed_simd"
 branch = "rust_1_32"
 replace-with = "vendored-sources"
 
 [source."https://github.com/CraneStation/target-lexicon"]
 git = "https://github.com/glandium/target-lexicon"
 branch = "thumbv7neon-v0.2"
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,10 +1,8 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
 [[package]]
 name = "Inflector"
 version = "0.11.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -85,17 +83,17 @@ dependencies = [
 ]
 
 [[package]]
 name = "audioipc"
 version = "0.2.4"
 dependencies = [
  "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "cc 1.0.23 (git+https://github.com/glandium/cc-rs?branch=1.0.23-clang-cl-aarch64)",
+ "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
  "cubeb 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "memmap 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "mio-named-pipes 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -152,17 +150,17 @@ dependencies = [
  "winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
 ]
 
 [[package]]
 name = "backtrace-sys"
 version = "0.1.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.23 (git+https://github.com/glandium/cc-rs?branch=1.0.23-clang-cl-aarch64)",
+ "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "baldrdash"
 version = "0.1.0"
 dependencies = [
  "bindgen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -410,29 +408,29 @@ dependencies = [
  "libc 0.2.43 (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.23 (git+https://github.com/glandium/cc-rs?branch=1.0.23-clang-cl-aarch64)",
+ "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cast"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "cc"
-version = "1.0.23"
-source = "git+https://github.com/glandium/cc-rs?branch=1.0.23-clang-cl-aarch64#2aa71628b1261b5515bd8668afca591669ba195d"
+version = "1.0.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "cert_storage"
 version = "0.0.1"
 dependencies = [
  "base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lmdb-rkv 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "nserror 0.1.0",
@@ -492,17 +490,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.23 (git+https://github.com/glandium/cc-rs?branch=1.0.23-clang-cl-aarch64)",
+ "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "comedy"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1571,17 +1569,17 @@ name = "libc"
 version = "0.2.43"
 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.23 (git+https://github.com/glandium/cc-rs?branch=1.0.23-clang-cl-aarch64)",
+ "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
 ]
 
 [[package]]
 name = "libudev"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -1623,17 +1621,17 @@ dependencies = [
  "lmdb-rkv-sys 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "lmdb-rkv-sys"
 version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.23 (git+https://github.com/glandium/cc-rs?branch=1.0.23-clang-cl-aarch64)",
+ "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "lock_api"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1739,17 +1737,17 @@ dependencies = [
  "libc 0.2.43 (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.23 (git+https://github.com/glandium/cc-rs?branch=1.0.23-clang-cl-aarch64)",
+ "cc 1.0.34 (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.43 (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.15"
@@ -3540,17 +3538,17 @@ dependencies = [
 "checksum build_const 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e90dc84f5e62d2ebe7676b83c22d33b6db8bd27340fb6ffbff0a364efa0cb9c9"
 "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
 "checksum byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "980479e6fde23246dfb54d47580d66b4e99202e7579c5eaa9fe10ecb5ebd2182"
 "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
 "checksum bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e178b8e0e239e844b083d5a0d4a156b2654e67f9f80144d48398fcd736a24fb8"
 "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 cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427"
-"checksum cc 1.0.23 (git+https://github.com/glandium/cc-rs?branch=1.0.23-clang-cl-aarch64)" = "<none>"
+"checksum cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)" = "30f813bf45048a18eda9190fd3c6b78644146056740c43172a5a3699118588fd"
 "checksum cexpr 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8fc0086be9ca82f7fc89fc873435531cb898b86e850005850de1f820e2db6e9b"
 "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
 "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
 "checksum clang-sys 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4227269cec09f5f83ff160be12a1e9b0262dd1aa305302d5ba296c2ebd291055"
 "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 comedy 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4f03fbb05a4df3523a44cda10340e6ae6bea03ee9d01240a1a2c1ef6c73e95"
 "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -55,11 +55,10 @@ rpath = false
 debug-assertions = false
 panic = "abort"
 codegen-units = 1
 
 [patch.crates-io]
 libudev-sys = { path = "dom/webauthn/libudev-sys" }
 serde_derive = { git = "https://github.com/servo/serde", branch = "deserialize_from_enums9" }
 winapi = { git = "https://github.com/froydnj/winapi-rs", branch = "aarch64" }
-cc = { git = "https://github.com/glandium/cc-rs", branch = "1.0.23-clang-cl-aarch64" }
 packed_simd = { git = "https://github.com/hsivonen/packed_simd", branch = "rust_1_32" }
 target-lexicon = { git = "https://github.com/glandium/target-lexicon", branch = "thumbv7neon-v0.2" }
--- a/third_party/rust/cc/.cargo-checksum.json
+++ b/third_party/rust/cc/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".travis.yml":"7b18272b20d4b58996deb3e2d5d76f15a27d6a63a061abeefb6553a2b8650736","Cargo.toml":"45aa71f2057dae228d798a6c696576ade44cdd3ec75163b6f95deed4a728bd31","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"3eeb4b0488908876c439a87cfe2bec6d550b37388993b2d8863fb1c587a84f46","appveyor.yml":"ab45bfdcf2596f357225a54e730c34d518a8f3ad56c2ed33af682cfd45bddc02","src/bin/gcc-shim.rs":"d6be9137cb48b86891e7b263adbf492e1193ffe682db9ba4a88eb1079b874b58","src/com.rs":"8b9a54af5400c259f877126cc68ea63ada4fe66e84c9b840711c95e570b15774","src/lib.rs":"6e2019557cc4effaaf5f4715f89f6e77fe4796946bce6f767d4d735dc539a934","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":"653b7d9ad6503aaf2ffc6c9b86014dbad456b53bcd124c9de4714067f49e5095"},"package":null}
\ No newline at end of file
+{"files":{"Cargo.toml":"13b4fcd3d3f5fa9fa28c6714fe82f142f366c8f2a30a218ef6c1128ec20c31bc","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"190336dc7613f3b991580c39170b72967cafbd4c2d96ca2681249a8d5df2b1af","azure-pipelines.yml":"bb1c0c4147eeff07ddf230ca7535cd15a8acd05f8d431bf90988cd0647bb0775","ci/azure-install-rust.yml":"358198fb3cb23dd145434f777edde39c652ae390a5d64caf634a00dd78007286","ci/azure-steps.yml":"34b8c5dfab1c0a298b0a71e14daf15b82af07e2fb8d85684c4ccbf9f7f95ffb8","src/bin/gcc-shim.rs":"d6be9137cb48b86891e7b263adbf492e1193ffe682db9ba4a88eb1079b874b58","src/com.rs":"8b9a54af5400c259f877126cc68ea63ada4fe66e84c9b840711c95e570b15774","src/lib.rs":"6217a06cc91af81df4affa92d78619fbaa3f57ffe5b7780d19373a9353a60415","src/registry.rs":"3cc1b5a50879fa751572878ae1d0afbfc960c11665258492754b2c8bccb0ff5d","src/setup_config.rs":"f5c45afc99ad3b7c1311242bc4baf37e861d740ab81bf6ca90e2aa283672e65a","src/winapi.rs":"d7929b36130e33f1caa6bd444b378b83023b2b82d589c6e0ab38c4ff6c950da8","src/windows_registry.rs":"8671c26da1e0f206fc1ef48d42a4ffe95dc93575093ee2b23e112be996a02b66","tests/cc_env.rs":"bf7b14aa52af04294f648b2934f0f1830c5a0bdac1676310b8aa1f61458e7782","tests/support/mod.rs":"80dc87e54025197104cfb62d1af7a3400a3a0ddf0f2d98ea4ef4111cb1f0c890","tests/test.rs":"d839b2bcdb367180e537c0d26cb2d918d5ddfc587801c7051f4955d25688ea7d"},"package":"30f813bf45048a18eda9190fd3c6b78644146056740c43172a5a3699118588fd"}
\ No newline at end of file
deleted file mode 100644
--- a/third_party/rust/cc/.travis.yml
+++ /dev/null
@@ -1,64 +0,0 @@
-language: rust
-sudo: false
-
-matrix:
-  include:
-    - rust: 1.16.0
-      install:
-      script: cargo build
-    - rust: stable
-      env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1
-    - rust: stable
-      env: TARGET=i686-unknown-linux-gnu
-    - 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
-
-    - 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:
-        - travis-cargo --only nightly doc-upload
-
-install:
-  - if [ -z "$NO_ADD" ]; then rustup target add $TARGET; fi
-
-script:
-  - cargo build --verbose
-  # FIXME: no idea why `--test-threads=1` is required on the OSX builder, it
-  # just randomly broke one day when the travis image was upgraded, and
-  # debugging turned up no easily found source of bugs...
-  #
-  # good build - https://travis-ci.org/alexcrichton/cc-rs/builds/409602374
-  #  bad build - https://travis-ci.org/alexcrichton/cc-rs/builds/410489079
-  #
-  # Those are using the same compiler, same commit, same... everything. Except
-  # the OSX image! No idea what changed...
-  - cargo test --verbose $NO_RUN -- --test-threads=1
-  - cargo test --verbose --features parallel $NO_RUN -- --test-threads=1
-  - cargo test --manifest-path cc-test/Cargo.toml --target $TARGET $NO_RUN
-  - cargo test --manifest-path cc-test/Cargo.toml --target $TARGET --features parallel $NO_RUN
-  - cargo test --manifest-path cc-test/Cargo.toml --target $TARGET --release $NO_RUN
-  - cargo doc
-  - cargo clean && cargo build
-  - rustdoc --test README.md -L target/debug -L target/debug/deps
-
-env:
-  global:
-    secure: "CBtqrudgE0PS8x3kTr44jKbC2D4nfnmdYVecooNm0qnER4B4TSvZpZSQoCgKK6k4BYQuOSyFTOwYx6M79w39ZMOgyCP9ytB+tyMWL0/+ZuUQL04yVg4M5vd3oJMkOaXbvG56ncgPyFrseY+FPDg+mXAzvJk/nily37YXjkQj2D0="
-
-notifications:
-  email:
-    on_success: never
-addons:
-  apt:
-    packages:
-      - g++-multilib
--- a/third_party/rust/cc/Cargo.toml
+++ b/third_party/rust/cc/Cargo.toml
@@ -1,29 +1,33 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# 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.23"
+version = "1.0.34"
 authors = ["Alex Crichton <alex@alexcrichton.com>"]
-license = "MIT/Apache-2.0"
-repository = "https://github.com/alexcrichton/cc-rs"
+exclude = ["/.travis.yml", "/appveyor.yml"]
+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"
-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
-code.
-"""
+readme = "README.md"
 keywords = ["build-dependencies"]
-readme = "README.md"
-categories = ["development-tools"]
-
-[badges]
-travis-ci = { repository = "alexcrichton/cc-rs" }
-appveyor = { repository = "alexcrichton/cc-rs" }
-
-[dependencies]
-rayon = { version = "1.0", optional = true }
+categories = ["development-tools::build-utils"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/alexcrichton/cc-rs"
+[dependencies.rayon]
+version = "1.0"
+optional = true
+[dev-dependencies.tempdir]
+version = "0.3"
 
 [features]
 parallel = ["rayon"]
-
-[dev-dependencies]
-tempdir = "0.3"
--- a/third_party/rust/cc/README.md
+++ b/third_party/rust/cc/README.md
@@ -1,14 +1,13 @@
 # cc-rs
 
 A library to compile C/C++/assembly into a Rust library/application.
 
-[![Build Status](https://travis-ci.org/alexcrichton/cc-rs.svg?branch=master)](https://travis-ci.org/alexcrichton/cc-rs)
-[![Build status](https://ci.appveyor.com/api/projects/status/onu270iw98h81nwv?svg=true)](https://ci.appveyor.com/project/alexcrichton/cc-rs)
+[![Build Status](https://dev.azure.com/alexcrichton/cc-rs/_apis/build/status/alexcrichton.cc-rs?branchName=master)](https://dev.azure.com/alexcrichton/cc-rs/_build/latest?definitionId=5&branchName=master)
 
 [Documentation](https://docs.rs/cc)
 
 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. This crate calls out
 to the most relevant compiler for a platform, for example using `cl` on MSVC.
 
 > **Note**: this crate was recently renamed from the `gcc` crate, so if you're
@@ -72,28 +71,29 @@ number of different environment variable
              something like: "-L=foo\ bar" is not possible.
 * `CC` - the actual C compiler used. Note that this is used as an exact
          executable name, so (for example) no extra flags can be passed inside
          this variable, and the builder must ensure that there aren't any
          trailing spaces. This compiler must understand the `-c` flag. For
          certain `TARGET`s, it also is assumed to know about other flags (most
          common is `-fPIC`).
 * `AR` - the `ar` (archiver) executable to use to build the static library.
+* `CRATE_CC_NO_DEFAULTS` - the default compiler flags may cause conflicts in some cross compiling scenarios. Setting this variable will disable the generation of default compiler flags.
 
 Each of these variables can also be supplied with certain prefixes and suffixes,
 in the following prioritized order:
 
 1. `<var>_<target>` - for example, `CC_x86_64-unknown-linux-gnu`
 2. `<var>_<target_with_underscores>` - for example, `CC_x86_64_unknown_linux_gnu`
 3. `<build-kind>_<var>` - for example, `HOST_CC` or `TARGET_CFLAGS`
 4. `<var>` - a plain `CC`, `AR` as above.
 
 If none of these variables exist, cc-rs uses built-in defaults
 
-In addition to the the above optional environment variables, `cc-rs` has some
+In addition to the above optional environment variables, `cc-rs` has some
 functions with hard requirements on some variables supplied by [cargo's
 build-script driver][cargo] that it has the `TARGET`, `OUT_DIR`, `OPT_LEVEL`,
 and `HOST` variables.
 
 [cargo]: http://doc.crates.io/build-script.html#inputs-to-the-build-script
 
 ## Optional features
 
deleted file mode 100644
--- a/third_party/rust/cc/appveyor.yml
+++ /dev/null
@@ -1,55 +0,0 @@
-environment:
-
-  # At the time this was added AppVeyor was having troubles with checking
-  # revocation of SSL certificates of sites like static.rust-lang.org and what
-  # we think is crates.io. The libcurl HTTP client by default checks for
-  # revocation on Windows and according to a mailing list [1] this can be
-  # disabled.
-  #
-  # The `CARGO_HTTP_CHECK_REVOKE` env var here tells cargo to disable SSL
-  # revocation checking on Windows in libcurl. Note, though, that rustup, which
-  # we're using to download Rust here, also uses libcurl as the default backend.
-  # Unlike Cargo, however, rustup doesn't have a mechanism to disable revocation
-  # checking. To get rustup working we set `RUSTUP_USE_HYPER` which forces it to
-  # use the Hyper instead of libcurl backend. Both Hyper and libcurl use
-  # schannel on Windows but it appears that Hyper configures it slightly
-  # differently such that revocation checking isn't turned on by default.
-  #
-  # [1]: https://curl.haxx.se/mail/lib-2016-03/0202.html
-  RUSTUP_USE_HYPER: 1
-  CARGO_HTTP_CHECK_REVOKE: false
-
-  matrix:
-  - TARGET: x86_64-pc-windows-msvc
-    ARCH: amd64
-    VS: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat
-  - TARGET: x86_64-pc-windows-msvc
-    ARCH: amd64
-    VS: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat
-  - TARGET: i686-pc-windows-msvc
-    ARCH: x86
-    VS: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat
-  - TARGET: i686-pc-windows-msvc
-    ARCH: x86
-    VS: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat
-  - TARGET: x86_64-pc-windows-gnu
-    MSYS_BITS: 64
-  - TARGET: i686-pc-windows-gnu
-    MSYS_BITS: 32
-install:
-  - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe"
-  - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
-  - if defined VS call "%VS%" %ARCH%
-  - set PATH=%PATH%;C:\Program Files (x86)\Rust\bin
-  - if defined MSYS_BITS set PATH=%PATH%;C:\msys64\mingw%MSYS_BITS%\bin
-  - rustc -V
-  - cargo -V
-
-build: false
-
-test_script:
-  - cargo test --target %TARGET%
-  - cargo test --features parallel --target %TARGET%
-  - cargo test --manifest-path cc-test/Cargo.toml --target %TARGET%
-  - cargo test --manifest-path cc-test/Cargo.toml --features parallel --target %TARGET%
-  - cargo test --manifest-path cc-test/Cargo.toml --release --target %TARGET%
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cc/azure-pipelines.yml
@@ -0,0 +1,87 @@
+trigger:
+  - master
+
+jobs:
+  - job: min
+    displayName: Minimum Rust
+    steps:
+      - template: ci/azure-install-rust.yml
+        parameters:
+          toolchain: 1.16.0
+      - script: cargo build
+
+  - job: Linux
+    pool:
+      vmImage: ubuntu-16.04
+    strategy:
+      matrix:
+        x86_64:
+          TARGET: x86_64-unknown-linux-gnu
+        i686:
+          TARGET: i686-unknown-linux-gnu
+        x86_64-beta:
+          TARGET: x86_64-unknown-linux-gnu
+          TOOLCHAIN: beta
+        x86_64-nightly:
+          TARGET: x86_64-unknown-linux-gnu
+          TOOLCHAIN: nightly
+
+  - job: macOS
+    pool:
+      vmImage: macos-10.13
+    steps:
+      - template: ci/azure-steps.yml
+    strategy:
+      matrix:
+        x86_64:
+          TARGET: x86_64-apple-darwin
+        aarch64-ios:
+          TARGET: aarch64-apple-ios
+          NO_RUN: --no-run
+
+  - job: Windows_vs2019
+    pool:
+      vmImage: windows-2019
+    steps:
+      - template: ci/azure-steps.yml
+    strategy:
+      matrix:
+        x86_64-msvc:
+          TARGET: x86_64-pc-windows-msvc
+
+  - job: Windows_vs2017
+    pool:
+      vmImage: vs2017-win2016
+    steps:
+      - template: ci/azure-steps.yml
+    strategy:
+      matrix:
+        x86_64-msvc:
+          TARGET: x86_64-pc-windows-msvc
+        i686-msvc:
+          TARGET: i686-pc-windows-msvc
+        x86_64-gnu:
+          TARGET: x86_64-pc-windows-gnu
+        i686-gnu:
+          TARGET: i686-pc-windows-gnu
+
+  - job: Windows_vs2015
+    pool:
+      vmImage: vs2015-win2012r2
+    steps:
+      - template: ci/azure-steps.yml
+    strategy:
+      matrix:
+        x86_64-msvc:
+          TARGET: x86_64-pc-windows-msvc
+        i686-msvc:
+          TARGET: i686-pc-windows-msvc
+
+  - job: docs
+    steps:
+      - template: ci/azure-install-rust.yml
+      - script: cargo doc --no-deps --all-features
+      - script: curl -LsSf https://git.io/fhJ8n | rustc - && (cd target/doc && ../../rust_out)
+        condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
+        env:
+          GITHUB_DEPLOY_KEY: $(GITHUB_DEPLOY_KEY)
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cc/ci/azure-install-rust.yml
@@ -0,0 +1,23 @@
+steps:
+  - bash: |
+      set -e
+      toolchain=$TOOLCHAIN
+      if [ "$toolchain" = "" ]; then
+        toolchain=stable
+      fi
+      curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $toolchain
+      echo "##vso[task.prependpath]$HOME/.cargo/bin"
+    displayName: Install rust (unix)
+    condition: ne( variables['Agent.OS'], 'Windows_NT' )
+
+  - script: |
+      curl -sSf -o rustup-init.exe https://win.rustup.rs
+      rustup-init.exe -y --default-toolchain stable-%TARGET%
+      echo ##vso[task.prependpath]%USERPROFILE%\.cargo\bin
+    displayName: Install rust (windows)
+    condition: eq( variables['Agent.OS'], 'Windows_NT' )
+
+  - script: |
+        rustc -Vv
+        cargo -V
+    displayName: Query rust and cargo versions
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cc/ci/azure-steps.yml
@@ -0,0 +1,17 @@
+steps:
+  - template: azure-install-rust.yml
+  - bash: rustup target add $TARGET
+    displayName: Install Rust target
+
+  - script: cargo build
+    displayName: "Normal build"
+  - bash: cargo test $NO_RUN -- --test-threads 1
+    displayName: "Crate tests"
+  - bash: cargo test $NO_RUN --features parallel -- --test-threads 1
+    displayName: "Crate tests (parallel)"
+  - bash: cargo test $NO_RUN --manifest-path cc-test/Cargo.toml --target $TARGET
+    displayName: "cc-test tests"
+  - bash: cargo test $NO_RUN --manifest-path cc-test/Cargo.toml --target $TARGET --features parallel
+    displayName: "cc-test tests (parallel)"
+  - bash: cargo test $NO_RUN --manifest-path cc-test/Cargo.toml --target $TARGET --release
+    displayName: "cc-test tests (release)"
--- a/third_party/rust/cc/src/lib.rs
+++ b/third_party/rust/cc/src/lib.rs
@@ -50,16 +50,17 @@
 //!         .define("FOO", Some("bar"))
 //!         .include("src")
 //!         .compile("foo");
 //! }
 //! ```
 
 #![doc(html_root_url = "https://docs.rs/cc/1.0")]
 #![cfg_attr(test, deny(warnings))]
+#![allow(deprecated)]
 #![deny(missing_docs)]
 
 #[cfg(feature = "parallel")]
 extern crate rayon;
 
 use std::env;
 use std::ffi::{OsStr, OsString};
 use std::fs;
@@ -107,22 +108,24 @@ pub struct Build {
     out_dir: Option<PathBuf>,
     opt_level: Option<String>,
     debug: Option<bool>,
     env: Vec<(OsString, OsString)>,
     compiler: Option<PathBuf>,
     archiver: Option<PathBuf>,
     cargo_metadata: bool,
     pic: Option<bool>,
+    use_plt: Option<bool>,
     static_crt: Option<bool>,
     shared_flag: Option<bool>,
     static_flag: Option<bool>,
     warnings_into_errors: bool,
     warnings: Option<bool>,
     extra_warnings: Option<bool>,
+    env_cache: Arc<Mutex<HashMap<String, Option<String>>>>,
 }
 
 /// 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.
@@ -313,20 +316,22 @@ impl Build {
             out_dir: None,
             opt_level: None,
             debug: None,
             env: Vec::new(),
             compiler: None,
             archiver: None,
             cargo_metadata: true,
             pic: None,
+            use_plt: None,
             static_crt: None,
             warnings: None,
             extra_warnings: None,
             warnings_into_errors: false,
+            env_cache: Arc::new(Mutex::new(HashMap::new())),
         }
     }
 
     /// Add a directory to the `-I` or include path for headers
     ///
     /// # Example
     ///
     /// ```no_run
@@ -815,16 +820,31 @@ impl Build {
     ///
     /// This option defaults to `false` for `windows-gnu` targets and
     /// to `true` for all other targets.
     pub fn pic(&mut self, pic: bool) -> &mut Build {
         self.pic = Some(pic);
         self
     }
 
+    /// Configures whether the Procedure Linkage Table is used for indirect
+    /// calls into shared libraries.
+    ///
+    /// The PLT is used to provide features like lazy binding, but introduces
+    /// a small performance loss due to extra pointer indirection. Setting
+    /// `use_plt` to `false` can provide a small performance increase.
+    ///
+    /// Note that skipping the PLT requires a recent version of GCC/Clang.
+    ///
+    /// This only applies to ELF targets. It has no effect on other platforms.
+    pub fn use_plt(&mut self, use_plt: bool) -> &mut Build {
+        self.use_plt = Some(use_plt);
+        self
+    }
+
     /// Configures whether the /MT flag or the /MD flag will be passed to msvc build tools.
     ///
     /// This option defaults to `false`, and affect only msvc targets.
     pub fn static_crt(&mut self, static_crt: bool) -> &mut Build {
         self.static_crt = Some(static_crt);
         self
     }
 
@@ -931,17 +951,17 @@ impl Build {
             fail(&e.message);
         }
     }
 
     #[cfg(feature = "parallel")]
     fn compile_objects(&self, objs: &[Object]) -> Result<(), Error> {
         use self::rayon::prelude::*;
 
-        if let Ok(amt) = env::var("NUM_JOBS") {
+        if let Some(amt) = self.getenv("NUM_JOBS") {
             if let Ok(amt) = amt.parse() {
                 let _ = rayon::ThreadPoolBuilder::new()
                     .num_threads(amt)
                     .build_global();
             }
         }
 
         // Check for any errors and return the first one found.
@@ -1068,260 +1088,30 @@ impl Build {
     /// Get the compiler that's in use for this configuration.
     ///
     /// This will return a result instead of panicing; see get_compiler() for the complete description.
     pub fn try_get_compiler(&self) -> Result<Tool, Error> {
         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 { .. } => {
-                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",
-                    None => {
-                        let features =
-                            env::var("CARGO_CFG_TARGET_FEATURE").unwrap_or(String::new());
-                        if features.contains("crt-static") {
-                            "/MT"
-                        } else {
-                            "/MD"
-                        }
-                    }
-                };
-                cmd.args.push(crt_flag.into());
+        let envflags = self.envflags(if self.cpp { "CXXFLAGS" } else { "CFLAGS" });
 
-                match &opt_level[..] {
-                    // Msvc uses /O1 to enable all optimizations that minimize code size.
-                    "z" | "s" | "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()),
-                    _ => {}
-                }
-            }
-            ToolFamily::Gnu | ToolFamily::Clang => {
-                // arm-linux-androideabi-gcc 4.8 shipped with Android NDK does
-                // not support '-Oz'
-                if opt_level == "z" && cmd.family != ToolFamily::Clang {
-                    cmd.args.push("-Os".into());
-                } else {
-                    cmd.args.push(format!("-O{}", opt_level).into());
-                }
+        // Disable default flag generation via environment variable or when
+        // certain cross compiling arguments are set
+        let use_defaults = self.getenv("CRATE_CC_NO_DEFAULTS").is_none();
 
-                if !target.contains("-ios") {
-                    cmd.push_cc_arg("-ffunction-sections".into());
-                    cmd.push_cc_arg("-fdata-sections".into());
-                }
-                if self.pic.unwrap_or(!target.contains("windows-gnu")) {
-                    cmd.push_cc_arg("-fPIC".into());
-                }
-            }
-        }
-        for arg in self.envflags(if self.cpp { "CXXFLAGS" } else { "CFLAGS" }) {
-            cmd.args.push(arg.into());
-        }
-
-        if self.get_debug() {
-            if self.cuda {
-                let nvcc_debug_flag = cmd.family.nvcc_debug_flag().into();
-                cmd.args.push(nvcc_debug_flag);
-            }
-            let family = cmd.family;
-            family.add_debug_flags(&mut cmd);
+        if use_defaults {
+            self.add_default_flags(&mut cmd, &target, &opt_level)?;
+        } else {
+            println!("Info: default compiler flags are disabled");
         }
 
-        // Target flags
-        match cmd.family {
-            ToolFamily::Clang => {
-                cmd.args.push(format!("--target={}", target).into());
-            }
-            ToolFamily::Msvc { clang_cl } => {
-                if clang_cl {
-                    if target.contains("x86_64") {
-                        cmd.args.push("-m64".into());
-                    } else if target.contains("86") {
-                        cmd.args.push("-m32".into());
-                        cmd.args.push("/arch:IA32".into());
-                    } else {
-                        cmd.args.push(format!("--target={}", target).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() {
-                    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.starts_with("thumbv7")) && target.contains("-linux-") {
-                    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());
-                    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());
-                    cmd.args.push("-marm".into());
-                    cmd.args.push("-mfloat-abi=soft".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());
-                }
-
-                // We can guarantee some settings for FRC
-                if target.starts_with("arm-frc-") {
-                    cmd.args.push("-march=armv7-a".into());
-                    cmd.args.push("-mcpu=cortex-a9".into());
-                    cmd.args.push("-mfpu=vfpv3".into());
-                    cmd.args.push("-mfloat-abi=softfp".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());
-                }
-
-                // 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" || target == "i586-unknown-linux-musl" {
-                    cmd.args.push("-Wl,-melf_i386".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.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.starts_with("thumbv7m") {
-                    cmd.args.push("-march=armv7-m".into());
-                }
-                if target.starts_with("armebv7r") | target.starts_with("armv7r") {
-                    if target.starts_with("armeb") {
-                        cmd.args.push("-mbig-endian".into());
-                    } else {
-                        cmd.args.push("-mlittle-endian".into());
-                    }
-
-                    // ARM mode
-                    cmd.args.push("-marm".into());
-
-                    // R Profile
-                    cmd.args.push("-march=armv7-r".into());
-
-                    if target.ends_with("eabihf") {
-                        // Calling convention
-                        cmd.args.push("-mfloat-abi=hard".into());
-
-                        // lowest common denominator FPU
-                        // (see Cortex-R4 technical reference manual)
-                        cmd.args.push("-mfpu=vfpv3-d16".into())
-                    } else {
-                        // Calling convention
-                        cmd.args.push("-mfloat-abi=soft".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.static_flag.unwrap_or(false) {
-            cmd.args.push("-static".into());
-        }
-        if self.shared_flag.unwrap_or(false) {
-            cmd.args.push("-shared".into());
-        }
-
-        if self.cpp {
-            match (self.cpp_set_stdlib.as_ref(), cmd.family) {
-                (None, _) => {}
-                (Some(stdlib), ToolFamily::Gnu) | (Some(stdlib), ToolFamily::Clang) => {
-                    cmd.push_cc_arg(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 arg in envflags {
+            cmd.push_cc_arg(arg.into());
         }
 
         for directory in self.include_directories.iter() {
             cmd.args.push(cmd.family.include_flag().into());
             cmd.args.push(directory.into());
         }
 
         // If warnings and/or extra_warnings haven't been explicitly set,
@@ -1366,16 +1156,295 @@ impl Build {
         if self.warnings_into_errors {
             let warnings_to_errors_flag = cmd.family.warnings_to_errors_flag().into();
             cmd.push_cc_arg(warnings_to_errors_flag);
         }
 
         Ok(cmd)
     }
 
+    fn add_default_flags(&self, cmd: &mut Tool, target: &str, opt_level: &str) -> Result<(), Error> {
+        // Non-target flags
+        // If the flag is not conditioned on target variable, it belongs here :)
+        match cmd.family {
+            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",
+                    None => {
+                        let features =
+                            self.getenv("CARGO_CFG_TARGET_FEATURE").unwrap_or(String::new());
+                        if features.contains("crt-static") {
+                            "/MT"
+                        } else {
+                            "/MD"
+                        }
+                    }
+                };
+                cmd.args.push(crt_flag.into());
+
+                match &opt_level[..] {
+                    // Msvc uses /O1 to enable all optimizations that minimize code size.
+                    "z" | "s" | "1" => cmd.push_opt_unless_duplicate("/O1".into()),
+                    // -O3 is a valid value for gcc and clang compilers, but not msvc. Cap to /O2.
+                    "2" | "3" => cmd.push_opt_unless_duplicate("/O2".into()),
+                    _ => {}
+                }
+            }
+            ToolFamily::Gnu | ToolFamily::Clang => {
+                // arm-linux-androideabi-gcc 4.8 shipped with Android NDK does
+                // not support '-Oz'
+                if opt_level == "z" && cmd.family != ToolFamily::Clang {
+                    cmd.push_opt_unless_duplicate("-Os".into());
+                } else {
+                    cmd.push_opt_unless_duplicate(format!("-O{}", opt_level).into());
+                }
+
+                if !target.contains("-ios") {
+                    cmd.push_cc_arg("-ffunction-sections".into());
+                    cmd.push_cc_arg("-fdata-sections".into());
+                }
+                if self.pic.unwrap_or(!target.contains("windows-gnu")) {
+                    cmd.push_cc_arg("-fPIC".into());
+                    // PLT only applies if code is compiled with PIC support,
+                    // and only for ELF targets.
+                    if target.contains("linux") && !self.use_plt.unwrap_or(true) {
+                        cmd.push_cc_arg("-fno-plt".into());
+                    }
+                }
+            }
+        }
+
+        if self.get_debug() {
+            if self.cuda {
+                let nvcc_debug_flag = cmd.family.nvcc_debug_flag().into();
+                cmd.args.push(nvcc_debug_flag);
+            }
+            let family = cmd.family;
+            family.add_debug_flags(cmd);
+        }
+
+        // Target flags
+        match cmd.family {
+            ToolFamily::Clang => {
+                cmd.args.push(format!("--target={}", target).into());
+            }
+            ToolFamily::Msvc { clang_cl } => {
+                if clang_cl {
+                    if target.contains("x86_64") {
+                        cmd.args.push("-m64".into());
+                    } else if target.contains("86") {
+                        cmd.args.push("-m32".into());
+                        cmd.args.push("/arch:IA32".into());
+                    } else {
+                        cmd.args.push(format!("--target={}", target).into());
+                    }
+                } else {
+                    if target.contains("i586") {
+                        cmd.args.push("/ARCH:IA32".into());
+                    }
+                }
+
+                // There is a check in corecrt.h that will generate a
+                // compilation error if
+                // _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE is
+                // not defined to 1. The check was added in Windows
+                // 8 days because only store apps were allowed on ARM.
+                // This changed with the release of Windows 10 IoT Core.
+                // The check will be going away in future versions of
+                // the SDK, but for all released versions of the
+                // Windows SDK it is required.
+                if target.contains("arm") || target.contains("thumb") {
+                    cmd.args.push("/D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1".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() {
+                    let features = self.getenv("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.starts_with("thumbv7")) && target.contains("-linux-") {
+                    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());
+                    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());
+                    cmd.args.push("-marm".into());
+                    cmd.args.push("-mfloat-abi=soft".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());
+                    if target.ends_with("hf") {
+                        cmd.args.push("-mfpu=vfp".into());
+                    } else {
+                        cmd.args.push("-mfloat-abi=soft".into());
+                    }
+                }
+
+                // We can guarantee some settings for FRC
+                if target.starts_with("arm-frc-") {
+                    cmd.args.push("-march=armv7-a".into());
+                    cmd.args.push("-mcpu=cortex-a9".into());
+                    cmd.args.push("-mfpu=vfpv3".into());
+                    cmd.args.push("-mfloat-abi=softfp".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());
+                }
+
+                // 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" || target == "i586-unknown-linux-musl" {
+                    cmd.args.push("-Wl,-melf_i386".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.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.starts_with("thumbv7m") {
+                    cmd.args.push("-march=armv7-m".into());
+                }
+                if target.starts_with("thumbv8m.base") {
+                    cmd.args.push("-march=armv8-m.base".into());
+                }
+                if target.starts_with("thumbv8m.main") {
+                    cmd.args.push("-march=armv8-m.main".into());
+
+                    if target.ends_with("eabihf") {
+                        cmd.args.push("-mfpu=fpv5-sp-d16".into())
+                    }
+                }
+                if target.starts_with("armebv7r") | target.starts_with("armv7r") {
+                    if target.starts_with("armeb") {
+                        cmd.args.push("-mbig-endian".into());
+                    } else {
+                        cmd.args.push("-mlittle-endian".into());
+                    }
+
+                    // ARM mode
+                    cmd.args.push("-marm".into());
+
+                    // R Profile
+                    cmd.args.push("-march=armv7-r".into());
+
+                    if target.ends_with("eabihf") {
+                        // Calling convention
+                        cmd.args.push("-mfloat-abi=hard".into());
+
+                        // lowest common denominator FPU
+                        // (see Cortex-R4 technical reference manual)
+                        cmd.args.push("-mfpu=vfpv3-d16".into())
+                    } else {
+                        // Calling convention
+                        cmd.args.push("-mfloat-abi=soft".into());
+                    }
+                }
+            }
+        }
+
+        if target.contains("-ios") {
+            // FIXME: potential bug. iOS is always compiled with Clang, but Gcc compiler may be
+            // detected instead.
+            self.ios_flags(cmd)?;
+        }
+
+        if self.static_flag.unwrap_or(false) {
+            cmd.args.push("-static".into());
+        }
+        if self.shared_flag.unwrap_or(false) {
+            cmd.args.push("-shared".into());
+        }
+
+        if self.cpp {
+            match (self.cpp_set_stdlib.as_ref(), cmd.family) {
+                (None, _) => {}
+                (Some(stdlib), ToolFamily::Gnu) | (Some(stdlib), ToolFamily::Clang) => {
+                    cmd.push_cc_arg(format!("-stdlib=lib{}", stdlib).into());
+                }
+                _ => {
+                    println!(
+                        "cargo:warning=cpp_set_stdlib is specified, but the {:?} compiler \
+                         does not support this option, ignored",
+                        cmd.family
+                    );
+                }
+            }
+        }
+
+        Ok(())
+    }
+
     fn has_flags(&self) -> bool {
         let flags_env_var_name = if self.cpp { "CXXFLAGS" } else { "CFLAGS" };
         let flags_env_var_value = self.get_var(flags_env_var_name);
         if let Ok(_) = flags_env_var_value { true } else { false }
     }
 
     fn msvc_macro_assembler(&self) -> Result<(Command, String), Error> {
         let target = self.get_target()?;
@@ -1413,22 +1482,17 @@ impl Build {
     fn assemble(&self, lib_name: &str, dst: &Path, objs: &[Object]) -> Result<(), Error> {
         // Delete the destination if it exists as the `ar` tool at least on Unix
         // appends to it, which we don't want.
         let _ = fs::remove_file(&dst);
 
         let objects: Vec<_> = objs.iter().map(|obj| obj.dst.clone()).collect();
         let target = self.get_target()?;
         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_else(|| self.cmd("lib.exe")),
-            };
-
+            let (mut cmd, program) = self.get_ar()?;
             let mut out = OsString::from("/OUT:");
             out.push(dst);
             cmd.arg(out).arg("/nologo");
 
             // Similar to https://github.com/rust-lang/rust/pull/47507
             // and https://github.com/rust-lang/rust/pull/48548
             let estimated_command_line_len = objects
                 .iter()
@@ -1463,17 +1527,17 @@ impl Build {
                     .unwrap();
 
                 let mut args_file_arg = OsString::from("@");
                 args_file_arg.push(args_file);
                 cmd.arg(args_file_arg);
             } else {
                 cmd.args(&objects).args(&self.objects);
             }
-            run(&mut cmd, "lib.exe")?;
+            run(&mut cmd, &program)?;
 
             // 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);
             match fs::hard_link(&dst, &lib_dst).or_else(|_| {
                 // if hard-link fails, just copy (ignoring the number of bytes written)
@@ -1644,31 +1708,33 @@ impl Build {
                 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") {
                     let target = target
+                        .replace("armv7neon", "arm")
                         .replace("armv7", "arm")
-                        .replace("armv7neon", "arm")
-                        .replace("thumbv7", "arm")
-                        .replace("thumbv7neon", "arm");
+                        .replace("thumbv7neon", "arm")
+                        .replace("thumbv7", "arm");
                     let gnu_compiler = format!("{}-{}", target, gnu);
                     let clang_compiler = format!("{}-{}", target, clang);
                     // Check if gnu compiler is present
                     // if not, use clang
                     if Command::new(&gnu_compiler).spawn().is_ok() {
                         gnu_compiler
                     } else {
                         clang_compiler
                     }
                 } else if target.contains("cloudabi") {
                     format!("{}-{}", target, traditional)
+                } else if target == "wasm32-unknown-wasi" || target == "wasm32-unknown-unknown" {
+                    "clang".to_string()
                 } 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"),
                         "aarch64-unknown-linux-musl" => Some("aarch64-linux-musl"),
                         "aarch64-unknown-netbsd" => Some("aarch64--netbsd"),
@@ -1711,16 +1777,19 @@ impl Build {
                         "armebv7r-none-eabi" => Some("arm-none-eabi"),
                         "armebv7r-none-eabihf" => Some("arm-none-eabi"),
                         "armv7r-none-eabi" => Some("arm-none-eabi"),
                         "armv7r-none-eabihf" => Some("arm-none-eabi"),
                         "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"),
+                        "thumbv8m.base-none-eabi" => Some("arm-none-eabi"),
+                        "thumbv8m.main-none-eabi" => Some("arm-none-eabi"),
+                        "thumbv8m.main-none-eabihf" => 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),
@@ -1900,27 +1969,33 @@ impl Build {
     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");
             return Ok((self.cmd(p), name.to_string()));
         }
         if let Ok(p) = self.get_var("AR") {
             return Ok((self.cmd(&p), p));
         }
-        let program = if self.get_target()?.contains("android") {
-            format!("{}-ar", self.get_target()?.replace("armv7", "arm"))
-        } else if self.get_target()?.contains("emscripten") {
+        let target = self.get_target()?;
+        let program = if target.contains("android") {
+            format!("{}-ar", target.replace("armv7", "arm"))
+        } else if target.contains("emscripten") {
             // Windows use bat files so we have to be a bit more specific
             if cfg!(windows) {
                 let mut cmd = self.cmd("cmd");
                 cmd.arg("/c").arg("emar.bat");
                 return Ok((cmd, "emar.bat".to_string()));
             }
 
             "emar".to_string()
+        } else if target.contains("msvc") {
+            match windows_registry::find(&target, "lib.exe") {
+                Some(t) => return Ok((t, "lib.exe".to_string())),
+                None => "lib.exe".to_string(),
+            }
         } else {
             "ar".to_string()
         };
         Ok((self.cmd(&program), program))
     }
 
     fn get_target(&self) -> Result<String, Error> {
         match self.target.clone() {
@@ -1958,18 +2033,23 @@ impl Build {
                     ErrorKind::EnvVarNotFound,
                     "Environment variable OUT_DIR not defined.",
                 )
             })?),
         }
     }
 
     fn getenv(&self, v: &str) -> Option<String> {
+        let mut cache = self.env_cache.lock().unwrap();
+        if let Some(val) = cache.get(v) {
+            return val.clone()
+        }
         let r = env::var(v).ok();
         self.print(&format!("{} = {:?}", v, r));
+        cache.insert(v.to_string(), r.clone());
         r
     }
 
     fn getenv_unwrap(&self, v: &str) -> Result<String, Error> {
         match self.getenv(v) {
             Some(s) => Ok(s),
             None => Err(Error::new(
                 ErrorKind::EnvVarNotFound,
@@ -2038,16 +2118,51 @@ impl Tool {
     /// with a "-Xcompiler" flag to get passed to the underlying C++ compiler.
     fn push_cc_arg(&mut self, flag: OsString) {
         if self.cuda {
             self.args.push(self.family.nvcc_redirect_flag().into());
         }
         self.args.push(flag);
     }
 
+    fn is_duplicate_opt_arg(&self, flag: &OsString) -> bool {
+        let flag = flag.to_str().unwrap();
+        let mut chars = flag.chars();
+
+        // Only duplicate check compiler flags
+        if self.is_like_msvc() {
+            if chars.next() != Some('/') {
+                return false;
+            }
+        } else if self.is_like_gnu() || self.is_like_clang() {
+            if chars.next() != Some('-') {
+                return false;
+            }
+        }
+
+        // Check for existing optimization flags (-O, /O)
+        if chars.next() == Some('O') {
+            return self.args().iter().any(|ref a|
+                a.to_str().unwrap_or("").chars().nth(1) == Some('O')
+            );
+        }
+
+        // TODO Check for existing -m..., -m...=..., /arch:... flags
+        return false;
+    }
+
+    /// Don't push optimization arg if it conflicts with existing args
+    fn push_opt_unless_duplicate(&mut self, flag: OsString) {
+        if self.is_duplicate_opt_arg(&flag) {
+            println!("Info: Ignoring duplicate arg {:?}", &flag);
+        } else {
+            self.push_cc_arg(flag);
+        }
+    }
+
     /// Converts this compiler into a `Command` that's ready to be run.
     ///
     /// 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) => {
--- a/third_party/rust/cc/src/windows_registry.rs
+++ b/third_party/rust/cc/src/windows_registry.rs
@@ -98,16 +98,18 @@ pub fn find_tool(target: &str, tool: &st
 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
 pub enum VsVers {
     /// Visual Studio 12 (2013)
     Vs12,
     /// Visual Studio 14 (2015)
     Vs14,
     /// Visual Studio 15 (2017)
     Vs15,
+    /// Visual Studio 16 (2019)
+    Vs16,
 
     /// Hidden variant that should not be matched on. Callers that want to
     /// handle an enumeration of `VsVers` instances should always have a default
     /// case meaning that it's a VS version they don't understand.
     #[doc(hidden)]
     #[allow(bad_style)]
     __Nonexhaustive_do_not_match_this_or_your_code_will_break,
 }
@@ -123,33 +125,36 @@ pub fn find_vs_version() -> Result<VsVer
 
 /// Documented above
 #[cfg(windows)]
 pub fn find_vs_version() -> Result<VsVers, String> {
     use std::env;
 
     match env::var("VisualStudioVersion") {
         Ok(version) => match &version[..] {
+            "16.0" => Ok(VsVers::Vs16),
             "15.0" => Ok(VsVers::Vs15),
             "14.0" => Ok(VsVers::Vs14),
             "12.0" => Ok(VsVers::Vs12),
             vers => Err(format!(
                 "\n\n\
                  unsupported or unknown VisualStudio version: {}\n\
                  if another version is installed consider running \
                  the appropriate vcvars script before building this \
                  crate\n\
                  ",
                 vers
             )),
         },
         _ => {
             // Check for the presense of a specific registry key
             // that indicates visual studio is installed.
-            if impl_::has_msbuild_version("15.0") {
+            if impl_::has_msbuild_version("16.0") {
+                Ok(VsVers::Vs16)
+            } else if impl_::has_msbuild_version("15.0") {
                 Ok(VsVers::Vs15)
             } else if impl_::has_msbuild_version("14.0") {
                 Ok(VsVers::Vs14)
             } else if impl_::has_msbuild_version("12.0") {
                 Ok(VsVers::Vs12)
             } else {
                 Err(format!(
                     "\n\n\
@@ -169,17 +174,17 @@ mod impl_ {
     use std::env;
     use std::ffi::OsString;
     use std::mem;
     use std::path::{Path, PathBuf};
     use std::fs::File;
     use std::io::Read;
     use registry::{RegistryKey, LOCAL_MACHINE};
     use com;
-    use setup_config::{SetupConfiguration, SetupInstance};
+    use setup_config::{EnumSetupInstances, SetupConfiguration, SetupInstance};
 
     use Tool;
 
     struct MsvcTool {
         tool: PathBuf,
         libs: Vec<PathBuf>,
         path: Vec<PathBuf>,
         include: Vec<PathBuf>,
@@ -212,32 +217,74 @@ mod impl_ {
 
     // In MSVC 15 (2017) MS once again changed the scheme for locating
     // the tooling.  Now we must go through some COM interfaces, which
     // is super fun for Rust.
     //
     // Note that much of this logic can be found [online] wrt paths, COM, etc.
     //
     // [online]: https://blogs.msdn.microsoft.com/vcblog/2017/03/06/finding-the-visual-c-compiler-tools-in-visual-studio-2017/
-    pub fn find_msvc_15(tool: &str, target: &str) -> Option<Tool> {
+    fn vs15_instances() -> Option<EnumSetupInstances> {
         otry!(com::initialize().ok());
 
         let config = otry!(SetupConfiguration::new().ok());
-        let iter = otry!(config.enum_all_instances().ok());
+        config.enum_all_instances().ok()
+    }
+
+    pub fn find_msvc_15(tool: &str, target: &str) -> Option<Tool> {
+        let iter = otry!(vs15_instances());
         for instance in iter {
             let instance = otry!(instance.ok());
             let tool = tool_from_vs15_instance(tool, target, &instance);
             if tool.is_some() {
                 return tool;
             }
         }
 
         None
     }
 
+    // While the paths to Visual Studio 2017's devenv and MSBuild could
+    // potentially be retrieved from the registry, finding them via
+    // SetupConfiguration has shown to be [more reliable], and is preferred
+    // according to Microsoft. To help head off potential regressions though,
+    // we keep the registry method as a fallback option.
+    //
+    // [more reliable]: https://github.com/alexcrichton/cc-rs/pull/331
+    fn find_tool_in_vs15_path(tool: &str, target: &str) -> Option<Tool> {
+        let mut path = match vs15_instances() {
+            Some(instances) => instances
+                .filter_map(|instance| {
+                    instance
+                        .ok()
+                        .and_then(|instance| instance.installation_path().ok())
+                }).map(|path| PathBuf::from(path).join(tool))
+                .find(|ref path| path.is_file()),
+            None => None,
+        };
+
+        if path.is_none() {
+            let key = r"SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7";
+            path = LOCAL_MACHINE
+                .open(key.as_ref())
+                .ok()
+                .and_then(|key| key.query_str("15.0").ok())
+                .map(|path| PathBuf::from(path).join(tool))
+                .filter(|ref path| path.is_file());
+        }
+
+        path.map(|path| {
+            let mut tool = Tool::new(path);
+            if target.contains("x86_64") {
+                tool.env.push(("Platform".into(), "X64".into()));
+            }
+            tool
+        })
+    }
+
     fn tool_from_vs15_instance(tool: &str, target: &str, instance: &SetupInstance) -> Option<Tool> {
         let (bin_path, host_dylib_path, lib_path, include_path) =
             otry!(vs15_vc_paths(target, instance));
         let tool_path = bin_path.join(tool);
         if !tool_path.exists() {
             return None;
         };
 
@@ -518,40 +565,40 @@ mod impl_ {
     // address space to work with and potentially being faster.
     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"), ("", "")],
             ("x86_64", X86) => vec![("x86_amd64", "")],
             ("x86_64", X86_64) => vec![("amd64", "amd64"), ("x86_amd64", "")],
-            ("arm", X86) => vec![("x86_arm", "")],
-            ("arm", X86_64) => vec![("amd64_arm", "amd64"), ("x86_arm", "")],
+            ("arm", X86) | ("thumbv7a", X86) => vec![("x86_arm", "")],
+            ("arm", X86_64) | ("thumbv7a", X86_64) => vec![("amd64_arm", "amd64"), ("x86_arm", "")],
             _ => vec![],
         }
     }
 
     fn lib_subdir(target: &str) -> Option<&'static str> {
         let arch = target.split('-').next().unwrap();
         match arch {
             "i586" | "i686" => Some("x86"),
             "x86_64" => Some("x64"),
-            "arm" => Some("arm"),
+            "arm" | "thumbv7a" => Some("arm"),
             "aarch64" => Some("arm64"),
             _ => None,
         }
     }
 
     // MSVC's x86 libraries are not in a subfolder
     fn vc_lib_subdir(target: &str) -> Option<&'static str> {
         let arch = target.split('-').next().unwrap();
         match arch {
             "i586" | "i686" => Some(""),
             "x86_64" => Some("amd64"),
-            "arm" => Some("arm"),
+            "arm" | "thumbv7a" => Some("arm"),
             "aarch64" => Some("arm64"),
             _ => None,
         }
     }
 
     #[allow(bad_style)]
     fn host_arch() -> u16 {
         type DWORD = u32;
@@ -590,17 +637,17 @@ mod impl_ {
     //
     // Returns the name of the maximal key as well as the opened maximal key.
     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());
+                .and_then(|s| s.trim_start_matches("v").replace(".", "").parse().ok());
             let val = match val {
                 Some(s) => s,
                 None => continue,
             };
             if val > max_vers {
                 if let Ok(k) = key.open(&subkey) {
                     max_vers = val;
                     max_key = Some((subkey, k));
@@ -626,58 +673,31 @@ mod impl_ {
         }
     }
 
     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
-            })
+        find_tool_in_vs15_path(r"Common7\IDE\devenv.exe", target)
     }
 
     // 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)
         }
     }
 
     fn find_msbuild_vs15(target: &str) -> Option<Tool> {
-        // Seems like this could also go through SetupConfiguration,
-        // or that find_msvc_15 could just use this registry key
-        // instead of the COM interface.
-        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"MSBuild\15.0\Bin\MSBuild.exe");
-                let mut tool = Tool::new(path);
-                if target.contains("x86_64") {
-                    tool.env.push(("Platform".into(), "X64".into()));
-                }
-                tool
-            })
+        find_tool_in_vs15_path(r"MSBuild\15.0\Bin\MSBuild.exe", target)
     }
 
     fn find_old_msbuild(target: &str) -> Option<Tool> {
         let key = r"SOFTWARE\Microsoft\MSBuild\ToolsVersions";
         LOCAL_MACHINE
             .open(key.as_ref())
             .ok()
             .and_then(|key| {
--- a/third_party/rust/cc/tests/test.rs
+++ b/third_party/rust/cc/tests/test.rs
@@ -193,16 +193,30 @@ fn gnu_i686_pic() {
             .file("foo.c")
             .compile("foo");
 
         test.cmd(0).must_have("-fPIC");
     }
 }
 
 #[test]
+fn gnu_x86_64_no_plt() {
+    let target = "x86_64-unknown-linux-gnu";
+    let test = Test::gnu();
+    test.gcc()
+        .pic(true)
+        .use_plt(false)
+        .target(&target)
+        .host(&target)
+        .file("foo.c")
+        .compile("foo");
+    test.cmd(0).must_have("-fno-plt");
+}
+
+#[test]
 fn gnu_set_stdlib() {
     let test = Test::gnu();
     test.gcc()
         .cpp_set_stdlib(Some("foo"))
         .file("foo.c")
         .compile("foo");
 
     test.cmd(0).must_not_have("-stdlib=foo");