diff options
author | Thomas Deutschmann <whissi@gentoo.org> | 2018-10-04 15:35:23 +0200 |
---|---|---|
committer | Thomas Deutschmann <whissi@gentoo.org> | 2018-10-04 15:35:39 +0200 |
commit | 87ee38a17afd372982e6411cc9c22bbf3229ed0c (patch) | |
tree | d4429ed9bf2c71bda25b827ed500922f0f9043f1 /www-client/firefox/files | |
parent | dev-ros/pr2_description: remove patch merged upstream (diff) | |
download | gentoo-87ee38a17afd372982e6411cc9c22bbf3229ed0c.tar.gz gentoo-87ee38a17afd372982e6411cc9c22bbf3229ed0c.tar.bz2 gentoo-87ee38a17afd372982e6411cc9c22bbf3229ed0c.zip |
www-client/firefox: make rust cc honor CC env variable
Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1496270
Package-Manager: Portage-2.3.50, Repoman-2.3.11
Signed-off-by: Thomas Deutschmann <whissi@gentoo.org>
Diffstat (limited to 'www-client/firefox/files')
-rw-r--r-- | www-client/firefox/files/firefox-60.0-update-cc-to-honor-CC.patch | 745 |
1 files changed, 745 insertions, 0 deletions
diff --git a/www-client/firefox/files/firefox-60.0-update-cc-to-honor-CC.patch b/www-client/firefox/files/firefox-60.0-update-cc-to-honor-CC.patch new file mode 100644 index 000000000000..9bca3f57a0ab --- /dev/null +++ b/www-client/firefox/files/firefox-60.0-update-cc-to-honor-CC.patch @@ -0,0 +1,745 @@ +https://bugzilla.mozilla.org/show_bug.cgi?id=1496270 +https://bugzilla.mozilla.org/show_bug.cgi?id=1445528 + +--- a/third_party/rust/cc/.cargo-checksum.json ++++ b/third_party/rust/cc/.cargo-checksum.json +@@ -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":"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":"6e8cea99f5fc8e5982b1ea9a336ee2f9a6158a9498c8f0c36f1e8cee8c99716e","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 +--- a/third_party/rust/cc/src/lib.rs ++++ b/third_party/rust/cc/src/lib.rs +@@ -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 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 default = if host.contains("solaris") { ++ gnu ++ } else { ++ traditional ++ }; ++ ++ 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())); ++ } ++ ++ // 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, ++ }; + +- return (args[1].to_string(), Some(t.to_string()), args[2..].iter().map(|s| s.to_string()).collect()); +- } ++ 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"); |