--- a/Cargo.lock
+++ b/Cargo.lock
@@ -188,23 +188,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.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.9 (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.4"
+version = "1.0.9"
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)",
@@ -249,17 +249,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.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.9 (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.38 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -891,17 +891,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.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.9 (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 = [
@@ -1014,17 +1014,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.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.9 (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"
@@ -2202,17 +2202,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.4 (registry+https://github.com/rust-lang/crates.io-index)" = "deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0"
+"checksum cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2b4911e4bdcb4100c7680e7e854ff38e23f1b34d4d9e079efae3da2801341ffc"
"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.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "939a1a34310b120d26eba35c29475933128b0ec58e24b43327f8dbe6036fc538"
"checksum clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "110d43e343eb29f4f51c1db31beb879d546db27998577e5715270a54bcf41d3f"
"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.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980"
--- a/third_party/rust/cc/.cargo-checksum.json
+++ b/third_party/rust/cc/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".travis.yml":"1a4a3f7f90349924378e93acbb524b9127e37c02cfbc6dc59fd904bbdc1c8d0b","Cargo.toml":"623dd06a83bcbf2f292ab51af93e9b79b689e3be06a62968b79f4e36f1bb769f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"186c5c8a62520cb7a3d90d77161c954b52ae8456fca0e0669bc3a5b889592a43","appveyor.yml":"ab45bfdcf2596f357225a54e730c34d518a8f3ad56c2ed33af682cfd45bddc02","src/bin/gcc-shim.rs":"d6be9137cb48b86891e7b263adbf492e1193ffe682db9ba4a88eb1079b874b58","src/com.rs":"0cb06f5db0fb70d27db0e5917ca337de6e7032119e6aabfea1bad9c719f5f34b","src/lib.rs":"996b650e19d5ccd6e64e741789427017c913644e980862a7286ec4ed53c14a17","src/registry.rs":"3876ef9573e3bbc050aef41a684b9a510cc1a91b15ae874fe032cf4377b4d116","src/setup_config.rs":"1a3eeb11c6847c31f2a4685b62ab35c76f0b6d5a17f7ed99e9df164283a771f7","src/winapi.rs":"cb5e6cab3eb570b0f97c660ca448ccfb5024262c0c7b245c181daad91a79f211","src/windows_registry.rs":"6de548aa94215e449f0e58e9a3b1702939d7c2f7b63a9040901c948bf138201d","tests/cc_env.rs":"7402315eea7ffa23b29b393c1de8e236294ede9de562ff0a562704a157135341","tests/support/mod.rs":"092551f9f6e3a999fa0aa02f93314aac0bda2b09268f948c423df56a43575e0b","tests/test.rs":"b1164258714e13173f3861126e97bedf1e29aa24618993c4eb0edd57c431dcc7"},"package":"deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0"}
\ No newline at end of file
+{"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
--- a/third_party/rust/cc/.travis.yml
+++ b/third_party/rust/cc/.travis.yml
@@ -7,40 +7,46 @@ matrix:
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
+ - 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:
- travis-cargo --only nightly doc-upload
install:
- if [ -z "$NO_ADD" ]; then rustup target add $TARGET; fi
script:
- cargo build --verbose
- - cargo test --verbose
- - cargo test --verbose --features parallel
- - cargo test --manifest-path cc-test/Cargo.toml --target $TARGET
- - cargo test --manifest-path cc-test/Cargo.toml --target $TARGET --features parallel
- - cargo test --manifest-path cc-test/Cargo.toml --target $TARGET --release
+ - cargo test --verbose $NO_RUN
+ - cargo test --verbose --features parallel $NO_RUN
+ - 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="
--- a/third_party/rust/cc/Cargo.toml
+++ b/third_party/rust/cc/Cargo.toml
@@ -7,28 +7,28 @@
#
# 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.4"
+version = "1.0.9"
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"
repository = "https://github.com/alexcrichton/cc-rs"
[dependencies.rayon]
-version = "0.9"
+version = "1.0"
optional = true
[dev-dependencies.tempdir]
version = "0.3"
[features]
parallel = ["rayon"]
[badges.appveyor]
repository = "alexcrichton/cc-rs"
--- a/third_party/rust/cc/src/com.rs
+++ b/third_party/rust/cc/src/com.rs
@@ -14,76 +14,101 @@ use std::os::windows::ffi::{OsStrExt, Os
use std::ptr::null_mut;
use std::slice::from_raw_parts;
use winapi::Interface;
use winapi::BSTR;
use winapi::CoInitializeEx;
use winapi::COINIT_MULTITHREADED;
use winapi::{SysFreeString, SysStringLen};
use winapi::IUnknown;
-use winapi::{S_OK, S_FALSE, HRESULT};
+use winapi::{HRESULT, S_FALSE, S_OK};
pub fn initialize() -> Result<(), HRESULT> {
let err = unsafe { CoInitializeEx(null_mut(), COINIT_MULTITHREADED) };
if err != S_OK && err != S_FALSE {
// S_FALSE just means COM is already initialized
return Err(err);
}
Ok(())
}
-pub struct ComPtr<T>(*mut T) where T: Interface;
-impl<T> ComPtr<T> where T: Interface {
+pub struct ComPtr<T>(*mut T)
+where
+ T: Interface;
+impl<T> ComPtr<T>
+where
+ T: Interface,
+{
/// Creates a `ComPtr` to wrap a raw pointer.
/// It takes ownership over the pointer which means it does __not__ call `AddRef`.
/// `T` __must__ be a COM interface that inherits from `IUnknown`.
pub unsafe fn from_raw(ptr: *mut T) -> ComPtr<T> {
assert!(!ptr.is_null());
ComPtr(ptr)
}
/// Casts up the inheritance chain
- pub fn up<U>(self) -> ComPtr<U> where T: Deref<Target=U>, U: Interface {
+ pub fn up<U>(self) -> ComPtr<U>
+ where
+ T: Deref<Target = U>,
+ U: Interface,
+ {
ComPtr(self.into_raw() as *mut U)
}
/// Extracts the raw pointer.
/// You are now responsible for releasing it yourself.
pub fn into_raw(self) -> *mut T {
let p = self.0;
forget(self);
p
}
/// For internal use only.
fn as_unknown(&self) -> &IUnknown {
unsafe { &*(self.0 as *mut IUnknown) }
}
/// Performs QueryInterface fun.
- pub fn cast<U>(&self) -> Result<ComPtr<U>, i32> where U: Interface {
+ pub fn cast<U>(&self) -> Result<ComPtr<U>, i32>
+ where
+ U: Interface,
+ {
let mut obj = null_mut();
let err = unsafe { self.as_unknown().QueryInterface(&U::uuidof(), &mut obj) };
- if err < 0 { return Err(err); }
+ if err < 0 {
+ return Err(err);
+ }
Ok(unsafe { ComPtr::from_raw(obj as *mut U) })
}
}
-impl<T> Deref for ComPtr<T> where T: Interface {
+impl<T> Deref for ComPtr<T>
+where
+ T: Interface,
+{
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.0 }
}
}
-impl<T> Clone for ComPtr<T> where T: Interface {
+impl<T> Clone for ComPtr<T>
+where
+ T: Interface,
+{
fn clone(&self) -> Self {
unsafe {
self.as_unknown().AddRef();
ComPtr::from_raw(self.0)
}
}
}
-impl<T> Drop for ComPtr<T> where T: Interface {
+impl<T> Drop for ComPtr<T>
+where
+ T: Interface,
+{
fn drop(&mut self) {
- unsafe { self.as_unknown().Release(); }
+ unsafe {
+ self.as_unknown().Release();
+ }
}
}
pub struct BStr(BSTR);
impl BStr {
pub unsafe fn from_raw(s: BSTR) -> BStr {
BStr(s)
}
pub fn to_osstring(&self) -> OsString {
@@ -97,29 +122,34 @@ impl Drop for BStr {
unsafe { SysFreeString(self.0) };
}
}
pub trait ToWide {
fn to_wide(&self) -> Vec<u16>;
fn to_wide_null(&self) -> Vec<u16>;
}
-impl<T> ToWide for T where T: AsRef<OsStr> {
+impl<T> ToWide for T
+where
+ T: AsRef<OsStr>,
+{
fn to_wide(&self) -> Vec<u16> {
self.as_ref().encode_wide().collect()
}
fn to_wide_null(&self) -> Vec<u16> {
self.as_ref().encode_wide().chain(Some(0)).collect()
}
}
-pub trait FromWide where Self: Sized {
+pub trait FromWide
+where
+ Self: Sized,
+{
fn from_wide(wide: &[u16]) -> Self;
fn from_wide_null(wide: &[u16]) -> Self {
let len = wide.iter().take_while(|&&c| c != 0).count();
Self::from_wide(&wide[..len])
}
}
impl FromWide for OsString {
fn from_wide(wide: &[u16]) -> OsString {
OsStringExt::from_wide(wide)
}
}
-
--- a/third_party/rust/cc/src/lib.rs
+++ b/third_party/rust/cc/src/lib.rs
@@ -56,25 +56,24 @@
#![doc(html_root_url = "https://docs.rs/cc/1.0")]
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
#[cfg(feature = "parallel")]
extern crate rayon;
use std::env;
-use std::ffi::{OsString, OsStr};
+use std::ffi::{OsStr, OsString};
use std::fs;
-use std::path::{PathBuf, Path};
-use std::process::{Command, Stdio, Child};
-use std::io::{self, BufReader, BufRead, Read, Write};
+use std::path::{Path, PathBuf};
+use std::process::{Child, Command, Stdio};
+use std::io::{self, BufRead, BufReader, Read, Write};
use std::thread::{self, JoinHandle};
-
-#[cfg(feature = "parallel")]
-use std::sync::Mutex;
+use std::collections::HashMap;
+use std::sync::{Arc, Mutex};
// These modules are all glue to support reading the MSVC version from
// the registry and from COM interfaces
#[cfg(windows)]
mod registry;
#[cfg(windows)]
#[macro_use]
mod winapi;
@@ -92,16 +91,17 @@ pub mod windows_registry;
/// documentation on each method itself.
#[derive(Clone, Debug)]
pub struct Build {
include_directories: Vec<PathBuf>,
definitions: Vec<(String, Option<String>)>,
objects: Vec<PathBuf>,
flags: Vec<String>,
flags_supported: Vec<String>,
+ known_flag_support_status: Arc<Mutex<HashMap<String, bool>>>,
files: Vec<PathBuf>,
cpp: bool,
cpp_link_stdlib: Option<Option<String>>,
cpp_set_stdlib: Option<String>,
cuda: bool,
target: Option<String>,
host: Option<String>,
out_dir: Option<PathBuf>,
@@ -236,64 +236,60 @@ impl ToolFamily {
}
}
/// 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::Gnu |
- ToolFamily::Clang => "-G",
+ 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::Gnu |
- ToolFamily::Clang => "-Xcompiler",
+ ToolFamily::Gnu | ToolFamily::Clang => "-Xcompiler",
}
}
}
/// Represents an object.
///
/// This is a source file -> object file pair.
#[derive(Clone, Debug)]
struct Object {
src: PathBuf,
dst: PathBuf,
}
impl Object {
/// Create a new source file -> object file pair.
fn new(src: PathBuf, dst: PathBuf) -> Object {
- Object {
- src: src,
- dst: dst,
- }
+ Object { src: src, dst: dst }
}
}
impl Build {
/// Construct a new instance of a blank set of configuration.
///
/// This builder is finished with the [`compile`] function.
///
/// [`compile`]: struct.Build.html#method.compile
pub fn new() -> Build {
Build {
include_directories: Vec::new(),
definitions: Vec::new(),
objects: Vec::new(),
flags: Vec::new(),
flags_supported: Vec::new(),
+ known_flag_support_status: Arc::new(Mutex::new(HashMap::new())),
files: Vec::new(),
shared_flag: None,
static_flag: None,
cpp: false,
cpp_link_stdlib: None,
cpp_set_stdlib: None,
cuda: false,
target: None,
@@ -339,20 +335,18 @@ impl Build {
/// ```no_run
/// cc::Build::new()
/// .file("src/foo.c")
/// .define("FOO", "BAR")
/// .define("BAZ", None)
/// .compile("foo");
/// ```
pub fn define<'a, V: Into<Option<&'a str>>>(&mut self, var: &str, val: V) -> &mut Build {
- self.definitions.push((
- var.to_string(),
- val.into().map(|s| s.to_string()),
- ));
+ self.definitions
+ .push((var.to_string(), val.into().map(|s| s.to_string())));
self
}
/// Add an arbitrary object file to link in
pub fn object<P: AsRef<Path>>(&mut self, obj: P) -> &mut Build {
self.objects.push(obj.as_ref().to_path_buf());
self
}
@@ -393,43 +387,56 @@ impl Build {
/// Run the compiler to test if it accepts the given flag.
///
/// For a convenience method for setting flags conditionally,
/// see `flag_if_supported()`.
///
/// It may return error if it's unable to run the compilier with a test file
/// (e.g. the compiler is missing or a write to the `out_dir` failed).
+ ///
+ /// Note: Once computed, the result of this call is stored in the
+ /// `known_flag_support` field. If `is_flag_supported(flag)`
+ /// is called again, the result will be read from the hash table.
pub fn is_flag_supported(&self, flag: &str) -> Result<bool, Error> {
+ let mut known_status = self.known_flag_support_status.lock().unwrap();
+ 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 mut cfg = Build::new();
cfg.flag(flag)
.target(&target)
.opt_level(0)
.host(&target)
.debug(false)
.cpp(self.cpp)
.cuda(self.cuda);
let compiler = cfg.try_get_compiler()?;
let mut cmd = compiler.to_command();
- command_add_output_file(&mut cmd, &obj, target.contains("msvc"), false);
+ let is_arm = target.contains("aarch64") || target.contains("arm");
+ command_add_output_file(&mut cmd, &obj, target.contains("msvc"), false, is_arm);
// We need to explicitly tell msvc not to link and create an exe
// in the root directory of the crate
if target.contains("msvc") {
cmd.arg("/c");
}
cmd.arg(&src);
let output = cmd.output()?;
- Ok(output.stderr.is_empty())
+ let is_supported = output.stderr.is_empty();
+
+ known_status.insert(flag.to_owned(), is_supported);
+ Ok(is_supported)
}
/// Add an arbitrary flag to the invocation of the compiler if it supports it
///
/// # Example
///
/// ```no_run
/// cc::Build::new()
@@ -772,19 +779,18 @@ impl Build {
}
#[doc(hidden)]
pub fn __set_env<A, B>(&mut self, a: A, b: B) -> &mut Build
where
A: AsRef<OsStr>,
B: AsRef<OsStr>,
{
- self.env.push(
- (a.as_ref().to_owned(), b.as_ref().to_owned()),
- );
+ self.env
+ .push((a.as_ref().to_owned(), b.as_ref().to_owned()));
self
}
/// Run the compiler, generating the file `output`
///
/// This will return a result instead of panicing; see compile() for the complete description.
pub fn try_compile(&self, output: &str) -> Result<(), Error> {
let (lib_name, gnu_lib_name) = if output.starts_with("lib") && output.ends_with(".a") {
@@ -875,76 +881,67 @@ impl Build {
fail(&e.message);
}
}
#[cfg(feature = "parallel")]
fn compile_objects(&self, objs: &[Object]) -> Result<(), Error> {
use self::rayon::prelude::*;
- let mut cfg = rayon::Configuration::new();
if let Ok(amt) = env::var("NUM_JOBS") {
if let Ok(amt) = amt.parse() {
- cfg = cfg.num_threads(amt);
- }
- }
- drop(rayon::initialize(cfg));
-
- let results: Mutex<Vec<Result<(), Error>>> = Mutex::new(Vec::new());
-
- objs.par_iter().with_max_len(1).for_each(
- |obj| {
- let res = self.compile_object(obj);
- results.lock().unwrap().push(res)
- },
- );
-
- // Check for any errors and return the first one found.
- for result in results.into_inner().unwrap().iter() {
- if result.is_err() {
- return result.clone();
+ let _ = rayon::ThreadPoolBuilder::new()
+ .num_threads(amt)
+ .build_global();
}
}
- Ok(())
+ // Check for any errors and return the first one found.
+ objs.par_iter()
+ .with_max_len(1)
+ .map(|obj| self.compile_object(obj))
+ .collect()
}
#[cfg(not(feature = "parallel"))]
fn compile_objects(&self, objs: &[Object]) -> Result<(), Error> {
for obj in objs {
self.compile_object(obj)?;
}
Ok(())
}
fn compile_object(&self, obj: &Object) -> Result<(), Error> {
let is_asm = obj.src.extension().and_then(|s| s.to_str()) == Some("asm");
- let msvc = self.get_target()?.contains("msvc");
+ let target = self.get_target()?;
+ let msvc = target.contains("msvc");
let (mut cmd, name) = if msvc && is_asm {
self.msvc_macro_assembler()?
} else {
let compiler = self.try_get_compiler()?;
let mut cmd = compiler.to_command();
for &(ref a, ref b) in self.env.iter() {
cmd.env(a, b);
}
(
cmd,
compiler
.path
.file_name()
- .ok_or_else(|| {
- Error::new(ErrorKind::IOError, "Failed to get compiler path.")
- })?
+ .ok_or_else(|| Error::new(ErrorKind::IOError, "Failed to get compiler path."))?
.to_string_lossy()
.into_owned(),
)
};
- command_add_output_file(&mut cmd, &obj.dst, msvc, is_asm);
- cmd.arg(if msvc { "/c" } else { "-c" });
+ let is_arm = target.contains("aarch64") || target.contains("arm");
+ command_add_output_file(&mut cmd, &obj.dst, msvc, is_asm, is_arm);
+ // armasm and armasm64 don't requrie -c option
+ if !msvc || !is_asm || !is_arm {
+ cmd.arg(if msvc { "/c" } else { "-c" });
+ }
cmd.arg(&obj.src);
run(&mut cmd, &name)?;
Ok(())
}
/// This will return a result instead of panicing; see expand() for the complete description.
pub fn try_expand(&self) -> Result<Vec<u8>, Error> {
@@ -962,19 +959,17 @@ impl Build {
for file in self.files.iter() {
cmd.arg(file);
}
let name = compiler
.path
.file_name()
- .ok_or_else(|| {
- Error::new(ErrorKind::IOError, "Failed to get compiler path.")
- })?
+ .ok_or_else(|| Error::new(ErrorKind::IOError, "Failed to get compiler path."))?
.to_string_lossy()
.into_owned();
Ok(run_output(&mut cmd, &name)?)
}
/// Run the compiler, returning the macro-expanded version of the input files.
///
@@ -1049,34 +1044,36 @@ impl Build {
} else {
"/MD"
}
}
};
cmd.args.push(crt_flag.into());
match &opt_level[..] {
- "z" | "s" => cmd.args.push("/Os".into()),
- "1" => cmd.args.push("/O1".into()),
+ // 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());
}
- cmd.push_cc_arg("-ffunction-sections".into());
- cmd.push_cc_arg("-fdata-sections".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());
}
}
}
for arg in self.envflags(if self.cpp { "CXXFLAGS" } else { "CFLAGS" }) {
cmd.args.push(arg.into());
}
@@ -1164,17 +1161,17 @@ impl Build {
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" {
+ 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())
@@ -1207,24 +1204,23 @@ impl Build {
}
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) => {
+ (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",
+ does not support this option, ignored",
cmd.family
);
}
}
}
for directory in self.include_directories.iter() {
cmd.args.push(cmd.family.include_flag().into());
@@ -1267,16 +1263,20 @@ impl Build {
Ok(cmd)
}
fn msvc_macro_assembler(&self) -> Result<(Command, String), Error> {
let target = self.get_target()?;
let tool = if target.contains("x86_64") {
"ml64.exe"
+ } else if target.contains("arm") {
+ "armasm.exe"
+ } else if target.contains("aarch64") {
+ "armasm64.exe"
} else {
"ml.exe"
};
let mut cmd = windows_registry::find(&target, tool).unwrap_or_else(|| self.cmd(tool));
for directory in self.include_directories.iter() {
cmd.arg("/I").arg(directory);
}
for &(ref key, ref value) in self.definitions.iter() {
@@ -1302,30 +1302,65 @@ impl Build {
// 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")
- },
- )
- }
+ None => windows_registry::find(&target, "lib.exe")
+ .unwrap_or_else(|| self.cmd("lib.exe")),
};
+
let mut out = OsString::from("/OUT:");
out.push(dst);
- run(
- cmd.arg(out).arg("/nologo").args(&objects).args(&self.objects),
- "lib.exe",
- )?;
+ 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()
+ .chain(&self.objects)
+ .map(|a| a.as_os_str().len())
+ .sum::<usize>();
+ if estimated_command_line_len > 1024 * 6 {
+ let mut args = String::from("\u{FEFF}"); // BOM
+ for arg in objects.iter().chain(&self.objects) {
+ args.push('"');
+ for c in arg.to_str().unwrap().chars() {
+ if c == '"' {
+ args.push('\\')
+ }
+ args.push(c)
+ }
+ args.push('"');
+ args.push('\n');
+ }
+
+ let mut utf16le = Vec::new();
+ for code_unit in args.encode_utf16() {
+ utf16le.push(code_unit as u8);
+ utf16le.push((code_unit >> 8) as u8);
+ }
+
+ let mut args_file = OsString::from(dst);
+ args_file.push(".args");
+ fs::File::create(&args_file)
+ .unwrap()
+ .write_all(&utf16le)
+ .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")?;
// 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)
@@ -1407,16 +1442,28 @@ impl Build {
ErrorKind::IOError,
"Unable to determine iOS SDK path.",
))
}
};
cmd.args.push("-isysroot".into());
cmd.args.push(sdk_path.trim().into());
+ cmd.args.push("-fembed-bitcode".into());
+ /*
+ * TODO we probably ultimatedly want the -fembed-bitcode-marker flag
+ * but can't have it now because of an issue in LLVM:
+ * https://github.com/alexcrichton/cc-rs/issues/301
+ * https://github.com/rust-lang/rust/pull/48896#comment-372192660
+ */
+ /*
+ if self.get_opt_level()? == "0" {
+ cmd.args.push("-fembed-bitcode-marker".into());
+ }
+ */
Ok(())
}
fn cmd<P: AsRef<OsStr>>(&self, prog: P) -> Command {
let mut cmd = Command::new(prog);
for &(ref a, ref b) in self.env.iter() {
cmd.env(a, b);
@@ -1432,47 +1479,54 @@ impl Build {
let target = self.get_target()?;
let (env, msvc, gnu, traditional) = if self.cpp {
("CXX", "cl.exe", "g++", "c++")
} else {
("CC", "cl.exe", "gcc", "cc")
};
// On Solaris, c++/cc unlikely to exist or be correct.
- let default = if host.contains("solaris") { gnu } else { traditional };
+ let default = if host.contains("solaris") {
+ gnu
+ } else {
+ traditional
+ };
- let tool_opt: Option<Tool> =
- self.env_tool(env)
- .map(|(tool, cc, args)| {
- let mut t = Tool::new(PathBuf::from(tool));
- if let Some(cc) = cc {
- t.cc_wrapper_path = Some(PathBuf::from(cc));
- }
- for arg in args {
- t.cc_wrapper_args.push(arg.into());
+ 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 {
+ t.cc_wrapper_path = Some(PathBuf::from(cc));
+ }
+ for arg in args {
+ t.cc_wrapper_args.push(arg.into());
+ }
+ t
+ })
+ .or_else(|| {
+ if target.contains("emscripten") {
+ let tool = if self.cpp { "em++" } else { "emcc" };
+ // Windows uses bat file so we have to be a bit more specific
+ if cfg!(windows) {
+ let mut t = Tool::new(PathBuf::from("cmd"));
+ t.args.push("/c".into());
+ t.args.push(format!("{}.bat", tool).into());
+ Some(t)
+ } else {
+ Some(Tool::new(PathBuf::from(tool)))
}
- t
- })
- .or_else(|| {
- if target.contains("emscripten") {
- let tool = if self.cpp { "em++" } else { "emcc" };
- // Windows uses bat file so we have to be a bit more specific
- if cfg!(windows) {
- let mut t = Tool::new(PathBuf::from("cmd"));
- t.args.push("/c".into());
- t.args.push(format!("{}.bat", tool).into());
- Some(t)
- } else {
- Some(Tool::new(PathBuf::from(tool)))
- }
- } else {
- None
- }
- })
- .or_else(|| windows_registry::find_tool(&target, "cl.exe"));
+ } else {
+ None
+ }
+ })
+ .or_else(|| windows_registry::find_tool(&target, "cl.exe"));
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 {
@@ -1496,28 +1550,31 @@ impl Build {
"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"),
"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"),
"mips64el-unknown-linux-gnuabi64" => Some("mips64el-linux-gnuabi64"),
"powerpc-unknown-linux-gnu" => Some("powerpc-linux-gnu"),
+ "powerpc-unknown-linux-gnuspe" => Some("powerpc-linux-gnuspe"),
"powerpc-unknown-netbsd" => Some("powerpc--netbsd"),
"powerpc64-unknown-linux-gnu" => Some("powerpc-linux-gnu"),
"powerpc64le-unknown-linux-gnu" => Some("powerpc64le-linux-gnu"),
"s390x-unknown-linux-gnu" => Some("s390x-linux-gnu"),
+ "sparc-unknown-linux-gnu" => Some("sparc-linux-gnu"),
"sparc64-unknown-linux-gnu" => Some("sparc64-linux-gnu"),
"sparc64-unknown-netbsd" => Some("sparc64--netbsd"),
"sparcv9-sun-solaris" => Some("sparcv9-sun-solaris"),
"thumbv6m-none-eabi" => Some("arm-none-eabi"),
"thumbv7em-none-eabi" => Some("arm-none-eabi"),
"thumbv7em-none-eabihf" => Some("arm-none-eabi"),
"thumbv7m-none-eabi" => Some("arm-none-eabi"),
"x86_64-pc-windows-gnu" => Some("x86_64-w64-mingw32"),
@@ -1533,24 +1590,28 @@ impl Build {
} else {
default.to_string()
};
Tool::new(PathBuf::from(compiler))
}
};
let tool = if self.cuda {
- assert!(tool.args.is_empty(),
- "CUDA compilation currently assumes empty pre-existing args");
+ 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,
};
let mut nvcc_tool = Tool::with_features(PathBuf::from(nvcc), self.cuda);
- nvcc_tool.args.push(format!("-ccbin={}", tool.path.display()).into());
+ nvcc_tool
+ .args
+ .push(format!("-ccbin={}", tool.path.display()).into());
nvcc_tool
} else {
tool
};
Ok(tool)
}
@@ -1563,60 +1624,104 @@ impl Build {
.or_else(|| self.getenv(&format!("{}_{}", var_base, target_u)))
.or_else(|| self.getenv(&format!("{}_{}", kind, var_base)))
.or_else(|| self.getenv(var_base));
match res {
Some(res) => Ok(res),
None => Err(Error::new(
ErrorKind::EnvVarNotFound,
- &format!(
- "Could not find environment variable {}.",
- var_base
- ),
+ &format!("Could not find environment variable {}.", var_base),
)),
}
}
fn envflags(&self, name: &str) -> Vec<String> {
self.get_var(name)
.unwrap_or(String::new())
.split(|c: char| c.is_whitespace())
.filter(|s| !s.is_empty())
.map(|s| s.to_string())
.collect()
}
-
/// Returns compiler path, optional modifier name from whitelist, and arguments vec
fn env_tool(&self, name: &str) -> Option<(String, Option<String>, Vec<String>)> {
- self.get_var(name).ok().map(|tool| {
- let whitelist = ["ccache", "distcc", "sccache"];
+ let tool = match self.get_var(name) {
+ Ok(tool) => tool,
+ Err(_) => return None,
+ };
+
+ // If this is an exact path on the filesystem we don't want to do any
+ // interpretation at all, just pass it on through. This'll hopefully get
+ // us to support spaces-in-paths.
+ if Path::new(&tool).exists() {
+ return Some((tool, None, Vec::new()));
+ }
- for t in whitelist.iter() {
- if tool.starts_with(t) && tool[t.len()..].starts_with(' ') {
- let args = tool.split_whitespace().collect::<Vec<_>>();
+ // Ok now we want to handle a couple of scenarios. We'll assume from
+ // here on out that spaces are splitting separate arguments. Two major
+ // features we want to support are:
+ //
+ // CC='sccache cc'
+ //
+ // aka using `sccache` or any other wrapper/caching-like-thing for
+ // compilations. We want to know what the actual compiler is still,
+ // though, because our `Tool` API support introspection of it to see
+ // what compiler is in use.
+ //
+ // additionally we want to support
+ //
+ // CC='cc -flag'
+ //
+ // where the CC env var is used to also pass default flags to the C
+ // compiler.
+ //
+ // It's true that everything here is a bit of a pain, but apparently if
+ // you're not literally make or bash then you get a lot of bug reports.
+ let known_wrappers = ["ccache", "distcc", "sccache", "icecc"];
- return (args[1].to_string(), Some(t.to_string()), args[2..].iter().map(|s| s.to_string()).collect());
- }
+ let mut parts = tool.split_whitespace();
+ let maybe_wrapper = match parts.next() {
+ Some(s) => s,
+ None => return None,
+ };
+
+ let file_stem = Path::new(maybe_wrapper)
+ .file_stem()
+ .unwrap()
+ .to_str()
+ .unwrap();
+ if known_wrappers.contains(&file_stem) {
+ if let Some(compiler) = parts.next() {
+ return Some((
+ compiler.to_string(),
+ Some(maybe_wrapper.to_string()),
+ parts.map(|s| s.to_string()).collect(),
+ ));
}
- (tool, None, Vec::new())
- })
+ }
+
+ Some((
+ maybe_wrapper.to_string(),
+ None,
+ parts.map(|s| s.to_string()).collect(),
+ ))
}
/// 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("darwin") {
+ } 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()))
}
@@ -1695,20 +1800,17 @@ impl Build {
r
}
fn getenv_unwrap(&self, v: &str) -> Result<String, Error> {
match self.getenv(v) {
Some(s) => Ok(s),
None => Err(Error::new(
ErrorKind::EnvVarNotFound,
- &format!(
- "Environment variable {} not defined.",
- v.to_string()
- ),
+ &format!("Environment variable {} not defined.", v.to_string()),
)),
}
}
fn print(&self, s: &str) {
if self.cargo_metadata {
println!("{}", s);
}
@@ -1726,18 +1828,19 @@ impl 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") {
ToolFamily::Clang
- } else if fname.contains("cl") && !fname.contains("cloudabi") &&
- !fname.contains("uclibc") {
+ } else if fname.contains("cl") && !fname.contains("cloudabi")
+ && !fname.contains("uclibc")
+ {
ToolFamily::Msvc
} else {
ToolFamily::Gnu
}
} else {
ToolFamily::Gnu
};
Tool {
@@ -1770,18 +1873,18 @@ impl Tool {
/// 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)
+ }
+ None => Command::new(&self.path),
};
cmd.args(&self.args);
for &(ref k, ref v) in self.env.iter() {
cmd.env(k, v);
}
cmd
}
@@ -1817,20 +1920,18 @@ impl Tool {
let mut cc_env = cc_wrapper_path.as_os_str().to_owned();
cc_env.push(" ");
cc_env.push(self.path.to_path_buf().into_os_string());
for arg in self.cc_wrapper_args.iter() {
cc_env.push(" ");
cc_env.push(arg);
}
cc_env
- },
- None => {
- OsString::from("")
}
+ None => OsString::from(""),
}
}
/// Returns the compiler flags in format of CFLAGS environment variable.
/// Important here - this will not be CFLAGS from env, its internal gcc's flags to use as CFLAGS
/// This is typically used by configure script
pub fn cflags_env(&self) -> OsString {
let mut flags = OsString::new();
@@ -1863,35 +1964,32 @@ fn run(cmd: &mut Command, program: &str)
let (mut child, print) = spawn(cmd, program)?;
let status = match child.wait() {
Ok(s) => s,
Err(_) => {
return Err(Error::new(
ErrorKind::ToolExecError,
&format!(
"Failed to wait on spawned child process, command {:?} with args {:?}.",
- cmd,
- program
+ cmd, program
),
))
}
};
print.join().unwrap();
println!("{}", status);
if status.success() {
Ok(())
} else {
Err(Error::new(
ErrorKind::ToolExecError,
&format!(
"Command {:?} with args {:?} did not execute successfully (status code {}).",
- cmd,
- program,
- status
+ cmd, program, status
),
))
}
}
fn run_output(cmd: &mut Command, program: &str) -> Result<Vec<u8>, Error> {
cmd.stdout(Stdio::piped());
let (mut child, print) = spawn(cmd, program)?;
@@ -1904,94 +2002,83 @@ fn run_output(cmd: &mut Command, program
.unwrap();
let status = match child.wait() {
Ok(s) => s,
Err(_) => {
return Err(Error::new(
ErrorKind::ToolExecError,
&format!(
"Failed to wait on spawned child process, command {:?} with args {:?}.",
- cmd,
- program
+ cmd, program
),
))
}
};
print.join().unwrap();
println!("{}", status);
if status.success() {
Ok(stdout)
} else {
Err(Error::new(
ErrorKind::ToolExecError,
&format!(
"Command {:?} with args {:?} did not execute successfully (status code {}).",
- cmd,
- program,
- status
+ cmd, program, status
),
))
}
}
fn spawn(cmd: &mut Command, program: &str) -> Result<(Child, JoinHandle<()>), Error> {
println!("running: {:?}", cmd);
// Capture the standard error coming from these programs, and write it out
// with cargo:warning= prefixes. Note that this is a bit wonky to avoid
// requiring the output to be UTF-8, we instead just ship bytes from one
// location to another.
match cmd.stderr(Stdio::piped()).spawn() {
Ok(mut child) => {
let stderr = BufReader::new(child.stderr.take().unwrap());
- let print = thread::spawn(move || for line in stderr.split(b'\n').filter_map(
- |l| l.ok(),
- )
- {
- print!("cargo:warning=");
- std::io::stdout().write_all(&line).unwrap();
- println!("");
+ let print = thread::spawn(move || {
+ for line in stderr.split(b'\n').filter_map(|l| l.ok()) {
+ print!("cargo:warning=");
+ std::io::stdout().write_all(&line).unwrap();
+ println!("");
+ }
});
Ok((child, print))
}
Err(ref e) if e.kind() == io::ErrorKind::NotFound => {
let extra = if cfg!(windows) {
" (see https://github.com/alexcrichton/cc-rs#compile-time-requirements \
- for help)"
+ for help)"
} else {
""
};
Err(Error::new(
ErrorKind::ToolNotFound,
- &format!(
- "Failed to find tool. Is `{}` installed?{}",
- program,
- extra
- ),
+ &format!("Failed to find tool. Is `{}` installed?{}", program, extra),
))
}
Err(_) => Err(Error::new(
ErrorKind::ToolExecError,
- &format!(
- "Command {:?} with args {:?} failed to start.",
- cmd,
- program
- ),
+ &format!("Command {:?} with args {:?} failed to start.", cmd, program),
)),
}
}
fn fail(s: &str) -> ! {
panic!("\n\nInternal error occurred: {}\n\n", s)
}
-
-fn command_add_output_file(cmd: &mut Command, dst: &Path, msvc: bool, is_asm: bool) {
- if msvc && is_asm {
+fn command_add_output_file(cmd: &mut Command, dst: &Path, msvc: bool, is_asm: bool, is_arm: bool) {
+ if msvc && is_asm && is_arm {
+ cmd.arg("-o").arg(&dst);
+ } else if msvc && is_asm {
cmd.arg("/Fo").arg(dst);
} else if msvc {
let mut s = OsString::from("/Fo");
s.push(&dst);
cmd.arg(s);
} else {
cmd.arg("-o").arg(&dst);
}
--- a/third_party/rust/cc/src/registry.rs
+++ b/third_party/rust/cc/src/registry.rs
@@ -3,17 +3,17 @@
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::ffi::{OsString, OsStr};
+use std::ffi::{OsStr, OsString};
use std::io;
use std::ops::RangeFrom;
use std::os::raw;
use std::os::windows::prelude::*;
pub struct RegistryKey(Repr);
type HKEY = *mut u8;
@@ -31,38 +31,41 @@ const ERROR_SUCCESS: DWORD = 0;
const ERROR_NO_MORE_ITEMS: DWORD = 259;
const HKEY_LOCAL_MACHINE: HKEY = 0x80000002 as HKEY;
const REG_SZ: DWORD = 1;
const KEY_READ: DWORD = 0x20019;
const KEY_WOW64_32KEY: DWORD = 0x200;
#[link(name = "advapi32")]
extern "system" {
- fn RegOpenKeyExW(key: HKEY,
- lpSubKey: LPCWSTR,
- ulOptions: DWORD,
- samDesired: REGSAM,
- phkResult: PHKEY)
- -> LONG;
- fn RegEnumKeyExW(key: HKEY,
- dwIndex: DWORD,
- lpName: LPWSTR,
- lpcName: LPDWORD,
- lpReserved: LPDWORD,
- lpClass: LPWSTR,
- lpcClass: LPDWORD,
- lpftLastWriteTime: PFILETIME)
- -> LONG;
- fn RegQueryValueExW(hKey: HKEY,
- lpValueName: LPCWSTR,
- lpReserved: LPDWORD,
- lpType: LPDWORD,
- lpData: LPBYTE,
- lpcbData: LPDWORD)
- -> LONG;
+ fn RegOpenKeyExW(
+ key: HKEY,
+ lpSubKey: LPCWSTR,
+ ulOptions: DWORD,
+ samDesired: REGSAM,
+ phkResult: PHKEY,
+ ) -> LONG;
+ fn RegEnumKeyExW(
+ key: HKEY,
+ dwIndex: DWORD,
+ lpName: LPWSTR,
+ lpcName: LPDWORD,
+ lpReserved: LPDWORD,
+ lpClass: LPWSTR,
+ lpcClass: LPDWORD,
+ lpftLastWriteTime: PFILETIME,
+ ) -> LONG;
+ fn RegQueryValueExW(
+ hKey: HKEY,
+ lpValueName: LPCWSTR,
+ lpReserved: LPDWORD,
+ lpType: LPDWORD,
+ lpData: LPBYTE,
+ lpcbData: LPDWORD,
+ ) -> LONG;
fn RegCloseKey(hKey: HKEY) -> LONG;
}
struct OwnedKey(HKEY);
enum Repr {
Const(HKEY),
Owned(OwnedKey),
@@ -85,21 +88,23 @@ impl RegistryKey {
Repr::Owned(ref val) => val.0,
}
}
pub fn open(&self, key: &OsStr) -> io::Result<RegistryKey> {
let key = key.encode_wide().chain(Some(0)).collect::<Vec<_>>();
let mut ret = 0 as *mut _;
let err = unsafe {
- RegOpenKeyExW(self.raw(),
- key.as_ptr(),
- 0,
- KEY_READ | KEY_WOW64_32KEY,
- &mut ret)
+ RegOpenKeyExW(
+ self.raw(),
+ key.as_ptr(),
+ 0,
+ KEY_READ | KEY_WOW64_32KEY,
+ &mut ret,
+ )
};
if err == ERROR_SUCCESS as LONG {
Ok(RegistryKey(Repr::Owned(OwnedKey(ret))))
} else {
Err(io::Error::from_raw_os_error(err as i32))
}
}
@@ -111,39 +116,46 @@ impl RegistryKey {
}
pub fn query_str(&self, name: &str) -> io::Result<OsString> {
let name: &OsStr = name.as_ref();
let name = name.encode_wide().chain(Some(0)).collect::<Vec<_>>();
let mut len = 0;
let mut kind = 0;
unsafe {
- let err = RegQueryValueExW(self.raw(),
- name.as_ptr(),
- 0 as *mut _,
- &mut kind,
- 0 as *mut _,
- &mut len);
+ let err = RegQueryValueExW(
+ self.raw(),
+ name.as_ptr(),
+ 0 as *mut _,
+ &mut kind,
+ 0 as *mut _,
+ &mut len,
+ );
if err != ERROR_SUCCESS as LONG {
return Err(io::Error::from_raw_os_error(err as i32));
}
if kind != REG_SZ {
- return Err(io::Error::new(io::ErrorKind::Other, "registry key wasn't a string"));
+ return Err(io::Error::new(
+ io::ErrorKind::Other,
+ "registry key wasn't a string",
+ ));
}
// The length here is the length in bytes, but we're using wide
// characters so we need to be sure to halve it for the capacity
// passed in.
let mut v = Vec::with_capacity(len as usize / 2);
- let err = RegQueryValueExW(self.raw(),
- name.as_ptr(),
- 0 as *mut _,
- 0 as *mut _,
- v.as_mut_ptr() as *mut _,
- &mut len);
+ let err = RegQueryValueExW(
+ self.raw(),
+ name.as_ptr(),
+ 0 as *mut _,
+ 0 as *mut _,
+ v.as_mut_ptr() as *mut _,
+ &mut len,
+ );
if err != ERROR_SUCCESS as LONG {
return Err(io::Error::from_raw_os_error(err as i32));
}
v.set_len(len as usize / 2);
// Some registry keys may have a terminating nul character, but
// we're not interested in that, so chop it off if it's there.
if v[v.len() - 1] == 0 {
@@ -164,24 +176,26 @@ impl Drop for OwnedKey {
impl<'a> Iterator for Iter<'a> {
type Item = io::Result<OsString>;
fn next(&mut self) -> Option<io::Result<OsString>> {
self.idx.next().and_then(|i| unsafe {
let mut v = Vec::with_capacity(256);
let mut len = v.capacity() as DWORD;
- let ret = RegEnumKeyExW(self.key.raw(),
- i,
- v.as_mut_ptr(),
- &mut len,
- 0 as *mut _,
- 0 as *mut _,
- 0 as *mut _,
- 0 as *mut _);
+ let ret = RegEnumKeyExW(
+ self.key.raw(),
+ i,
+ v.as_mut_ptr(),
+ &mut len,
+ 0 as *mut _,
+ 0 as *mut _,
+ 0 as *mut _,
+ 0 as *mut _,
+ );
if ret == ERROR_NO_MORE_ITEMS as LONG {
None
} else if ret != ERROR_SUCCESS as LONG {
Some(Err(io::Error::from_raw_os_error(ret as i32)))
} else {
v.set_len(len as usize);
Some(Ok(OsString::from_wide(&v)))
}
--- a/third_party/rust/cc/src/setup_config.rs
+++ b/third_party/rust/cc/src/setup_config.rs
@@ -10,17 +10,17 @@
use std::ffi::OsString;
use std::ptr::null_mut;
use winapi::Interface;
use winapi::{LPFILETIME, ULONG};
use winapi::S_FALSE;
use winapi::BSTR;
use winapi::LPCOLESTR;
-use winapi::{CLSCTX_ALL, CoCreateInstance};
+use winapi::{CoCreateInstance, CLSCTX_ALL};
use winapi::LPSAFEARRAY;
use winapi::{IUnknown, IUnknownVtbl};
use winapi::{HRESULT, LCID, LPCWSTR, PULONGLONG};
use com::{BStr, ComPtr};
// Bindings to the Setup.Configuration stuff
pub type InstanceState = u32;
@@ -150,93 +150,116 @@ interface ISetupHelper(ISetupHelperVtbl)
fn ParseVersionRange(
pwszVersionRange: LPCOLESTR,
pullMinVersion: PULONGLONG,
pullMaxVersion: PULONGLONG,
) -> HRESULT,
}}
DEFINE_GUID!{CLSID_SetupConfiguration,
- 0x177f0c4a, 0x1cd3, 0x4de7, 0xa3, 0x2c, 0x71, 0xdb, 0xbb, 0x9f, 0xa3, 0x6d}
+0x177f0c4a, 0x1cd3, 0x4de7, 0xa3, 0x2c, 0x71, 0xdb, 0xbb, 0x9f, 0xa3, 0x6d}
// Safe wrapper around the COM interfaces
pub struct SetupConfiguration(ComPtr<ISetupConfiguration>);
impl SetupConfiguration {
pub fn new() -> Result<SetupConfiguration, i32> {
let mut obj = null_mut();
- let err = unsafe { CoCreateInstance(
- &CLSID_SetupConfiguration, null_mut(), CLSCTX_ALL,
- &ISetupConfiguration::uuidof(), &mut obj,
- ) };
- if err < 0 { return Err(err); }
+ let err = unsafe {
+ CoCreateInstance(
+ &CLSID_SetupConfiguration,
+ null_mut(),
+ CLSCTX_ALL,
+ &ISetupConfiguration::uuidof(),
+ &mut obj,
+ )
+ };
+ if err < 0 {
+ return Err(err);
+ }
let obj = unsafe { ComPtr::from_raw(obj as *mut ISetupConfiguration) };
Ok(SetupConfiguration(obj))
}
pub fn get_instance_for_current_process(&self) -> Result<SetupInstance, i32> {
let mut obj = null_mut();
let err = unsafe { self.0.GetInstanceForCurrentProcess(&mut obj) };
- if err < 0 { return Err(err); }
+ if err < 0 {
+ return Err(err);
+ }
Ok(unsafe { SetupInstance::from_raw(obj) })
}
pub fn enum_instances(&self) -> Result<EnumSetupInstances, i32> {
let mut obj = null_mut();
let err = unsafe { self.0.EnumInstances(&mut obj) };
- if err < 0 { return Err(err); }
+ if err < 0 {
+ return Err(err);
+ }
Ok(unsafe { EnumSetupInstances::from_raw(obj) })
}
pub fn enum_all_instances(&self) -> Result<EnumSetupInstances, i32> {
let mut obj = null_mut();
let this = try!(self.0.cast::<ISetupConfiguration2>());
let err = unsafe { this.EnumAllInstances(&mut obj) };
- if err < 0 { return Err(err); }
+ if err < 0 {
+ return Err(err);
+ }
Ok(unsafe { EnumSetupInstances::from_raw(obj) })
}
}
pub struct SetupInstance(ComPtr<ISetupInstance>);
impl SetupInstance {
pub unsafe fn from_raw(obj: *mut ISetupInstance) -> SetupInstance {
SetupInstance(ComPtr::from_raw(obj))
}
pub fn instance_id(&self) -> Result<OsString, i32> {
let mut s = null_mut();
let err = unsafe { self.0.GetInstanceId(&mut s) };
let bstr = unsafe { BStr::from_raw(s) };
- if err < 0 { return Err(err); }
+ if err < 0 {
+ return Err(err);
+ }
Ok(bstr.to_osstring())
}
pub fn installation_name(&self) -> Result<OsString, i32> {
let mut s = null_mut();
let err = unsafe { self.0.GetInstallationName(&mut s) };
let bstr = unsafe { BStr::from_raw(s) };
- if err < 0 { return Err(err); }
+ if err < 0 {
+ return Err(err);
+ }
Ok(bstr.to_osstring())
}
pub fn installation_path(&self) -> Result<OsString, i32> {
let mut s = null_mut();
let err = unsafe { self.0.GetInstallationPath(&mut s) };
let bstr = unsafe { BStr::from_raw(s) };
- if err < 0 { return Err(err); }
+ if err < 0 {
+ return Err(err);
+ }
Ok(bstr.to_osstring())
}
pub fn installation_version(&self) -> Result<OsString, i32> {
let mut s = null_mut();
let err = unsafe { self.0.GetInstallationVersion(&mut s) };
let bstr = unsafe { BStr::from_raw(s) };
- if err < 0 { return Err(err); }
+ if err < 0 {
+ return Err(err);
+ }
Ok(bstr.to_osstring())
}
pub fn product_path(&self) -> Result<OsString, i32> {
let mut s = null_mut();
let this = try!(self.0.cast::<ISetupInstance2>());
let err = unsafe { this.GetProductPath(&mut s) };
let bstr = unsafe { BStr::from_raw(s) };
- if err < 0 { return Err(err); }
+ if err < 0 {
+ return Err(err);
+ }
Ok(bstr.to_osstring())
}
}
pub struct EnumSetupInstances(ComPtr<IEnumSetupInstances>);
impl EnumSetupInstances {
pub unsafe fn from_raw(obj: *mut IEnumSetupInstances) -> EnumSetupInstances {
@@ -244,14 +267,17 @@ impl EnumSetupInstances {
}
}
impl Iterator for EnumSetupInstances {
type Item = Result<SetupInstance, i32>;
fn next(&mut self) -> Option<Result<SetupInstance, i32>> {
let mut obj = null_mut();
let err = unsafe { self.0.Next(1, &mut obj, null_mut()) };
- if err < 0 { return Some(Err(err)); }
- if err == S_FALSE { return None; }
+ if err < 0 {
+ return Some(Err(err));
+ }
+ if err == S_FALSE {
+ return None;
+ }
Some(Ok(unsafe { SetupInstance::from_raw(obj) }))
}
}
-
--- a/third_party/rust/cc/src/winapi.rs
+++ b/third_party/rust/cc/src/winapi.rs
@@ -39,18 +39,18 @@ pub const COINIT_MULTITHREADED: u32 = 0x
pub type CLSCTX = u32;
pub const CLSCTX_INPROC_SERVER: CLSCTX = 0x1;
pub const CLSCTX_INPROC_HANDLER: CLSCTX = 0x2;
pub const CLSCTX_LOCAL_SERVER: CLSCTX = 0x4;
pub const CLSCTX_REMOTE_SERVER: CLSCTX = 0x10;
-pub const CLSCTX_ALL: CLSCTX = CLSCTX_INPROC_SERVER |
- CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER;
+pub const CLSCTX_ALL: CLSCTX =
+ CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct GUID {
pub Data1: raw::c_ulong,
pub Data2: raw::c_ushort,
pub Data3: raw::c_ushort,
pub Data4: [raw::c_uchar; 8],
@@ -64,23 +64,27 @@ pub struct FILETIME {
}
pub trait Interface {
fn uuidof() -> GUID;
}
#[link(name = "ole32")]
#[link(name = "oleaut32")]
-extern { }
+extern "C" {}
extern "system" {
pub fn CoInitializeEx(pvReserved: LPVOID, dwCoInit: DWORD) -> HRESULT;
- pub fn CoCreateInstance(rclsid: REFCLSID, pUnkOuter: LPUNKNOWN,
- dwClsContext: DWORD, riid: REFIID,
- ppv: *mut LPVOID) -> HRESULT;
+ pub fn CoCreateInstance(
+ rclsid: REFCLSID,
+ pUnkOuter: LPUNKNOWN,
+ dwClsContext: DWORD,
+ riid: REFIID,
+ ppv: *mut LPVOID,
+ ) -> HRESULT;
pub fn SysFreeString(bstrString: BSTR);
pub fn SysStringLen(pbstr: BSTR) -> UINT;
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct SAFEARRAYBOUND {
pub cElements: ULONG,
--- a/third_party/rust/cc/src/windows_registry.rs
+++ b/third_party/rust/cc/src/windows_registry.rs
@@ -64,17 +64,21 @@ pub fn find_tool(target: &str, tool: &st
if tool.contains("msbuild") {
return impl_::find_msbuild(target);
}
// If VCINSTALLDIR is set, then someone's probably already run vcvars and we
// should just find whatever that indicates.
if env::var_os("VCINSTALLDIR").is_some() {
return env::var_os("PATH")
- .and_then(|path| env::split_paths(&path).map(|p| p.join(tool)).find(|p| p.exists()))
+ .and_then(|path| {
+ env::split_paths(&path)
+ .map(|p| p.join(tool))
+ .find(|p| p.exists())
+ })
.map(|path| Tool::new(path.into()));
}
// Ok, if we're here, now comes the fun part of the probing. Default shells
// or shells like MSYS aren't really configured to execute `cl.exe` and the
// various compiler tools shipped as part of Visual Studio. Here we try to
// first find the relevant tool, then we also have to be sure to fill in
// environment variables like `LIB`, `INCLUDE`, and `PATH` to ensure that
@@ -114,45 +118,48 @@ 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[..] {
- "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)),
- }
- }
+ Ok(version) => match &version[..] {
+ "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") {
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\
- couldn't determine visual studio generator\n\
- if VisualStudio is installed, however, consider \
- running the appropriate vcvars script before building \
- this crate\n\
- "))
+ Err(format!(
+ "\n\n\
+ couldn't determine visual studio generator\n\
+ if VisualStudio is installed, however, consider \
+ running the appropriate vcvars script before building \
+ this crate\n\
+ "
+ ))
}
}
}
}
#[cfg(windows)]
mod impl_ {
use std::env;
@@ -180,17 +187,22 @@ mod impl_ {
tool: tool,
libs: Vec::new(),
path: Vec::new(),
include: Vec::new(),
}
}
fn into_tool(self) -> Tool {
- let MsvcTool { tool, libs, path, include } = self;
+ let MsvcTool {
+ tool,
+ libs,
+ path,
+ include,
+ } = self;
let mut tool = Tool::new(tool.into());
add_env(&mut tool, "LIB", libs);
add_env(&mut tool, "PATH", path);
add_env(&mut tool, "INCLUDE", include);
tool
}
}
@@ -212,59 +224,69 @@ mod impl_ {
if tool.is_some() {
return tool;
}
}
None
}
- 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));
+ 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 };
+ if !tool_path.exists() {
+ return None;
+ };
let mut tool = MsvcTool::new(tool_path);
tool.path.push(host_dylib_path);
tool.libs.push(lib_path);
tool.include.push(include_path);
if let Some((atl_lib_path, atl_include_path)) = atl_paths(target, &bin_path) {
tool.libs.push(atl_lib_path);
tool.include.push(atl_include_path);
}
otry!(add_sdks(&mut tool, target));
Some(tool.into_tool())
}
- fn vs15_vc_paths(target: &str, instance: &SetupInstance) -> Option<(PathBuf, PathBuf, PathBuf, PathBuf)> {
+ fn vs15_vc_paths(
+ target: &str,
+ instance: &SetupInstance,
+ ) -> Option<(PathBuf, PathBuf, PathBuf, PathBuf)> {
let instance_path: PathBuf = otry!(instance.installation_path().ok()).into();
- let version_path = instance_path.join(r"VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt");
+ let version_path =
+ instance_path.join(r"VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt");
let mut version_file = otry!(File::open(version_path).ok());
let mut version = String::new();
otry!(version_file.read_to_string(&mut version).ok());
let version = version.trim();
let host = match host_arch() {
X86 => "X86",
X86_64 => "X64",
_ => return None,
};
let target = otry!(lib_subdir(target));
// The directory layout here is MSVC/bin/Host$host/$target/
let path = instance_path.join(r"VC\Tools\MSVC").join(version);
// This is the path to the toolchain for a particular target, running
// on a given host
- let bin_path = path.join("bin").join(&format!("Host{}", host)).join(&target);
+ let bin_path = path.join("bin")
+ .join(&format!("Host{}", host))
+ .join(&target);
// But! we also need PATH to contain the target directory for the host
// architecture, because it contains dlls like mspdb140.dll compiled for
// the host architecture.
- let host_dylib_path = path.join("bin").join(&format!("Host{}", host)).join(&host.to_lowercase());
+ let host_dylib_path = path.join("bin")
+ .join(&format!("Host{}", host))
+ .join(&host.to_lowercase());
let lib_path = path.join("lib").join(&target);
let include_path = path.join("include");
Some((bin_path, host_dylib_path, lib_path, include_path))
}
fn atl_paths(target: &str, path: &Path) -> Option<(PathBuf, PathBuf)> {
let atl_path = path.join("atlfmc");
let sub = otry!(lib_subdir(target));
@@ -283,17 +305,18 @@ mod impl_ {
otry!(add_sdks(&mut tool, target));
Some(tool.into_tool())
}
fn add_sdks(tool: &mut MsvcTool, target: &str) -> Option<()> {
let sub = otry!(lib_subdir(target));
let (ucrt, ucrt_version) = otry!(get_ucrt_dir());
- tool.path.push(ucrt.join("bin").join(&ucrt_version).join(sub));
+ tool.path
+ .push(ucrt.join("bin").join(&ucrt_version).join(sub));
let ucrt_include = ucrt.join("include").join(&ucrt_version);
tool.include.push(ucrt_include.join("ucrt"));
let ucrt_lib = ucrt.join("lib").join(&ucrt_version);
tool.libs.push(ucrt_lib.join("ucrt").join(sub));
if let Some((sdk, version)) = get_sdk10_dir() {
@@ -348,25 +371,31 @@ mod impl_ {
tool.include.push(sdk_include.join("winrt"));
Some(tool.into_tool())
}
fn add_env(tool: &mut Tool, env: &str, paths: Vec<PathBuf>) {
let prev = env::var_os(env).unwrap_or(OsString::new());
let prev = env::split_paths(&prev);
let new = paths.into_iter().chain(prev);
- tool.env.push((env.to_string().into(), env::join_paths(new).unwrap()));
+ tool.env
+ .push((env.to_string().into(), env::join_paths(new).unwrap()));
}
// Given a possible MSVC installation directory, we look for the linker and
// then add the MSVC library path.
fn get_tool(tool: &str, path: &Path, target: &str) -> Option<MsvcTool> {
bin_subdir(target)
.into_iter()
- .map(|(sub, host)| (path.join("bin").join(sub).join(tool), path.join("bin").join(host)))
+ .map(|(sub, host)| {
+ (
+ path.join("bin").join(sub).join(tool),
+ path.join("bin").join(host),
+ )
+ })
.filter(|&(ref path, _)| path.is_file())
.map(|(path, host)| {
let mut tool = MsvcTool::new(path);
tool.path.push(host);
tool
})
.filter_map(|mut tool| {
let sub = otry!(vc_lib_subdir(target));
@@ -397,26 +426,27 @@ mod impl_ {
// what vcvars does so that's good enough for us.
//
// Returns a pair of (root, version) for the ucrt dir if found
fn get_ucrt_dir() -> Option<(PathBuf, String)> {
let key = r"SOFTWARE\Microsoft\Windows Kits\Installed Roots";
let key = otry!(LOCAL_MACHINE.open(key.as_ref()).ok());
let root = otry!(key.query_str("KitsRoot10").ok());
let readdir = otry!(Path::new(&root).join("lib").read_dir().ok());
- let max_libdir = otry!(readdir.filter_map(|dir| dir.ok())
- .map(|dir| dir.path())
- .filter(|dir| {
- dir.components()
+ let max_libdir = otry!(
+ readdir
+ .filter_map(|dir| dir.ok())
+ .map(|dir| dir.path())
+ .filter(|dir| dir.components()
.last()
.and_then(|c| c.as_os_str().to_str())
.map(|c| c.starts_with("10.") && dir.join("ucrt").is_dir())
- .unwrap_or(false)
- })
- .max());
+ .unwrap_or(false))
+ .max()
+ );
let version = max_libdir.components().last().unwrap();
let version = version.as_os_str().to_str().unwrap().to_string();
Some((root.into(), version))
}
// Vcvars finds the correct version of the Windows 10 SDK by looking
// for the include `um\Windows.h` because sometimes a given version will
// only have UCRT bits without the rest of the SDK. Since we only care about
@@ -425,24 +455,27 @@ mod impl_ {
// only need to bother checking x64, making this code a tiny bit simpler.
// Like we do for the Universal CRT, we sort the possibilities
// asciibetically to find the newest one as that is what vcvars does.
fn get_sdk10_dir() -> Option<(PathBuf, String)> {
let key = r"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0";
let key = otry!(LOCAL_MACHINE.open(key.as_ref()).ok());
let root = otry!(key.query_str("InstallationFolder").ok());
let readdir = otry!(Path::new(&root).join("lib").read_dir().ok());
- let mut dirs = readdir.filter_map(|dir| dir.ok())
+ let mut dirs = readdir
+ .filter_map(|dir| dir.ok())
.map(|dir| dir.path())
.collect::<Vec<_>>();
dirs.sort();
- let dir = otry!(dirs.into_iter()
- .rev()
- .filter(|dir| dir.join("um").join("x64").join("kernel32.lib").is_file())
- .next());
+ let dir = otry!(
+ dirs.into_iter()
+ .rev()
+ .filter(|dir| dir.join("um").join("x64").join("kernel32.lib").is_file())
+ .next()
+ );
let version = dir.components().last().unwrap();
let version = version.as_os_str().to_str().unwrap().to_string();
Some((root.into(), version))
}
// Interestingly there are several subdirectories, `win7` `win8` and
// `winv6.3`. Vcvars seems to only care about `winv6.3` though, so the same
// applies to us. Note that if we were targetting kernel mode drivers
@@ -492,27 +525,29 @@ mod impl_ {
}
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"),
+ "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"),
+ "aarch64" => Some("arm64"),
_ => None,
}
}
#[allow(bad_style)]
fn host_arch() -> u16 {
type DWORD = u32;
type WORD = u16;
@@ -548,17 +583,18 @@ mod impl_ {
// Given a registry key, look at all the sub keys and find the one which has
// the maximal numeric value.
//
// 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()
+ let val = subkey
+ .to_str()
.and_then(|s| s.trim_left_matches("v").replace(".", "").parse().ok());
let val = match val {
Some(s) => s,
None => continue,
};
if val > max_vers {
if let Ok(k) = key.open(&subkey) {
max_vers = val;
@@ -567,25 +603,26 @@ mod impl_ {
}
}
max_key
}
pub fn has_msbuild_version(version: &str) -> bool {
match version {
"15.0" => {
- find_msbuild_vs15("x86_64-pc-windows-msvc").is_some() ||
- find_msbuild_vs15("i686-pc-windows-msvc").is_some()
+ find_msbuild_vs15("x86_64-pc-windows-msvc").is_some()
+ || find_msbuild_vs15("i686-pc-windows-msvc").is_some()
}
- "12.0" | "14.0" => {
- LOCAL_MACHINE.open(
- &OsString::from(format!("SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\{}",
- version))).is_ok()
- }
- _ => false
+ "12.0" | "14.0" => LOCAL_MACHINE
+ .open(&OsString::from(format!(
+ "SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\{}",
+ version
+ )))
+ .is_ok(),
+ _ => false,
}
}
// 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);
@@ -594,34 +631,34 @@ mod impl_ {
}
}
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())
+ LOCAL_MACHINE
+ .open(key.as_ref())
.ok()
- .and_then(|key| {
- key.query_str("15.0").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
})
}
fn find_old_msbuild(target: &str) -> Option<Tool> {
let key = r"SOFTWARE\Microsoft\MSBuild\ToolsVersions";
- LOCAL_MACHINE.open(key.as_ref())
+ LOCAL_MACHINE
+ .open(key.as_ref())
.ok()
.and_then(|key| {
max_version(&key).and_then(|(_vers, key)| key.query_str("MSBuildToolsPath").ok())
})
.map(|path| {
let mut path = PathBuf::from(path);
path.push("MSBuild.exe");
let mut tool = Tool::new(path);
--- a/third_party/rust/cc/tests/cc_env.rs
+++ b/third_party/rust/cc/tests/cc_env.rs
@@ -9,16 +9,20 @@ mod support;
use support::Test;
#[test]
fn main() {
ccache();
distcc();
ccache_spaces();
ccache_env_flags();
+ leading_spaces();
+ extra_flags();
+ path_to_ccache();
+ more_spaces();
}
fn ccache() {
let test = Test::gnu();
env::set_var("CC", "ccache cc");
let compiler = test.gcc().file("foo.c").get_compiler();
@@ -66,8 +70,50 @@ fn ccache_env_flags() {
.cflags_env()
.into_string()
.unwrap()
.contains(" lol-this-is-not-a-compiler") == false
);
env::set_var("CC", "");
}
+
+fn leading_spaces() {
+ let test = Test::gnu();
+ test.shim("ccache");
+
+ env::set_var("CC", " test ");
+ let compiler = test.gcc().file("foo.c").get_compiler();
+ assert_eq!(compiler.path(), Path::new("test"));
+
+ env::set_var("CC", "");
+}
+
+fn extra_flags() {
+ let test = Test::gnu();
+ test.shim("ccache");
+
+ env::set_var("CC", "ccache cc -m32");
+ let compiler = test.gcc().file("foo.c").get_compiler();
+ assert_eq!(compiler.path(), Path::new("cc"));
+}
+
+fn path_to_ccache() {
+ let test = Test::gnu();
+ test.shim("ccache");
+
+ env::set_var("CC", "/path/to/ccache.exe cc -m32");
+ let compiler = test.gcc().file("foo.c").get_compiler();
+ assert_eq!(compiler.path(), Path::new("cc"));
+ assert_eq!(
+ compiler.cc_env(),
+ OsString::from("/path/to/ccache.exe cc -m32"),
+ );
+}
+
+fn more_spaces() {
+ let test = Test::gnu();
+ test.shim("ccache");
+
+ env::set_var("CC", "cc -m32");
+ let compiler = test.gcc().file("foo.c").get_compiler();
+ assert_eq!(compiler.path(), Path::new("cc"));
+}
--- a/third_party/rust/cc/tests/support/mod.rs
+++ b/third_party/rust/cc/tests/support/mod.rs
@@ -80,17 +80,19 @@ impl Test {
}
pub fn cmd(&self, i: u32) -> Execution {
let mut s = String::new();
File::open(self.td.path().join(format!("out{}", i)))
.unwrap()
.read_to_string(&mut s)
.unwrap();
- Execution { args: s.lines().map(|s| s.to_string()).collect() }
+ Execution {
+ args: s.lines().map(|s| s.to_string()).collect(),
+ }
}
}
impl Execution {
pub fn must_have<P: AsRef<OsStr>>(&self, p: P) -> &Execution {
if !self.has(p.as_ref()) {
panic!("didn't find {:?} in {:?}", p.as_ref(), self.args);
} else {
@@ -106,17 +108,24 @@ impl Execution {
}
}
pub fn has(&self, p: &OsStr) -> bool {
self.args.iter().any(|arg| OsStr::new(arg) == p)
}
pub fn must_have_in_order(&self, before: &str, after: &str) -> &Execution {
- let before_position = self.args.iter().rposition(|x| OsStr::new(x) == OsStr::new(before));
- let after_position = self.args.iter().rposition(|x| OsStr::new(x) == OsStr::new(after));
+ let before_position = self.args
+ .iter()
+ .rposition(|x| OsStr::new(x) == OsStr::new(before));
+ let after_position = self.args
+ .iter()
+ .rposition(|x| OsStr::new(x) == OsStr::new(after));
match (before_position, after_position) {
- (Some(b), Some(a)) if b < a => {},
- (b, a) => { panic!("{:?} (last position: {:?}) did not appear before {:?} (last position: {:?})", before, b, after, a) },
+ (Some(b), Some(a)) if b < a => {}
+ (b, a) => panic!(
+ "{:?} (last position: {:?}) did not appear before {:?} (last position: {:?})",
+ before, b, after, a
+ ),
};
self
}
}
--- a/third_party/rust/cc/tests/test.rs
+++ b/third_party/rust/cc/tests/test.rs
@@ -3,66 +3,53 @@ extern crate tempdir;
use support::Test;
mod support;
#[test]
fn gnu_smoke() {
let test = Test::gnu();
- test.gcc()
- .file("foo.c")
- .compile("foo");
+ test.gcc().file("foo.c").compile("foo");
test.cmd(0)
.must_have("-O2")
.must_have("foo.c")
.must_not_have("-g")
.must_have("-c")
.must_have("-ffunction-sections")
.must_have("-fdata-sections");
test.cmd(1).must_have(test.td.path().join("foo.o"));
}
#[test]
fn gnu_opt_level_1() {
let test = Test::gnu();
- test.gcc()
- .opt_level(1)
- .file("foo.c")
- .compile("foo");
+ test.gcc().opt_level(1).file("foo.c").compile("foo");
- test.cmd(0)
- .must_have("-O1")
- .must_not_have("-O2");
+ test.cmd(0).must_have("-O1").must_not_have("-O2");
}
#[test]
fn gnu_opt_level_s() {
let test = Test::gnu();
- test.gcc()
- .opt_level_str("s")
- .file("foo.c")
- .compile("foo");
+ test.gcc().opt_level_str("s").file("foo.c").compile("foo");
test.cmd(0)
.must_have("-Os")
.must_not_have("-O1")
.must_not_have("-O2")
.must_not_have("-O3")
.must_not_have("-Oz");
}
#[test]
fn gnu_debug() {
let test = Test::gnu();
- test.gcc()
- .debug(true)
- .file("foo.c")
- .compile("foo");
+ test.gcc().debug(true).file("foo.c").compile("foo");
test.cmd(0).must_have("-g");
}
#[test]
fn gnu_warnings_into_errors() {
let test = Test::gnu();
test.gcc()
.warnings_into_errors(true)
@@ -76,46 +63,44 @@ fn gnu_warnings_into_errors() {
fn gnu_warnings() {
let test = Test::gnu();
test.gcc()
.warnings(true)
.flag("-Wno-missing-field-initializers")
.file("foo.c")
.compile("foo");
- test.cmd(0).must_have("-Wall")
- .must_have("-Wextra");
+ test.cmd(0).must_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");
- test.cmd(0).must_have_in_order("-Wall", "-Wno-missing-field-initializers");
+ test.cmd(0)
+ .must_have_in_order("-Wall", "-Wno-missing-field-initializers");
}
#[test]
fn gnu_x86_64() {
for vendor in &["unknown-linux-gnu", "apple-darwin"] {
let target = format!("x86_64-{}", vendor);
let test = Test::gnu();
test.gcc()
.target(&target)
.host(&target)
.file("foo.c")
.compile("foo");
- test.cmd(0)
- .must_have("-fPIC")
- .must_have("-m64");
+ test.cmd(0).must_have("-fPIC").must_have("-m64");
}
}
#[test]
fn gnu_x86_64_no_pic() {
for vendor in &["unknown-linux-gnu", "apple-darwin"] {
let target = format!("x86_64-{}", vendor);
let test = Test::gnu();
@@ -136,18 +121,17 @@ fn gnu_i686() {
let target = format!("i686-{}", vendor);
let test = Test::gnu();
test.gcc()
.target(&target)
.host(&target)
.file("foo.c")
.compile("foo");
- test.cmd(0)
- .must_have("-m32");
+ test.cmd(0).must_have("-m32");
}
}
#[test]
fn gnu_i686_pic() {
for vendor in &["unknown-linux-gnu", "apple-darwin"] {
let target = format!("i686-{}", vendor);
let test = Test::gnu();
@@ -171,20 +155,17 @@ fn gnu_set_stdlib() {
.compile("foo");
test.cmd(0).must_not_have("-stdlib=foo");
}
#[test]
fn gnu_include() {
let test = Test::gnu();
- test.gcc()
- .include("foo/bar")
- .file("foo.c")
- .compile("foo");
+ test.gcc().include("foo/bar").file("foo.c").compile("foo");
test.cmd(0).must_have("-I").must_have("foo/bar");
}
#[test]
fn gnu_define() {
let test = Test::gnu();
test.gcc()
@@ -194,40 +175,36 @@ fn gnu_define() {
.compile("foo");
test.cmd(0).must_have("-DFOO=bar").must_have("-DBAR");
}
#[test]
fn gnu_compile_assembly() {
let test = Test::gnu();
- test.gcc()
- .file("foo.S")
- .compile("foo");
+ test.gcc().file("foo.S").compile("foo");
test.cmd(0).must_have("foo.S");
}
#[test]
fn gnu_shared() {
let test = Test::gnu();
test.gcc()
.file("foo.c")
.shared_flag(true)
.static_flag(false)
.compile("foo");
- test.cmd(0)
- .must_have("-shared")
- .must_not_have("-static");
+ test.cmd(0).must_have("-shared").must_not_have("-static");
}
#[test]
fn gnu_flag_if_supported() {
if cfg!(windows) {
- return
+ return;
}
let test = Test::gnu();
test.gcc()
.file("foo.c")
.flag_if_supported("-Wall")
.flag_if_supported("-Wflag-does-not-exist")
.flag_if_supported("-std=c++11")
.compile("foo");
@@ -236,87 +213,73 @@ fn gnu_flag_if_supported() {
.must_have("-Wall")
.must_not_have("-Wflag-does-not-exist")
.must_not_have("-std=c++11");
}
#[test]
fn gnu_flag_if_supported_cpp() {
if cfg!(windows) {
- return
+ return;
}
let test = Test::gnu();
test.gcc()
.cpp(true)
.file("foo.cpp")
.flag_if_supported("-std=c++11")
.compile("foo");
- test.cmd(0)
- .must_have("-std=c++11");
+ test.cmd(0).must_have("-std=c++11");
}
#[test]
fn gnu_static() {
let test = Test::gnu();
test.gcc()
.file("foo.c")
.shared_flag(false)
.static_flag(true)
.compile("foo");
- test.cmd(0)
- .must_have("-static")
- .must_not_have("-shared");
+ test.cmd(0).must_have("-static").must_not_have("-shared");
}
#[test]
fn msvc_smoke() {
let test = Test::msvc();
- test.gcc()
- .file("foo.c")
- .compile("foo");
+ test.gcc().file("foo.c").compile("foo");
test.cmd(0)
.must_have("/O2")
.must_have("foo.c")
.must_not_have("/Z7")
.must_have("/c")
.must_have("/MD");
test.cmd(1).must_have(test.td.path().join("foo.o"));
}
#[test]
fn msvc_opt_level_0() {
let test = Test::msvc();
- test.gcc()
- .opt_level(0)
- .file("foo.c")
- .compile("foo");
+ test.gcc().opt_level(0).file("foo.c").compile("foo");
test.cmd(0).must_not_have("/O2");
}
#[test]
fn msvc_debug() {
let test = Test::msvc();
- test.gcc()
- .debug(true)
- .file("foo.c")
- .compile("foo");
+ test.gcc().debug(true).file("foo.c").compile("foo");
test.cmd(0).must_have("/Z7");
}
#[test]
fn msvc_include() {
let test = Test::msvc();
- test.gcc()
- .include("foo/bar")
- .file("foo.c")
- .compile("foo");
+ test.gcc().include("foo/bar").file("foo.c").compile("foo");
test.cmd(0).must_have("/I").must_have("foo/bar");
}
#[test]
fn msvc_define() {
let test = Test::msvc();
test.gcc()
@@ -326,26 +289,20 @@ fn msvc_define() {
.compile("foo");
test.cmd(0).must_have("/DFOO=bar").must_have("/DBAR");
}
#[test]
fn msvc_static_crt() {
let test = Test::msvc();
- test.gcc()
- .static_crt(true)
- .file("foo.c")
- .compile("foo");
+ test.gcc().static_crt(true).file("foo.c").compile("foo");
test.cmd(0).must_have("/MT");
}
#[test]
fn msvc_no_static_crt() {
let test = Test::msvc();
- test.gcc()
- .static_crt(false)
- .file("foo.c")
- .compile("foo");
+ test.gcc().static_crt(false).file("foo.c").compile("foo");
test.cmd(0).must_have("/MD");
}