From f98f6c717a6e709b9f0edd3cf0ea4f18e2ca9767 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 3 Feb 2017 22:18:32 -0800 Subject: [PATCH] Pass -fPIC to native compiles on 32-bit This is apparently a regression from 1.14.0 to 1.15.0. Previously we passed `-fPIC` to C compilers on i686 targets, but the `gcc` crate apparently [explicitly] didn't do this. I don't recall why that was avoided but it was [previously passed by the makefiles][mk] and this seems to have [caused a regression][regression] in Firefox, so this commit reverts back to passing `-fPIC`. [explicitly]: https://github.com/alexcrichton/gcc-rs/commit/362bdf20 [mk]: https://github.com/rust-lang/rust/blob/c781fc4a/mk/cfg/i686-unknown-linux-gnu.mk#L11 [regression]: https://bugzilla.mozilla.org/show_bug.cgi?id=1336155 --- src/Cargo.lock | 20 +- src/vendor/gcc/.cargo-checksum.json | 2 +- src/vendor/gcc/.gitignore | 2 + src/vendor/gcc/.travis.yml | 7 + src/vendor/gcc/Cargo.toml | 10 +- src/vendor/gcc/README.md | 6 +- src/vendor/gcc/src/bin/gcc-shim.rs | 4 +- src/vendor/gcc/src/lib.rs | 641 +++++++++++++++---------- src/vendor/gcc/src/registry.rs | 59 ++- src/vendor/gcc/src/windows_registry.rs | 138 +++--- src/vendor/gcc/tests/support/mod.rs | 42 +- src/vendor/gcc/tests/test.rs | 99 ++-- 12 files changed, 601 insertions(+), 429 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 95b963f6a78..288a8b65833 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -19,7 +19,7 @@ version = "0.0.0" dependencies = [ "build_helper 0.1.0", "core 0.0.0", - "gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.0.0", ] @@ -42,7 +42,7 @@ dependencies = [ "build_helper 0.1.0", "cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -74,7 +74,7 @@ name = "cmake" version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -91,7 +91,7 @@ name = "compiler_builtins" version = "0.0.0" dependencies = [ "core 0.0.0", - "gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -132,7 +132,7 @@ name = "flate" version = "0.0.0" dependencies = [ "build_helper 0.1.0", - "gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -141,7 +141,7 @@ version = "0.0.0" [[package]] name = "gcc" -version = "0.3.40" +version = "0.3.43" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -396,7 +396,7 @@ name = "rustc_llvm" version = "0.0.0" dependencies = [ "build_helper 0.1.0", - "gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_bitflags 0.0.0", ] @@ -539,7 +539,7 @@ version = "0.0.0" dependencies = [ "arena 0.0.0", "build_helper 0.1.0", - "gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.0.0", "rustc 0.0.0", "rustc_back 0.0.0", @@ -571,7 +571,7 @@ dependencies = [ "collections 0.0.0", "compiler_builtins 0.0.0", "core 0.0.0", - "gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.0.0", "panic_abort 0.0.0", "panic_unwind 0.0.0", @@ -661,7 +661,7 @@ dependencies = [ "checksum cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0e5bcf27e097a184c1df4437654ed98df3d7a516e8508a6ba45d8b092bbdf283" "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" "checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922" -"checksum gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "872db9e59486ef2b14f8e8c10e9ef02de2bccef6363d7f34835dedb386b3d950" +"checksum gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)" = "c07c758b972368e703a562686adb39125707cc1ef3399da8c019fc6c2498a75d" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" "checksum libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "044d1360593a78f5c8e5e710beccdc24ab71d1f01bc19a29bcacdba22e8475d8" "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" diff --git a/src/vendor/gcc/.cargo-checksum.json b/src/vendor/gcc/.cargo-checksum.json index e85f4b21813..69e2a953a17 100644 --- a/src/vendor/gcc/.cargo-checksum.json +++ b/src/vendor/gcc/.cargo-checksum.json @@ -1 +1 @@ -{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"f9b1ca6ae27d1c18215265024629a8960c31379f206d9ed20f64e0b2dcf79805",".travis.yml":"675ffe583db77282d010306f29e6d81e5070ab081deddd0300137dfbd2cb83de","Cargo.toml":"19bb617b74de761515ef5d087fd0e30912fda1d7c22fd04fa211236dab99a509","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"ecb2d93f4c81edbd48d8742ff7887dc0a4530a5890967839090bbc972d49bebe","appveyor.yml":"46c77d913eaa45871296942c2cd96ef092c9dcaf19201cb5c500a5107faeb06f","src/bin/gcc-shim.rs":"11edfe1fc6f932bd42ffffda5145833302bc163e0b87dc0d54f4bd0997ad4708","src/lib.rs":"7e7c60beccfdd145e876da81bb07dd09c5248dab0b26d93190bab4242799d51a","src/registry.rs":"3e2a42581ebb82e325dd5600c6571cef937b35003b2927dc618967f5238a2058","src/windows_registry.rs":"1f4211caec5a192b5f05c8a47efb27aa6a0ab976c659b9318a0cf603a28d6746","tests/cc_env.rs":"d92c5e3d3d43ac244e63b2cd2c93a521fcf124bf1ccf8d4c6bfa7f8333d88976","tests/support/mod.rs":"f4dad5a8133c3dd6678d9a3de057b82e624ef547b9b3e4ac9508a48962fc387b","tests/test.rs":"164220f11be2eebc20315826513999970660a82feff8cc4b15b4e9d73d98324e"},"package":"872db9e59486ef2b14f8e8c10e9ef02de2bccef6363d7f34835dedb386b3d950"} \ No newline at end of file +{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"4cc6445feac7e9a1f8f1e1c51cc3afd0cf7bb931e3c5a6f18c41258401652702",".travis.yml":"e68f9d10a8e367890cf734239c39952ee480cf0e8da9520b377df4a2b8ccc9e8","Cargo.toml":"4c5eb683d4c57fff819ebf564a8db93b5c87284993def6bc066ba1e311d5b090","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"b1a639560fd536f2c3ab708a8e1066b675edd4d018dfa4e5e18d0d7327d81c15","appveyor.yml":"46c77d913eaa45871296942c2cd96ef092c9dcaf19201cb5c500a5107faeb06f","src/bin/gcc-shim.rs":"d6be9137cb48b86891e7b263adbf492e1193ffe682db9ba4a88eb1079b874b58","src/lib.rs":"eb4ca086dd2ffa5e30f022f556d0def6d1142160da392afb328393b3f435e8f7","src/registry.rs":"3876ef9573e3bbc050aef41a684b9a510cc1a91b15ae874fe032cf4377b4d116","src/windows_registry.rs":"36c6a7f8322407faff2dcfd4789d0876d034885944bc0340ac7c1f7cbfc307f1","tests/cc_env.rs":"d92c5e3d3d43ac244e63b2cd2c93a521fcf124bf1ccf8d4c6bfa7f8333d88976","tests/support/mod.rs":"56bcfd1e2ff5ae8e581c71229444a3d96094bf689808808dd80e315bd6632083","tests/test.rs":"b63e74d571e7d585edc53693bcf0caae88fc040613ace91e32437d4a62cddb6a"},"package":"c07c758b972368e703a562686adb39125707cc1ef3399da8c019fc6c2498a75d"} \ No newline at end of file diff --git a/src/vendor/gcc/.gitignore b/src/vendor/gcc/.gitignore index a9d37c560c6..3b874ca574d 100644 --- a/src/vendor/gcc/.gitignore +++ b/src/vendor/gcc/.gitignore @@ -1,2 +1,4 @@ target Cargo.lock +.idea +*.iml diff --git a/src/vendor/gcc/.travis.yml b/src/vendor/gcc/.travis.yml index bf55f49173d..10d3d13d876 100644 --- a/src/vendor/gcc/.travis.yml +++ b/src/vendor/gcc/.travis.yml @@ -3,6 +3,13 @@ rust: - stable - beta - nightly +matrix: + include: + # Minimum version supported + - rust: 1.6.0 + install: + script: cargo build + sudo: false install: - if [ "$TRAVIS_OS_NAME" = "linux" ]; then OS=unknown-linux-gnu; else OS=apple-darwin; fi diff --git a/src/vendor/gcc/Cargo.toml b/src/vendor/gcc/Cargo.toml index 7efdbf9b4b3..9fee7788cef 100644 --- a/src/vendor/gcc/Cargo.toml +++ b/src/vendor/gcc/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "gcc" -version = "0.3.40" +version = "0.3.43" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" repository = "https://github.com/alexcrichton/gcc-rs" -documentation = "http://alexcrichton.com/gcc-rs" +documentation = "https://docs.rs/gcc" description = """ A build-time dependency for Cargo build scripts to assist in invoking the native C compiler to compile native C code into a static archive to be linked into Rust @@ -13,8 +13,12 @@ code. """ keywords = ["build-dependencies"] +[badges] +travis-ci = { repository = "alexcrichton/gcc-rs" } +appveyor = { repository = "alexcrichton/gcc-rs" } + [dependencies] -rayon = { version = "0.4", optional = true } +rayon = { version = "0.6", optional = true } [features] parallel = ["rayon"] diff --git a/src/vendor/gcc/README.md b/src/vendor/gcc/README.md index ecc79c67352..2d3e5ed7387 100644 --- a/src/vendor/gcc/README.md +++ b/src/vendor/gcc/README.md @@ -5,7 +5,7 @@ A library to compile C/C++ code into a Rust library/application. [![Build Status](https://travis-ci.org/alexcrichton/gcc-rs.svg?branch=master)](https://travis-ci.org/alexcrichton/gcc-rs) [![Build status](https://ci.appveyor.com/api/projects/status/onu270iw98h81nwv?svg=true)](https://ci.appveyor.com/project/alexcrichton/gcc-rs) -[Documentation](http://alexcrichton.com/gcc-rs) +[Documentation](https://docs.rs/gcc) A simple library meant to be used as a build dependency with Cargo packages in order to build a set of C/C++ files into a static archive. Note that while this @@ -106,7 +106,9 @@ gcc = { version = "0.3", features = ["parallel"] } ``` By default gcc-rs will limit parallelism to `$NUM_JOBS`, or if not present it -will limit it to the number of cpus on the machine. +will limit it to the number of cpus on the machine. If you are using cargo, +use `-jN` option of `build`, `test` and `run` commands as `$NUM_JOBS` +is supplied by cargo. ## Compile-time Requirements diff --git a/src/vendor/gcc/src/bin/gcc-shim.rs b/src/vendor/gcc/src/bin/gcc-shim.rs index 43fd811d361..7fd0ea8fa84 100644 --- a/src/vendor/gcc/src/bin/gcc-shim.rs +++ b/src/vendor/gcc/src/bin/gcc-shim.rs @@ -10,7 +10,7 @@ fn main() { for i in 0.. { let candidate = out_dir.join(format!("out{}", i)); if candidate.exists() { - continue + continue; } let mut f = File::create(candidate).unwrap(); for arg in env::args().skip(1) { @@ -18,6 +18,6 @@ fn main() { } File::create(out_dir.join("libfoo.a")).unwrap(); - break + break; } } diff --git a/src/vendor/gcc/src/lib.rs b/src/vendor/gcc/src/lib.rs index 43cc371117f..f2d9da7f694 100644 --- a/src/vendor/gcc/src/lib.rs +++ b/src/vendor/gcc/src/lib.rs @@ -42,7 +42,7 @@ //! } //! ``` -#![doc(html_root_url = "http://alexcrichton.com/gcc-rs")] +#![doc(html_root_url = "https://docs.rs/gcc/0.3")] #![cfg_attr(test, deny(warnings))] #![deny(missing_docs)] @@ -52,10 +52,10 @@ use std::env; use std::ffi::{OsString, OsStr}; use std::fs; -use std::io; use std::path::{PathBuf, Path}; use std::process::{Command, Stdio}; -use std::io::{BufReader, BufRead, Write}; +use std::io::{self, BufReader, BufRead, Read, Write}; +use std::thread; #[cfg(windows)] mod registry; @@ -94,6 +94,52 @@ pub struct Tool { path: PathBuf, args: Vec, env: Vec<(OsString, OsString)>, + family: ToolFamily +} + +/// Represents the family of tools this tool belongs to. +/// +/// Each family of tools differs in how and what arguments they accept. +/// +/// Detection of a family is done on best-effort basis and may not accurately reflect the tool. +#[derive(Copy, Clone, Debug)] +enum ToolFamily { + /// Tool is GNU Compiler Collection-like. + Gnu, + /// Tool is Clang-like. It differs from the GCC in a sense that it accepts superset of flags + /// and its cross-compilation approach is different. + Clang, + /// Tool is the MSVC cl.exe. + Msvc, +} + +impl ToolFamily { + /// What the flag to request debug info for this family of tools look like + fn debug_flag(&self) -> &'static str { + match *self { + ToolFamily::Msvc => "/Z7", + ToolFamily::Gnu | + ToolFamily::Clang => "-g", + } + } + + /// What the flag to include directories into header search path looks like + fn include_flag(&self) -> &'static str { + match *self { + ToolFamily::Msvc => "/I", + ToolFamily::Gnu | + ToolFamily::Clang => "-I", + } + } + + /// What the flag to request macro-expanded source output looks like + fn expand_flag(&self) -> &'static str { + match *self { + ToolFamily::Msvc => "/E", + ToolFamily::Gnu | + ToolFamily::Clang => "-E", + } + } } /// Compile a library from the given set of input C files. @@ -114,7 +160,7 @@ pub fn compile_library(output: &str, files: &[&str]) { for f in files.iter() { c.file(*f); } - c.compile(output) + c.compile(output); } impl Config { @@ -194,8 +240,7 @@ pub fn cpp(&mut self, cpp: bool) -> &mut Config { /// otherwise cargo will link against the specified library. /// /// The given library name must not contain the `lib` prefix. - pub fn cpp_link_stdlib(&mut self, cpp_link_stdlib: Option<&str>) - -> &mut Config { + pub fn cpp_link_stdlib(&mut self, cpp_link_stdlib: Option<&str>) -> &mut Config { self.cpp_link_stdlib = Some(cpp_link_stdlib.map(|s| s.into())); self } @@ -220,8 +265,7 @@ pub fn cpp_link_stdlib(&mut self, cpp_link_stdlib: Option<&str>) /// be used, otherwise `-stdlib` is added to the compile invocation. /// /// The given library name must not contain the `lib` prefix. - pub fn cpp_set_stdlib(&mut self, cpp_set_stdlib: Option<&str>) - -> &mut Config { + pub fn cpp_set_stdlib(&mut self, cpp_set_stdlib: Option<&str>) -> &mut Config { self.cpp_set_stdlib = cpp_set_stdlib.map(|s| s.into()); self.cpp_link_stdlib(cpp_set_stdlib); self @@ -322,7 +366,8 @@ pub fn pic(&mut self, pic: bool) -> &mut Config { #[doc(hidden)] pub fn __set_env(&mut self, a: A, b: B) -> &mut Config - where A: AsRef, B: AsRef + where A: AsRef, + B: AsRef { self.env.push((a.as_ref().to_owned(), b.as_ref().to_owned())); self @@ -355,18 +400,18 @@ pub fn compile(&self, output: &str) { if self.get_target().contains("msvc") { let compiler = self.get_base_compiler(); - let atlmfc_lib = compiler.env().iter().find(|&&(ref var, _)| { - var == OsStr::new("LIB") - }).and_then(|&(_, ref lib_paths)| { - env::split_paths(lib_paths).find(|path| { - let sub = Path::new("atlmfc/lib"); - path.ends_with(sub) || path.parent().map_or(false, |p| p.ends_with(sub)) - }) - }); + let atlmfc_lib = compiler.env() + .iter() + .find(|&&(ref var, _)| var.as_os_str() == OsStr::new("LIB")) + .and_then(|&(_, ref lib_paths)| { + env::split_paths(lib_paths).find(|path| { + let sub = Path::new("atlmfc/lib"); + path.ends_with(sub) || path.parent().map_or(false, |p| p.ends_with(sub)) + }) + }); if let Some(atlmfc_lib) = atlmfc_lib { - self.print(&format!("cargo:rustc-link-search=native={}", - atlmfc_lib.display())); + self.print(&format!("cargo:rustc-link-search=native={}", atlmfc_lib.display())); } } @@ -394,9 +439,7 @@ fn compile_objects(&self, objs: &[(PathBuf, PathBuf)]) { } drop(rayon::initialize(cfg)); - objs.par_iter().weight_max().for_each(|&(ref src, ref dst)| { - self.compile_object(src, dst) - }) + objs.par_iter().weight_max().for_each(|&(ref src, ref dst)| self.compile_object(src, dst)); } #[cfg(not(feature = "parallel"))] @@ -417,8 +460,12 @@ fn compile_object(&self, file: &Path, dst: &Path) { for &(ref a, ref b) in self.env.iter() { cmd.env(a, b); } - (cmd, compiler.path.file_name().unwrap() - .to_string_lossy().into_owned()) + (cmd, + compiler.path + .file_name() + .unwrap() + .to_string_lossy() + .into_owned()) }; if msvc && is_asm { cmd.arg("/Fo").arg(dst); @@ -429,12 +476,35 @@ fn compile_object(&self, file: &Path, dst: &Path) { } else { cmd.arg("-o").arg(&dst); } - cmd.arg(if msvc {"/c"} else {"-c"}); + cmd.arg(if msvc { "/c" } else { "-c" }); cmd.arg(file); run(&mut cmd, &name); } + /// Run the compiler, returning the macro-expanded version of the input files. + /// + /// This is only relevant for C and C++ files. + pub fn expand(&self) -> Vec { + let compiler = self.get_compiler(); + let mut cmd = compiler.to_command(); + for &(ref a, ref b) in self.env.iter() { + cmd.env(a, b); + } + cmd.arg(compiler.family.expand_flag()); + for file in self.files.iter() { + cmd.arg(file); + } + + let name = compiler.path + .file_name() + .unwrap() + .to_string_lossy() + .into_owned(); + + run(&mut cmd, &name) + } + /// Get the compiler that's in use for this configuration. /// /// This function will return a `Tool` which represents the culmination @@ -451,136 +521,159 @@ fn compile_object(&self, file: &Path, dst: &Path) { /// falling back to the default configuration. pub fn get_compiler(&self) -> Tool { let opt_level = self.get_opt_level(); - let debug = self.get_debug(); let target = self.get_target(); - let msvc = target.contains("msvc"); - self.print(&format!("debug={} opt-level={}", debug, opt_level)); let mut cmd = self.get_base_compiler(); - let nvcc = cmd.path.to_str() - .map(|path| path.contains("nvcc")) + let nvcc = cmd.path.file_name() + .and_then(|p| p.to_str()).map(|p| p.contains("nvcc")) .unwrap_or(false); - if msvc { - cmd.args.push("/nologo".into()); - let features = env::var("CARGO_CFG_TARGET_FEATURE") - .unwrap_or(String::new()); - if features.contains("crt-static") { - cmd.args.push("/MT".into()); - } else { - cmd.args.push("/MD".into()); + // Non-target flags + // If the flag is not conditioned on target variable, it belongs here :) + match cmd.family { + ToolFamily::Msvc => { + cmd.args.push("/nologo".into()); + let features = env::var("CARGO_CFG_TARGET_FEATURE") + .unwrap_or(String::new()); + if features.contains("crt-static") { + cmd.args.push("/MT".into()); + } else { + cmd.args.push("/MD".into()); + } + match &opt_level[..] { + "z" | "s" => cmd.args.push("/Os".into()), + "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()), + _ => {} + } } - match &opt_level[..] { - "z" | "s" => cmd.args.push("/Os".into()), - "2" => cmd.args.push("/O2".into()), - "1" => cmd.args.push("/O1".into()), - _ => {} + ToolFamily::Gnu | + ToolFamily::Clang => { + cmd.args.push(format!("-O{}", opt_level).into()); + if !nvcc { + cmd.args.push("-ffunction-sections".into()); + cmd.args.push("-fdata-sections".into()); + if self.pic.unwrap_or(!target.contains("windows-gnu")) { + cmd.args.push("-fPIC".into()); + } + } else if self.pic.unwrap_or(false) { + cmd.args.push("-Xcompiler".into()); + cmd.args.push("\'-fPIC\'".into()); + } } - if target.contains("i586") { - cmd.args.push("/ARCH:IA32".into()); - } - } else if nvcc { - cmd.args.push(format!("-O{}", opt_level).into()); - } else { - cmd.args.push(format!("-O{}", opt_level).into()); - cmd.args.push("-ffunction-sections".into()); - cmd.args.push("-fdata-sections".into()); } for arg in self.envflags(if self.cpp {"CXXFLAGS"} else {"CFLAGS"}) { cmd.args.push(arg.into()); } - if debug { - cmd.args.push(if msvc {"/Z7"} else {"-g"}.into()); + if self.get_debug() { + cmd.args.push(cmd.family.debug_flag().into()); + } + + // Target flags + match cmd.family { + ToolFamily::Clang => { + cmd.args.push(format!("--target={}", target).into()); + } + ToolFamily::Msvc => { + if target.contains("i586") { + cmd.args.push("/ARCH:IA32".into()); + } + } + ToolFamily::Gnu => { + if target.contains("i686") || target.contains("i586") { + cmd.args.push("-m32".into()); + } else if target.contains("x86_64") || target.contains("powerpc64") { + cmd.args.push("-m64".into()); + } + + if target.contains("musl") { + cmd.args.push("-static".into()); + } + + // armv7 targets get to use armv7 instructions + if target.starts_with("armv7-unknown-linux-") { + cmd.args.push("-march=armv7-a".into()); + } + + // On android we can guarantee some extra float instructions + // (specified in the android spec online) + if target.starts_with("armv7-linux-androideabi") { + cmd.args.push("-march=armv7-a".into()); + cmd.args.push("-mfpu=vfpv3-d16".into()); + } + + // For us arm == armv6 by default + if target.starts_with("arm-unknown-linux-") { + cmd.args.push("-march=armv6".into()); + cmd.args.push("-marm".into()); + } + + // Turn codegen down on i586 to avoid some instructions. + if target.starts_with("i586-unknown-linux-") { + cmd.args.push("-march=pentium".into()); + } + + // Set codegen level for i686 correctly + if target.starts_with("i686-unknown-linux-") { + cmd.args.push("-march=i686".into()); + } + + // Looks like `musl-gcc` makes is hard for `-m32` to make its way + // all the way to the linker, so we need to actually instruct the + // linker that we're generating 32-bit executables as well. This'll + // typically only be used for build scripts which transitively use + // these flags that try to compile executables. + if target == "i686-unknown-linux-musl" { + cmd.args.push("-Wl,-melf_i386".into()); + } + + if target.starts_with("thumb") { + cmd.args.push("-mthumb".into()); + + if target.ends_with("eabihf") { + cmd.args.push("-mfloat-abi=hard".into()) + } + } + if target.starts_with("thumbv6m") { + cmd.args.push("-march=armv6s-m".into()); + } + if target.starts_with("thumbv7em") { + cmd.args.push("-march=armv7e-m".into()); + + if target.ends_with("eabihf") { + cmd.args.push("-mfpu=fpv4-sp-d16".into()) + } + } + if target.starts_with("thumbv7m") { + cmd.args.push("-march=armv7-m".into()); + } + } } if target.contains("-ios") { + // FIXME: potential bug. iOS is always compiled with Clang, but Gcc compiler may be + // detected instead. self.ios_flags(&mut cmd); - } else if !msvc { - if target.contains("i686") || target.contains("i586") { - cmd.args.push("-m32".into()); - } else if target.contains("x86_64") || target.contains("powerpc64") { - cmd.args.push("-m64".into()); - } - - if !nvcc && self.pic.unwrap_or(!target.contains("i686") && !target.contains("windows-gnu")) { - cmd.args.push("-fPIC".into()); - } else if nvcc && self.pic.unwrap_or(false) { - cmd.args.push("-Xcompiler".into()); - cmd.args.push("\'-fPIC\'".into()); - } - - if target.contains("musl") { - cmd.args.push("-static".into()); - } - - // armv7 targets get to use armv7 instructions - if target.starts_with("armv7-unknown-linux-") { - cmd.args.push("-march=armv7-a".into()); - } - - // On android we can guarantee some extra float instructions - // (specified in the android spec online) - if target.starts_with("armv7-linux-androideabi") { - cmd.args.push("-march=armv7-a".into()); - cmd.args.push("-mfpu=vfpv3-d16".into()); - } - - // For us arm == armv6 by default - if target.starts_with("arm-unknown-linux-") { - cmd.args.push("-march=armv6".into()); - cmd.args.push("-marm".into()); - } - - // Turn codegen down on i586 to avoid some instructions. - if target.starts_with("i586-unknown-linux-") { - cmd.args.push("-march=pentium".into()); - } - - // Set codegen level for i686 correctly - if target.starts_with("i686-unknown-linux-") { - cmd.args.push("-march=i686".into()); - } - - // Looks like `musl-gcc` makes is hard for `-m32` to make its way - // all the way to the linker, so we need to actually instruct the - // linker that we're generating 32-bit executables as well. This'll - // typically only be used for build scripts which transitively use - // these flags that try to compile executables. - if target == "i686-unknown-linux-musl" { - cmd.args.push("-Wl,-melf_i386".into()); - } - - if target.starts_with("thumb") { - cmd.args.push("-mthumb".into()); - - if target.ends_with("eabihf") { - cmd.args.push("-mfloat-abi=hard".into()) - } - } - if target.starts_with("thumbv6m") { - cmd.args.push("-march=armv6s-m".into()); - } - if target.starts_with("thumbv7em") { - cmd.args.push("-march=armv7e-m".into()); - - if target.ends_with("eabihf") { - cmd.args.push("-mfpu=fpv4-sp-d16".into()) - } - } - if target.starts_with("thumbv7m") { - cmd.args.push("-march=armv7-m".into()); - } } - if self.cpp && !msvc { - if let Some(ref stdlib) = self.cpp_set_stdlib { - cmd.args.push(format!("-stdlib=lib{}", stdlib).into()); + if self.cpp { + match (self.cpp_set_stdlib.as_ref(), cmd.family) { + (None, _) => { } + (Some(stdlib), ToolFamily::Gnu) | + (Some(stdlib), ToolFamily::Clang) => { + cmd.args.push(format!("-stdlib=lib{}", stdlib).into()); + } + _ => { + println!("cargo:warning=cpp_set_stdlib is specified, but the {:?} compiler \ + does not support this option, ignored", cmd.family); + } } } for directory in self.include_directories.iter() { - cmd.args.push(if msvc {"/I"} else {"-I"}.into()); + cmd.args.push(cmd.family.include_flag().into()); cmd.args.push(directory.into()); } @@ -589,7 +682,7 @@ pub fn get_compiler(&self) -> Tool { } for &(ref key, ref value) in self.definitions.iter() { - let lead = if msvc {"/"} else {"-"}; + let lead = if let ToolFamily::Msvc = cmd.family {"/"} else {"-"}; if let &Some(ref value) = value { cmd.args.push(format!("{}D{}={}", lead, key, value).into()); } else { @@ -601,10 +694,12 @@ pub fn get_compiler(&self) -> Tool { fn msvc_macro_assembler(&self) -> (Command, String) { let target = self.get_target(); - let tool = if target.contains("x86_64") {"ml64.exe"} else {"ml.exe"}; - let mut cmd = windows_registry::find(&target, tool).unwrap_or_else(|| { - self.cmd(tool) - }); + let tool = if target.contains("x86_64") { + "ml64.exe" + } else { + "ml.exe" + }; + let mut cmd = windows_registry::find(&target, tool).unwrap_or_else(|| self.cmd(tool)); for directory in self.include_directories.iter() { cmd.arg("/I").arg(directory); } @@ -635,31 +730,37 @@ fn assemble(&self, lib_name: &str, dst: &Path, objects: &[PathBuf]) { 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(self.cmd("lib.exe")), + None => windows_registry::find(&target, "lib.exe").unwrap_or(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"); + run(cmd.arg(out) + .arg("/nologo") + .args(objects) + .args(&self.objects), + "lib.exe"); // The Rust compiler will look for libfoo.a and foo.lib, but the // MSVC linker will also be passed foo.lib, so be sure that both // exist for now. let lib_dst = dst.with_file_name(format!("{}.lib", lib_name)); let _ = fs::remove_file(&lib_dst); - fs::hard_link(&dst, &lib_dst).or_else(|_| { - //if hard-link fails, just copy (ignoring the number of bytes written) - fs::copy(&dst, &lib_dst).map(|_| ()) - }).ok().expect("Copying from {:?} to {:?} failed.");; + fs::hard_link(&dst, &lib_dst) + .or_else(|_| { + // if hard-link fails, just copy (ignoring the number of bytes written) + fs::copy(&dst, &lib_dst).map(|_| ()) + }) + .ok() + .expect("Copying from {:?} to {:?} failed.");; } else { let ar = self.get_ar(); let cmd = ar.file_name().unwrap().to_string_lossy(); - run(self.cmd(&ar).arg("crs") - .arg(dst) - .args(objects) - .args(&self.objects), &cmd); + run(self.cmd(&ar) + .arg("crs") + .arg(dst) + .args(objects) + .args(&self.objects), + &cmd); } } @@ -677,7 +778,7 @@ enum ArchSpec { "arm64" | "aarch64" => ArchSpec::Device("arm64"), "i386" | "i686" => ArchSpec::Simulator("-m32"), "x86_64" => ArchSpec::Simulator("-m64"), - _ => fail("Unknown arch for iOS target") + _ => fail("Unknown arch for iOS target"), }; let sdk = match arch { @@ -686,7 +787,7 @@ enum ArchSpec { cmd.args.push(arch.into()); cmd.args.push("-miphoneos-version-min=7.0".into()); "iphoneos" - }, + } ArchSpec::Simulator(arch) => { cmd.args.push(arch.into()); cmd.args.push("-mios-simulator-version-min=7.0".into()); @@ -715,12 +816,12 @@ fn cmd>(&self, prog: P) -> Command { for &(ref a, ref b) in self.env.iter() { cmd.env(a, b); } - return cmd + return cmd; } fn get_base_compiler(&self) -> Tool { if let Some(ref c) = self.compiler { - return Tool::new(c.clone()) + return Tool::new(c.clone()); } let host = self.get_host(); let target = self.get_target(); @@ -729,87 +830,88 @@ fn get_base_compiler(&self) -> Tool { } else { ("CC", "cl.exe", "gcc", "cc") }; - self.env_tool(env).map(|(tool, args)| { - let mut t = Tool::new(PathBuf::from(tool)); - for arg in args { - t.args.push(arg.into()); - } - return t - }).or_else(|| { - if target.contains("emscripten") { - if self.cpp { - Some(Tool::new(PathBuf::from("em++"))) + self.env_tool(env) + .map(|(tool, args)| { + let mut t = Tool::new(PathBuf::from(tool)); + for arg in args { + t.args.push(arg.into()); + } + return t; + }) + .or_else(|| { + if target.contains("emscripten") { + if self.cpp { + Some(Tool::new(PathBuf::from("em++"))) + } else { + Some(Tool::new(PathBuf::from("emcc"))) + } } else { - Some(Tool::new(PathBuf::from("emcc"))) + None } - } else { - None - } - }).or_else(|| { - windows_registry::find_tool(&target, "cl.exe") - }).unwrap_or_else(|| { - let compiler = if host.contains("windows") && - target.contains("windows") { - if target.contains("msvc") { - msvc.to_string() + }) + .or_else(|| windows_registry::find_tool(&target, "cl.exe")) + .unwrap_or_else(|| { + let compiler = if host.contains("windows") && target.contains("windows") { + if target.contains("msvc") { + msvc.to_string() + } else { + format!("{}.exe", gnu) + } + } else if target.contains("android") { + format!("{}-{}", target.replace("armv7", "arm"), gnu) + } else if self.get_host() != target { + // CROSS_COMPILE is of the form: "arm-linux-gnueabi-" + let cc_env = self.getenv("CROSS_COMPILE"); + let cross_compile = cc_env.as_ref().map(|s| s.trim_right_matches('-')); + let prefix = cross_compile.or(match &target[..] { + "aarch64-unknown-linux-gnu" => Some("aarch64-linux-gnu"), + "arm-unknown-linux-gnueabi" => Some("arm-linux-gnueabi"), + "arm-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"), + "arm-unknown-linux-musleabi" => Some("arm-linux-musleabi"), + "arm-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"), + "arm-unknown-netbsdelf-eabi" => Some("arm--netbsdelf-eabi"), + "armv6-unknown-netbsdelf-eabihf" => Some("armv6--netbsdelf-eabihf"), + "armv7-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"), + "armv7-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"), + "armv7-unknown-netbsdelf-eabihf" => Some("armv7--netbsdelf-eabihf"), + "i686-pc-windows-gnu" => Some("i686-w64-mingw32"), + "i686-unknown-linux-musl" => Some("musl"), + "i686-unknown-netbsdelf" => Some("i486--netbsdelf"), + "mips-unknown-linux-gnu" => Some("mips-linux-gnu"), + "mipsel-unknown-linux-gnu" => Some("mipsel-linux-gnu"), + "mips64-unknown-linux-gnuabi64" => Some("mips64-linux-gnuabi64"), + "mips64el-unknown-linux-gnuabi64" => Some("mips64el-linux-gnuabi64"), + "powerpc-unknown-linux-gnu" => Some("powerpc-linux-gnu"), + "powerpc-unknown-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"), + "sparc64-unknown-netbsd" => Some("sparc64--netbsd"), + "thumbv6m-none-eabi" => Some("arm-none-eabi"), + "thumbv7em-none-eabi" => Some("arm-none-eabi"), + "thumbv7em-none-eabihf" => Some("arm-none-eabi"), + "thumbv7m-none-eabi" => Some("arm-none-eabi"), + "x86_64-pc-windows-gnu" => Some("x86_64-w64-mingw32"), + "x86_64-rumprun-netbsd" => Some("x86_64-rumprun-netbsd"), + "x86_64-unknown-linux-musl" => Some("musl"), + "x86_64-unknown-netbsd" => Some("x86_64--netbsd"), + _ => None, + }); + match prefix { + Some(prefix) => format!("{}-{}", prefix, gnu), + None => default.to_string(), + } } else { - format!("{}.exe", gnu) - } - } else if target.contains("android") { - format!("{}-{}", target, gnu) - } else if self.get_host() != target { - // CROSS_COMPILE is of the form: "arm-linux-gnueabi-" - let cc_env = self.getenv("CROSS_COMPILE"); - let cross_compile = cc_env.as_ref().map(|s| s.trim_right_matches('-')); - let prefix = cross_compile.or(match &target[..] { - "aarch64-unknown-linux-gnu" => Some("aarch64-linux-gnu"), - "arm-unknown-linux-gnueabi" => Some("arm-linux-gnueabi"), - "arm-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"), - "arm-unknown-linux-musleabi" => Some("arm-linux-musleabi"), - "arm-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"), - "arm-unknown-netbsdelf-eabi" => Some("arm--netbsdelf-eabi"), - "armv6-unknown-netbsdelf-eabihf" => Some("armv6--netbsdelf-eabihf"), - "armv7-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"), - "armv7-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"), - "armv7-unknown-netbsdelf-eabihf" => Some("armv7--netbsdelf-eabihf"), - "i686-pc-windows-gnu" => Some("i686-w64-mingw32"), - "i686-unknown-linux-musl" => Some("musl"), - "i686-unknown-netbsdelf" => Some("i486--netbsdelf"), - "mips-unknown-linux-gnu" => Some("mips-linux-gnu"), - "mipsel-unknown-linux-gnu" => Some("mipsel-linux-gnu"), - "mips64-unknown-linux-gnuabi64" => Some("mips64-linux-gnuabi64"), - "mips64el-unknown-linux-gnuabi64" => Some("mips64el-linux-gnuabi64"), - "powerpc-unknown-linux-gnu" => Some("powerpc-linux-gnu"), - "powerpc-unknown-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"), - "sparc64-unknown-netbsd" => Some("sparc64--netbsd"), - "thumbv6m-none-eabi" => Some("arm-none-eabi"), - "thumbv7em-none-eabi" => Some("arm-none-eabi"), - "thumbv7em-none-eabihf" => Some("arm-none-eabi"), - "thumbv7m-none-eabi" => Some("arm-none-eabi"), - "x86_64-pc-windows-gnu" => Some("x86_64-w64-mingw32"), - "x86_64-rumprun-netbsd" => Some("x86_64-rumprun-netbsd"), - "x86_64-unknown-linux-musl" => Some("musl"), - "x86_64-unknown-netbsd" => Some("x86_64--netbsd"), - _ => None, - }); - match prefix { - Some(prefix) => format!("{}-{}", prefix, gnu), - None => default.to_string(), - } - } else { - default.to_string() - }; - Tool::new(PathBuf::from(compiler)) - }) + default.to_string() + }; + Tool::new(PathBuf::from(compiler)) + }) } fn get_var(&self, var_base: &str) -> Result { let target = self.get_target(); let host = self.get_host(); - let kind = if host == target {"HOST"} else {"TARGET"}; + let kind = if host == target { "HOST" } else { "TARGET" }; let target_u = target.replace("-", "_"); let res = self.getenv(&format!("{}_{}", var_base, target)) .or_else(|| self.getenv(&format!("{}_{}", var_base, target_u))) @@ -823,8 +925,10 @@ fn get_var(&self, var_base: &str) -> Result { } fn envflags(&self, name: &str) -> Vec { - self.get_var(name).unwrap_or(String::new()) - .split(|c: char| c.is_whitespace()).filter(|s| !s.is_empty()) + self.get_var(name) + .unwrap_or(String::new()) + .split(|c: char| c.is_whitespace()) + .filter(|s| !s.is_empty()) .map(|s| s.to_string()) .collect() } @@ -834,8 +938,7 @@ fn env_tool(&self, name: &str) -> Option<(String, Vec)> { let whitelist = ["ccache", "distcc"]; for t in whitelist.iter() { if tool.starts_with(t) && tool[t.len()..].starts_with(" ") { - return (t.to_string(), - vec![tool[t.len()..].trim_left().to_string()]) + return (t.to_string(), vec![tool[t.len()..].trim_left().to_string()]); } } (tool, Vec::new()) @@ -860,17 +963,18 @@ fn get_cpp_link_stdlib(&self) -> Option { } fn get_ar(&self) -> PathBuf { - self.archiver.clone().or_else(|| { - self.get_var("AR").map(PathBuf::from).ok() - }).unwrap_or_else(|| { - if self.get_target().contains("android") { - PathBuf::from(format!("{}-ar", self.get_target())) - } else if self.get_target().contains("emscripten") { - PathBuf::from("emar") - } else { - PathBuf::from("ar") - } - }) + self.archiver + .clone() + .or_else(|| self.get_var("AR").map(PathBuf::from).ok()) + .unwrap_or_else(|| { + if self.get_target().contains("android") { + PathBuf::from(format!("{}-ar", self.get_target().replace("armv7", "arm"))) + } else if self.get_target().contains("emscripten") { + PathBuf::from("emar") + } else { + PathBuf::from("ar") + } + }) } fn get_target(&self) -> String { @@ -882,9 +986,7 @@ fn get_host(&self) -> String { } fn get_opt_level(&self) -> String { - self.opt_level.as_ref().cloned().unwrap_or_else(|| { - self.getenv_unwrap("OPT_LEVEL") - }) + self.opt_level.as_ref().cloned().unwrap_or_else(|| self.getenv_unwrap("OPT_LEVEL")) } fn get_debug(&self) -> bool { @@ -892,9 +994,7 @@ fn get_debug(&self) -> bool { } fn get_out_dir(&self) -> PathBuf { - self.out_dir.clone().unwrap_or_else(|| { - env::var_os("OUT_DIR").map(PathBuf::from).unwrap() - }) + self.out_dir.clone().unwrap_or_else(|| env::var_os("OUT_DIR").map(PathBuf::from).unwrap()) } fn getenv(&self, v: &str) -> Option { @@ -919,10 +1019,23 @@ fn print(&self, s: &str) { impl Tool { fn new(path: PathBuf) -> Tool { + // Try to detect family of the tool from its name, falling back to Gnu. + let family = if let Some(fname) = path.file_name().and_then(|p| p.to_str()) { + if fname.contains("clang") { + ToolFamily::Clang + } else if fname.contains("cl") { + ToolFamily::Msvc + } else { + ToolFamily::Gnu + } + } else { + ToolFamily::Gnu + }; Tool { path: path, args: Vec::new(), env: Vec::new(), + family: family } } @@ -937,7 +1050,7 @@ pub fn to_command(&self) -> Command { for &(ref k, ref v) in self.env.iter() { cmd.env(k, v); } - return cmd + cmd } /// Returns the path for this compiler. @@ -963,23 +1076,27 @@ pub fn env(&self) -> &[(OsString, OsString)] { } } -fn run(cmd: &mut Command, program: &str) { +fn run(cmd: &mut Command, program: &str) -> Vec { println!("running: {:?}", cmd); // Capture the standard error coming from these programs, and write it out // with cargo:warning= prefixes. Note that this is a bit wonky to avoid // requiring the output to be UTF-8, we instead just ship bytes from one // location to another. - let spawn_result = match cmd.stderr(Stdio::piped()).spawn() { + let (spawn_result, stdout) = match cmd.stdout(Stdio::piped()).stderr(Stdio::piped()).spawn() { Ok(mut child) => { let stderr = BufReader::new(child.stderr.take().unwrap()); - for line in stderr.split(b'\n').filter_map(|l| l.ok()) { - print!("cargo:warning="); - std::io::stdout().write_all(&line).unwrap(); - println!(""); - } - child.wait() + 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 mut stdout = vec![]; + child.stdout.take().unwrap().read_to_end(&mut stdout).unwrap(); + (child.wait(), stdout) } - Err(e) => Err(e), + Err(e) => (Err(e), vec![]), }; let status = match spawn_result { Ok(status) => status, @@ -991,7 +1108,10 @@ fn run(cmd: &mut Command, program: &str) { "" }; fail(&format!("failed to execute command: {}\nIs `{}` \ - not installed?{}", e, program, extra)); + not installed?{}", + e, + program, + extra)); } Err(e) => fail(&format!("failed to execute command: {}", e)), }; @@ -999,6 +1119,7 @@ fn run(cmd: &mut Command, program: &str) { if !status.success() { fail(&format!("command did not execute successfully, got: {}", status)); } + stdout } fn fail(s: &str) -> ! { diff --git a/src/vendor/gcc/src/registry.rs b/src/vendor/gcc/src/registry.rs index d871cd21f3c..a45272344db 100644 --- a/src/vendor/gcc/src/registry.rs +++ b/src/vendor/gcc/src/registry.rs @@ -40,7 +40,8 @@ fn RegOpenKeyExW(key: HKEY, lpSubKey: LPCWSTR, ulOptions: DWORD, samDesired: REGSAM, - phkResult: PHKEY) -> LONG; + phkResult: PHKEY) + -> LONG; fn RegEnumKeyExW(key: HKEY, dwIndex: DWORD, lpName: LPWSTR, @@ -48,13 +49,15 @@ fn RegEnumKeyExW(key: HKEY, lpReserved: LPDWORD, lpClass: LPWSTR, lpcClass: LPDWORD, - lpftLastWriteTime: PFILETIME) -> LONG; + lpftLastWriteTime: PFILETIME) + -> LONG; fn RegQueryValueExW(hKey: HKEY, lpValueName: LPCWSTR, lpReserved: LPDWORD, lpType: LPDWORD, lpData: LPBYTE, - lpcbData: LPDWORD) -> LONG; + lpcbData: LPDWORD) + -> LONG; fn RegCloseKey(hKey: HKEY) -> LONG; } @@ -73,8 +76,7 @@ pub struct Iter<'a> { unsafe impl Sync for Repr {} unsafe impl Send for Repr {} -pub static LOCAL_MACHINE: RegistryKey = - RegistryKey(Repr::Const(HKEY_LOCAL_MACHINE)); +pub static LOCAL_MACHINE: RegistryKey = RegistryKey(Repr::Const(HKEY_LOCAL_MACHINE)); impl RegistryKey { fn raw(&self) -> HKEY { @@ -88,8 +90,11 @@ pub fn open(&self, key: &OsStr) -> io::Result { let key = key.encode_wide().chain(Some(0)).collect::>(); 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)))) @@ -99,7 +104,10 @@ pub fn open(&self, key: &OsStr) -> io::Result { } pub fn iter(&self) -> Iter { - Iter { idx: 0.., key: self } + Iter { + idx: 0.., + key: self, + } } pub fn query_str(&self, name: &str) -> io::Result { @@ -108,25 +116,31 @@ pub fn query_str(&self, name: &str) -> io::Result { 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)) + 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 _, + 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)) + return Err(io::Error::from_raw_os_error(err as i32)); } v.set_len(len as usize / 2); @@ -142,7 +156,9 @@ pub fn query_str(&self, name: &str) -> io::Result { impl Drop for OwnedKey { fn drop(&mut self) { - unsafe { RegCloseKey(self.0); } + unsafe { + RegCloseKey(self.0); + } } } @@ -153,8 +169,13 @@ fn next(&mut self) -> Option> { 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 _, + 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 diff --git a/src/vendor/gcc/src/windows_registry.rs b/src/vendor/gcc/src/windows_registry.rs index e16a33f2464..08b1df5f9b2 100644 --- a/src/vendor/gcc/src/windows_registry.rs +++ b/src/vendor/gcc/src/windows_registry.rs @@ -78,31 +78,29 @@ fn into_tool(self) -> Tool { add_env(&mut tool, "LIB", libs); add_env(&mut tool, "PATH", path); add_env(&mut tool, "INCLUDE", include); - return tool + tool } } // This logic is all tailored for MSVC, if we're not that then bail out // early. if !target.contains("msvc") { - return None + return None; } // Looks like msbuild isn't located in the same location as other tools like // cl.exe and lib.exe. To handle this we probe for it manually with // dedicated registry keys. if tool.contains("msbuild") { - return find_msbuild(target) + return find_msbuild(target); } // If VCINSTALLDIR is set, then someone's probably already run vcvars and we // should just find whatever that indicates. if env::var_os("VCINSTALLDIR").is_some() { - return env::var_os("PATH").and_then(|path| { - env::split_paths(&path).map(|p| p.join(tool)).find(|p| p.exists()) - }).map(|path| { - Tool::new(path.into()) - }) + return env::var_os("PATH") + .and_then(|path| env::split_paths(&path).map(|p| p.join(tool)).find(|p| p.exists())) + .map(|path| Tool::new(path.into())); } // Ok, if we're here, now comes the fun part of the probing. Default shells @@ -112,13 +110,10 @@ fn into_tool(self) -> Tool { // environment variables like `LIB`, `INCLUDE`, and `PATH` to ensure that // the tool is actually usable. - return find_msvc_latest(tool, target, "15.0").or_else(|| { - find_msvc_latest(tool, target, "14.0") - }).or_else(|| { - find_msvc_12(tool, target) - }).or_else(|| { - find_msvc_11(tool, target) - }); + return find_msvc_latest(tool, target, "15.0") + .or_else(|| find_msvc_latest(tool, target, "14.0")) + .or_else(|| find_msvc_12(tool, target)) + .or_else(|| find_msvc_11(tool, target)); // For MSVC 14 or newer we need to find the Universal CRT as well as either // the Windows 10 SDK or Windows 8.1 SDK. @@ -151,7 +146,7 @@ fn find_msvc_latest(tool: &str, target: &str, ver: &str) -> Option { tool.include.push(sdk_include.join("winrt")); tool.include.push(sdk_include.join("shared")); } else { - return None + return None; } Some(tool.into_tool()) } @@ -198,26 +193,27 @@ fn add_env(tool: &mut Tool, env: &str, paths: Vec) { // Given a possible MSVC installation directory, we look for the linker and // then add the MSVC library path. fn get_tool(tool: &str, path: &Path, target: &str) -> Option { - bin_subdir(target).into_iter().map(|(sub, host)| { - (path.join("bin").join(sub).join(tool), - path.join("bin").join(host)) - }).filter(|&(ref path, _)| { - path.is_file() - }).map(|(path, host)| { - let mut tool = MsvcTool::new(path); - tool.path.push(host); - tool - }).filter_map(|mut tool| { - let sub = otry!(vc_lib_subdir(target)); - tool.libs.push(path.join("lib").join(sub)); - tool.include.push(path.join("include")); - let atlmfc_path = path.join("atlmfc"); - if atlmfc_path.exists() { - tool.libs.push(atlmfc_path.join("lib").join(sub)); - tool.include.push(atlmfc_path.join("include")); - } - Some(tool) - }).next() + bin_subdir(target) + .into_iter() + .map(|(sub, host)| (path.join("bin").join(sub).join(tool), path.join("bin").join(host))) + .filter(|&(ref path, _)| path.is_file()) + .map(|(path, host)| { + let mut tool = MsvcTool::new(path); + tool.path.push(host); + tool + }) + .filter_map(|mut tool| { + let sub = otry!(vc_lib_subdir(target)); + tool.libs.push(path.join("lib").join(sub)); + tool.include.push(path.join("include")); + let atlmfc_path = path.join("atlmfc"); + if atlmfc_path.exists() { + tool.libs.push(atlmfc_path.join("lib").join(sub)); + tool.include.push(atlmfc_path.join("include")); + } + Some(tool) + }) + .next() } // To find MSVC we look in a specific registry key for the version we are @@ -240,17 +236,16 @@ fn get_ucrt_dir() -> Option<(PathBuf, String)> { 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().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()); + 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()); let version = max_libdir.components().last().unwrap(); let version = version.as_os_str().to_str().unwrap().to_string(); Some((root.into(), version)) @@ -270,12 +265,13 @@ fn get_sdk10_dir() -> Option<(PathBuf, String)> { 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()) - .map(|dir| dir.path()) - .collect::>(); + .map(|dir| dir.path()) + .collect::>(); 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)) @@ -319,10 +315,8 @@ fn get_sdk8_dir() -> Option { fn bin_subdir(target: &str) -> Vec<(&'static str, &'static str)> { let arch = target.split('-').next().unwrap(); match (arch, host_arch()) { - ("i586", X86) | - ("i686", X86) => vec![("", "")], - ("i586", X86_64) | - ("i686", X86_64) => vec![("amd64_x86", "amd64"), ("", "")], + ("i586", X86) | ("i686", X86) => vec![("", "")], + ("i586", X86_64) | ("i686", X86_64) => vec![("amd64_x86", "amd64"), ("", "")], ("x86_64", X86) => vec![("x86_amd64", "")], ("x86_64", X86_64) => vec![("amd64", "amd64"), ("x86_amd64", "")], ("arm", X86) => vec![("x86_arm", "")], @@ -393,9 +387,8 @@ fn max_version(key: &RegistryKey) -> Option<(OsString, RegistryKey)> { let mut max_vers = 0; let mut max_key = None; for subkey in key.iter().filter_map(|k| k.ok()) { - let val = subkey.to_str().and_then(|s| { - s.trim_left_matches("v").replace(".", "").parse().ok() - }); + let val = subkey.to_str() + .and_then(|s| s.trim_left_matches("v").replace(".", "").parse().ok()); let val = match val { Some(s) => s, None => continue, @@ -407,24 +400,25 @@ fn max_version(key: &RegistryKey) -> Option<(OsString, RegistryKey)> { } } } - return max_key + max_key } // see http://stackoverflow.com/questions/328017/path-to-msbuild fn find_msbuild(target: &str) -> Option { let key = r"SOFTWARE\Microsoft\MSBuild\ToolsVersions"; - LOCAL_MACHINE.open(key.as_ref()).ok().and_then(|key| { - max_version(&key).and_then(|(_vers, key)| { - key.query_str("MSBuildToolsPath").ok() + LOCAL_MACHINE.open(key.as_ref()) + .ok() + .and_then(|key| { + max_version(&key).and_then(|(_vers, key)| key.query_str("MSBuildToolsPath").ok()) + }) + .map(|path| { + let mut path = PathBuf::from(path); + path.push("MSBuild.exe"); + let mut tool = Tool::new(path); + if target.contains("x86_64") { + tool.env.push(("Platform".into(), "X64".into())); + } + tool }) - }).map(|path| { - let mut path = PathBuf::from(path); - path.push("MSBuild.exe"); - let mut tool = Tool::new(path); - if target.contains("x86_64") { - tool.env.push(("Platform".into(), "X64".into())); - } - tool - }) } } diff --git a/src/vendor/gcc/tests/support/mod.rs b/src/vendor/gcc/tests/support/mod.rs index 5c40984eb6a..135a6635b59 100644 --- a/src/vendor/gcc/tests/support/mod.rs +++ b/src/vendor/gcc/tests/support/mod.rs @@ -37,28 +37,27 @@ pub fn new() -> Test { pub fn gnu() -> Test { let t = Test::new(); t.shim("cc").shim("ar"); - return t + t } pub fn msvc() -> Test { let mut t = Test::new(); t.shim("cl").shim("lib.exe"); t.msvc = true; - return t + t } pub fn shim(&self, name: &str) -> &Test { let fname = format!("{}{}", name, env::consts::EXE_SUFFIX); - fs::hard_link(&self.gcc, self.td.path().join(&fname)).or_else(|_| { - fs::copy(&self.gcc, self.td.path().join(&fname)).map(|_| ()) - }).unwrap(); + fs::hard_link(&self.gcc, self.td.path().join(&fname)) + .or_else(|_| fs::copy(&self.gcc, self.td.path().join(&fname)).map(|_| ())) + .unwrap(); self } pub fn gcc(&self) -> gcc::Config { let mut cfg = gcc::Config::new(); - let mut path = env::split_paths(&env::var_os("PATH").unwrap()) - .collect::>(); + let mut path = env::split_paths(&env::var_os("PATH").unwrap()).collect::>(); path.insert(0, self.td.path().to_owned()); let target = if self.msvc { "x86_64-pc-windows-msvc" @@ -66,26 +65,27 @@ pub fn gcc(&self) -> gcc::Config { "x86_64-unknown-linux-gnu" }; - cfg.target(target).host(target) - .opt_level(2) - .debug(false) - .out_dir(self.td.path()) - .__set_env("PATH", env::join_paths(path).unwrap()) - .__set_env("GCCTEST_OUT_DIR", self.td.path()); + cfg.target(target) + .host(target) + .opt_level(2) + .debug(false) + .out_dir(self.td.path()) + .__set_env("PATH", env::join_paths(path).unwrap()) + .__set_env("GCCTEST_OUT_DIR", self.td.path()); if self.msvc { cfg.compiler(self.td.path().join("cl")); cfg.archiver(self.td.path().join("lib.exe")); } - return cfg + cfg } pub fn cmd(&self, i: u32) -> Execution { let mut s = String::new(); - File::open(self.td.path().join(format!("out{}", i))).unwrap() - .read_to_string(&mut s).unwrap(); - Execution { - args: s.lines().map(|s| s.to_string()).collect(), - } + File::open(self.td.path().join(format!("out{}", i))) + .unwrap() + .read_to_string(&mut s) + .unwrap(); + Execution { args: s.lines().map(|s| s.to_string()).collect() } } } @@ -107,8 +107,6 @@ pub fn must_not_have>(&self, p: P) -> &Execution { } pub fn has(&self, p: &OsStr) -> bool { - self.args.iter().any(|arg| { - OsStr::new(arg) == p - }) + self.args.iter().any(|arg| OsStr::new(arg) == p) } } diff --git a/src/vendor/gcc/tests/test.rs b/src/vendor/gcc/tests/test.rs index 1b6a0bd0d10..5a034ff347b 100644 --- a/src/vendor/gcc/tests/test.rs +++ b/src/vendor/gcc/tests/test.rs @@ -9,14 +9,16 @@ fn gnu_smoke() { let test = Test::gnu(); test.gcc() - .file("foo.c").compile("libfoo.a"); + .file("foo.c") + .compile("libfoo.a"); - test.cmd(0).must_have("-O2") - .must_have("foo.c") - .must_not_have("-g") - .must_have("-c") - .must_have("-ffunction-sections") - .must_have("-fdata-sections"); + test.cmd(0) + .must_have("-O2") + .must_have("foo.c") + .must_not_have("-g") + .must_have("-c") + .must_have("-ffunction-sections") + .must_have("-fdata-sections"); test.cmd(1).must_have(test.td.path().join("foo.o")); } @@ -25,10 +27,12 @@ fn gnu_opt_level_1() { let test = Test::gnu(); test.gcc() .opt_level(1) - .file("foo.c").compile("libfoo.a"); + .file("foo.c") + .compile("libfoo.a"); - test.cmd(0).must_have("-O1") - .must_not_have("-O2"); + test.cmd(0) + .must_have("-O1") + .must_not_have("-O2"); } #[test] @@ -36,13 +40,15 @@ fn gnu_opt_level_s() { let test = Test::gnu(); test.gcc() .opt_level_str("s") - .file("foo.c").compile("libfoo.a"); + .file("foo.c") + .compile("libfoo.a"); - test.cmd(0).must_have("-Os") - .must_not_have("-O1") - .must_not_have("-O2") - .must_not_have("-O3") - .must_not_have("-Oz"); + test.cmd(0) + .must_have("-Os") + .must_not_have("-O1") + .must_not_have("-O2") + .must_not_have("-O3") + .must_not_have("-Oz"); } #[test] @@ -50,7 +56,8 @@ fn gnu_debug() { let test = Test::gnu(); test.gcc() .debug(true) - .file("foo.c").compile("libfoo.a"); + .file("foo.c") + .compile("libfoo.a"); test.cmd(0).must_have("-g"); } @@ -62,10 +69,12 @@ fn gnu_x86_64() { test.gcc() .target(&target) .host(&target) - .file("foo.c").compile("libfoo.a"); + .file("foo.c") + .compile("libfoo.a"); - test.cmd(0).must_have("-fPIC") - .must_have("-m64"); + test.cmd(0) + .must_have("-fPIC") + .must_have("-m64"); } } @@ -78,7 +87,8 @@ fn gnu_x86_64_no_pic() { .pic(false) .target(&target) .host(&target) - .file("foo.c").compile("libfoo.a"); + .file("foo.c") + .compile("libfoo.a"); test.cmd(0).must_not_have("-fPIC"); } @@ -92,10 +102,12 @@ fn gnu_i686() { test.gcc() .target(&target) .host(&target) - .file("foo.c").compile("libfoo.a"); + .file("foo.c") + .compile("libfoo.a"); - test.cmd(0).must_not_have("-fPIC") - .must_have("-m32"); + test.cmd(0) + .must_not_have("-fPIC") + .must_have("-m32"); } } @@ -108,7 +120,8 @@ fn gnu_i686_pic() { .pic(true) .target(&target) .host(&target) - .file("foo.c").compile("libfoo.a"); + .file("foo.c") + .compile("libfoo.a"); test.cmd(0).must_have("-fPIC"); } @@ -119,7 +132,8 @@ fn gnu_set_stdlib() { let test = Test::gnu(); test.gcc() .cpp_set_stdlib(Some("foo")) - .file("foo.c").compile("libfoo.a"); + .file("foo.c") + .compile("libfoo.a"); test.cmd(0).must_not_have("-stdlib=foo"); } @@ -129,7 +143,8 @@ fn gnu_include() { let test = Test::gnu(); test.gcc() .include("foo/bar") - .file("foo.c").compile("libfoo.a"); + .file("foo.c") + .compile("libfoo.a"); test.cmd(0).must_have("-I").must_have("foo/bar"); } @@ -140,7 +155,8 @@ fn gnu_define() { test.gcc() .define("FOO", Some("bar")) .define("BAR", None) - .file("foo.c").compile("libfoo.a"); + .file("foo.c") + .compile("libfoo.a"); test.cmd(0).must_have("-DFOO=bar").must_have("-DBAR"); } @@ -149,7 +165,8 @@ fn gnu_define() { fn gnu_compile_assembly() { let test = Test::gnu(); test.gcc() - .file("foo.S").compile("libfoo.a"); + .file("foo.S") + .compile("libfoo.a"); test.cmd(0).must_have("foo.S"); } @@ -157,12 +174,14 @@ fn gnu_compile_assembly() { fn msvc_smoke() { let test = Test::msvc(); test.gcc() - .file("foo.c").compile("libfoo.a"); + .file("foo.c") + .compile("libfoo.a"); - test.cmd(0).must_have("/O2") - .must_have("foo.c") - .must_not_have("/Z7") - .must_have("/c"); + test.cmd(0) + .must_have("/O2") + .must_have("foo.c") + .must_not_have("/Z7") + .must_have("/c"); test.cmd(1).must_have(test.td.path().join("foo.o")); } @@ -171,7 +190,8 @@ fn msvc_opt_level_0() { let test = Test::msvc(); test.gcc() .opt_level(0) - .file("foo.c").compile("libfoo.a"); + .file("foo.c") + .compile("libfoo.a"); test.cmd(0).must_not_have("/O2"); } @@ -181,7 +201,8 @@ fn msvc_debug() { let test = Test::msvc(); test.gcc() .debug(true) - .file("foo.c").compile("libfoo.a"); + .file("foo.c") + .compile("libfoo.a"); test.cmd(0).must_have("/Z7"); } @@ -190,7 +211,8 @@ fn msvc_include() { let test = Test::msvc(); test.gcc() .include("foo/bar") - .file("foo.c").compile("libfoo.a"); + .file("foo.c") + .compile("libfoo.a"); test.cmd(0).must_have("/I").must_have("foo/bar"); } @@ -201,7 +223,8 @@ fn msvc_define() { test.gcc() .define("FOO", Some("bar")) .define("BAR", None) - .file("foo.c").compile("libfoo.a"); + .file("foo.c") + .compile("libfoo.a"); test.cmd(0).must_have("/DFOO=bar").must_have("/DBAR"); }