diff options
Diffstat (limited to 'cc')
-rw-r--r-- | cc/.travis.yml | 63 | ||||
-rw-r--r-- | cc/Cargo.toml | 8 | ||||
-rw-r--r-- | cc/README.md | 6 | ||||
-rw-r--r-- | cc/appveyor.yml | 55 | ||||
-rw-r--r-- | cc/azure-pipelines.yml | 101 | ||||
-rw-r--r-- | cc/ci/azure-install-rust.yml | 24 | ||||
-rw-r--r-- | cc/ci/azure-steps.yml | 21 | ||||
-rw-r--r-- | cc/src/com.rs | 4 | ||||
-rw-r--r-- | cc/src/lib.rs | 293 | ||||
-rw-r--r-- | cc/src/setup_config.rs | 22 | ||||
-rw-r--r-- | cc/src/winapi.rs | 4 | ||||
-rw-r--r-- | cc/src/windows_registry.rs | 112 | ||||
-rw-r--r-- | cc/tests/cc_env.rs | 8 | ||||
-rw-r--r-- | cc/tests/support/mod.rs | 6 | ||||
-rw-r--r-- | cc/tests/test.rs | 8 |
15 files changed, 450 insertions, 285 deletions
diff --git a/cc/.travis.yml b/cc/.travis.yml deleted file mode 100644 index 47bbfd8..0000000 --- a/cc/.travis.yml +++ /dev/null @@ -1,63 +0,0 @@ -language: rust -sudo: false - -matrix: - include: - - rust: 1.16.0 - install: - script: cargo build - - rust: stable - env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1 - - rust: stable - env: TARGET=i686-unknown-linux-gnu - - os: osx - env: TARGET=x86_64-apple-darwin NO_ADD=1 - - os: osx - env: TARGET=aarch64-apple-ios NO_RUN=--no-run TARGET_SYSROOT=$(xcrun -sdk iphoneos --show-sdk-path) - - rust: beta - env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1 - - rust: nightly - env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1 - - - rust: nightly - before_script: - - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH - install: - script: - - cargo doc --no-deps --all-features - after_success: - - travis-cargo --only nightly doc-upload - -install: - - if [ -z "$NO_ADD" ]; then rustup target add $TARGET; fi - -script: - - cargo build --verbose - # FIXME: no idea why `--test-threads=1` is required on the OSX builder, it - # just randomly broke one day when the travis image was upgraded, and - # debugging turned up no easily found source of bugs... - # - # good build - https://travis-ci.org/alexcrichton/cc-rs/builds/409602374 - # bad build - https://travis-ci.org/alexcrichton/cc-rs/builds/410489079 - # - # Those are using the same compiler, same commit, same... everything. Except - # the OSX image! No idea what changed... - - cargo test --verbose $NO_RUN -- --test-threads=1 - - cargo test --verbose --features parallel $NO_RUN -- --test-threads=1 - - cargo test --manifest-path cc-test/Cargo.toml --target $TARGET $NO_RUN - - cargo test --manifest-path cc-test/Cargo.toml --target $TARGET --features parallel $NO_RUN - - cargo test --manifest-path cc-test/Cargo.toml --target $TARGET --release $NO_RUN - - cargo doc - - cargo clean && cargo build - -env: - global: - secure: "CBtqrudgE0PS8x3kTr44jKbC2D4nfnmdYVecooNm0qnER4B4TSvZpZSQoCgKK6k4BYQuOSyFTOwYx6M79w39ZMOgyCP9ytB+tyMWL0/+ZuUQL04yVg4M5vd3oJMkOaXbvG56ncgPyFrseY+FPDg+mXAzvJk/nily37YXjkQj2D0=" - -notifications: - email: - on_success: never -addons: - apt: - packages: - - g++-multilib diff --git a/cc/Cargo.toml b/cc/Cargo.toml index 3966026..3a4c83b 100644 --- a/cc/Cargo.toml +++ b/cc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cc" -version = "1.0.28" +version = "1.0.37" authors = ["Alex Crichton <alex@alexcrichton.com>"] license = "MIT/Apache-2.0" repository = "https://github.com/alexcrichton/cc-rs" @@ -13,13 +13,9 @@ code. """ keywords = ["build-dependencies"] readme = "README.md" -categories = ["development-tools"] +categories = ["development-tools::build-utils"] exclude = ["/.travis.yml", "/appveyor.yml"] -[badges] -travis-ci = { repository = "alexcrichton/cc-rs" } -appveyor = { repository = "alexcrichton/cc-rs" } - [dependencies] rayon = { version = "1.0", optional = true } diff --git a/cc/README.md b/cc/README.md index f65d0c0..e3c6ad0 100644 --- a/cc/README.md +++ b/cc/README.md @@ -2,8 +2,7 @@ A library to compile C/C++/assembly into a Rust library/application. -[![Build Status](https://travis-ci.org/alexcrichton/cc-rs.svg?branch=master)](https://travis-ci.org/alexcrichton/cc-rs) -[![Build status](https://ci.appveyor.com/api/projects/status/onu270iw98h81nwv?svg=true)](https://ci.appveyor.com/project/alexcrichton/cc-rs) +[![Build Status](https://dev.azure.com/alexcrichton/cc-rs/_apis/build/status/alexcrichton.cc-rs?branchName=master)](https://dev.azure.com/alexcrichton/cc-rs/_build/latest?definitionId=5&branchName=master) [Documentation](https://docs.rs/cc) @@ -77,6 +76,7 @@ number of different environment variables. certain `TARGET`s, it also is assumed to know about other flags (most common is `-fPIC`). * `AR` - the `ar` (archiver) executable to use to build the static library. +* `CRATE_CC_NO_DEFAULTS` - the default compiler flags may cause conflicts in some cross compiling scenarios. Setting this variable will disable the generation of default compiler flags. Each of these variables can also be supplied with certain prefixes and suffixes, in the following prioritized order: @@ -88,7 +88,7 @@ in the following prioritized order: If none of these variables exist, cc-rs uses built-in defaults -In addition to the the above optional environment variables, `cc-rs` has some +In addition to the above optional environment variables, `cc-rs` has some functions with hard requirements on some variables supplied by [cargo's build-script driver][cargo] that it has the `TARGET`, `OUT_DIR`, `OPT_LEVEL`, and `HOST` variables. diff --git a/cc/appveyor.yml b/cc/appveyor.yml deleted file mode 100644 index 5e563db..0000000 --- a/cc/appveyor.yml +++ /dev/null @@ -1,55 +0,0 @@ -environment: - - # At the time this was added AppVeyor was having troubles with checking - # revocation of SSL certificates of sites like static.rust-lang.org and what - # we think is crates.io. The libcurl HTTP client by default checks for - # revocation on Windows and according to a mailing list [1] this can be - # disabled. - # - # The `CARGO_HTTP_CHECK_REVOKE` env var here tells cargo to disable SSL - # revocation checking on Windows in libcurl. Note, though, that rustup, which - # we're using to download Rust here, also uses libcurl as the default backend. - # Unlike Cargo, however, rustup doesn't have a mechanism to disable revocation - # checking. To get rustup working we set `RUSTUP_USE_HYPER` which forces it to - # use the Hyper instead of libcurl backend. Both Hyper and libcurl use - # schannel on Windows but it appears that Hyper configures it slightly - # differently such that revocation checking isn't turned on by default. - # - # [1]: https://curl.haxx.se/mail/lib-2016-03/0202.html - RUSTUP_USE_HYPER: 1 - CARGO_HTTP_CHECK_REVOKE: false - - matrix: - - TARGET: x86_64-pc-windows-msvc - ARCH: amd64 - VS: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat - - TARGET: x86_64-pc-windows-msvc - ARCH: amd64 - VS: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat - - TARGET: i686-pc-windows-msvc - ARCH: x86 - VS: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat - - TARGET: i686-pc-windows-msvc - ARCH: x86 - VS: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat - - TARGET: x86_64-pc-windows-gnu - MSYS_BITS: 64 - - TARGET: i686-pc-windows-gnu - MSYS_BITS: 32 -install: - - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe" - - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" - - if defined VS call "%VS%" %ARCH% - - set PATH=%PATH%;C:\Program Files (x86)\Rust\bin - - if defined MSYS_BITS set PATH=%PATH%;C:\msys64\mingw%MSYS_BITS%\bin - - rustc -V - - cargo -V - -build: false - -test_script: - - cargo test --target %TARGET% - - cargo test --features parallel --target %TARGET% - - cargo test --manifest-path cc-test/Cargo.toml --target %TARGET% - - cargo test --manifest-path cc-test/Cargo.toml --features parallel --target %TARGET% - - cargo test --manifest-path cc-test/Cargo.toml --release --target %TARGET% diff --git a/cc/azure-pipelines.yml b/cc/azure-pipelines.yml new file mode 100644 index 0000000..e816196 --- /dev/null +++ b/cc/azure-pipelines.yml @@ -0,0 +1,101 @@ +trigger: + - master + +jobs: + - job: min_linux + pool: + vmImage: ubuntu-16.04 + displayName: Minimum Rust (Linux) + variables: + TOOLCHAIN: 1.16.0 + steps: + - template: ci/azure-install-rust.yml + - script: cargo build + + - job: min_Windows + pool: + vmImage: vs2017-win2016 + displayName: Minimum Rust (Windows) + variables: + TOOLCHAIN: 1.16.0 + steps: + - template: ci/azure-install-rust.yml + - script: cargo build + + - job: Linux + pool: + vmImage: ubuntu-16.04 + steps: + - template: ci/azure-steps.yml + strategy: + matrix: + x86_64: + TARGET: x86_64-unknown-linux-gnu + i686: + TARGET: i686-unknown-linux-gnu + x86_64-beta: + TARGET: x86_64-unknown-linux-gnu + TOOLCHAIN: beta + x86_64-nightly: + TARGET: x86_64-unknown-linux-gnu + TOOLCHAIN: nightly + + - job: macOS + pool: + vmImage: macos-10.13 + steps: + - template: ci/azure-steps.yml + strategy: + matrix: + x86_64: + TARGET: x86_64-apple-darwin + aarch64-ios: + TARGET: aarch64-apple-ios + NO_RUN: --no-run + + - job: Windows_vs2019 + pool: + vmImage: windows-2019 + steps: + - template: ci/azure-steps.yml + strategy: + matrix: + x86_64-msvc: + TARGET: x86_64-pc-windows-msvc + + - job: Windows_vs2017 + pool: + vmImage: vs2017-win2016 + steps: + - template: ci/azure-steps.yml + strategy: + matrix: + x86_64-msvc: + TARGET: x86_64-pc-windows-msvc + i686-msvc: + TARGET: i686-pc-windows-msvc + x86_64-gnu: + TARGET: x86_64-pc-windows-gnu + i686-gnu: + TARGET: i686-pc-windows-gnu + + - job: Windows_vs2015 + pool: + vmImage: vs2015-win2012r2 + steps: + - template: ci/azure-steps.yml + strategy: + matrix: + x86_64-msvc: + TARGET: x86_64-pc-windows-msvc + i686-msvc: + TARGET: i686-pc-windows-msvc + + - job: docs + steps: + - template: ci/azure-install-rust.yml + - script: cargo doc --no-deps --all-features + - script: curl -LsSf https://git.io/fhJ8n | rustc - && (cd target/doc && ../../rust_out) + condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master')) + env: + GITHUB_DEPLOY_KEY: $(GITHUB_DEPLOY_KEY) diff --git a/cc/ci/azure-install-rust.yml b/cc/ci/azure-install-rust.yml new file mode 100644 index 0000000..118d65e --- /dev/null +++ b/cc/ci/azure-install-rust.yml @@ -0,0 +1,24 @@ +steps: + - bash: | + set -e + toolchain=$TOOLCHAIN + if [ "$toolchain" = "" ]; then + toolchain=stable + fi + curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $toolchain + echo "##vso[task.prependpath]$HOME/.cargo/bin" + displayName: Install rust (unix) + condition: ne( variables['Agent.OS'], 'Windows_NT' ) + + - script: | + IF "%TOOLCHAIN%"=="" (SET TOOLCHAIN=stable-%TARGET%) + curl -sSf -o rustup-init.exe https://win.rustup.rs + rustup-init.exe -y --default-toolchain %TOOLCHAIN% + echo ##vso[task.prependpath]%USERPROFILE%\.cargo\bin + displayName: Install rust (windows) + condition: eq( variables['Agent.OS'], 'Windows_NT' ) + + - script: | + rustc -Vv + cargo -V + displayName: Query rust and cargo versions diff --git a/cc/ci/azure-steps.yml b/cc/ci/azure-steps.yml new file mode 100644 index 0000000..c240ed0 --- /dev/null +++ b/cc/ci/azure-steps.yml @@ -0,0 +1,21 @@ +steps: + - template: azure-install-rust.yml + - bash: rustup target add $TARGET + displayName: Install Rust target + + - bash: sudo apt-get install g++-multilib + condition: eq( variables['Agent.OS'], 'Linux' ) + displayName: Install g++-multilib + + - script: cargo build + displayName: "Normal build" + - bash: cargo test $NO_RUN -- --test-threads 1 + displayName: "Crate tests" + - bash: cargo test $NO_RUN --features parallel -- --test-threads 1 + displayName: "Crate tests (parallel)" + - bash: cargo test $NO_RUN --manifest-path cc-test/Cargo.toml --target $TARGET + displayName: "cc-test tests" + - bash: cargo test $NO_RUN --manifest-path cc-test/Cargo.toml --target $TARGET --features parallel + displayName: "cc-test tests (parallel)" + - bash: cargo test $NO_RUN --manifest-path cc-test/Cargo.toml --target $TARGET --release + displayName: "cc-test tests (release)" diff --git a/cc/src/com.rs b/cc/src/com.rs index 2b16475..9b75d47 100644 --- a/cc/src/com.rs +++ b/cc/src/com.rs @@ -13,12 +13,12 @@ use std::ops::Deref; use std::os::windows::ffi::{OsStrExt, OsStringExt}; use std::ptr::null_mut; use std::slice::from_raw_parts; +use winapi::CoInitializeEx; +use winapi::IUnknown; use winapi::Interface; use winapi::BSTR; -use winapi::CoInitializeEx; use winapi::COINIT_MULTITHREADED; use winapi::{SysFreeString, SysStringLen}; -use winapi::IUnknown; use winapi::{HRESULT, S_FALSE, S_OK}; pub fn initialize() -> Result<(), HRESULT> { diff --git a/cc/src/lib.rs b/cc/src/lib.rs index 5eebd07..9fef147 100644 --- a/cc/src/lib.rs +++ b/cc/src/lib.rs @@ -61,15 +61,15 @@ #[cfg(feature = "parallel")] extern crate rayon; +use std::collections::HashMap; use std::env; use std::ffi::{OsStr, OsString}; use std::fs; +use std::io::{self, BufRead, BufReader, 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}; -use std::collections::HashMap; use std::sync::{Arc, Mutex}; +use std::thread::{self, JoinHandle}; // These modules are all glue to support reading the MSVC version from // the registry and from COM interfaces @@ -891,7 +891,7 @@ impl Build { return Err(Error::new( ErrorKind::IOError, "Getting object file details failed.", - )) + )); } }; @@ -956,7 +956,7 @@ impl Build { fn compile_objects(&self, objs: &[Object]) -> Result<(), Error> { use self::rayon::prelude::*; - if let Ok(amt) = env::var("NUM_JOBS") { + if let Some(amt) = self.getenv("NUM_JOBS") { if let Ok(amt) = amt.parse() { let _ = rayon::ThreadPoolBuilder::new() .num_threads(amt) @@ -1093,7 +1093,86 @@ impl Build { let target = self.get_target()?; let mut cmd = self.get_base_compiler()?; + let envflags = self.envflags(if self.cpp { "CXXFLAGS" } else { "CFLAGS" }); + + // Disable default flag generation via environment variable or when + // certain cross compiling arguments are set + let use_defaults = self.getenv("CRATE_CC_NO_DEFAULTS").is_none(); + + if use_defaults { + self.add_default_flags(&mut cmd, &target, &opt_level)?; + } else { + println!("Info: default compiler flags are disabled"); + } + + for arg in envflags { + cmd.push_cc_arg(arg.into()); + } + + for directory in self.include_directories.iter() { + cmd.args.push(cmd.family.include_flag().into()); + cmd.args.push(directory.into()); + } + + // If warnings and/or extra_warnings haven't been explicitly set, + // then we set them only if the environment doesn't already have + // CFLAGS/CXXFLAGS, since those variables presumably already contain + // the desired set of warnings flags. + + if self + .warnings + .unwrap_or(if self.has_flags() { false } else { true }) + { + let wflags = cmd.family.warnings_flags().into(); + cmd.push_cc_arg(wflags); + } + + if self + .extra_warnings + .unwrap_or(if self.has_flags() { false } else { true }) + { + if let Some(wflags) = cmd.family.extra_warnings_flags() { + cmd.push_cc_arg(wflags.into()); + } + } + + for flag in self.flags.iter() { + cmd.args.push(flag.into()); + } + for flag in self.flags_supported.iter() { + if self.is_flag_supported(flag).unwrap_or(false) { + cmd.push_cc_arg(flag.into()); + } + } + + for &(ref key, ref value) in self.definitions.iter() { + 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 { + cmd.args.push(format!("{}D{}", lead, key).into()); + } + } + + if self.warnings_into_errors { + let warnings_to_errors_flag = cmd.family.warnings_to_errors_flag().into(); + cmd.push_cc_arg(warnings_to_errors_flag); + } + + Ok(cmd) + } + + fn add_default_flags( + &self, + cmd: &mut Tool, + target: &str, + opt_level: &str, + ) -> Result<(), Error> { // Non-target flags // If the flag is not conditioned on target variable, it belongs here :) match cmd.family { @@ -1107,8 +1186,9 @@ impl Build { Some(true) => "/MT", Some(false) => "/MD", None => { - let features = - env::var("CARGO_CFG_TARGET_FEATURE").unwrap_or(String::new()); + let features = self + .getenv("CARGO_CFG_TARGET_FEATURE") + .unwrap_or(String::new()); if features.contains("crt-static") { "/MT" } else { @@ -1120,9 +1200,9 @@ impl Build { match &opt_level[..] { // Msvc uses /O1 to enable all optimizations that minimize code size. - "z" | "s" | "1" => cmd.args.push("/O1".into()), + "z" | "s" | "1" => cmd.push_opt_unless_duplicate("/O1".into()), // -O3 is a valid value for gcc and clang compilers, but not msvc. Cap to /O2. - "2" | "3" => cmd.args.push("/O2".into()), + "2" | "3" => cmd.push_opt_unless_duplicate("/O2".into()), _ => {} } } @@ -1130,9 +1210,9 @@ impl Build { // arm-linux-androideabi-gcc 4.8 shipped with Android NDK does // not support '-Oz' if opt_level == "z" && cmd.family != ToolFamily::Clang { - cmd.args.push("-Os".into()); + cmd.push_opt_unless_duplicate("-Os".into()); } else { - cmd.args.push(format!("-O{}", opt_level).into()); + cmd.push_opt_unless_duplicate(format!("-O{}", opt_level).into()); } if !target.contains("-ios") { @@ -1149,9 +1229,6 @@ impl Build { } } } - for arg in self.envflags(if self.cpp { "CXXFLAGS" } else { "CFLAGS" }) { - cmd.args.push(arg.into()); - } if self.get_debug() { if self.cuda { @@ -1159,7 +1236,7 @@ impl Build { cmd.args.push(nvcc_debug_flag); } let family = cmd.family; - family.add_debug_flags(&mut cmd); + family.add_debug_flags(cmd); } // Target flags @@ -1171,11 +1248,11 @@ impl Build { if clang_cl { if target.contains("x86_64") { cmd.args.push("-m64".into()); - } else if target.contains("i586") { + } else if target.contains("86") { cmd.args.push("-m32".into()); cmd.args.push("/arch:IA32".into()); } else { - cmd.args.push("-m32".into()); + cmd.args.push(format!("--target={}", target).into()); } } else { if target.contains("i586") { @@ -1193,7 +1270,8 @@ impl Build { // the SDK, but for all released versions of the // Windows SDK it is required. if target.contains("arm") || target.contains("thumb") { - cmd.args.push("/D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1".into()); + cmd.args + .push("/D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1".into()); } } ToolFamily::Gnu => { @@ -1206,14 +1284,18 @@ impl Build { } if self.static_flag.is_none() { - let features = env::var("CARGO_CFG_TARGET_FEATURE").unwrap_or(String::new()); + let features = self + .getenv("CARGO_CFG_TARGET_FEATURE") + .unwrap_or(String::new()); if features.contains("crt-static") { cmd.args.push("-static".into()); } } // armv7 targets get to use armv7 instructions - if (target.starts_with("armv7") || target.starts_with("thumbv7")) && target.contains("-linux-") { + if (target.starts_with("armv7") || target.starts_with("thumbv7")) + && target.contains("-linux-") + { cmd.args.push("-march=armv7-a".into()); } @@ -1346,7 +1428,7 @@ impl Build { 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)?; + self.ios_flags(cmd)?; } if self.static_flag.unwrap_or(false) { @@ -1372,62 +1454,17 @@ impl Build { } } - for directory in self.include_directories.iter() { - cmd.args.push(cmd.family.include_flag().into()); - cmd.args.push(directory.into()); - } - - // If warnings and/or extra_warnings haven't been explicitly set, - // then we set them only if the environment doesn't already have - // CFLAGS/CXXFLAGS, since those variables presumably already contain - // the desired set of warnings flags. - - if self.warnings.unwrap_or(if self.has_flags() { false } else { true }) { - let wflags = cmd.family.warnings_flags().into(); - cmd.push_cc_arg(wflags); - } - - if self.extra_warnings.unwrap_or(if self.has_flags() { false } else { true }) { - if let Some(wflags) = cmd.family.extra_warnings_flags() { - cmd.push_cc_arg(wflags.into()); - } - } - - for flag in self.flags.iter() { - cmd.args.push(flag.into()); - } - - for flag in self.flags_supported.iter() { - if self.is_flag_supported(flag).unwrap_or(false) { - cmd.push_cc_arg(flag.into()); - } - } - - for &(ref key, ref value) in self.definitions.iter() { - 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 { - cmd.args.push(format!("{}D{}", lead, key).into()); - } - } - - if self.warnings_into_errors { - let warnings_to_errors_flag = cmd.family.warnings_to_errors_flag().into(); - cmd.push_cc_arg(warnings_to_errors_flag); - } - - Ok(cmd) + Ok(()) } fn has_flags(&self) -> bool { let flags_env_var_name = if self.cpp { "CXXFLAGS" } else { "CFLAGS" }; let flags_env_var_value = self.get_var(flags_env_var_name); - if let Ok(_) = flags_env_var_value { true } else { false } + if let Ok(_) = flags_env_var_value { + true + } else { + false + } } fn msvc_macro_assembler(&self) -> Result<(Command, String), Error> { @@ -1471,12 +1508,7 @@ impl Build { let objects: Vec<_> = objs.iter().map(|obj| obj.dst.clone()).collect(); let target = self.get_target()?; if target.contains("msvc") { - let mut cmd = match self.archiver { - Some(ref s) => self.cmd(s), - None => windows_registry::find(&target, "lib.exe") - .unwrap_or_else(|| self.cmd("lib.exe")), - }; - + let (mut cmd, program) = self.get_ar()?; let mut out = OsString::from("/OUT:"); out.push(dst); cmd.arg(out).arg("/nologo"); @@ -1521,7 +1553,7 @@ impl Build { } else { cmd.args(&objects).args(&self.objects); } - run(&mut cmd, "lib.exe")?; + run(&mut cmd, &program)?; // The Rust compiler will look for libfoo.a and foo.lib, but the // MSVC linker will also be passed foo.lib, so be sure that both @@ -1537,7 +1569,7 @@ impl Build { return Err(Error::new( ErrorKind::IOError, "Could not copy or create a hard-link to the generated lib file.", - )) + )); } }; } else { @@ -1574,7 +1606,7 @@ impl Build { return Err(Error::new( ErrorKind::ArchitectureInvalid, "Unknown architecture for iOS target.", - )) + )); } }; @@ -1593,7 +1625,8 @@ impl Build { }; self.print(&format!("Detecting iOS SDK path for {}", sdk)); - let sdk_path = self.cmd("xcrun") + let sdk_path = self + .cmd("xcrun") .arg("--show-sdk-path") .arg("--sdk") .arg(sdk) @@ -1607,7 +1640,7 @@ impl Build { return Err(Error::new( ErrorKind::IOError, "Unable to determine iOS SDK path.", - )) + )); } }; @@ -1658,7 +1691,8 @@ impl Build { let cl_exe = windows_registry::find_tool(&target, "cl.exe"); - let tool_opt: Option<Tool> = self.env_tool(env) + 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 @@ -1717,6 +1751,10 @@ impl Build { } } else if target.contains("cloudabi") { format!("{}-{}", target, traditional) + } else if target == "wasm32-wasi" || + target == "wasm32-unknown-wasi" || + target == "wasm32-unknown-unknown" { + "clang".to_string() } else if self.get_host()? != target { // CROSS_COMPILE is of the form: "arm-linux-gnueabi-" let cc_env = self.getenv("CROSS_COMPILE"); @@ -1751,6 +1789,12 @@ impl Build { "mipsel-unknown-linux-gnu" => Some("mipsel-linux-gnu"), "mips64-unknown-linux-gnuabi64" => Some("mips64-linux-gnuabi64"), "mips64el-unknown-linux-gnuabi64" => Some("mips64el-linux-gnuabi64"), + "mipsisa32r6-unknown-linux-gnu" => Some("mipsisa32r6-linux-gnu"), + "mipsisa32r6el-unknown-linux-gnu" => Some("mipsisa32r6el-linux-gnu"), + "mipsisa64r6-unknown-linux-gnuabi64" => Some("mipsisa64r6-linux-gnuabi64"), + "mipsisa64r6el-unknown-linux-gnuabi64" => { + Some("mipsisa64r6el-linux-gnuabi64") + } "powerpc-unknown-linux-gnu" => Some("powerpc-linux-gnu"), "powerpc-unknown-linux-gnuspe" => Some("powerpc-linux-gnuspe"), "powerpc-unknown-netbsd" => Some("powerpc--netbsd"), @@ -1818,9 +1862,9 @@ impl Build { // configure for invocations like `clang-cl` we still get a "works out // of the box" experience. if let Some(cl_exe) = cl_exe { - if tool.family == (ToolFamily::Msvc { clang_cl: true }) && - tool.env.len() == 0 && - target.contains("msvc") + if tool.family == (ToolFamily::Msvc { clang_cl: true }) + && tool.env.len() == 0 + && target.contains("msvc") { for &(ref k, ref v) in cl_exe.env.iter() { tool.env.push((k.to_owned(), v.to_owned())); @@ -1836,7 +1880,8 @@ impl Build { let host = self.get_host()?; let kind = if host == target { "HOST" } else { "TARGET" }; let target_u = target.replace("-", "_"); - let res = self.getenv(&format!("{}_{}", var_base, target)) + let res = self + .getenv(&format!("{}_{}", var_base, target)) .or_else(|| self.getenv(&format!("{}_{}", var_base, target_u))) .or_else(|| self.getenv(&format!("{}_{}", kind, var_base))) .or_else(|| self.getenv(var_base)); @@ -1961,9 +2006,10 @@ impl Build { if let Ok(p) = self.get_var("AR") { return Ok((self.cmd(&p), p)); } - let program = if self.get_target()?.contains("android") { - format!("{}-ar", self.get_target()?.replace("armv7", "arm")) - } else if self.get_target()?.contains("emscripten") { + let target = self.get_target()?; + let program = if target.contains("android") { + format!("{}-ar", target.replace("armv7", "arm")) + } else if target.contains("emscripten") { // Windows use bat files so we have to be a bit more specific if cfg!(windows) { let mut cmd = self.cmd("cmd"); @@ -1972,6 +2018,11 @@ impl Build { } "emar".to_string() + } else if target.contains("msvc") { + match windows_registry::find(&target, "lib.exe") { + Some(t) => return Ok((t, "lib.exe".to_string())), + None => "lib.exe".to_string(), + } } else { "ar".to_string() }; @@ -2021,7 +2072,7 @@ impl Build { fn getenv(&self, v: &str) -> Option<String> { let mut cache = self.env_cache.lock().unwrap(); if let Some(val) = cache.get(v) { - return val.clone() + return val.clone(); } let r = env::var(v).ok(); self.print(&format!("{} = {:?}", v, r)); @@ -2062,10 +2113,11 @@ impl Tool { let family = if let Some(fname) = path.file_name().and_then(|p| p.to_str()) { if fname.contains("clang-cl") { ToolFamily::Msvc { clang_cl: true } - } else if fname.contains("cl") && - !fname.contains("cloudabi") && - !fname.contains("uclibc") && - !fname.contains("clang") { + } else if fname.contains("cl") + && !fname.contains("cloudabi") + && !fname.contains("uclibc") + && !fname.contains("clang") + { ToolFamily::Msvc { clang_cl: false } } else if fname.contains("clang") { ToolFamily::Clang @@ -2104,6 +2156,42 @@ impl Tool { self.args.push(flag); } + fn is_duplicate_opt_arg(&self, flag: &OsString) -> bool { + let flag = flag.to_str().unwrap(); + let mut chars = flag.chars(); + + // Only duplicate check compiler flags + if self.is_like_msvc() { + if chars.next() != Some('/') { + return false; + } + } else if self.is_like_gnu() || self.is_like_clang() { + if chars.next() != Some('-') { + return false; + } + } + + // Check for existing optimization flags (-O, /O) + if chars.next() == Some('O') { + return self + .args() + .iter() + .any(|ref a| a.to_str().unwrap_or("").chars().nth(1) == Some('O')); + } + + // TODO Check for existing -m..., -m...=..., /arch:... flags + return false; + } + + /// Don't push optimization arg if it conflicts with existing args + fn push_opt_unless_duplicate(&mut self, flag: OsString) { + if self.is_duplicate_opt_arg(&flag) { + println!("Info: Ignoring duplicate arg {:?}", &flag); + } else { + self.push_cc_arg(flag); + } + } + /// Converts this compiler into a `Command` that's ready to be run. /// /// This is useful for when the compiler needs to be executed and the @@ -2120,7 +2208,11 @@ impl Tool { }; cmd.args(&self.cc_wrapper_args); - let value = self.args.iter().filter(|a| !self.removed_args.contains(a)).collect::<Vec<_>>(); + let value = self + .args + .iter() + .filter(|a| !self.removed_args.contains(a)) + .collect::<Vec<_>>(); cmd.args(&value); for &(ref k, ref v) in self.env.iter() { @@ -2215,7 +2307,7 @@ fn run(cmd: &mut Command, program: &str) -> Result<(), Error> { "Failed to wait on spawned child process, command {:?} with args {:?}.", cmd, program ), - )) + )); } }; print.join().unwrap(); @@ -2253,7 +2345,7 @@ fn run_output(cmd: &mut Command, program: &str) -> Result<Vec<u8>, Error> { "Failed to wait on spawned child process, command {:?} with args {:?}.", cmd, program ), - )) + )); } }; print.join().unwrap(); @@ -2311,7 +2403,8 @@ fn spawn(cmd: &mut Command, program: &str) -> Result<(Child, JoinHandle<()>), Er } fn fail(s: &str) -> ! { - panic!("\n\nInternal error occurred: {}\n\n", s) + let _ = writeln!(io::stderr(), "\n\nerror occurred: {}\n\n", s); + std::process::exit(1); } fn command_add_output_file(cmd: &mut Command, dst: &Path, msvc: bool, is_asm: bool, is_arm: bool) { diff --git a/cc/src/setup_config.rs b/cc/src/setup_config.rs index 7c03d38..56fe114 100644 --- a/cc/src/setup_config.rs +++ b/cc/src/setup_config.rs @@ -11,14 +11,14 @@ use std::ffi::OsString; use std::ptr::null_mut; use winapi::Interface; -use winapi::{LPFILETIME, ULONG}; -use winapi::S_FALSE; use winapi::BSTR; use winapi::LPCOLESTR; -use winapi::{CoCreateInstance, CLSCTX_ALL}; use winapi::LPSAFEARRAY; +use winapi::S_FALSE; +use winapi::{CoCreateInstance, CLSCTX_ALL}; use winapi::{IUnknown, IUnknownVtbl}; use winapi::{HRESULT, LCID, LPCWSTR, PULONGLONG}; +use winapi::{LPFILETIME, ULONG}; use com::{BStr, ComPtr}; @@ -31,7 +31,7 @@ pub const eRegistered: InstanceState = 2; pub const eNoRebootRequired: InstanceState = 4; pub const eComplete: InstanceState = -1i32 as u32; -RIDL!{#[uuid(0xb41463c3, 0x8866, 0x43b5, 0xbc, 0x33, 0x2b, 0x06, 0x76, 0xf7, 0xf4, 0x2e)] +RIDL! {#[uuid(0xb41463c3, 0x8866, 0x43b5, 0xbc, 0x33, 0x2b, 0x06, 0x76, 0xf7, 0xf4, 0x2e)] interface ISetupInstance(ISetupInstanceVtbl): IUnknown(IUnknownVtbl) { fn GetInstanceId( pbstrInstanceId: *mut BSTR, @@ -62,7 +62,7 @@ interface ISetupInstance(ISetupInstanceVtbl): IUnknown(IUnknownVtbl) { ) -> HRESULT, }} -RIDL!{#[uuid(0x89143c9a, 0x05af, 0x49b0, 0xb7, 0x17, 0x72, 0xe2, 0x18, 0xa2, 0x18, 0x5c)] +RIDL! {#[uuid(0x89143c9a, 0x05af, 0x49b0, 0xb7, 0x17, 0x72, 0xe2, 0x18, 0xa2, 0x18, 0x5c)] interface ISetupInstance2(ISetupInstance2Vtbl): ISetupInstance(ISetupInstanceVtbl) { fn GetState( pState: *mut InstanceState, @@ -78,7 +78,7 @@ interface ISetupInstance2(ISetupInstance2Vtbl): ISetupInstance(ISetupInstanceVtb ) -> HRESULT, }} -RIDL!{#[uuid(0x6380bcff, 0x41d3, 0x4b2e, 0x8b, 0x2e, 0xbf, 0x8a, 0x68, 0x10, 0xc8, 0x48)] +RIDL! {#[uuid(0x6380bcff, 0x41d3, 0x4b2e, 0x8b, 0x2e, 0xbf, 0x8a, 0x68, 0x10, 0xc8, 0x48)] interface IEnumSetupInstances(IEnumSetupInstancesVtbl): IUnknown(IUnknownVtbl) { fn Next( celt: ULONG, @@ -94,7 +94,7 @@ interface IEnumSetupInstances(IEnumSetupInstancesVtbl): IUnknown(IUnknownVtbl) { ) -> HRESULT, }} -RIDL!{#[uuid(0x42843719, 0xdb4c, 0x46c2, 0x8e, 0x7c, 0x64, 0xf1, 0x81, 0x6e, 0xfd, 0x5b)] +RIDL! {#[uuid(0x42843719, 0xdb4c, 0x46c2, 0x8e, 0x7c, 0x64, 0xf1, 0x81, 0x6e, 0xfd, 0x5b)] interface ISetupConfiguration(ISetupConfigurationVtbl): IUnknown(IUnknownVtbl) { fn EnumInstances( ppEnumInstances: *mut *mut IEnumSetupInstances, @@ -108,7 +108,7 @@ interface ISetupConfiguration(ISetupConfigurationVtbl): IUnknown(IUnknownVtbl) { ) -> HRESULT, }} -RIDL!{#[uuid(0x26aab78c, 0x4a60, 0x49d6, 0xaf, 0x3b, 0x3c, 0x35, 0xbc, 0x93, 0x36, 0x5d)] +RIDL! {#[uuid(0x26aab78c, 0x4a60, 0x49d6, 0xaf, 0x3b, 0x3c, 0x35, 0xbc, 0x93, 0x36, 0x5d)] interface ISetupConfiguration2(ISetupConfiguration2Vtbl): ISetupConfiguration(ISetupConfigurationVtbl) { fn EnumAllInstances( @@ -116,7 +116,7 @@ interface ISetupConfiguration2(ISetupConfiguration2Vtbl): ) -> HRESULT, }} -RIDL!{#[uuid(0xda8d8a16, 0xb2b6, 0x4487, 0xa2, 0xf1, 0x59, 0x4c, 0xcc, 0xcd, 0x6b, 0xf5)] +RIDL! {#[uuid(0xda8d8a16, 0xb2b6, 0x4487, 0xa2, 0xf1, 0x59, 0x4c, 0xcc, 0xcd, 0x6b, 0xf5)] interface ISetupPackageReference(ISetupPackageReferenceVtbl): IUnknown(IUnknownVtbl) { fn GetId( pbstrId: *mut BSTR, @@ -141,7 +141,7 @@ interface ISetupPackageReference(ISetupPackageReferenceVtbl): IUnknown(IUnknownV ) -> HRESULT, }} -RIDL!{#[uuid(0x42b21b78, 0x6192, 0x463e, 0x87, 0xbf, 0xd5, 0x77, 0x83, 0x8f, 0x1d, 0x5c)] +RIDL! {#[uuid(0x42b21b78, 0x6192, 0x463e, 0x87, 0xbf, 0xd5, 0x77, 0x83, 0x8f, 0x1d, 0x5c)] interface ISetupHelper(ISetupHelperVtbl): IUnknown(IUnknownVtbl) { fn ParseVersion( pwszVersion: LPCOLESTR, @@ -154,7 +154,7 @@ interface ISetupHelper(ISetupHelperVtbl): IUnknown(IUnknownVtbl) { ) -> HRESULT, }} -DEFINE_GUID!{CLSID_SetupConfiguration, +DEFINE_GUID! {CLSID_SetupConfiguration, 0x177f0c4a, 0x1cd3, 0x4de7, 0xa3, 0x2c, 0x71, 0xdb, 0xbb, 0x9f, 0xa3, 0x6d} // Safe wrapper around the COM interfaces diff --git a/cc/src/winapi.rs b/cc/src/winapi.rs index cc83963..c416325 100644 --- a/cc/src/winapi.rs +++ b/cc/src/winapi.rs @@ -115,7 +115,7 @@ macro_rules! DEFINE_GUID { Data3: $w2, Data4: [$b1, $b2, $b3, $b4, $b5, $b6, $b7, $b8], }; - } + }; } macro_rules! RIDL { @@ -207,7 +207,7 @@ macro_rules! RIDL { ); } -RIDL!{#[uuid(0x00000000, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)] +RIDL! {#[uuid(0x00000000, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)] interface IUnknown(IUnknownVtbl) { fn QueryInterface( riid: REFIID, diff --git a/cc/src/windows_registry.rs b/cc/src/windows_registry.rs index ca6b989..af812a7 100644 --- a/cc/src/windows_registry.rs +++ b/cc/src/windows_registry.rs @@ -17,10 +17,12 @@ use Tool; #[cfg(windows)] macro_rules! otry { - ($expr:expr) => (match $expr { - Some(val) => val, - None => return None, - }) + ($expr:expr) => { + match $expr { + Some(val) => val, + None => return None, + } + }; } /// Attempts to find a tool within an MSVC installation using the Windows @@ -103,6 +105,8 @@ pub enum VsVers { Vs14, /// Visual Studio 15 (2017) Vs15, + /// Visual Studio 16 (2019) + Vs16, /// Hidden variant that should not be matched on. Callers that want to /// handle an enumeration of `VsVers` instances should always have a default @@ -128,6 +132,7 @@ pub fn find_vs_version() -> Result<VsVers, String> { match env::var("VisualStudioVersion") { Ok(version) => match &version[..] { + "16.0" => Ok(VsVers::Vs16), "15.0" => Ok(VsVers::Vs15), "14.0" => Ok(VsVers::Vs14), "12.0" => Ok(VsVers::Vs12), @@ -144,7 +149,9 @@ pub fn find_vs_version() -> Result<VsVers, String> { _ => { // Check for the presense of a specific registry key // that indicates visual studio is installed. - if impl_::has_msbuild_version("15.0") { + if impl_::has_msbuild_version("16.0") { + Ok(VsVers::Vs16) + } else if impl_::has_msbuild_version("15.0") { Ok(VsVers::Vs15) } else if impl_::has_msbuild_version("14.0") { Ok(VsVers::Vs14) @@ -166,15 +173,16 @@ pub fn find_vs_version() -> Result<VsVers, String> { #[cfg(windows)] mod impl_ { + use com; + use registry::{RegistryKey, LOCAL_MACHINE}; + use setup_config::{EnumSetupInstances, SetupConfiguration, SetupInstance}; use std::env; use std::ffi::OsString; - use std::mem; - use std::path::{Path, PathBuf}; use std::fs::File; use std::io::Read; - use registry::{RegistryKey, LOCAL_MACHINE}; - use com; - use setup_config::{EnumSetupInstances, SetupConfiguration, SetupInstance}; + use std::mem; + use std::iter; + use std::path::{Path, PathBuf}; use Tool; @@ -210,6 +218,41 @@ mod impl_ { } } + fn vs16_instances() -> Box<Iterator<Item=PathBuf>> { + let instances = if let Some(instances) = vs15_instances() { + instances + } else { + return Box::new(iter::empty()); + }; + Box::new(instances.filter_map(|instance| { + let instance = otry!(instance.ok()); + let installation_name = otry!(instance.installation_name().ok()); + if otry!(installation_name.to_str()).starts_with("VisualStudio/16.") { + Some(PathBuf::from(otry!(instance.installation_path().ok()))) + } else { + None + } + })) + } + + fn find_tool_in_vs16_path(tool: &str, target: &str) -> Option<Tool> { + vs16_instances().filter_map(|path| { + let path = path.join(tool); + if !path.is_file() { + return None; + } + let mut tool = Tool::new(path); + if target.contains("x86_64") { + tool.env.push(("Platform".into(), "X64".into())); + } + Some(tool) + }).next() + } + + fn find_msbuild_vs16(target: &str) -> Option<Tool> { + find_tool_in_vs16_path(r"MSBuild\Current\Bin\MSBuild.exe", target) + } + // In MSVC 15 (2017) MS once again changed the scheme for locating // the tooling. Now we must go through some COM interfaces, which // is super fun for Rust. @@ -251,7 +294,8 @@ mod impl_ { instance .ok() .and_then(|instance| instance.installation_path().ok()) - }).map(|path| PathBuf::from(path).join(tool)) + }) + .map(|path| PathBuf::from(path).join(tool)) .find(|ref path| path.is_file()), None => None, }; @@ -263,7 +307,7 @@ mod impl_ { .ok() .and_then(|key| key.query_str("15.0").ok()) .map(|path| PathBuf::from(path).join(tool)) - .filter(|ref path| path.is_file()); + .and_then(|path| if path.is_file() { Some(path) } else { None }); } path.map(|path| { @@ -319,13 +363,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") + 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") + let host_dylib_path = path + .join("bin") .join(&format!("Host{}", host)) .join(&host.to_lowercase()); let lib_path = path.join("lib").join(&target); @@ -478,17 +524,16 @@ 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() - .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)) @@ -512,12 +557,11 @@ mod impl_ { .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)) @@ -637,7 +681,7 @@ mod impl_ { for subkey in key.iter().filter_map(|k| k.ok()) { let val = subkey .to_str() - .and_then(|s| s.trim_start_matches("v").replace(".", "").parse().ok()); + .and_then(|s| s.trim_left_matches("v").replace(".", "").parse().ok()); let val = match val { Some(s) => s, None => continue, @@ -654,6 +698,10 @@ mod impl_ { pub fn has_msbuild_version(version: &str) -> bool { match version { + "16.0" => { + find_msbuild_vs16("x86_64-pc-windows-msvc").is_some() + || find_msbuild_vs16("i686-pc-windows-msvc").is_some() + } "15.0" => { find_msbuild_vs15("x86_64-pc-windows-msvc").is_some() || find_msbuild_vs15("i686-pc-windows-msvc").is_some() diff --git a/cc/tests/cc_env.rs b/cc/tests/cc_env.rs index f9386d7..e862fea 100644 --- a/cc/tests/cc_env.rs +++ b/cc/tests/cc_env.rs @@ -2,8 +2,8 @@ extern crate cc; extern crate tempdir; use std::env; -use std::path::Path; use std::ffi::OsString; +use std::path::Path; mod support; use support::Test; @@ -63,14 +63,16 @@ fn ccache_env_flags() { .cflags_env() .into_string() .unwrap() - .contains("ccache") == false + .contains("ccache") + == false ); assert!( compiler .cflags_env() .into_string() .unwrap() - .contains(" lol-this-is-not-a-compiler") == false + .contains(" lol-this-is-not-a-compiler") + == false ); env::set_var("CC", ""); diff --git a/cc/tests/support/mod.rs b/cc/tests/support/mod.rs index cae8151..72ca3fa 100644 --- a/cc/tests/support/mod.rs +++ b/cc/tests/support/mod.rs @@ -113,10 +113,12 @@ impl Execution { } pub fn must_have_in_order(&self, before: &str, after: &str) -> &Execution { - let before_position = self.args + let before_position = self + .args .iter() .rposition(|x| OsStr::new(x) == OsStr::new(before)); - let after_position = self.args + let after_position = self + .args .iter() .rposition(|x| OsStr::new(x) == OsStr::new(after)); match (before_position, after_position) { diff --git a/cc/tests/test.rs b/cc/tests/test.rs index 573a99a..5147b77 100644 --- a/cc/tests/test.rs +++ b/cc/tests/test.rs @@ -115,9 +115,7 @@ fn gnu_warnings_overridable() { fn gnu_no_warnings_if_cflags() { env::set_var("CFLAGS", "-Wflag-does-not-exist"); let test = Test::gnu(); - test.gcc() - .file("foo.c") - .compile("foo"); + test.gcc().file("foo.c").compile("foo"); test.cmd(0).must_not_have("-Wall").must_not_have("-Wextra"); env::set_var("CFLAGS", ""); @@ -127,9 +125,7 @@ fn gnu_no_warnings_if_cflags() { fn gnu_no_warnings_if_cxxflags() { env::set_var("CXXFLAGS", "-Wflag-does-not-exist"); let test = Test::gnu(); - test.gcc() - .file("foo.c") - .compile("foo"); + test.gcc().file("foo.c").compile("foo"); test.cmd(0).must_not_have("-Wall").must_not_have("-Wextra"); env::set_var("CXXFLAGS", ""); |