зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1445528: Update 'cc' crate to version 1.0.9. r=jgraham
This patch was automatically generated by running the following commands: $ cargo update -p cc $ ./mach vendor rust MozReview-Commit-ID: 51NVIhtno6O --HG-- extra : rebase_source : e4273dccdf531dfadd01c82e3d1131d509f9ffc7
This commit is contained in:
Родитель
ae9f501d06
Коммит
d21e75b6f1
|
@ -193,13 +193,13 @@ 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]]
|
||||
|
@ -254,7 +254,7 @@ 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]]
|
||||
|
@ -896,7 +896,7 @@ 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)",
|
||||
]
|
||||
|
||||
|
@ -1019,7 +1019,7 @@ 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)",
|
||||
|
@ -2200,7 +2200,7 @@ dependencies = [
|
|||
"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"
|
||||
|
|
|
@ -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"}
|
||||
{"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"}
|
|
@ -12,10 +12,16 @@ matrix:
|
|||
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:
|
||||
|
@ -31,11 +37,11 @@ install:
|
|||
|
||||
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
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
[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"
|
||||
|
@ -23,7 +23,7 @@ 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"
|
||||
|
|
|
@ -19,7 +19,7 @@ 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) };
|
||||
|
@ -30,8 +30,13 @@ pub fn initialize() -> Result<(), HRESULT> {
|
|||
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`.
|
||||
|
@ -40,7 +45,11 @@ impl<T> ComPtr<T> where T: Interface {
|
|||
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.
|
||||
|
@ -55,20 +64,31 @@ impl<T> ComPtr<T> where T: Interface {
|
|||
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();
|
||||
|
@ -76,9 +96,14 @@ impl<T> Clone for ComPtr<T> where T: Interface {
|
|||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
@ -102,7 +127,10 @@ 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()
|
||||
}
|
||||
|
@ -110,7 +138,10 @@ impl<T> ToWide for T where T: AsRef<OsStr> {
|
|||
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();
|
||||
|
@ -122,4 +153,3 @@ impl FromWide for OsString {
|
|||
OsStringExt::from_wide(wide)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -61,15 +61,14 @@
|
|||
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
|
||||
|
@ -97,6 +96,7 @@ pub struct Build {
|
|||
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>>,
|
||||
|
@ -241,8 +241,7 @@ impl ToolFamily {
|
|||
fn nvcc_debug_flag(&self) -> &'static str {
|
||||
match *self {
|
||||
ToolFamily::Msvc => unimplemented!(),
|
||||
ToolFamily::Gnu |
|
||||
ToolFamily::Clang => "-G",
|
||||
ToolFamily::Gnu | ToolFamily::Clang => "-G",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -251,8 +250,7 @@ impl ToolFamily {
|
|||
fn nvcc_redirect_flag(&self) -> &'static str {
|
||||
match *self {
|
||||
ToolFamily::Msvc => unimplemented!(),
|
||||
ToolFamily::Gnu |
|
||||
ToolFamily::Clang => "-Xcompiler",
|
||||
ToolFamily::Gnu | ToolFamily::Clang => "-Xcompiler",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -269,10 +267,7 @@ struct Object {
|
|||
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 }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -289,6 +284,7 @@ impl Build {
|
|||
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,
|
||||
|
@ -344,10 +340,8 @@ impl Build {
|
|||
/// .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
|
||||
}
|
||||
|
||||
|
@ -398,7 +392,16 @@ impl Build {
|
|||
///
|
||||
/// 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");
|
||||
|
@ -413,7 +416,8 @@ impl Build {
|
|||
.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
|
||||
|
@ -424,7 +428,10 @@ impl Build {
|
|||
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
|
||||
|
@ -777,9 +784,8 @@ impl Build {
|
|||
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
|
||||
}
|
||||
|
||||
|
@ -880,31 +886,19 @@ impl Build {
|
|||
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);
|
||||
let _ = rayon::ThreadPoolBuilder::new()
|
||||
.num_threads(amt)
|
||||
.build_global();
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
objs.par_iter()
|
||||
.with_max_len(1)
|
||||
.map(|obj| self.compile_object(obj))
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "parallel"))]
|
||||
|
@ -917,7 +911,8 @@ impl Build {
|
|||
|
||||
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 {
|
||||
|
@ -931,15 +926,17 @@ impl Build {
|
|||
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)?;
|
||||
|
@ -967,9 +964,7 @@ impl Build {
|
|||
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();
|
||||
|
||||
|
@ -1054,8 +1049,8 @@ impl Build {
|
|||
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()),
|
||||
_ => {}
|
||||
|
@ -1070,8 +1065,10 @@ impl Build {
|
|||
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());
|
||||
}
|
||||
|
@ -1169,7 +1166,7 @@ impl Build {
|
|||
// 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());
|
||||
}
|
||||
|
||||
|
@ -1212,14 +1209,13 @@ impl Build {
|
|||
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
|
||||
);
|
||||
}
|
||||
|
@ -1272,6 +1268,10 @@ impl Build {
|
|||
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"
|
||||
};
|
||||
|
@ -1307,20 +1307,55 @@ impl Build {
|
|||
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
|
||||
|
@ -1412,6 +1447,18 @@ impl Build {
|
|||
|
||||
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(())
|
||||
}
|
||||
|
@ -1437,37 +1484,44 @@ impl Build {
|
|||
};
|
||||
|
||||
// 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());
|
||||
}
|
||||
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)))
|
||||
}
|
||||
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 {
|
||||
None
|
||||
Some(Tool::new(PathBuf::from(tool)))
|
||||
}
|
||||
})
|
||||
.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,
|
||||
|
@ -1501,6 +1555,7 @@ impl Build {
|
|||
"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"),
|
||||
|
@ -1509,10 +1564,12 @@ impl Build {
|
|||
"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"),
|
||||
|
@ -1538,14 +1595,18 @@ impl Build {
|
|||
};
|
||||
|
||||
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
|
||||
|
@ -1568,10 +1629,7 @@ impl Build {
|
|||
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),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
@ -1585,21 +1643,68 @@ impl Build {
|
|||
.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,
|
||||
};
|
||||
|
||||
for t in whitelist.iter() {
|
||||
if tool.starts_with(t) && tool[t.len()..].starts_with(' ') {
|
||||
let args = tool.split_whitespace().collect::<Vec<_>>();
|
||||
// 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()));
|
||||
}
|
||||
|
||||
return (args[1].to_string(), Some(t.to_string()), args[2..].iter().map(|s| s.to_string()).collect());
|
||||
}
|
||||
// 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"];
|
||||
|
||||
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++`
|
||||
|
@ -1611,7 +1716,7 @@ impl Build {
|
|||
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()))
|
||||
|
@ -1700,10 +1805,7 @@ impl Build {
|
|||
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()),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
@ -1731,8 +1833,9 @@ impl Tool {
|
|||
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
|
||||
|
@ -1775,8 +1878,8 @@ impl Tool {
|
|||
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() {
|
||||
|
@ -1822,10 +1925,8 @@ impl Tool {
|
|||
cc_env.push(arg);
|
||||
}
|
||||
cc_env
|
||||
},
|
||||
None => {
|
||||
OsString::from("")
|
||||
}
|
||||
None => OsString::from(""),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1868,8 +1969,7 @@ fn run(cmd: &mut Command, program: &str) -> Result<(), Error> {
|
|||
ErrorKind::ToolExecError,
|
||||
&format!(
|
||||
"Failed to wait on spawned child process, command {:?} with args {:?}.",
|
||||
cmd,
|
||||
program
|
||||
cmd, program
|
||||
),
|
||||
))
|
||||
}
|
||||
|
@ -1884,9 +1984,7 @@ fn run(cmd: &mut Command, program: &str) -> Result<(), Error> {
|
|||
ErrorKind::ToolExecError,
|
||||
&format!(
|
||||
"Command {:?} with args {:?} did not execute successfully (status code {}).",
|
||||
cmd,
|
||||
program,
|
||||
status
|
||||
cmd, program, status
|
||||
),
|
||||
))
|
||||
}
|
||||
|
@ -1909,8 +2007,7 @@ fn run_output(cmd: &mut Command, program: &str) -> Result<Vec<u8>, Error> {
|
|||
ErrorKind::ToolExecError,
|
||||
&format!(
|
||||
"Failed to wait on spawned child process, command {:?} with args {:?}.",
|
||||
cmd,
|
||||
program
|
||||
cmd, program
|
||||
),
|
||||
))
|
||||
}
|
||||
|
@ -1925,9 +2022,7 @@ fn run_output(cmd: &mut Command, program: &str) -> Result<Vec<u8>, Error> {
|
|||
ErrorKind::ToolExecError,
|
||||
&format!(
|
||||
"Command {:?} with args {:?} did not execute successfully (status code {}).",
|
||||
cmd,
|
||||
program,
|
||||
status
|
||||
cmd, program, status
|
||||
),
|
||||
))
|
||||
}
|
||||
|
@ -1943,39 +2038,30 @@ fn spawn(cmd: &mut Command, program: &str) -> Result<(Child, JoinHandle<()>), Er
|
|||
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),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
@ -1984,9 +2070,10 @@ 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");
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// 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;
|
||||
|
@ -36,28 +36,31 @@ 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;
|
||||
}
|
||||
|
||||
|
@ -90,11 +93,13 @@ impl 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))))
|
||||
|
@ -116,29 +121,36 @@ impl RegistryKey {
|
|||
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));
|
||||
}
|
||||
|
@ -169,14 +181,16 @@ impl<'a> Iterator for Iter<'a> {
|
|||
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 {
|
||||
|
|
|
@ -15,7 +15,7 @@ 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};
|
||||
|
@ -155,7 +155,7 @@ interface ISetupHelper(ISetupHelperVtbl): IUnknown(IUnknownVtbl) {
|
|||
}}
|
||||
|
||||
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>);
|
||||
|
@ -163,31 +163,44 @@ 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) })
|
||||
}
|
||||
}
|
||||
|
@ -202,28 +215,36 @@ impl SetupInstance {
|
|||
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> {
|
||||
|
@ -231,7 +252,9 @@ impl SetupInstance {
|
|||
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())
|
||||
}
|
||||
}
|
||||
|
@ -249,9 +272,12 @@ impl Iterator for EnumSetupInstances {
|
|||
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) }))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,8 +44,8 @@ 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)]
|
||||
|
@ -69,13 +69,17 @@ pub trait Interface {
|
|||
|
||||
#[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;
|
||||
}
|
||||
|
|
|
@ -69,7 +69,11 @@ pub fn find_tool(target: &str, tool: &str) -> Option<Tool> {
|
|||
// 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()));
|
||||
}
|
||||
|
||||
|
@ -119,19 +123,20 @@ 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.
|
||||
|
@ -142,12 +147,14 @@ pub fn find_vs_version() -> Result<VsVers, String> {
|
|||
} 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\
|
||||
"
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -185,7 +192,12 @@ mod impl_ {
|
|||
}
|
||||
|
||||
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);
|
||||
|
@ -217,11 +229,13 @@ mod impl_ {
|
|||
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);
|
||||
|
@ -238,9 +252,13 @@ mod impl_ {
|
|||
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());
|
||||
|
@ -255,11 +273,15 @@ mod impl_ {
|
|||
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))
|
||||
|
@ -288,7 +310,8 @@ mod impl_ {
|
|||
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"));
|
||||
|
@ -353,7 +376,8 @@ mod impl_ {
|
|||
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
|
||||
|
@ -361,7 +385,12 @@ mod impl_ {
|
|||
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);
|
||||
|
@ -402,16 +431,17 @@ mod impl_ {
|
|||
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))
|
||||
|
@ -430,14 +460,17 @@ mod impl_ {
|
|||
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))
|
||||
|
@ -497,6 +530,7 @@ mod impl_ {
|
|||
"i586" | "i686" => Some("x86"),
|
||||
"x86_64" => Some("x64"),
|
||||
"arm" => Some("arm"),
|
||||
"aarch64" => Some("arm64"),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -508,6 +542,7 @@ mod impl_ {
|
|||
"i586" | "i686" => Some(""),
|
||||
"x86_64" => Some("amd64"),
|
||||
"arm" => Some("arm"),
|
||||
"aarch64" => Some("arm64"),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -553,7 +588,8 @@ mod impl_ {
|
|||
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,
|
||||
|
@ -572,15 +608,16 @@ mod impl_ {
|
|||
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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -599,11 +636,10 @@ mod impl_ {
|
|||
// 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);
|
||||
|
@ -616,7 +652,8 @@ mod impl_ {
|
|||
|
||||
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())
|
||||
|
|
|
@ -14,6 +14,10 @@ fn main() {
|
|||
distcc();
|
||||
ccache_spaces();
|
||||
ccache_env_flags();
|
||||
leading_spaces();
|
||||
extra_flags();
|
||||
path_to_ccache();
|
||||
more_spaces();
|
||||
}
|
||||
|
||||
fn ccache() {
|
||||
|
@ -71,3 +75,45 @@ fn ccache_env_flags() {
|
|||
|
||||
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"));
|
||||
}
|
||||
|
|
|
@ -85,7 +85,9 @@ impl Test {
|
|||
.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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,11 +113,18 @@ impl Execution {
|
|||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
|
|
@ -8,9 +8,7 @@ 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")
|
||||
|
@ -25,23 +23,15 @@ fn gnu_smoke() {
|
|||
#[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")
|
||||
|
@ -54,10 +44,7 @@ fn gnu_opt_level_s() {
|
|||
#[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");
|
||||
}
|
||||
|
||||
|
@ -81,8 +68,7 @@ fn gnu_warnings() {
|
|||
.file("foo.c")
|
||||
.compile("foo");
|
||||
|
||||
test.cmd(0).must_have("-Wall")
|
||||
.must_have("-Wextra");
|
||||
test.cmd(0).must_have("-Wall").must_have("-Wextra");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -94,7 +80,8 @@ fn gnu_warnings_overridable() {
|
|||
.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]
|
||||
|
@ -108,9 +95,7 @@ fn gnu_x86_64() {
|
|||
.file("foo.c")
|
||||
.compile("foo");
|
||||
|
||||
test.cmd(0)
|
||||
.must_have("-fPIC")
|
||||
.must_have("-m64");
|
||||
test.cmd(0).must_have("-fPIC").must_have("-m64");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,8 +126,7 @@ fn gnu_i686() {
|
|||
.file("foo.c")
|
||||
.compile("foo");
|
||||
|
||||
test.cmd(0)
|
||||
.must_have("-m32");
|
||||
test.cmd(0).must_have("-m32");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,10 +160,7 @@ fn gnu_set_stdlib() {
|
|||
#[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");
|
||||
}
|
||||
|
@ -199,9 +180,7 @@ fn gnu_define() {
|
|||
#[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");
|
||||
}
|
||||
|
||||
|
@ -214,15 +193,13 @@ fn gnu_shared() {
|
|||
.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()
|
||||
|
@ -241,7 +218,7 @@ fn gnu_flag_if_supported() {
|
|||
#[test]
|
||||
fn gnu_flag_if_supported_cpp() {
|
||||
if cfg!(windows) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
let test = Test::gnu();
|
||||
test.gcc()
|
||||
|
@ -250,8 +227,7 @@ fn gnu_flag_if_supported_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]
|
||||
|
@ -263,17 +239,13 @@ fn gnu_static() {
|
|||
.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")
|
||||
|
@ -287,10 +259,7 @@ fn msvc_smoke() {
|
|||
#[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");
|
||||
}
|
||||
|
@ -298,20 +267,14 @@ fn msvc_opt_level_0() {
|
|||
#[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");
|
||||
}
|
||||
|
@ -331,10 +294,7 @@ fn msvc_define() {
|
|||
#[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");
|
||||
}
|
||||
|
@ -342,10 +302,7 @@ fn msvc_static_crt() {
|
|||
#[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");
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче