Bug 1716518 - Upgrade cc to v1.0.68. r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D117771
This commit is contained in:
Mike Hommey 2021-06-15 21:00:53 +00:00
parent 3177d195f4
commit cf1e29b146
8 changed files with 624 additions and 190 deletions

4
Cargo.lock generated
View File

@ -506,9 +506,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.0.59"
version = "1.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66120af515773fb005778dc07c261bd201ec8ce50bd6e7144c927753fe013381"
checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787"
dependencies = [
"jobserver",
]

View File

@ -1 +1 @@
{"files":{"Cargo.lock":"bd34a585a35969291c78b96b1f239fa09f1f9dbeee48474989695def1ed64052","Cargo.toml":"cb73923110f764c2a6da0fde98db8f5f7c7194bd56e96e2f302da9ba29cba0a8","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"68fe1bc9f8aab4d8d195e8bc39fe76562742dc392f5c490e5404e01463100277","src/bin/gcc-shim.rs":"b77907875029494b6288841c3aed2e4939ed40708c7f597fca5c9e2570490ca6","src/com.rs":"bcdaf1c28b71e6ef889c6b08d1ce9d7c0761344a677f523bc4c3cd297957f804","src/lib.rs":"96f4782c70e0bd8d9ab7ce3efcc2091d2591c3276c0ed672e2379748bb3930aa","src/registry.rs":"3cc1b5a50879fa751572878ae1d0afbfc960c11665258492754b2c8bccb0ff5d","src/setup_config.rs":"7014103587d3382eac599cb76f016e2609b8140970861b2237982d1db24af265","src/winapi.rs":"ea8b7edbb9ff87957254f465c2334e714c5d6b3b19a8d757c48ea7ca0881c50c","src/windows_registry.rs":"52afe8554f577c87841c48ddee3ba7ffe70a00129e1d6eeb2ec0efb3d2b9aa11","tests/cc_env.rs":"e02b3b0824ad039b47e4462c5ef6dbe6c824c28e7953af94a0f28f7b5158042e","tests/cflags.rs":"57f06eb5ce1557e5b4a032d0c4673e18fbe6f8d26c1deb153126e368b96b41b3","tests/cxxflags.rs":"c2c6c6d8a0d7146616fa1caed26876ee7bc9fcfffd525eb4743593cade5f3371","tests/support/mod.rs":"16274867f23871e9b07614eda4c7344da13d1751fed63d4f633857e40be86394","tests/test.rs":"65c073e0e2cf4aa0433066102788e9f57442719e6f32f5ad5248aa7132bb4597"},"package":"66120af515773fb005778dc07c261bd201ec8ce50bd6e7144c927753fe013381"}
{"files":{"Cargo.lock":"24720bf62cfad67ca24dfc9192a8f1c11a0f262655c087795605f188cee5c5f0","Cargo.toml":"84ef3b052c7b9ba469573df3ee45d89d426f2cd30d350f43198f115b9c5691fc","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"9916275542d23bfa0815b1f48d4546e514739fadc79775500de6a81cf17aac09","src/bin/gcc-shim.rs":"b77907875029494b6288841c3aed2e4939ed40708c7f597fca5c9e2570490ca6","src/com.rs":"bcdaf1c28b71e6ef889c6b08d1ce9d7c0761344a677f523bc4c3cd297957f804","src/lib.rs":"20d349f8528f191a4cf04a5a42daaaa8085c4e00885c78456ebada92dc39b7fb","src/registry.rs":"3cc1b5a50879fa751572878ae1d0afbfc960c11665258492754b2c8bccb0ff5d","src/setup_config.rs":"7014103587d3382eac599cb76f016e2609b8140970861b2237982d1db24af265","src/vs_instances.rs":"2d3f8278a803b0e7052f4eeb1979b29f963dd0143f4458e2cb5f33c4e5f0963b","src/winapi.rs":"ea8b7edbb9ff87957254f465c2334e714c5d6b3b19a8d757c48ea7ca0881c50c","src/windows_registry.rs":"090b5de68e19dab9e1884175dc2a6866f697bd043d6b3a0d4b3836c9d6812569","tests/cc_env.rs":"e02b3b0824ad039b47e4462c5ef6dbe6c824c28e7953af94a0f28f7b5158042e","tests/cflags.rs":"57f06eb5ce1557e5b4a032d0c4673e18fbe6f8d26c1deb153126e368b96b41b3","tests/cxxflags.rs":"c2c6c6d8a0d7146616fa1caed26876ee7bc9fcfffd525eb4743593cade5f3371","tests/support/mod.rs":"16274867f23871e9b07614eda4c7344da13d1751fed63d4f633857e40be86394","tests/test.rs":"65c073e0e2cf4aa0433066102788e9f57442719e6f32f5ad5248aa7132bb4597"},"package":"4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787"}

14
third_party/rust/cc/Cargo.lock generated vendored
View File

@ -2,7 +2,7 @@
# It is not intended for manual editing.
[[package]]
name = "cc"
version = "1.0.59"
version = "1.0.68"
dependencies = [
"jobserver",
"tempfile",
@ -16,9 +16,9 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "getrandom"
version = "0.1.14"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6"
dependencies = [
"cfg-if",
"libc",
@ -36,15 +36,15 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.74"
version = "0.2.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2f02823cf78b754822df5f7f268fb59822e7296276d3e069d8e8cb26a14bd10"
checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
[[package]]
name = "ppv-lite86"
version = "0.2.8"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea"
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "rand"

View File

@ -13,9 +13,9 @@
[package]
edition = "2018"
name = "cc"
version = "1.0.59"
version = "1.0.68"
authors = ["Alex Crichton <alex@alexcrichton.com>"]
exclude = ["/.travis.yml", "/appveyor.yml"]
exclude = ["/.github", "/.travis.yml", "/appveyor.yml"]
description = "A build-time dependency for Cargo build scripts to assist in invoking the native\nC compiler to compile native C code into a static archive to be linked into Rust\ncode.\n"
homepage = "https://github.com/alexcrichton/cc-rs"
documentation = "https://docs.rs/cc"

View File

@ -8,9 +8,6 @@ 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. This crate calls out
to the most relevant compiler for a platform, for example using `cl` on MSVC.
> **Note**: this crate was recently renamed from the `gcc` crate, so if you're
> looking for the `gcc` crate you're in the right spot!
## Using cc-rs
First, you'll want to both add a build script for your crate (`build.rs`) and
@ -36,19 +33,31 @@ fn main() {
And that's it! Running `cargo build` should take care of the rest and your Rust
application will now have the C files `foo.c` and `bar.c` compiled into a file
named libfoo.a. You can call the functions in Rust by declaring functions in
named `libfoo.a`. If the C files contain
```c
void foo_function(void) { ... }
```
and
```c
int32_t bar_function(int32_t x) { ... }
```
you can call them from Rust by declaring them in
your Rust code like so:
```rust,no_run
extern {
fn foo_function();
fn bar_function();
fn bar_function(x: i32) -> i32;
}
pub fn call() {
unsafe {
foo_function();
bar_function();
bar_function(42);
}
}
@ -57,6 +66,8 @@ fn main() {
}
```
See [the Rustonomicon](https://doc.rust-lang.org/nomicon/ffi.html) for more details.
## External configuration via environment variables
To control the programs and flags used for building, the builder can set a
@ -64,7 +75,7 @@ number of different environment variables.
* `CFLAGS` - a series of space separated flags passed to compilers. Note that
individual flags cannot currently contain spaces, so doing
something like: "-L=foo\ bar" is not possible.
something like: `-L=foo\ bar` is not possible.
* `CC` - the actual C compiler used. Note that this is used as an exact
executable name, so (for example) no extra flags can be passed inside
this variable, and the builder must ensure that there aren't any
@ -73,6 +84,7 @@ number of different environment variables.
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.
* `CXX...` - see [C++ Support](#c-support).
Each of these variables can also be supplied with certain prefixes and suffixes,
in the following prioritized order:
@ -89,7 +101,7 @@ 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.
[cargo]: http://doc.crates.io/build-script.html#inputs-to-the-build-script
[cargo]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#inputs-to-the-build-script
## Optional features
@ -116,7 +128,7 @@ is being run. This crate does not ship a C compiler with it. The compiler
required varies per platform, but there are three broad categories:
* Unix platforms require `cc` to be the C compiler. This can be found by
installing cc/clang on Linux distributions and Xcode on OSX, for example.
installing cc/clang on Linux distributions and Xcode on macOS, for example.
* Windows platforms targeting MSVC (e.g. your target triple ends in `-msvc`)
require `cl.exe` to be available and in `PATH`. This is typically found in
standard Visual Studio installations and the `PATH` can be set up by running
@ -126,12 +138,12 @@ required varies per platform, but there are three broad categories:
[MinGW-w64](http://mingw-w64.org) distribution, which is using the
[Win-builds](http://win-builds.org) installation system.
You may also acquire it via
[MSYS2](http://msys2.github.io), as explained [here][msys2-help]. Make sure
[MSYS2](https://www.msys2.org/), as explained [here][msys2-help]. Make sure
to install the appropriate architecture corresponding to your installation of
rustc. GCC from older [MinGW](http://www.mingw.org) project is compatible
only with 32-bit rust compiler.
[msys2-help]: http://github.com/rust-lang/rust#building-on-windows
[msys2-help]: https://github.com/rust-lang/rust#building-on-windows
## C++ support
@ -147,10 +159,25 @@ fn main() {
}
```
When using C++ library compilation switch, the `CXX` and `CXXFLAGS` env
variables are used instead of `CC` and `CFLAGS` and the C++ standard library is
linked to the crate target.
Remember that C++ does name mangling so `extern "C"` might be required to enable rust linker to find your functions.
For C++ libraries, the `CXX` and `CXXFLAGS` environment variables are used instead of `CC` and `CFLAGS`.
The C++ standard library may be linked to the crate target. By default it's `libc++` for macOS, FreeBSD, and OpenBSD, `libc++_shared` for Android, nothing for MSVC, and `libstdc++` for anything else. It can be changed in one of two ways:
1. by using the `cpp_link_stdlib` method on `Build`:
```rust,no-run
fn main() {
cc::Build::new()
.cpp(true)
.file("foo.cpp")
.cpp_link_stdlib("stdc++") // use libstdc++
.compile("libfoo.a");
}
```
2. by setting the `CXXSTDLIB` environment variable.
In particular, for Android you may want to [use `c++_static` if you have at most one shared library](https://developer.android.com/ndk/guides/cpp-support).
Remember that C++ does name mangling so `extern "C"` might be required to enable Rust linker to find your functions.
## CUDA C++ support
@ -182,9 +209,9 @@ fn main() {
This project is licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
http://www.apache.org/licenses/LICENSE-2.0)
https://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
http://opensource.org/licenses/MIT)
https://opensource.org/licenses/MIT)
at your option.

View File

@ -78,10 +78,12 @@ mod winapi;
mod com;
#[cfg(windows)]
mod setup_config;
#[cfg(windows)]
mod vs_instances;
pub mod windows_registry;
/// A builder for compilation of a native static library.
/// A builder for compilation of a native library.
///
/// A `Build` is the main type of the `cc` crate and is used to control all the
/// various configuration options and such of a compile. You'll find more
@ -337,6 +339,35 @@ impl Build {
self
}
/// Add multiple directories to the `-I` include path.
///
/// # Example
///
/// ```no_run
/// # use std::path::Path;
/// # let condition = true;
/// #
/// let mut extra_dir = None;
/// if condition {
/// extra_dir = Some(Path::new("/path/to"));
/// }
///
/// cc::Build::new()
/// .file("src/foo.c")
/// .includes(extra_dir)
/// .compile("foo");
/// ```
pub fn includes<P>(&mut self, dirs: P) -> &mut Build
where
P: IntoIterator,
P::Item: AsRef<Path>,
{
for dir in dirs {
self.include(dir);
}
self
}
/// Specify a `-D` variable with an optional value.
///
/// # Example
@ -655,11 +686,11 @@ impl Build {
/// Set the standard library to link against when compiling with C++
/// support.
///
/// The default value of this property depends on the current target: On
/// OS X `Some("c++")` is used, when compiling for a Visual Studio based
/// target `None` is used and for other targets `Some("stdc++")` is used.
/// See [`get_cpp_link_stdlib`](cc::Build::get_cpp_link_stdlib) documentation
/// for the default value.
/// If the `CXXSTDLIB` environment variable is set, its value will
/// override the default value.
/// override the default value, but not the value explicitly set by calling
/// this function.
///
/// A value of `None` indicates that no automatic linking should happen,
/// otherwise cargo will link against the specified library.
@ -669,6 +700,7 @@ impl Build {
/// Common values:
/// - `stdc++` for GNU
/// - `c++` for Clang
/// - `c++_shared` or `c++_static` for Android
///
/// # Example
///
@ -1384,7 +1416,7 @@ impl Build {
cmd.push_opt_unless_duplicate("-DANDROID".into());
}
if !target.contains("-ios") {
if !target.contains("apple-ios") {
cmd.push_cc_arg("-ffunction-sections".into());
cmd.push_cc_arg("-fdata-sections".into());
}
@ -1423,7 +1455,38 @@ impl Build {
if !(target.contains("android")
&& android_clang_compiler_uses_target_arg_internally(&cmd.path))
{
cmd.args.push(format!("--target={}", target).into());
if target.contains("darwin") {
if let Some(arch) =
map_darwin_target_from_rust_to_compiler_architecture(target)
{
cmd.args
.push(format!("--target={}-apple-darwin", arch).into());
}
} else if target.contains("macabi") {
if let Some(arch) =
map_darwin_target_from_rust_to_compiler_architecture(target)
{
let ios = if arch == "arm64" { "ios" } else { "ios13.0" };
cmd.args
.push(format!("--target={}-apple-{}-macabi", arch, ios).into());
}
} else if target.contains("ios-sim") {
if let Some(arch) =
map_darwin_target_from_rust_to_compiler_architecture(target)
{
let deployment_target = env::var("IPHONEOS_DEPLOYMENT_TARGET")
.unwrap_or_else(|_| "7.0".into());
cmd.args.push(
format!(
"--target={}-apple-ios{}-simulator",
arch, deployment_target
)
.into(),
);
}
} else {
cmd.args.push(format!("--target={}", target).into());
}
}
}
ToolFamily::Msvc { clang_cl } => {
@ -1471,15 +1534,10 @@ impl Build {
}
if target.contains("darwin") {
if target.contains("x86_64") {
if let Some(arch) = map_darwin_target_from_rust_to_compiler_architecture(target)
{
cmd.args.push("-arch".into());
cmd.args.push("x86_64".into());
} else if target.contains("arm64e") {
cmd.args.push("-arch".into());
cmd.args.push("arm64e".into());
} else if target.contains("aarch64") {
cmd.args.push("-arch".into());
cmd.args.push("arm64".into());
cmd.args.push(arch.into());
}
}
@ -1558,7 +1616,7 @@ impl Build {
cmd.args.push("-march=i686".into());
}
// Looks like `musl-gcc` makes is hard for `-m32` to make its way
// Looks like `musl-gcc` makes it 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
@ -1635,14 +1693,17 @@ impl Build {
let mut parts = target.split('-');
if let Some(arch) = parts.next() {
let arch = &arch[5..];
cmd.args.push(("-march=rv".to_owned() + arch).into());
if target.contains("linux") && arch.starts_with("64") {
cmd.args.push(("-march=rv64gc").into());
cmd.args.push("-mabi=lp64d".into());
} else if target.contains("linux") && arch.starts_with("32") {
cmd.args.push(("-march=rv32gc").into());
cmd.args.push("-mabi=ilp32d".into());
} else if arch.starts_with("64") {
cmd.args.push(("-march=rv".to_owned() + arch).into());
cmd.args.push("-mabi=lp64".into());
} else {
cmd.args.push(("-march=rv".to_owned() + arch).into());
cmd.args.push("-mabi=ilp32".into());
}
cmd.args.push("-mcmodel=medany".into());
@ -1651,9 +1712,7 @@ impl Build {
}
}
if target.contains("-ios") {
// FIXME: potential bug. iOS is always compiled with Clang, but Gcc compiler may be
// detected instead.
if target.contains("apple-ios") {
self.ios_flags(cmd)?;
}
@ -1732,66 +1791,28 @@ impl Build {
}
fn assemble(&self, lib_name: &str, dst: &Path, objs: &[Object]) -> Result<(), Error> {
// Delete the destination if it exists as the `ar` tool at least on Unix
// appends to it, which we don't want.
// Delete the destination if it exists as we want to
// create on the first iteration instead of appending.
let _ = fs::remove_file(&dst);
let objects: Vec<_> = objs.iter().map(|obj| obj.dst.clone()).collect();
// Add objects to the archive in limited-length batches. This helps keep
// the length of the command line within a reasonable length to avoid
// blowing system limits on limiting platforms like Windows.
let objs: Vec<_> = objs
.iter()
.map(|o| o.dst.clone())
.chain(self.objects.clone())
.collect();
for chunk in objs.chunks(100) {
self.assemble_progressive(dst, chunk)?;
}
let target = self.get_target()?;
if target.contains("msvc") {
let (mut cmd, program) = self.get_ar()?;
let mut out = OsString::from("-out:");
out.push(dst);
cmd.arg(out).arg("-nologo");
for flag in self.ar_flags.iter() {
cmd.arg(flag);
}
// Similar to https://github.com/rust-lang/rust/pull/47507
// and https://github.com/rust-lang/rust/pull/48548
let estimated_command_line_len = objects
.iter()
.chain(&self.objects)
.map(|a| a.as_os_str().len())
.sum::<usize>();
if estimated_command_line_len > 1024 * 6 {
let mut args = String::from("\u{FEFF}"); // BOM
for arg in objects.iter().chain(&self.objects) {
args.push('"');
for c in arg.to_str().unwrap().chars() {
if c == '"' {
args.push('\\')
}
args.push(c)
}
args.push('"');
args.push('\n');
}
let mut utf16le = Vec::new();
for code_unit in args.encode_utf16() {
utf16le.push(code_unit as u8);
utf16le.push((code_unit >> 8) as u8);
}
let mut args_file = OsString::from(dst);
args_file.push(".args");
fs::File::create(&args_file)
.unwrap()
.write_all(&utf16le)
.unwrap();
let mut args_file_arg = OsString::from("@");
args_file_arg.push(args_file);
cmd.arg(args_file_arg);
} else {
cmd.args(&objects).args(&self.objects);
}
run(&mut cmd, &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
// exist for now.
let lib_dst = dst.with_file_name(format!("{}.lib", lib_name));
let _ = fs::remove_file(&lib_dst);
match fs::hard_link(&dst, &lib_dst).or_else(|_| {
@ -1806,6 +1827,35 @@ impl Build {
));
}
};
} else {
// Non-msvc targets (those using `ar`) need a separate step to add
// the symbol table to archives since our construction command of
// `cq` doesn't add it for us.
let (mut ar, cmd) = self.get_ar()?;
run(ar.arg("s").arg(dst), &cmd)?;
}
Ok(())
}
fn assemble_progressive(&self, dst: &Path, objs: &[PathBuf]) -> Result<(), Error> {
let target = self.get_target()?;
if target.contains("msvc") {
let (mut cmd, program) = self.get_ar()?;
let mut out = OsString::from("-out:");
out.push(dst);
cmd.arg(out).arg("-nologo");
for flag in self.ar_flags.iter() {
cmd.arg(flag);
}
// If the library file already exists, add the libary name
// as an argument to let lib.exe know we are appending the objs.
if dst.exists() {
cmd.arg(dst);
}
cmd.args(objs);
run(&mut cmd, &program)?;
} else {
let (mut ar, cmd) = self.get_ar()?;
@ -1835,10 +1885,7 @@ impl Build {
for flag in self.ar_flags.iter() {
ar.arg(flag);
}
run(
ar.arg("crs").arg(dst).args(&objects).args(&self.objects),
&cmd,
)?;
run(ar.arg("cq").arg(dst).args(objs), &cmd)?;
}
Ok(())
@ -1848,6 +1895,7 @@ impl Build {
enum ArchSpec {
Device(&'static str),
Simulator(&'static str),
Catalyst(&'static str),
}
let target = self.get_target()?;
@ -1857,18 +1905,38 @@ impl Build {
"Unknown architecture for iOS target.",
)
})?;
let arch = match arch {
"arm" | "armv7" | "thumbv7" => ArchSpec::Device("armv7"),
"armv7s" | "thumbv7s" => ArchSpec::Device("armv7s"),
"arm64e" => ArchSpec::Device("arm64e"),
"arm64" | "aarch64" => ArchSpec::Device("arm64"),
"i386" | "i686" => ArchSpec::Simulator("-m32"),
"x86_64" => ArchSpec::Simulator("-m64"),
_ => {
return Err(Error::new(
ErrorKind::ArchitectureInvalid,
"Unknown architecture for iOS target.",
));
let is_catalyst = match target.split('-').nth(3) {
Some(v) => v == "macabi",
None => false,
};
let arch = if is_catalyst {
match arch {
"arm64e" => ArchSpec::Catalyst("arm64e"),
"arm64" | "aarch64" => ArchSpec::Catalyst("arm64"),
"x86_64" => ArchSpec::Catalyst("-m64"),
_ => {
return Err(Error::new(
ErrorKind::ArchitectureInvalid,
"Unknown architecture for iOS target.",
));
}
}
} else {
match arch {
"arm" | "armv7" | "thumbv7" => ArchSpec::Device("armv7"),
"armv7s" | "thumbv7s" => ArchSpec::Device("armv7s"),
"arm64e" => ArchSpec::Device("arm64e"),
"arm64" | "aarch64" => ArchSpec::Device("arm64"),
"i386" | "i686" => ArchSpec::Simulator("-m32"),
"x86_64" => ArchSpec::Simulator("-m64"),
_ => {
return Err(Error::new(
ErrorKind::ArchitectureInvalid,
"Unknown architecture for iOS target.",
));
}
}
};
@ -1889,6 +1957,7 @@ impl Build {
.push(format!("-mios-simulator-version-min={}", min_version).into());
"iphonesimulator"
}
ArchSpec::Catalyst(_) => "macosx",
};
self.print(&format!("Detecting iOS SDK path for {}", sdk));
@ -1992,6 +2061,8 @@ impl Build {
} else {
format!("{}.exe", gnu)
}
} else if target.contains("apple-ios") {
clang.to_string()
} else if target.contains("android") {
autodetect_android_compiler(&target, &host, gnu, clang)
} else if target.contains("cloudabi") {
@ -2002,7 +2073,11 @@ impl Build {
{
"clang".to_string()
} else if target.contains("vxworks") {
"wr-c++".to_string()
if self.cpp {
"wr-c++".to_string()
} else {
"wr-cc".to_string()
}
} else if self.get_host()? != target {
let prefix = self.prefix_for_target(&target);
match prefix {
@ -2040,6 +2115,40 @@ impl Build {
tool
};
// New "standalone" C/C++ cross-compiler executables from recent Android NDK
// are just shell scripts that call main clang binary (from Android NDK) with
// proper `--target` argument.
//
// For example, armv7a-linux-androideabi16-clang passes
// `--target=armv7a-linux-androideabi16` to clang.
//
// As the shell script calls the main clang binary, the command line limit length
// on Windows is restricted to around 8k characters instead of around 32k characters.
// To remove this limit, we call the main clang binary directly and contruct the
// `--target=` ourselves.
if host.contains("windows") && android_clang_compiler_uses_target_arg_internally(&tool.path)
{
if let Some(path) = tool.path.file_name() {
let file_name = path.to_str().unwrap().to_owned();
let (target, clang) = file_name.split_at(file_name.rfind("-").unwrap());
tool.path.set_file_name(clang.trim_start_matches("-"));
tool.path.set_extension("exe");
tool.args.push(format!("--target={}", target).into());
// Additionally, shell scripts for target i686-linux-android versions 16 to 24
// pass the `mstackrealign` option so we do that here as well.
if target.contains("i686-linux-android") {
let (_, version) = target.split_at(target.rfind("d").unwrap() + 1);
if let Ok(version) = version.parse::<u32>() {
if version > 15 && version < 25 {
tool.args.push("-mstackrealign".into());
}
}
}
};
}
// If we found `cl.exe` in our environment, the tool we're returning is
// an MSVC-like tool, *and* no env vars were set then set env vars for
// the tool that we're returning.
@ -2087,9 +2196,8 @@ impl Build {
fn envflags(&self, name: &str) -> Vec<String> {
self.get_var(name)
.unwrap_or(String::new())
.split(|c: char| c.is_whitespace())
.filter(|s| !s.is_empty())
.map(|s| s.to_string())
.split_ascii_whitespace()
.map(|slice| slice.to_string())
.collect()
}
@ -2175,8 +2283,11 @@ impl Build {
))
}
/// Returns the default C++ standard library for the current target: `libc++`
/// for OS X and `libstdc++` for anything else.
/// Returns the C++ standard library:
/// 1. If [cpp_link_stdlib](cc::Build::cpp_link_stdlib) is set, uses its value.
/// 2. Else if the `CXXSTDLIB` environment variable is set, uses its value.
/// 3. Else the default is `libc++` for OS X and BSDs, `libc++_shared` for Android,
/// `None` for MSVC and `libstdc++` for anything else.
fn get_cpp_link_stdlib(&self) -> Result<Option<String>, Error> {
match self.cpp_link_stdlib.clone() {
Some(s) => Ok(s),
@ -2197,6 +2308,8 @@ impl Build {
Ok(Some("c++".to_string()))
} else if target.contains("openbsd") {
Ok(Some("c++".to_string()))
} else if target.contains("android") {
Ok(Some("c++_shared".to_string()))
} else {
Ok(Some("stdc++".to_string()))
}
@ -2231,6 +2344,12 @@ impl Build {
Some(t) => return Ok((t, "lib.exe".to_string())),
None => "lib.exe".to_string(),
}
} else if target.contains("illumos") {
// The default 'ar' on illumos uses a non-standard flags,
// but the OS comes bundled with a GNU-compatible variant.
//
// Use the GNU-variant to match other Unix systems.
"gar".to_string()
} else if self.get_host()? != target {
match self.prefix_for_target(&target) {
Some(p) => {
@ -2286,7 +2405,9 @@ impl Build {
"i686-unknown-linux-musl" => Some("musl"),
"i686-unknown-netbsd" => Some("i486--netbsdelf"),
"mips-unknown-linux-gnu" => Some("mips-linux-gnu"),
"mips-unknown-linux-musl" => Some("mips-linux-musl"),
"mipsel-unknown-linux-gnu" => Some("mipsel-linux-gnu"),
"mipsel-unknown-linux-musl" => Some("mipsel-linux-musl"),
"mips64-unknown-linux-gnuabi64" => Some("mips64-linux-gnuabi64"),
"mips64el-unknown-linux-gnuabi64" => Some("mips64el-linux-gnuabi64"),
"mipsisa32r6-unknown-linux-gnu" => Some("mipsisa32r6-linux-gnu"),
@ -2324,6 +2445,9 @@ impl Build {
"riscv-none-embed",
]),
"riscv64gc-unknown-linux-gnu" => Some("riscv64-linux-gnu"),
"riscv32gc-unknown-linux-gnu" => Some("riscv32-linux-gnu"),
"riscv64gc-unknown-linux-musl" => Some("riscv64-linux-musl"),
"riscv32gc-unknown-linux-musl" => Some("riscv32-linux-musl"),
"s390x-unknown-linux-gnu" => Some("s390x-linux-gnu"),
"sparc-unknown-linux-gnu" => Some("sparc-linux-gnu"),
"sparc64-unknown-linux-gnu" => Some("sparc64-linux-gnu"),
@ -2489,14 +2613,13 @@ impl Build {
return Ok(ret.clone());
}
let sdk_path = self
.cmd("xcrun")
.arg("--show-sdk-path")
.arg("--sdk")
.arg(sdk)
.stderr(Stdio::inherit())
.output()?
.stdout;
let sdk_path = run_output(
self.cmd("xcrun")
.arg("--show-sdk-path")
.arg("--sdk")
.arg(sdk),
"xcrun",
)?;
let sdk_path = match String::from_utf8(sdk_path) {
Ok(p) => p,
@ -2548,11 +2671,7 @@ 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.ends_with("cl") || fname == "cl.exe" {
ToolFamily::Msvc { clang_cl: false }
} else if fname.contains("clang") {
match clang_driver {
@ -2842,7 +2961,7 @@ fn spawn(cmd: &mut Command, program: &str) -> Result<(Child, JoinHandle<()>), Er
}
fn fail(s: &str) -> ! {
let _ = writeln!(io::stderr(), "\n\nerror occurred: {}\n\n", s);
eprintln!("\n\nerror occurred: {}\n\n", s);
std::process::exit(1);
}
@ -2958,3 +3077,16 @@ fn autodetect_android_compiler(target: &str, host: &str, gnu: &str, clang: &str)
clang_compiler
}
}
// Rust and clang/cc don't agree on how to name the target.
fn map_darwin_target_from_rust_to_compiler_architecture(target: &str) -> Option<&'static str> {
if target.contains("x86_64") {
Some("x86_64")
} else if target.contains("arm64e") {
Some("arm64e")
} else if target.contains("aarch64") {
Some("arm64")
} else {
None
}
}

199
third_party/rust/cc/src/vs_instances.rs vendored Normal file
View File

@ -0,0 +1,199 @@
use std::borrow::Cow;
use std::collections::HashMap;
use std::convert::TryFrom;
use std::io::BufRead;
use std::path::PathBuf;
use crate::setup_config::{EnumSetupInstances, SetupInstance};
pub enum VsInstance {
Com(SetupInstance),
Vswhere(VswhereInstance),
}
impl VsInstance {
pub fn installation_name(&self) -> Option<Cow<str>> {
match self {
VsInstance::Com(s) => s
.installation_name()
.ok()
.and_then(|s| s.into_string().ok())
.map(Cow::from),
VsInstance::Vswhere(v) => v.map.get("installationName").map(Cow::from),
}
}
pub fn installation_path(&self) -> Option<PathBuf> {
match self {
VsInstance::Com(s) => s.installation_path().ok().map(PathBuf::from),
VsInstance::Vswhere(v) => v.map.get("installationPath").map(PathBuf::from),
}
}
pub fn installation_version(&self) -> Option<Cow<str>> {
match self {
VsInstance::Com(s) => s
.installation_version()
.ok()
.and_then(|s| s.into_string().ok())
.map(Cow::from),
VsInstance::Vswhere(v) => v.map.get("installationVersion").map(Cow::from),
}
}
}
pub enum VsInstances {
ComBased(EnumSetupInstances),
VswhereBased(VswhereInstance),
}
impl IntoIterator for VsInstances {
type Item = VsInstance;
#[allow(bare_trait_objects)]
type IntoIter = Box<Iterator<Item = Self::Item>>;
fn into_iter(self) -> Self::IntoIter {
match self {
VsInstances::ComBased(e) => {
Box::new(e.into_iter().filter_map(Result::ok).map(VsInstance::Com))
}
VsInstances::VswhereBased(v) => Box::new(std::iter::once(VsInstance::Vswhere(v))),
}
}
}
#[derive(Debug)]
pub struct VswhereInstance {
map: HashMap<String, String>,
}
impl TryFrom<&Vec<u8>> for VswhereInstance {
type Error = &'static str;
fn try_from(output: &Vec<u8>) -> Result<Self, Self::Error> {
let map: HashMap<_, _> = output
.lines()
.filter_map(Result::ok)
.filter_map(|s| {
let mut splitn = s.splitn(2, ": ");
Some((splitn.next()?.to_owned(), splitn.next()?.to_owned()))
})
.collect();
if !map.contains_key("installationName")
|| !map.contains_key("installationPath")
|| !map.contains_key("installationVersion")
{
return Err("required properties not found");
}
Ok(Self { map })
}
}
#[cfg(test)]
mod tests_ {
use std::borrow::Cow;
use std::convert::TryFrom;
use std::path::PathBuf;
#[test]
fn it_parses_vswhere_output_correctly() {
let output = br"instanceId: 58104422
installDate: 21/02/2021 21:50:33
installationName: VisualStudio/16.9.2+31112.23
installationPath: C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools
installationVersion: 16.9.31112.23
productId: Microsoft.VisualStudio.Product.BuildTools
productPath: C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\Common7\Tools\LaunchDevCmd.bat
state: 4294967295
isComplete: 1
isLaunchable: 1
isPrerelease: 0
isRebootRequired: 0
displayName: Visual Studio Build Tools 2019
description: The Visual Studio Build Tools allows you to build native and managed MSBuild-based applications without requiring the Visual Studio IDE. There are options to install the Visual C++ compilers and libraries, MFC, ATL, and C++/CLI support.
channelId: VisualStudio.16.Release
channelUri: https://aka.ms/vs/16/release/channel
enginePath: C:\Program Files (x86)\Microsoft Visual Studio\Installer\resources\app\ServiceHub\Services\Microsoft.VisualStudio.Setup.Service
releaseNotes: https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes-v16.9#16.9.2
thirdPartyNotices: https://go.microsoft.com/fwlink/?LinkId=660909
updateDate: 2021-03-17T21:16:46.5963702Z
catalog_buildBranch: d16.9
catalog_buildVersion: 16.9.31112.23
catalog_id: VisualStudio/16.9.2+31112.23
catalog_localBuild: build-lab
catalog_manifestName: VisualStudio
catalog_manifestType: installer
catalog_productDisplayVersion: 16.9.2
catalog_productLine: Dev16
catalog_productLineVersion: 2019
catalog_productMilestone: RTW
catalog_productMilestoneIsPreRelease: False
catalog_productName: Visual Studio
catalog_productPatchVersion: 2
catalog_productPreReleaseMilestoneSuffix: 1.0
catalog_productSemanticVersion: 16.9.2+31112.23
catalog_requiredEngineVersion: 2.9.3365.38425
properties_campaignId: 156063665.1613940062
properties_channelManifestId: VisualStudio.16.Release/16.9.2+31112.23
properties_nickname:
properties_setupEngineFilePath: C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installershell.exe
"
.to_vec();
let vswhere_instance = super::VswhereInstance::try_from(&output);
assert!(vswhere_instance.is_ok());
let vs_instance = super::VsInstance::Vswhere(vswhere_instance.unwrap());
assert_eq!(
vs_instance.installation_name(),
Some(Cow::from("VisualStudio/16.9.2+31112.23"))
);
assert_eq!(
vs_instance.installation_path(),
Some(PathBuf::from(
r"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools"
))
);
assert_eq!(
vs_instance.installation_version(),
Some(Cow::from("16.9.31112.23"))
);
}
#[test]
fn it_returns_an_error_for_empty_output() {
let output = b"".to_vec();
let vswhere_instance = super::VswhereInstance::try_from(&output);
assert!(vswhere_instance.is_err());
}
#[test]
fn it_returns_an_error_for_output_consisting_of_empty_lines() {
let output = br"
"
.to_vec();
let vswhere_instance = super::VswhereInstance::try_from(&output);
assert!(vswhere_instance.is_err());
}
#[test]
fn it_returns_an_error_for_output_without_required_properties() {
let output = br"instanceId: 58104422
installDate: 21/02/2021 21:50:33
productId: Microsoft.VisualStudio.Product.BuildTools
productPath: C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\Common7\Tools\LaunchDevCmd.bat
"
.to_vec();
let vswhere_instance = super::VswhereInstance::try_from(&output);
assert!(vswhere_instance.is_err());
}
}

View File

@ -47,8 +47,6 @@ pub fn find_tool(_target: &str, _tool: &str) -> Option<Tool> {
/// Documented above.
#[cfg(windows)]
pub fn find_tool(target: &str, tool: &str) -> Option<Tool> {
use std::env;
// This logic is all tailored for MSVC, if we're not that then bail out
// early.
if !target.contains("msvc") {
@ -66,18 +64,6 @@ pub fn find_tool(target: &str, tool: &str) -> Option<Tool> {
return impl_::find_devenv(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::with_family(path.into(), MSVC_FAMILY));
}
// Ok, if we're here, now comes the fun part of the probing. Default shells
// or shells like MSYS aren't really configured to execute `cl.exe` and the
// various compiler tools shipped as part of Visual Studio. Here we try to
@ -85,7 +71,8 @@ pub fn find_tool(target: &str, tool: &str) -> Option<Tool> {
// environment variables like `LIB`, `INCLUDE`, and `PATH` to ensure that
// the tool is actually usable.
return impl_::find_msvc_15plus(tool, target)
return impl_::find_msvc_environment(tool, target)
.or_else(|| impl_::find_msvc_15plus(tool, target))
.or_else(|| impl_::find_msvc_14(tool, target))
.or_else(|| impl_::find_msvc_12(tool, target))
.or_else(|| impl_::find_msvc_11(tool, target));
@ -170,7 +157,9 @@ pub fn find_vs_version() -> Result<VsVers, String> {
mod impl_ {
use crate::com;
use crate::registry::{RegistryKey, LOCAL_MACHINE};
use crate::setup_config::{EnumSetupInstances, SetupConfiguration, SetupInstance};
use crate::setup_config::SetupConfiguration;
use crate::vs_instances::{VsInstances, VswhereInstance};
use std::convert::TryFrom;
use std::env;
use std::ffi::OsString;
use std::fs::File;
@ -178,6 +167,7 @@ mod impl_ {
use std::iter;
use std::mem;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str::FromStr;
use super::MSVC_FAMILY;
@ -215,23 +205,61 @@ mod impl_ {
}
}
/// Checks to see if the `VSCMD_ARG_TGT_ARCH` environment variable matches the
/// given target's arch. Returns `None` if the variable does not exist.
#[cfg(windows)]
fn is_vscmd_target(target: &str) -> Option<bool> {
let vscmd_arch = env::var("VSCMD_ARG_TGT_ARCH").ok()?;
// Convert the Rust target arch to its VS arch equivalent.
let arch = match target.split("-").next() {
Some("x86_64") => "x64",
Some("aarch64") => "arm64",
Some("i686") | Some("i586") => "x86",
Some("thumbv7a") => "arm",
// An unrecognized arch.
_ => return Some(false),
};
Some(vscmd_arch == arch)
}
/// Attempt to find the tool using environment variables set by vcvars.
pub fn find_msvc_environment(target: &str, tool: &str) -> Option<Tool> {
// Early return if the environment doesn't contain a VC install.
if env::var_os("VCINSTALLDIR").is_none() {
return None;
}
let vs_install_dir = env::var_os("VSINSTALLDIR")?.into();
// If the vscmd target differs from the requested target then
// attempt to get the tool using the VS install directory.
if is_vscmd_target(target) == Some(false) {
// We will only get here with versions 15+.
tool_from_vs15plus_instance(tool, target, &vs_install_dir)
} else {
// Fallback to simply using the current environment.
env::var_os("PATH")
.and_then(|path| {
env::split_paths(&path)
.map(|p| p.join(tool))
.find(|p| p.exists())
})
.map(|path| Tool::with_family(path.into(), MSVC_FAMILY))
}
}
#[allow(bare_trait_objects)]
fn vs16_instances() -> Box<Iterator<Item = PathBuf>> {
let instances = if let Some(instances) = vs15plus_instances() {
fn vs16_instances(target: &str) -> Box<Iterator<Item = PathBuf>> {
let instances = if let Some(instances) = vs15plus_instances(target) {
instances
} else {
return Box::new(iter::empty());
};
Box::new(instances.filter_map(|instance| {
let instance = instance.ok()?;
let installation_name = instance.installation_name().ok()?;
if installation_name.to_str()?.starts_with("VisualStudio/16.") {
Some(PathBuf::from(instance.installation_path().ok()?))
} else if installation_name
.to_str()?
.starts_with("VisualStudioPreview/16.")
{
Some(PathBuf::from(instance.installation_path().ok()?))
Box::new(instances.into_iter().filter_map(|instance| {
let installation_name = instance.installation_name()?;
if installation_name.starts_with("VisualStudio/16.") {
Some(instance.installation_path()?)
} else if installation_name.starts_with("VisualStudioPreview/16.") {
Some(instance.installation_path()?)
} else {
None
}
@ -239,7 +267,7 @@ mod impl_ {
}
fn find_tool_in_vs16_path(tool: &str, target: &str) -> Option<Tool> {
vs16_instances()
vs16_instances(target)
.filter_map(|path| {
let path = path.join(tool);
if !path.is_file() {
@ -267,11 +295,62 @@ mod impl_ {
// [online]: https://blogs.msdn.microsoft.com/vcblog/2017/03/06/finding-the-visual-c-compiler-tools-in-visual-studio-2017/
//
// Returns MSVC 15+ instances (15, 16 right now), the order should be consider undefined.
fn vs15plus_instances() -> Option<EnumSetupInstances> {
//
// However, on ARM64 this method doesn't work because VS Installer fails to register COM component on ARM64.
// Hence, as the last resort we try to use vswhere.exe to list available instances.
fn vs15plus_instances(target: &str) -> Option<VsInstances> {
vs15plus_instances_using_com().or_else(|| vs15plus_instances_using_vswhere(target))
}
fn vs15plus_instances_using_com() -> Option<VsInstances> {
com::initialize().ok()?;
let config = SetupConfiguration::new().ok()?;
config.enum_all_instances().ok()
let enum_setup_instances = config.enum_all_instances().ok()?;
Some(VsInstances::ComBased(enum_setup_instances))
}
fn vs15plus_instances_using_vswhere(target: &str) -> Option<VsInstances> {
let program_files_path: PathBuf = env::var("ProgramFiles(x86)")
.or_else(|_| env::var("ProgramFiles"))
.ok()?
.into();
let vswhere_path =
program_files_path.join(r"Microsoft Visual Studio\Installer\vswhere.exe");
if !vswhere_path.exists() {
return None;
}
let arch = target.split('-').next().unwrap();
let tools_arch = match arch {
"i586" | "i686" | "x86_64" => Some("x86.x64"),
"arm" | "thumbv7a" => Some("ARM"),
"aarch64" => Some("ARM64"),
_ => None,
};
let vswhere_output = Command::new(vswhere_path)
.args(&[
"-latest",
"-products",
"*",
"-requires",
&format!("Microsoft.VisualStudio.Component.VC.Tools.{}", tools_arch?),
"-format",
"text",
"-nologo",
])
.stderr(std::process::Stdio::inherit())
.output()
.ok()?;
let vs_instances =
VsInstances::VswhereBased(VswhereInstance::try_from(&vswhere_output.stdout).ok()?);
Some(vs_instances)
}
// Inspired from official microsoft/vswhere ParseVersionString
@ -284,15 +363,16 @@ mod impl_ {
}
pub fn find_msvc_15plus(tool: &str, target: &str) -> Option<Tool> {
let iter = vs15plus_instances()?;
iter.filter_map(|instance| {
let instance = instance.ok()?;
let version = parse_version(instance.installation_version().ok()?.to_str()?)?;
let tool = tool_from_vs15plus_instance(tool, target, &instance)?;
Some((version, tool))
})
.max_by(|(a_version, _), (b_version, _)| a_version.cmp(b_version))
.map(|(_version, tool)| tool)
let iter = vs15plus_instances(target)?;
iter.into_iter()
.filter_map(|instance| {
let version = parse_version(&instance.installation_version()?)?;
let instance_path = instance.installation_path()?;
let tool = tool_from_vs15plus_instance(tool, target, &instance_path)?;
Some((version, tool))
})
.max_by(|(a_version, _), (b_version, _)| a_version.cmp(b_version))
.map(|(_version, tool)| tool)
}
// While the paths to Visual Studio 2017's devenv and MSBuild could
@ -303,14 +383,11 @@ mod impl_ {
//
// [more reliable]: https://github.com/alexcrichton/cc-rs/pull/331
fn find_tool_in_vs15_path(tool: &str, target: &str) -> Option<Tool> {
let mut path = match vs15plus_instances() {
let mut path = match vs15plus_instances(target) {
Some(instances) => instances
.filter_map(|instance| {
instance
.ok()
.and_then(|instance| instance.installation_path().ok())
})
.map(|path| PathBuf::from(path).join(tool))
.into_iter()
.filter_map(|instance| instance.installation_path())
.map(|path| path.join(tool))
.find(|ref path| path.is_file()),
None => None,
};
@ -337,10 +414,10 @@ mod impl_ {
fn tool_from_vs15plus_instance(
tool: &str,
target: &str,
instance: &SetupInstance,
instance_path: &PathBuf,
) -> Option<Tool> {
let (bin_path, host_dylib_path, lib_path, include_path) =
vs15plus_vc_paths(target, instance)?;
vs15plus_vc_paths(target, instance_path)?;
let tool_path = bin_path.join(tool);
if !tool_path.exists() {
return None;
@ -364,9 +441,8 @@ mod impl_ {
fn vs15plus_vc_paths(
target: &str,
instance: &SetupInstance,
instance_path: &PathBuf,
) -> Option<(PathBuf, PathBuf, PathBuf, PathBuf)> {
let instance_path: PathBuf = instance.installation_path().ok()?.into();
let version_path =
instance_path.join(r"VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt");
let mut version_file = File::open(version_path).ok()?;
@ -403,7 +479,7 @@ mod impl_ {
}
fn atl_paths(target: &str, path: &Path) -> Option<(PathBuf, PathBuf)> {
let atl_path = path.join("atlfmc");
let atl_path = path.join("atlmfc");
let sub = lib_subdir(target)?;
if atl_path.exists() {
Some((atl_path.join("lib").join(sub), atl_path.join("include")))