Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

1
vendor/cc/.cargo-checksum.json vendored Normal file
View File

@@ -0,0 +1 @@
{"files":{"CHANGELOG.md":"e9d77b2fb3b8c46112910133ffc46bf40f15317741598bbcc1452ca7ea62d48d","Cargo.lock":"69f61fc6a47d79be6eeed1cee439cd03b401b1fdc444830daed961aa1b57e852","Cargo.toml":"d0de7077bef69967fb29e0ea659631eddc1f13c7d99bc367999c3bda7190226b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"f1ddbede208a5b78333a25dac0a7598e678e9b601a7d99a791069bddaf180dfe","clippy.toml":"aa7850db4350883c8f373bd0d6b4d19bf3b75f13c1c238e24368c109cb52fb1d","src/command_helpers.rs":"99a6f27456bdb0918db0ead6759d2e533894f6d7e7d9ac539b6510b56ecd3565","src/detect_compiler_family.c":"97ca4b021495611e828becea6187add37414186a16dfedd26c2947cbce6e8b2f","src/flags.rs":"6e30d74c10638fe4a70601a967007269b6ac20119d4cbad8d4bd3cd3082884ee","src/lib.rs":"e7bb929d07dc224fa34d33ac969b03e53be4e23598506414d9d72b499d5325e0","src/parallel/async_executor.rs":"4ce24435fff6b6555b43fee042c16bd65d4150d0346567f246b9190d85b45983","src/parallel/command_runner.rs":"1d17d9a037de93b31cc7ee6a914a1e1f6c1ac156cf8619f0014dcbaca6a0b215","src/parallel/job_token.rs":"6cceffcf0f7e7d82d775287e88a4f9a62dc690c321933204f9b531cf40072bf1","src/parallel/mod.rs":"bf156170790d40a76015a8c78cc2a391cbe1b60bb96c1fac1d047d26e342386a","src/parallel/stderr.rs":"840fe8d0ba613c98fa92cbebc374a028a3212ba7dcea58285483223a31acc7eb","src/target.rs":"895e63775f0b180af547b8bf8ef5643b2e70fa5a38989bee88c8be6496813329","src/target/apple.rs":"796e2a4228d2aa7d0e7390936dba6bf6c9b03093c11e7f0cc85b9671af659353","src/target/generated.rs":"a287c74db21c49b0c9c77fa8e43b6b84dc74997512a7acdc58a2df7121120892","src/target/llvm.rs":"6520a55e773fdf52373c402fc1d9376c50c2bf09d66e7a1cfda6fc2dd3156540","src/target/parser.rs":"ba0aa89dad0159603ecad48a00479c15021f434d9eb19feed5d236862c451ff0","src/tempfile.rs":"3d9a4bd894862a345aa230a61ec266f0c68f4ef9713d1d9c727482e61f1ea7c3","src/tool.rs":"eb523590bcfda77fb05b91a58b33d6102a7499c5d4030da4bc64a0919f70bac2","src/utilities.rs":"52b30b24a1c31cdefb105309ee5220cfc9fca76eaf4e6d6509c3e19f431448fe"},"package":"e1354349954c6fc9cb0deab020f27f783cf0b604e8bb754dc4658ecf0d29c35f"}

631
vendor/cc/CHANGELOG.md vendored Normal file
View File

@@ -0,0 +1,631 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [1.2.36](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.35...cc-v1.2.36) - 2025-09-05
### Other
- Regenerate windows sys bindings ([#1548](https://github.com/rust-lang/cc-rs/pull/1548))
- Update windows-bindgen requirement from 0.62 to 0.63 ([#1547](https://github.com/rust-lang/cc-rs/pull/1547))
- Add fn get_ucrt_dir for find-msvc-tools ([#1546](https://github.com/rust-lang/cc-rs/pull/1546))
- Regenerate target info ([#1544](https://github.com/rust-lang/cc-rs/pull/1544))
- fix publish.yml ([#1543](https://github.com/rust-lang/cc-rs/pull/1543))
- Replace periods with underscores as well when parsing env variables ([#1541](https://github.com/rust-lang/cc-rs/pull/1541))
## [1.2.35](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.34...cc-v1.2.35) - 2025-09-01
### Fixed
- fix building for aarch64-apple-visionos-sim on nightly ([#1534](https://github.com/rust-lang/cc-rs/pull/1534))
- fix tests apple_sdkroot_wrong ([#1530](https://github.com/rust-lang/cc-rs/pull/1530))
### Other
- Regenerate target info ([#1536](https://github.com/rust-lang/cc-rs/pull/1536))
- Optimize Tool::to_command ([#1535](https://github.com/rust-lang/cc-rs/pull/1535))
- Extract find-msvc-tools ([#1531](https://github.com/rust-lang/cc-rs/pull/1531))
- Add prefer_clang_cl_over_msvc ([#1516](https://github.com/rust-lang/cc-rs/pull/1516))
## [1.2.34](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.33...cc-v1.2.34) - 2025-08-22
### Fixed
- add `-mcpu=mvp` and `-mmutable-globals` for `wasm32v1-none` ([#1524](https://github.com/rust-lang/cc-rs/pull/1524))
### Other
- Optimize parse_version in find_tools.rs ([#1527](https://github.com/rust-lang/cc-rs/pull/1527))
- Fallback to manually searching for tool dir ([#1526](https://github.com/rust-lang/cc-rs/pull/1526))
## [1.2.33](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.32...cc-v1.2.33) - 2025-08-15
### Other
- Regenerate target info ([#1521](https://github.com/rust-lang/cc-rs/pull/1521))
- [win][arm64ec] Add testing for Arm64EC Windows ([#1512](https://github.com/rust-lang/cc-rs/pull/1512))
- Fix parsing of nigthly targets ([#1517](https://github.com/rust-lang/cc-rs/pull/1517))
- [win][arm64ec] Fix finding assembler and setting is_arm for Arm64EC ([#1511](https://github.com/rust-lang/cc-rs/pull/1511))
## [1.2.32](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.31...cc-v1.2.32) - 2025-08-08
### Fixed
- fix new clippy lint introduced in rust 1.89.0 ([#1509](https://github.com/rust-lang/cc-rs/pull/1509))
### Other
- clarify cargo default if no rerun emitted ([#1508](https://github.com/rust-lang/cc-rs/pull/1508))
- extract compile_objects_sequential ([#1507](https://github.com/rust-lang/cc-rs/pull/1507))
- Windows `find_tools`: add support for finding Clang ([#1506](https://github.com/rust-lang/cc-rs/pull/1506))
- Add m68k-unknown-linux-gnu cross-compile target ([#1505](https://github.com/rust-lang/cc-rs/pull/1505))
## [1.2.31](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.30...cc-v1.2.31) - 2025-08-01
### Other
- Add doc for using sccache/ccache etc ([#1502](https://github.com/rust-lang/cc-rs/pull/1502))
- ability to statically link against C++ stdlib ([#1497](https://github.com/rust-lang/cc-rs/pull/1497))
- Add instructions on using sccache ([#1503](https://github.com/rust-lang/cc-rs/pull/1503))
- Add support for recognizing some architectures supported by GCC, but not LLVM. ([#1500](https://github.com/rust-lang/cc-rs/pull/1500))
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [1.2.39](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.38...cc-v1.2.39) - 2025-09-26
### Other
- Fix cross compilation to xtensa-esp32s3-espidf ([#1569](https://github.com/rust-lang/cc-rs/pull/1569))
- Fix autodetect_wasi_compiler: support non utf-8 path ([#1568](https://github.com/rust-lang/cc-rs/pull/1568))
- Regenerate target info ([#1567](https://github.com/rust-lang/cc-rs/pull/1567))
- Fix rustcflags mapping: require -Clinker-plugin-lto for -flto ([#1564](https://github.com/rust-lang/cc-rs/pull/1564))
- Use `$WASI_SDK_PATH` on WASI targets by default ([#1562](https://github.com/rust-lang/cc-rs/pull/1562))
- Fix atomicity violations in concurrent cache operations ([#1559](https://github.com/rust-lang/cc-rs/pull/1559))
## [1.2.38](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.37...cc-v1.2.38) - 2025-09-19
### Other
- updated the following local packages: find-msvc-tools
## [1.2.37](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.36...cc-v1.2.37) - 2025-09-12
### Other
- Fix errmsg in RustcCodegenFlags::set_rustc_flag ([#1551](https://github.com/rust-lang/cc-rs/pull/1551))
- propagate stack protector to Linux C compilers ([#1550](https://github.com/rust-lang/cc-rs/pull/1550))
- Extract new fn `run_commands_in_parallel` ([#1549](https://github.com/rust-lang/cc-rs/pull/1549))
## [1.2.30](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.29...cc-v1.2.30) - 2025-07-18
### Other
- define _REENTRANT by default ([#1496](https://github.com/rust-lang/cc-rs/pull/1496))
## [1.2.29](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.28...cc-v1.2.29) - 2025-07-05
### Other
- Fix target parsing for powerpc ([#1490](https://github.com/rust-lang/cc-rs/pull/1490))
## [1.2.28](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.27...cc-v1.2.28) - 2025-07-04
### Other
- Recognize `mlibc` environment ([#1488](https://github.com/rust-lang/cc-rs/pull/1488))
- Fix clippy warnings about not using variables in `format!` strings ([#1489](https://github.com/rust-lang/cc-rs/pull/1489))
## [1.2.27](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.26...cc-v1.2.27) - 2025-06-13
### Other
- Regenerate windows sys bindings ([#1485](https://github.com/rust-lang/cc-rs/pull/1485))
- Update windows-bindgen requirement from 0.61 to 0.62 ([#1484](https://github.com/rust-lang/cc-rs/pull/1484))
- Regenerate target info ([#1483](https://github.com/rust-lang/cc-rs/pull/1483))
## [1.2.26](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.25...cc-v1.2.26) - 2025-06-06
### Other
- Also set `SDKROOT` when building apple platforms ([#1475](https://github.com/rust-lang/cc-rs/pull/1475))
- use windows 2022 in CI ([#1479](https://github.com/rust-lang/cc-rs/pull/1479))
- Detect -Wslash-u-filename warning on clang-cl ([#1477](https://github.com/rust-lang/cc-rs/pull/1477))
## [1.2.25](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.24...cc-v1.2.25) - 2025-05-30
### Other
- make `powerp64` use `powerpc64-linux-gnu` prefix ([#1474](https://github.com/rust-lang/cc-rs/pull/1474))
## [1.2.24](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.23...cc-v1.2.24) - 2025-05-23
### Other
- Regenerate windows sys bindings ([#1471](https://github.com/rust-lang/cc-rs/pull/1471))
## [1.2.23](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.22...cc-v1.2.23) - 2025-05-16
### Other
- support "vxworks" and "nto" OSes on `get_base_archiver_variant` ([#1456](https://github.com/rust-lang/cc-rs/pull/1456))
## [1.2.22](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.21...cc-v1.2.22) - 2025-05-09
### Other
- Add `flags` method to `cc::Build` for adding multiple flags ([#1466](https://github.com/rust-lang/cc-rs/pull/1466))
## [1.2.21](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.20...cc-v1.2.21) - 2025-05-02
### Other
- Fix wasm32-unknown-unknown by passing -c ([#1424](https://github.com/rust-lang/cc-rs/pull/1424))
## [1.2.20](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.19...cc-v1.2.20) - 2025-04-25
### Other
- Regenerate target info ([#1461](https://github.com/rust-lang/cc-rs/pull/1461))
- Fix parser.rs on latest rustc nightly ([#1459](https://github.com/rust-lang/cc-rs/pull/1459))
## [1.2.19](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.18...cc-v1.2.19) - 2025-04-11
### Other
- Fix musl compilation: Add musl as a prefix fallback ([#1455](https://github.com/rust-lang/cc-rs/pull/1455))
## [1.2.18](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.17...cc-v1.2.18) - 2025-04-04
### Other
- Regenerate target info ([#1450](https://github.com/rust-lang/cc-rs/pull/1450))
- Use `std::thread::available_parallelism` for determining the default number of jobs ([#1447](https://github.com/rust-lang/cc-rs/pull/1447))
- Fix mips64-openwrt-linux-musl parsing ([#1449](https://github.com/rust-lang/cc-rs/pull/1449))
- Use compiler prefix `x86_64-linux-musl` ([#1443](https://github.com/rust-lang/cc-rs/pull/1443))
## [1.2.17](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.16...cc-v1.2.17) - 2025-03-21
### Other
- Regenerate target info ([#1439](https://github.com/rust-lang/cc-rs/pull/1439))
- Regenerate windows sys bindings ([#1437](https://github.com/rust-lang/cc-rs/pull/1437))
- Fix wasm32-wali-linux-musl target parsing ([#1434](https://github.com/rust-lang/cc-rs/pull/1434))
- Parse `rustc` target names ([#1413](https://github.com/rust-lang/cc-rs/pull/1413))
- Regenerate target info ([#1429](https://github.com/rust-lang/cc-rs/pull/1429))
- Added base support for `wasm32-wali-linux-musl` target ([#1373](https://github.com/rust-lang/cc-rs/pull/1373))
## [1.2.16](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.15...cc-v1.2.16) - 2025-02-28
### Fixed
- force windows compiler to run in `out_dir` to prevent artifacts in cwd (#1415)
### Other
- use `/arch:SSE2` for `x86` target arch (#1425)
- Regenerate windows-sys binding ([#1422](https://github.com/rust-lang/cc-rs/pull/1422))
- Regenerate target info ([#1418](https://github.com/rust-lang/cc-rs/pull/1418))
- Add LIB var when compiling flag_check (#1417)
- Change flag ordering ([#1403](https://github.com/rust-lang/cc-rs/pull/1403))
- Fix archiver detection for musl cross compilation ([#1404](https://github.com/rust-lang/cc-rs/pull/1404))
## [1.2.15](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.14...cc-v1.2.15) - 2025-02-21
### Other
- Regenerate target info ([#1406](https://github.com/rust-lang/cc-rs/pull/1406))
- Always read from all `CFLAGS`-style flags ([#1401](https://github.com/rust-lang/cc-rs/pull/1401))
- Simplify the error output on failed `Command` invocation ([#1397](https://github.com/rust-lang/cc-rs/pull/1397))
## [1.2.14](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.13...cc-v1.2.14) - 2025-02-14
### Other
- Regenerate target info ([#1398](https://github.com/rust-lang/cc-rs/pull/1398))
- Add support for setting `-gdwarf-{version}` based on RUSTFLAGS ([#1395](https://github.com/rust-lang/cc-rs/pull/1395))
- Add support for alternative network stack io-sock on QNX 7.1 aarch64 and x86_64 ([#1312](https://github.com/rust-lang/cc-rs/pull/1312))
## [1.2.13](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.12...cc-v1.2.13) - 2025-02-08
### Other
- Fix cross-compiling for Apple platforms ([#1389](https://github.com/rust-lang/cc-rs/pull/1389))
## [1.2.12](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.11...cc-v1.2.12) - 2025-02-04
### Other
- Split impl Build ([#1382](https://github.com/rust-lang/cc-rs/pull/1382))
- Don't specify both `-target` and `-mtargetos=` on Apple targets ([#1384](https://github.com/rust-lang/cc-rs/pull/1384))
## [1.2.11](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.10...cc-v1.2.11) - 2025-01-31
### Other
- Fix more flag inheritance ([#1380](https://github.com/rust-lang/cc-rs/pull/1380))
- Include wrapper args. in `stdout` family heuristics to restore classifying `clang --driver-mode=cl` as `Msvc { clang_cl: true }` ([#1378](https://github.com/rust-lang/cc-rs/pull/1378))
- Constrain `-Clto` and `-Cembed-bitcode` flag inheritance to be `clang`-only ([#1379](https://github.com/rust-lang/cc-rs/pull/1379))
- Pass deployment target with `-m*-version-min=` ([#1339](https://github.com/rust-lang/cc-rs/pull/1339))
- Regenerate target info ([#1376](https://github.com/rust-lang/cc-rs/pull/1376))
## [1.2.10](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.9...cc-v1.2.10) - 2025-01-17
### Other
- Fix CC_FORCE_DISABLE=0 evaluating to true ([#1371](https://github.com/rust-lang/cc-rs/pull/1371))
- Regenerate target info ([#1369](https://github.com/rust-lang/cc-rs/pull/1369))
- Make hidden lifetimes explicit. ([#1366](https://github.com/rust-lang/cc-rs/pull/1366))
## [1.2.9](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.8...cc-v1.2.9) - 2025-01-12
### Other
- Don't pass inherited PGO flags to GNU compilers (#1363)
- Adjusted zig cc judgment and avoided zigbuild errors([#1360](https://github.com/rust-lang/cc-rs/pull/1360)) ([#1361](https://github.com/rust-lang/cc-rs/pull/1361))
- Fix compilation on macOS using clang and fix compilation using zig-cc ([#1364](https://github.com/rust-lang/cc-rs/pull/1364))
## [1.2.8](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.7...cc-v1.2.8) - 2025-01-11
### Other
- Add `is_like_clang_cl()` getter (#1357)
- Fix clippy error in lib.rs ([#1356](https://github.com/rust-lang/cc-rs/pull/1356))
- Regenerate target info ([#1352](https://github.com/rust-lang/cc-rs/pull/1352))
- Fix compiler family detection issue with clang-cl on macOS ([#1328](https://github.com/rust-lang/cc-rs/pull/1328))
- Update `windows-bindgen` dependency ([#1347](https://github.com/rust-lang/cc-rs/pull/1347))
- Fix clippy warnings ([#1346](https://github.com/rust-lang/cc-rs/pull/1346))
## [1.2.7](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.6...cc-v1.2.7) - 2025-01-03
### Other
- Regenerate target info ([#1342](https://github.com/rust-lang/cc-rs/pull/1342))
- Document new supported architecture names in windows::find
- Make is_flag_supported_inner take an &Tool ([#1337](https://github.com/rust-lang/cc-rs/pull/1337))
- Fix is_flag_supported on msvc ([#1336](https://github.com/rust-lang/cc-rs/pull/1336))
- Allow using Visual Studio target names in `find_tool` ([#1335](https://github.com/rust-lang/cc-rs/pull/1335))
## [1.2.6](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.5...cc-v1.2.6) - 2024-12-27
### Other
- Don't inherit the `/Oy` flag for 64-bit targets ([#1330](https://github.com/rust-lang/cc-rs/pull/1330))
## [1.2.5](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.4...cc-v1.2.5) - 2024-12-19
### Other
- Check linking when testing if compiler flags are supported ([#1322](https://github.com/rust-lang/cc-rs/pull/1322))
## [1.2.4](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.3...cc-v1.2.4) - 2024-12-13
### Other
- Add support for C/C++ compiler for Neutrino QNX: `qcc` ([#1319](https://github.com/rust-lang/cc-rs/pull/1319))
- use -maix64 instead of -m64 ([#1307](https://github.com/rust-lang/cc-rs/pull/1307))
## [1.2.3](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.2...cc-v1.2.3) - 2024-12-06
### Other
- Improve detection of environment when compiling from msbuild or msvc ([#1310](https://github.com/rust-lang/cc-rs/pull/1310))
- Better error message when failing on unknown targets ([#1313](https://github.com/rust-lang/cc-rs/pull/1313))
- Optimize RustcCodegenFlags ([#1305](https://github.com/rust-lang/cc-rs/pull/1305))
## [1.2.2](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.1...cc-v1.2.2) - 2024-11-29
### Other
- Inherit flags from rustc ([#1279](https://github.com/rust-lang/cc-rs/pull/1279))
- Add support for using sccache wrapper with cuda/nvcc ([#1304](https://github.com/rust-lang/cc-rs/pull/1304))
- Fix msvc stdout not shown on error ([#1303](https://github.com/rust-lang/cc-rs/pull/1303))
- Regenerate target info ([#1301](https://github.com/rust-lang/cc-rs/pull/1301))
- Fix compilation of C++ code for armv7-unknown-linux-gnueabihf ([#1298](https://github.com/rust-lang/cc-rs/pull/1298))
- Fetch target info from Cargo even if `Build::target` is manually set ([#1299](https://github.com/rust-lang/cc-rs/pull/1299))
- Fix two files with different extensions having the same object name ([#1295](https://github.com/rust-lang/cc-rs/pull/1295))
- Allow disabling cc's ability to compile via env var CC_FORCE_DISABLE ([#1292](https://github.com/rust-lang/cc-rs/pull/1292))
- Regenerate target info ([#1293](https://github.com/rust-lang/cc-rs/pull/1293))
## [1.2.1](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.0...cc-v1.2.1) - 2024-11-14
### Other
- When invoking `cl -?`, set stdin to null ([#1288](https://github.com/rust-lang/cc-rs/pull/1288))
## [1.2.0](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.37...cc-v1.2.0) - 2024-11-11
### Added
- add i686-pc-windows-gnullvm prefix detection ([#1283](https://github.com/rust-lang/cc-rs/pull/1283))
### Other
- Allow only specifying the architecture ([#1285](https://github.com/rust-lang/cc-rs/pull/1285))
- Fix WASM vs. WASI options ([#1284](https://github.com/rust-lang/cc-rs/pull/1284))
## [1.1.37](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.36...cc-v1.1.37) - 2024-11-08
### Other
- Use relative directory for obj files hash ([#1270](https://github.com/rust-lang/cc-rs/pull/1270))
- Regenerate target info ([#1280](https://github.com/rust-lang/cc-rs/pull/1280))
## [1.1.36](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.35...cc-v1.1.36) - 2024-11-05
### Other
- Fix CUDA build with clang++. ([#1273](https://github.com/rust-lang/cc-rs/pull/1273))
## [1.1.35](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.34...cc-v1.1.35) - 2024-11-04
### Other
- Remove support for FRC ([#1268](https://github.com/rust-lang/cc-rs/pull/1268))
- Do not add -fPIC by default on UEFI targets ([#1263](https://github.com/rust-lang/cc-rs/pull/1263))
- Use -windows-gnu for all UEFI targets ([#1264](https://github.com/rust-lang/cc-rs/pull/1264))
## [1.1.34](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.33...cc-v1.1.34) - 2024-11-02
### Other
- Remove redundant flags ([#1256](https://github.com/rust-lang/cc-rs/pull/1256))
## [1.1.33](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.32...cc-v1.1.33) - 2024-11-02
### Other
- Reduce size of `cc::Build` and size of generated targets ([#1257](https://github.com/rust-lang/cc-rs/pull/1257))
## [1.1.32](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.31...cc-v1.1.32) - 2024-11-02
### Other
- Use `rustc`'s knowledge of LLVM/Clang target triples ([#1252](https://github.com/rust-lang/cc-rs/pull/1252))
- Use Cargo's target information when possible ([#1225](https://github.com/rust-lang/cc-rs/pull/1225))
## [1.1.31](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.30...cc-v1.1.31) - 2024-10-19
### Other
- Add comment explaining why cc does not rebuild on env PATH change ([#1247](https://github.com/rust-lang/cc-rs/pull/1247))
## [1.1.30](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.29...cc-v1.1.30) - 2024-10-11
### Other
- Don't pass -fPIC by default on wasm ([#1245](https://github.com/rust-lang/cc-rs/pull/1245))
## [1.1.29](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.28...cc-v1.1.29) - 2024-10-11
### Other
- Regenerate target info ([#1243](https://github.com/rust-lang/cc-rs/pull/1243))
## [1.1.28](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.27...cc-v1.1.28) - 2024-10-06
### Other
- Environment variables: For one accepting boolean, treat "0", "false" and empty env as false ([#1238](https://github.com/rust-lang/cc-rs/pull/1238))
## [1.1.27](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.26...cc-v1.1.27) - 2024-10-06
### Other
- Revert "Use debug version of MSVC runtime library on debug ([#1231](https://github.com/rust-lang/cc-rs/pull/1231))" ([#1237](https://github.com/rust-lang/cc-rs/pull/1237))
- Disable `CC_ENABLE_DEBUG_OUTPUT` if it is set to "0" ([#1234](https://github.com/rust-lang/cc-rs/pull/1234))
## [1.1.26](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.25...cc-v1.1.26) - 2024-10-06
### Other
- Use debug version of MSVC runtime library on debug ([#1231](https://github.com/rust-lang/cc-rs/pull/1231))
## [1.1.25](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.24...cc-v1.1.25) - 2024-10-05
### Other
- Remove incorrect "lib" prefixes in CXXSTDLIB doc comments ([#1228](https://github.com/rust-lang/cc-rs/pull/1228))
## [1.1.24](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.23...cc-v1.1.24) - 2024-10-01
### Other
- Fix wasm32-wasip1-threads: shared-memory disallowed due to not compiled with 'atomics' or 'bulk-memory' features ([#1221](https://github.com/rust-lang/cc-rs/pull/1221))
- Reduce the need for the host target triple ([#1224](https://github.com/rust-lang/cc-rs/pull/1224))
- Add auto cancellation for CI jobs ([#1222](https://github.com/rust-lang/cc-rs/pull/1222))
## [1.1.23](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.22...cc-v1.1.23) - 2024-09-30
### Other
- Update doc for detecting changes/upgrades of compilers ([#1218](https://github.com/rust-lang/cc-rs/pull/1218))
## [1.1.22](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.21...cc-v1.1.22) - 2024-09-27
### Other
- Don't rerun if PATH changes ([#1215](https://github.com/rust-lang/cc-rs/pull/1215))
## [1.1.21](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.20...cc-v1.1.21) - 2024-09-18
### Other
- disable pic for targets that end in `-none` ([#1212](https://github.com/rust-lang/cc-rs/pull/1212))
## [1.1.20](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.19...cc-v1.1.20) - 2024-09-17
### Other
- Add buildcache as known Rust and C/C++ compiler wrapper ([#1209](https://github.com/rust-lang/cc-rs/pull/1209))
## [1.1.19](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.18...cc-v1.1.19) - 2024-09-15
### Other
- Add support arm64e-apple-darwin ([#1207](https://github.com/rust-lang/cc-rs/pull/1207))
## [1.1.18](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.17...cc-v1.1.18) - 2024-09-07
### Other
- Fixed unsoundness in `StderrForwarder::forward_available` ([#1203](https://github.com/rust-lang/cc-rs/pull/1203))
## [1.1.17](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.16...cc-v1.1.17) - 2024-09-06
### Fixed
- fix finding toolchains when invoked by msbuild ([#1201](https://github.com/rust-lang/cc-rs/pull/1201))
## [1.1.16](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.15...cc-v1.1.16) - 2024-09-04
### Other
- Treat VxWorks wr-cc as a Gnu compiler ([#1198](https://github.com/rust-lang/cc-rs/pull/1198))
## [1.1.15](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.14...cc-v1.1.15) - 2024-08-26
### Other
- Add -mfloat-abi=hard as a default argument when using any arm/thumb-none-eabihf target ([#1194](https://github.com/rust-lang/cc-rs/pull/1194))
## [1.1.14](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.13...cc-v1.1.14) - 2024-08-23
### Other
- allow finding tools from path if VisualStudioDir is set
## [1.1.13](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.12...cc-v1.1.13) - 2024-08-16
### Other
- Fix detect family: should detect emscripten as clang, closes [#1185](https://github.com/rust-lang/cc-rs/pull/1185) ([#1186](https://github.com/rust-lang/cc-rs/pull/1186))
## [1.1.12](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.11...cc-v1.1.12) - 2024-08-15
### Other
- improve docs ([#1183](https://github.com/rust-lang/cc-rs/pull/1183))
## [1.1.11](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.10...cc-v1.1.11) - 2024-08-14
### Other
- Add support for parsing shell encoded `*FLAGS` ([#1181](https://github.com/rust-lang/cc-rs/pull/1181))
- Replace vector of tuples with BTreeMap which already is sorted and free of duplicates ([#1177](https://github.com/rust-lang/cc-rs/pull/1177))
## [1.1.10](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.9...cc-v1.1.10) - 2024-08-11
### Other
- Remap Windows targets triples to their LLVM counterparts ([#1176](https://github.com/rust-lang/cc-rs/pull/1176))
## [1.1.9](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.8...cc-v1.1.9) - 2024-08-11
### Other
- Add custom CC wrapper to the wrapper whitelist ([#1175](https://github.com/rust-lang/cc-rs/pull/1175))
## [1.1.8](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.7...cc-v1.1.8) - 2024-08-06
### Other
- Fix broken link in docs.rs ([#1173](https://github.com/rust-lang/cc-rs/pull/1173))
## [1.1.7](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.6...cc-v1.1.7) - 2024-07-29
### Other
- add `.objects` ([#1166](https://github.com/rust-lang/cc-rs/pull/1166))
## [1.1.6](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.5...cc-v1.1.6) - 2024-07-19
### Other
- Clippy fixes ([#1163](https://github.com/rust-lang/cc-rs/pull/1163))
## [1.1.5](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.4...cc-v1.1.5) - 2024-07-15
### Other
- Fix cyclic compilation: Use vendored once_cell ([#1154](https://github.com/rust-lang/cc-rs/pull/1154))
## [1.1.4](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.3...cc-v1.1.4) - 2024-07-14
### Other
- Support compiling on wasm targets (Supersede [#1068](https://github.com/rust-lang/cc-rs/pull/1068)) ([#1160](https://github.com/rust-lang/cc-rs/pull/1160))
## [1.1.3](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.2...cc-v1.1.3) - 2024-07-14
### Other
- Reduce msrv to 1.63 ([#1158](https://github.com/rust-lang/cc-rs/pull/1158))
- Revert "Use raw-dylib for windows-sys ([#1137](https://github.com/rust-lang/cc-rs/pull/1137))" ([#1157](https://github.com/rust-lang/cc-rs/pull/1157))
- Fix typos ([#1152](https://github.com/rust-lang/cc-rs/pull/1152))
- Fix `doc_lazy_continuation` lints ([#1153](https://github.com/rust-lang/cc-rs/pull/1153))
## [1.1.2](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.1...cc-v1.1.2) - 2024-07-12
### Other
- Add empty `jobserver` feature. ([#1150](https://github.com/rust-lang/cc-rs/pull/1150))
## [1.1.1](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.0...cc-v1.1.1) - 2024-07-12
### Other
- Fix is_flag_supported not respecting emit_rerun_if_env_changed ([#1147](https://github.com/rust-lang/cc-rs/pull/1147)) ([#1148](https://github.com/rust-lang/cc-rs/pull/1148))
## [1.1.0](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.106...cc-v1.1.0) - 2024-07-08
### Added
- add cargo_output to eliminate last vestiges of stdout pollution ([#1141](https://github.com/rust-lang/cc-rs/pull/1141))
## [1.0.106](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.105...cc-v1.0.106) - 2024-07-08
### Other
- Drop support for Visual Studio 12 (2013) ([#1046](https://github.com/rust-lang/cc-rs/pull/1046))
- Use raw-dylib for windows-sys ([#1137](https://github.com/rust-lang/cc-rs/pull/1137))
- Bump msrv to 1.67 ([#1143](https://github.com/rust-lang/cc-rs/pull/1143))
- Bump msrv to 1.65 ([#1140](https://github.com/rust-lang/cc-rs/pull/1140))
- Fix clippy warnings ([#1138](https://github.com/rust-lang/cc-rs/pull/1138))
## [1.0.105](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.104...cc-v1.0.105) - 2024-07-07
### Other
- Regenerate windows sys bindings ([#1132](https://github.com/rust-lang/cc-rs/pull/1132))
- Fix generate-windows-sys-bindings ([#1133](https://github.com/rust-lang/cc-rs/pull/1133))
- Fix gen-windows-sys-binding ([#1130](https://github.com/rust-lang/cc-rs/pull/1130))
- Fix gen-windows-sys-binding ([#1127](https://github.com/rust-lang/cc-rs/pull/1127))
- Update windows-bindgen requirement from 0.57 to 0.58 ([#1123](https://github.com/rust-lang/cc-rs/pull/1123))
## [1.0.104](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.103...cc-v1.0.104) - 2024-07-01
### Other
- Fixed link break about compile-time-requirements ([#1118](https://github.com/rust-lang/cc-rs/pull/1118))
## [1.0.103](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.102...cc-v1.0.103) - 2024-06-30
### Other
- Fix compilation for wasm: env WASI_SYSROOT should be optional ([#1114](https://github.com/rust-lang/cc-rs/pull/1114))
## [1.0.102](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.101...cc-v1.0.102) - 2024-06-29
### Other
- Fix invalid wasi targets compatibility ([#1105](https://github.com/rust-lang/cc-rs/pull/1105))
- Speedup regenerate-target-info and regenerate-windows-sys ([#1110](https://github.com/rust-lang/cc-rs/pull/1110))
## [1.0.101](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.100...cc-v1.0.101) - 2024-06-25
### Other
- Use `Build::getenv` instead of `env::var*` in anywhere that makes sense ([#1103](https://github.com/rust-lang/cc-rs/pull/1103))
## [1.0.100](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.99...cc-v1.0.100) - 2024-06-23
### Other
- Update publish.yml to use release-plz ([#1101](https://github.com/rust-lang/cc-rs/pull/1101))
- Accept `OsStr` instead of `str` for flags ([#1100](https://github.com/rust-lang/cc-rs/pull/1100))
- Use `dep:` syntax to avoid implicit features. ([#1099](https://github.com/rust-lang/cc-rs/pull/1099))
- Minor clippy fixes. ([#1098](https://github.com/rust-lang/cc-rs/pull/1098))
- Fix WASI compilation for C++ ([#1083](https://github.com/rust-lang/cc-rs/pull/1083))
- Regenerate windows sys bindings ([#1096](https://github.com/rust-lang/cc-rs/pull/1096))
- Rename regenerate-windows-sys to regenerate-windows-sys.yml ([#1095](https://github.com/rust-lang/cc-rs/pull/1095))
- Create regenerate-windows-sys.yml ([#1094](https://github.com/rust-lang/cc-rs/pull/1094))
- Update windows-bindgen requirement from 0.56 to 0.57 ([#1091](https://github.com/rust-lang/cc-rs/pull/1091))
- Eagerly close tempfile to fix [#1082](https://github.com/rust-lang/cc-rs/pull/1082) ([#1087](https://github.com/rust-lang/cc-rs/pull/1087))
- Output msvc.exe in the output directory ([#1090](https://github.com/rust-lang/cc-rs/pull/1090))
- Fix clippy warnings on Windows ([#1088](https://github.com/rust-lang/cc-rs/pull/1088))
- Don't try to free DLL on drop ([#1089](https://github.com/rust-lang/cc-rs/pull/1089))
- Fix panic safety issue in StderrForwarder ([#1079](https://github.com/rust-lang/cc-rs/pull/1079))

165
vendor/cc/Cargo.lock generated vendored Normal file
View File

@@ -0,0 +1,165 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "bitflags"
version = "2.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394"
[[package]]
name = "cc"
version = "1.2.39"
dependencies = [
"find-msvc-tools",
"jobserver",
"libc",
"shlex",
"tempfile",
]
[[package]]
name = "cfg-if"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
[[package]]
name = "errno"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "fastrand"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
[[package]]
name = "find-msvc-tools"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959"
[[package]]
name = "getrandom"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
dependencies = [
"cfg-if",
"libc",
"r-efi",
"wasi",
]
[[package]]
name = "jobserver"
version = "0.1.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
dependencies = [
"getrandom",
"libc",
]
[[package]]
name = "libc"
version = "0.2.176"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174"
[[package]]
name = "linux-raw-sys"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "r-efi"
version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
[[package]]
name = "rustix"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "tempfile"
version = "3.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16"
dependencies = [
"fastrand",
"getrandom",
"once_cell",
"rustix",
"windows-sys",
]
[[package]]
name = "wasi"
version = "0.14.7+wasi-0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c"
dependencies = [
"wasip2",
]
[[package]]
name = "wasip2"
version = "1.0.1+wasi-0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
dependencies = [
"wit-bindgen",
]
[[package]]
name = "windows-link"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
[[package]]
name = "windows-sys"
version = "0.61.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f109e41dd4a3c848907eb83d5a42ea98b3769495597450cf6d153507b166f0f"
dependencies = [
"windows-link",
]
[[package]]
name = "wit-bindgen"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"

75
vendor/cc/Cargo.toml vendored Normal file
View File

@@ -0,0 +1,75 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
rust-version = "1.63"
name = "cc"
version = "1.2.39"
authors = ["Alex Crichton <alex@alexcrichton.com>"]
build = false
exclude = [
"/.github",
"tests",
"src/bin",
]
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
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
code.
"""
homepage = "https://github.com/rust-lang/cc-rs"
documentation = "https://docs.rs/cc"
readme = "README.md"
keywords = ["build-dependencies"]
categories = ["development-tools::build-utils"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-lang/cc-rs"
[features]
jobserver = []
parallel = [
"dep:libc",
"dep:jobserver",
]
[lib]
name = "cc"
path = "src/lib.rs"
[dependencies.find-msvc-tools]
version = "0.1.2"
[dependencies.jobserver]
version = "0.1.30"
optional = true
default-features = false
[dependencies.shlex]
version = "1.3.0"
[dev-dependencies.tempfile]
version = "3"
[target."cfg(unix)".dependencies.libc]
version = "0.2.62"
optional = true
default-features = false
[lints.rust.unexpected_cfgs]
level = "allow"
priority = 0
check-cfg = ["cfg(disable_clang_cl_tests)"]

201
vendor/cc/LICENSE-APACHE vendored Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

25
vendor/cc/LICENSE-MIT vendored Normal file
View File

@@ -0,0 +1,25 @@
Copyright (c) 2014 Alex Crichton
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

27
vendor/cc/README.md vendored Normal file
View File

@@ -0,0 +1,27 @@
# cc-rs
A library for [Cargo build scripts](https://doc.rust-lang.org/cargo/reference/build-scripts.html)
to compile a set of C/C++/assembly/CUDA files into a static archive for Cargo
to link into the crate being built. This crate does not compile code itself;
it calls out to the default compiler for the platform. This crate will
automatically detect situations such as cross compilation and
various environment variables and will build code appropriately.
Refer to the [documentation](https://docs.rs/cc) for detailed usage instructions.
## License
This project is licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
https://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
https://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in cc-rs by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.

5
vendor/cc/clippy.toml vendored Normal file
View File

@@ -0,0 +1,5 @@
disallowed-methods = [
{ path = "std::env::var_os", reason = "Please use Build::getenv" },
{ path = "std::env::var", reason = "Please use Build::getenv" },
]
doc-valid-idents = ["AppleClang", "OpenBSD", ".."]

430
vendor/cc/src/command_helpers.rs vendored Normal file
View File

@@ -0,0 +1,430 @@
//! Miscellaneous helpers for running commands
use std::{
borrow::Cow,
collections::hash_map,
ffi::OsString,
fmt::Display,
fs,
hash::Hasher,
io::{self, Read, Write},
path::Path,
process::{Child, ChildStderr, Command, Stdio},
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
};
use crate::{Error, ErrorKind, Object};
#[derive(Clone, Debug)]
pub(crate) struct CargoOutput {
pub(crate) metadata: bool,
pub(crate) warnings: bool,
pub(crate) debug: bool,
pub(crate) output: OutputKind,
checked_dbg_var: Arc<AtomicBool>,
}
/// Different strategies for handling compiler output (to stdout)
#[derive(Clone, Debug)]
pub(crate) enum OutputKind {
/// Forward the output to this process' stdout ([`Stdio::inherit()`])
Forward,
/// Discard the output ([`Stdio::null()`])
Discard,
/// Capture the result (`[Stdio::piped()`])
Capture,
}
impl CargoOutput {
pub(crate) fn new() -> Self {
#[allow(clippy::disallowed_methods)]
Self {
metadata: true,
warnings: true,
output: OutputKind::Forward,
debug: match std::env::var_os("CC_ENABLE_DEBUG_OUTPUT") {
Some(v) => v != "0" && v != "false" && !v.is_empty(),
None => false,
},
checked_dbg_var: Arc::new(AtomicBool::new(false)),
}
}
pub(crate) fn print_metadata(&self, s: &dyn Display) {
if self.metadata {
println!("{s}");
}
}
pub(crate) fn print_warning(&self, arg: &dyn Display) {
if self.warnings {
println!("cargo:warning={arg}");
}
}
pub(crate) fn print_debug(&self, arg: &dyn Display) {
if self.metadata
&& self
.checked_dbg_var
.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
.is_ok()
{
println!("cargo:rerun-if-env-changed=CC_ENABLE_DEBUG_OUTPUT");
}
if self.debug {
println!("{arg}");
}
}
fn stdio_for_warnings(&self) -> Stdio {
if self.warnings {
Stdio::piped()
} else {
Stdio::null()
}
}
fn stdio_for_output(&self) -> Stdio {
match self.output {
OutputKind::Capture => Stdio::piped(),
OutputKind::Forward => Stdio::inherit(),
OutputKind::Discard => Stdio::null(),
}
}
}
pub(crate) struct StderrForwarder {
inner: Option<(ChildStderr, Vec<u8>)>,
#[cfg(feature = "parallel")]
is_non_blocking: bool,
#[cfg(feature = "parallel")]
bytes_available_failed: bool,
/// number of bytes buffered in inner
bytes_buffered: usize,
}
const MIN_BUFFER_CAPACITY: usize = 100;
impl StderrForwarder {
pub(crate) fn new(child: &mut Child) -> Self {
Self {
inner: child
.stderr
.take()
.map(|stderr| (stderr, Vec::with_capacity(MIN_BUFFER_CAPACITY))),
bytes_buffered: 0,
#[cfg(feature = "parallel")]
is_non_blocking: false,
#[cfg(feature = "parallel")]
bytes_available_failed: false,
}
}
pub(crate) fn forward_available(&mut self) -> bool {
if let Some((stderr, buffer)) = self.inner.as_mut() {
loop {
// For non-blocking we check to see if there is data available, so we should try to
// read at least that much. For blocking, always read at least the minimum amount.
#[cfg(not(feature = "parallel"))]
let to_reserve = MIN_BUFFER_CAPACITY;
#[cfg(feature = "parallel")]
let to_reserve = if self.is_non_blocking && !self.bytes_available_failed {
match crate::parallel::stderr::bytes_available(stderr) {
#[cfg(windows)]
Ok(0) => break false,
#[cfg(unix)]
Ok(0) => {
// On Unix, depending on the implementation, we may sometimes get 0 in a
// loop (either there is data available or the pipe is broken), so
// continue with the non-blocking read anyway.
MIN_BUFFER_CAPACITY
}
#[cfg(windows)]
Err(_) => {
// On Windows, if we get an error then the pipe is broken, so flush
// the buffer and bail.
if !buffer.is_empty() {
write_warning(&buffer[..]);
}
self.inner = None;
break true;
}
#[cfg(unix)]
Err(_) => {
// On Unix, depending on the implementation, we may get spurious
// errors so make a note not to use bytes_available again and try
// the non-blocking read anyway.
self.bytes_available_failed = true;
MIN_BUFFER_CAPACITY
}
#[cfg(target_family = "wasm")]
Err(_) => panic!("bytes_available should always succeed on wasm"),
Ok(bytes_available) => MIN_BUFFER_CAPACITY.max(bytes_available),
}
} else {
MIN_BUFFER_CAPACITY
};
if self.bytes_buffered + to_reserve > buffer.len() {
buffer.resize(self.bytes_buffered + to_reserve, 0);
}
match stderr.read(&mut buffer[self.bytes_buffered..]) {
Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => {
// No data currently, yield back.
break false;
}
Err(err) if err.kind() == std::io::ErrorKind::Interrupted => {
// Interrupted, try again.
continue;
}
Ok(bytes_read) if bytes_read != 0 => {
self.bytes_buffered += bytes_read;
let mut consumed = 0;
for line in buffer[..self.bytes_buffered].split_inclusive(|&b| b == b'\n') {
// Only forward complete lines, leave the rest in the buffer.
if let Some((b'\n', line)) = line.split_last() {
consumed += line.len() + 1;
write_warning(line);
}
}
if consumed > 0 && consumed < self.bytes_buffered {
// Remove the consumed bytes from buffer
buffer.copy_within(consumed.., 0);
}
self.bytes_buffered -= consumed;
}
res => {
// End of stream: flush remaining data and bail.
if self.bytes_buffered > 0 {
write_warning(&buffer[..self.bytes_buffered]);
}
if let Err(err) = res {
write_warning(
format!("Failed to read from child stderr: {err}").as_bytes(),
);
}
self.inner.take();
break true;
}
}
}
} else {
true
}
}
#[cfg(feature = "parallel")]
pub(crate) fn set_non_blocking(&mut self) -> Result<(), Error> {
assert!(!self.is_non_blocking);
#[cfg(unix)]
if let Some((stderr, _)) = self.inner.as_ref() {
crate::parallel::stderr::set_non_blocking(stderr)?;
}
self.is_non_blocking = true;
Ok(())
}
#[cfg(feature = "parallel")]
pub(crate) fn forward_all(&mut self) {
while !self.forward_available() {}
}
#[cfg(not(feature = "parallel"))]
fn forward_all(&mut self) {
let forward_result = self.forward_available();
assert!(forward_result, "Should have consumed all data");
}
}
fn write_warning(line: &[u8]) {
let stdout = io::stdout();
let mut stdout = stdout.lock();
stdout.write_all(b"cargo:warning=").unwrap();
stdout.write_all(line).unwrap();
stdout.write_all(b"\n").unwrap();
}
fn wait_on_child(
cmd: &Command,
child: &mut Child,
cargo_output: &CargoOutput,
) -> Result<(), Error> {
StderrForwarder::new(child).forward_all();
let status = match child.wait() {
Ok(s) => s,
Err(e) => {
return Err(Error::new(
ErrorKind::ToolExecError,
format!("failed to wait on spawned child process `{cmd:?}`: {e}"),
));
}
};
cargo_output.print_debug(&status);
if status.success() {
Ok(())
} else {
Err(Error::new(
ErrorKind::ToolExecError,
format!("command did not execute successfully (status code {status}): {cmd:?}"),
))
}
}
/// Find the destination object path for each file in the input source files,
/// and store them in the output Object.
pub(crate) fn objects_from_files(files: &[Arc<Path>], dst: &Path) -> Result<Vec<Object>, Error> {
let mut objects = Vec::with_capacity(files.len());
for file in files {
let basename = file
.file_name()
.ok_or_else(|| {
Error::new(
ErrorKind::InvalidArgument,
"No file_name for object file path!",
)
})?
.to_string_lossy();
let dirname = file
.parent()
.ok_or_else(|| {
Error::new(
ErrorKind::InvalidArgument,
"No parent for object file path!",
)
})?
.to_string_lossy();
// Hash the dirname. This should prevent conflicts if we have multiple
// object files with the same filename in different subfolders.
let mut hasher = hash_map::DefaultHasher::new();
// Make the dirname relative (if possible) to avoid full system paths influencing the sha
// and making the output system-dependent
//
// NOTE: Here we allow using std::env::var (instead of Build::getenv) because
// CARGO_* variables always trigger a rebuild when changed
#[allow(clippy::disallowed_methods)]
let dirname = if let Some(root) = std::env::var_os("CARGO_MANIFEST_DIR") {
let root = root.to_string_lossy();
Cow::Borrowed(dirname.strip_prefix(&*root).unwrap_or(&dirname))
} else {
dirname
};
hasher.write(dirname.as_bytes());
if let Some(extension) = file.extension() {
hasher.write(extension.to_string_lossy().as_bytes());
}
let obj = dst
.join(format!("{:016x}-{}", hasher.finish(), basename))
.with_extension("o");
match obj.parent() {
Some(s) => fs::create_dir_all(s)?,
None => {
return Err(Error::new(
ErrorKind::InvalidArgument,
"dst is an invalid path with no parent",
));
}
};
objects.push(Object::new(file.to_path_buf(), obj));
}
Ok(objects)
}
pub(crate) fn run(cmd: &mut Command, cargo_output: &CargoOutput) -> Result<(), Error> {
let mut child = spawn(cmd, cargo_output)?;
wait_on_child(cmd, &mut child, cargo_output)
}
pub(crate) fn run_output(cmd: &mut Command, cargo_output: &CargoOutput) -> Result<Vec<u8>, Error> {
// We specifically need the output to be captured, so override default
let mut captured_cargo_output = cargo_output.clone();
captured_cargo_output.output = OutputKind::Capture;
let mut child = spawn(cmd, &captured_cargo_output)?;
let mut stdout = vec![];
child
.stdout
.take()
.unwrap()
.read_to_end(&mut stdout)
.unwrap();
// Don't care about this output, use the normal settings
wait_on_child(cmd, &mut child, cargo_output)?;
Ok(stdout)
}
pub(crate) fn spawn(cmd: &mut Command, cargo_output: &CargoOutput) -> Result<Child, Error> {
struct ResetStderr<'cmd>(&'cmd mut Command);
impl Drop for ResetStderr<'_> {
fn drop(&mut self) {
// Reset stderr to default to release pipe_writer so that print thread will
// not block forever.
self.0.stderr(Stdio::inherit());
}
}
cargo_output.print_debug(&format_args!("running: {cmd:?}"));
let cmd = ResetStderr(cmd);
let child = cmd
.0
.stderr(cargo_output.stdio_for_warnings())
.stdout(cargo_output.stdio_for_output())
.spawn();
match child {
Ok(child) => Ok(child),
Err(ref e) if e.kind() == io::ErrorKind::NotFound => {
let extra = if cfg!(windows) {
" (see https://docs.rs/cc/latest/cc/#compile-time-requirements for help)"
} else {
""
};
Err(Error::new(
ErrorKind::ToolNotFound,
format!("failed to find tool {:?}: {e}{extra}", cmd.0.get_program()),
))
}
Err(e) => Err(Error::new(
ErrorKind::ToolExecError,
format!("command `{:?}` failed to start: {e}", cmd.0),
)),
}
}
pub(crate) struct CmdAddOutputFileArgs {
pub(crate) cuda: bool,
pub(crate) is_assembler_msvc: bool,
pub(crate) msvc: bool,
pub(crate) clang: bool,
pub(crate) gnu: bool,
pub(crate) is_asm: bool,
pub(crate) is_arm: bool,
}
pub(crate) fn command_add_output_file(cmd: &mut Command, dst: &Path, args: CmdAddOutputFileArgs) {
if args.is_assembler_msvc
|| !(!args.msvc || args.clang || args.gnu || args.cuda || (args.is_asm && args.is_arm))
{
let mut s = OsString::from("-Fo");
s.push(dst);
cmd.arg(s);
} else {
cmd.arg("-o").arg(dst);
}
}

15
vendor/cc/src/detect_compiler_family.c vendored Normal file
View File

@@ -0,0 +1,15 @@
#ifdef __clang__
#pragma message "clang"
#endif
#ifdef __GNUC__
#pragma message "gcc"
#endif
#ifdef __EMSCRIPTEN__
#pragma message "emscripten"
#endif
#ifdef __VXWORKS__
#pragma message "VxWorks"
#endif

561
vendor/cc/src/flags.rs vendored Normal file
View File

@@ -0,0 +1,561 @@
use crate::target::TargetInfo;
use crate::{Build, Error, ErrorKind, Tool, ToolFamily};
use std::borrow::Cow;
use std::ffi::OsString;
#[derive(Debug, PartialEq, Default)]
pub(crate) struct RustcCodegenFlags<'a> {
branch_protection: Option<&'a str>,
code_model: Option<&'a str>,
no_vectorize_loops: bool,
no_vectorize_slp: bool,
profile_generate: Option<&'a str>,
profile_use: Option<&'a str>,
control_flow_guard: Option<&'a str>,
lto: Option<&'a str>,
relocation_model: Option<&'a str>,
embed_bitcode: Option<bool>,
force_frame_pointers: Option<bool>,
no_redzone: Option<bool>,
soft_float: Option<bool>,
dwarf_version: Option<u32>,
stack_protector: Option<&'a str>,
linker_plugin_lto: Option<bool>,
}
impl<'this> RustcCodegenFlags<'this> {
// Parse flags obtained from CARGO_ENCODED_RUSTFLAGS
pub(crate) fn parse(rustflags_env: &'this str) -> Result<Self, Error> {
fn is_flag_prefix(flag: &str) -> bool {
[
"-Z",
"-C",
"--codegen",
"-L",
"-l",
"-o",
"-W",
"--warn",
"-A",
"--allow",
"-D",
"--deny",
"-F",
"--forbid",
]
.contains(&flag)
}
fn handle_flag_prefix<'a>(prev: &'a str, curr: &'a str) -> (&'a str, &'a str) {
match prev {
"--codegen" | "-C" => ("-C", curr),
// Handle flags passed like --codegen=code-model=small
_ if curr.starts_with("--codegen=") => ("-C", &curr[10..]),
"-Z" => ("-Z", curr),
"-L" | "-l" | "-o" => (prev, curr),
// Handle lint flags
"-W" | "--warn" => ("-W", curr),
"-A" | "--allow" => ("-A", curr),
"-D" | "--deny" => ("-D", curr),
"-F" | "--forbid" => ("-F", curr),
_ => ("", curr),
}
}
let mut codegen_flags = Self::default();
let mut prev_prefix = None;
for curr in rustflags_env.split("\u{1f}") {
let prev = prev_prefix.take().unwrap_or("");
if prev.is_empty() && is_flag_prefix(curr) {
prev_prefix = Some(curr);
continue;
}
let (prefix, rustc_flag) = handle_flag_prefix(prev, curr);
codegen_flags.set_rustc_flag(prefix, rustc_flag)?;
}
Ok(codegen_flags)
}
fn set_rustc_flag(&mut self, prefix: &str, flag: &'this str) -> Result<(), Error> {
// Convert a textual representation of a bool-like rustc flag argument into an actual bool
fn arg_to_bool(arg: impl AsRef<str>) -> Option<bool> {
match arg.as_ref() {
"y" | "yes" | "on" | "true" => Some(true),
"n" | "no" | "off" | "false" => Some(false),
_ => None,
}
}
fn arg_to_u32(arg: impl AsRef<str>) -> Option<u32> {
arg.as_ref().parse().ok()
}
let (flag, value) = if let Some((flag, value)) = flag.split_once('=') {
(flag, Some(value))
} else {
(flag, None)
};
let flag = if prefix.is_empty() {
Cow::Borrowed(flag)
} else {
Cow::Owned(format!("{prefix}{flag}"))
};
let flag = flag.as_ref();
fn flag_not_empty_generic<T>(
flag: &str,
flag_value: Option<T>,
) -> Result<Option<T>, Error> {
if let Some(flag_value) = flag_value {
Ok(Some(flag_value))
} else {
Err(Error::new(
ErrorKind::InvalidFlag,
format!("{flag} must have a value"),
))
}
}
let flag_not_empty = |flag_value| flag_not_empty_generic(flag, flag_value);
match flag {
// https://doc.rust-lang.org/rustc/codegen-options/index.html#code-model
"-Ccode-model" => {
self.code_model = flag_not_empty(value)?;
}
// https://doc.rust-lang.org/rustc/codegen-options/index.html#no-vectorize-loops
"-Cno-vectorize-loops" => self.no_vectorize_loops = true,
// https://doc.rust-lang.org/rustc/codegen-options/index.html#no-vectorize-slp
"-Cno-vectorize-slp" => self.no_vectorize_slp = true,
// https://doc.rust-lang.org/rustc/codegen-options/index.html#profile-generate
"-Cprofile-generate" => {
self.profile_generate = flag_not_empty(value)?;
}
// https://doc.rust-lang.org/rustc/codegen-options/index.html#profile-use
"-Cprofile-use" => {
self.profile_use = flag_not_empty(value)?;
}
// https://doc.rust-lang.org/rustc/codegen-options/index.html#control-flow-guard
"-Ccontrol-flow-guard" => self.control_flow_guard = value.or(Some("true")),
// https://doc.rust-lang.org/rustc/codegen-options/index.html#lto
"-Clto" => self.lto = value.or(Some("true")),
// https://doc.rust-lang.org/rustc/linker-plugin-lto.html
"-Clinker-plugin-lto" => self.linker_plugin_lto = Some(true),
// https://doc.rust-lang.org/rustc/codegen-options/index.html#relocation-model
"-Crelocation-model" => {
self.relocation_model = flag_not_empty(value)?;
}
// https://doc.rust-lang.org/rustc/codegen-options/index.html#embed-bitcode
"-Cembed-bitcode" => self.embed_bitcode = value.map_or(Some(true), arg_to_bool),
// https://doc.rust-lang.org/rustc/codegen-options/index.html#force-frame-pointers
"-Cforce-frame-pointers" => {
self.force_frame_pointers = value.map_or(Some(true), arg_to_bool)
}
// https://doc.rust-lang.org/rustc/codegen-options/index.html#no-redzone
"-Cno-redzone" => self.no_redzone = value.map_or(Some(true), arg_to_bool),
// https://doc.rust-lang.org/rustc/codegen-options/index.html#soft-float
// Note: This flag is now deprecated in rustc.
"-Csoft-float" => self.soft_float = value.map_or(Some(true), arg_to_bool),
// https://doc.rust-lang.org/beta/unstable-book/compiler-flags/branch-protection.html
// FIXME: Drop the -Z variant and update the doc link once the option is stabilised
"-Zbranch-protection" | "-Cbranch-protection" => {
self.branch_protection = flag_not_empty(value)?;
}
// https://doc.rust-lang.org/beta/unstable-book/compiler-flags/dwarf-version.html
// FIXME: Drop the -Z variant and update the doc link once the option is stablized
"-Zdwarf-version" | "-Cdwarf-version" => {
self.dwarf_version = flag_not_empty_generic(flag, value.and_then(arg_to_u32))?;
}
// https://github.com/rust-lang/rust/issues/114903
// FIXME: Drop the -Z variant and update the doc link once the option is stabilized
"-Zstack-protector" | "-Cstack-protector" => {
self.stack_protector = flag_not_empty(value)?;
}
_ => {}
}
Ok(())
}
// Rust and clang/cc don't agree on what equivalent flags should look like.
pub(crate) fn cc_flags(&self, build: &Build, tool: &mut Tool, target: &TargetInfo<'_>) {
let family = tool.family;
// Push `flag` to `flags` if it is supported by the currently used CC
let mut push_if_supported = |flag: OsString| {
if build
.is_flag_supported_inner(&flag, tool, target)
.unwrap_or(false)
{
tool.args.push(flag);
} else {
build.cargo_output.print_warning(&format!(
"Inherited flag {flag:?} is not supported by the currently used CC"
));
}
};
let clang_or_gnu =
matches!(family, ToolFamily::Clang { .. }) || matches!(family, ToolFamily::Gnu);
// Flags shared between clang and gnu
if clang_or_gnu {
// https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mbranch-protection
// https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html#index-mbranch-protection (Aarch64)
// https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html#index-mbranch-protection-1 (ARM)
// https://developer.arm.com/documentation/101754/0619/armclang-Reference/armclang-Command-line-Options/-mbranch-protection
if let Some(value) = self.branch_protection {
push_if_supported(
format!("-mbranch-protection={}", value.replace(",", "+")).into(),
);
}
// https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mcmodel
// https://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html (several archs, search for `-mcmodel=`).
// FIXME(madsmtm): Parse the model, to make sure we pass the correct value (depending on arch).
if let Some(value) = self.code_model {
push_if_supported(format!("-mcmodel={value}").into());
}
// https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fno-vectorize
// https://gcc.gnu.org/onlinedocs/gnat_ugn/Vectorization-of-loops.html
if self.no_vectorize_loops {
push_if_supported("-fno-vectorize".into());
}
// https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fno-slp-vectorize
// https://gcc.gnu.org/onlinedocs/gnat_ugn/Vectorization-of-loops.html
if self.no_vectorize_slp {
push_if_supported("-fno-slp-vectorize".into());
}
if let Some(value) = self.relocation_model {
let cc_flag = match value {
// https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fPIC
// https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-fPIC
"pic" => Some("-fPIC"),
// https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fPIE
// https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-fPIE
"pie" => Some("-fPIE"),
// https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mdynamic-no-pic
// https://gcc.gnu.org/onlinedocs/gcc/RS_002f6000-and-PowerPC-Options.html#index-mdynamic-no-pic
"dynamic-no-pic" => Some("-mdynamic-no-pic"),
_ => None,
};
if let Some(cc_flag) = cc_flag {
push_if_supported(cc_flag.into());
}
}
// https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fno-omit-frame-pointer
// https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fomit-frame-pointer
// https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-fomit-frame-pointer
if let Some(value) = self.force_frame_pointers {
let cc_flag = if value {
"-fno-omit-frame-pointer"
} else {
"-fomit-frame-pointer"
};
push_if_supported(cc_flag.into());
}
// https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mno-red-zone
// https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html#index-mno-red-zone
// https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mred-zone
// https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html#index-mred-zone
if let Some(value) = self.no_redzone {
let cc_flag = if value { "-mno-red-zone" } else { "-mred-zone" };
push_if_supported(cc_flag.into());
}
// https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-msoft-float
// https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mhard-float
// https://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html (several archs, search for `-msoft-float`).
// https://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html (several archs, search for `-mhard-float`).
if let Some(value) = self.soft_float {
let cc_flag = if value {
"-msoft-float"
} else {
// Do not use -mno-soft-float, that's basically just an alias for -mno-implicit-float.
"-mhard-float"
};
push_if_supported(cc_flag.into());
}
// https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-gdwarf-2
// https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html#index-gdwarf
if let Some(value) = self.dwarf_version {
push_if_supported(format!("-gdwarf-{value}").into());
}
// https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fstack-protector
// https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html#index-fstack-protector
if let Some(value) = self.stack_protector {
// don't need to propagate stack-protector on MSVC since /GS is already the default
// https://learn.microsoft.com/en-us/cpp/build/reference/gs-buffer-security-check?view=msvc-170
//
// Do NOT `stack-protector=none` since it weakens security for C code,
// and `-Zstack-protector=basic` is deprecated and will be removed soon.
let cc_flag = match value {
"strong" => Some("-fstack-protector-strong"),
"all" => Some("-fstack-protector-all"),
_ => None,
};
if let Some(cc_flag) = cc_flag {
push_if_supported(cc_flag.into());
}
}
}
// Compiler-exclusive flags
match family {
ToolFamily::Clang { .. } => {
// GNU and Clang compilers both support the same PGO flags, but they use different libraries and
// different formats for the profile files which are not compatible.
// clang and rustc both internally use llvm, so we want to inherit the PGO flags only for clang.
// https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fprofile-generate
if let Some(value) = self.profile_generate {
push_if_supported(format!("-fprofile-generate={value}").into());
}
// https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fprofile-use
if let Some(value) = self.profile_use {
push_if_supported(format!("-fprofile-use={value}").into());
}
// https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fembed-bitcode
if let Some(value) = self.embed_bitcode {
let cc_val = if value { "all" } else { "off" };
push_if_supported(format!("-fembed-bitcode={cc_val}").into());
}
// https://doc.rust-lang.org/rustc/linker-plugin-lto.html
if self.linker_plugin_lto.unwrap_or(false) {
// https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-flto
let cc_val = match self.lto {
Some("thin") => "thin",
_ => "full",
};
push_if_supported(format!("-flto={cc_val}").into());
}
// https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mguard
if let Some(value) = self.control_flow_guard {
let cc_val = match value {
"y" | "yes" | "on" | "true" | "checks" => Some("cf"),
"nochecks" => Some("cf-nochecks"),
"n" | "no" | "off" | "false" => Some("none"),
_ => None,
};
if let Some(cc_val) = cc_val {
push_if_supported(format!("-mguard={cc_val}").into());
}
}
}
ToolFamily::Gnu => {}
ToolFamily::Msvc { .. } => {
// https://learn.microsoft.com/en-us/cpp/build/reference/guard-enable-control-flow-guard
if let Some(value) = self.control_flow_guard {
let cc_val = match value {
"y" | "yes" | "on" | "true" | "checks" => Some("cf"),
"n" | "no" | "off" | "false" => Some("cf-"),
_ => None,
};
if let Some(cc_val) = cc_val {
push_if_supported(format!("/guard:{cc_val}").into());
}
}
// https://learn.microsoft.com/en-us/cpp/build/reference/oy-frame-pointer-omission
if let Some(value) = self.force_frame_pointers {
// Flag is unsupported on 64-bit arches
if !target.arch.contains("64") {
let cc_flag = if value { "/Oy-" } else { "/Oy" };
push_if_supported(cc_flag.into());
}
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[track_caller]
fn check(env: &str, expected: &RustcCodegenFlags) {
let actual = RustcCodegenFlags::parse(env).unwrap();
assert_eq!(actual, *expected);
}
#[test]
fn codegen_type() {
let expected = RustcCodegenFlags {
code_model: Some("tiny"),
..RustcCodegenFlags::default()
};
check("-Ccode-model=tiny", &expected);
check("-C\u{1f}code-model=tiny", &expected);
check("--codegen\u{1f}code-model=tiny", &expected);
check("--codegen=code-model=tiny", &expected);
}
#[test]
fn precedence() {
check(
"-ccode-model=tiny\u{1f}-Ccode-model=small",
&RustcCodegenFlags {
code_model: Some("small"),
..RustcCodegenFlags::default()
},
);
}
#[test]
fn two_valid_prefixes() {
let expected = RustcCodegenFlags::default();
check("-L\u{1f}-Clto", &expected);
}
#[test]
fn stack_protector() {
let expected = RustcCodegenFlags {
stack_protector: Some("strong"),
..RustcCodegenFlags::default()
};
check("-Zstack-protector=strong", &expected);
check("-Cstack-protector=strong", &expected);
}
#[test]
fn three_valid_prefixes() {
let expected = RustcCodegenFlags {
lto: Some("true"),
..RustcCodegenFlags::default()
};
check("-L\u{1f}-L\u{1f}-Clto", &expected);
}
#[test]
fn all_rustc_flags() {
// Throw all possible flags at the parser to catch false positives
let flags = [
// Set all the flags we recognise first
"-Ccode-model=tiny",
"-Ccontrol-flow-guard=yes",
"-Cembed-bitcode=no",
"-Cforce-frame-pointers=yes",
"-Clto=false",
"-Clink-dead-code=yes",
"-Cno-redzone=yes",
"-Cno-vectorize-loops",
"-Cno-vectorize-slp",
"-Cprofile-generate=fooprofile",
"-Cprofile-use=fooprofile",
"-Crelocation-model=pic",
"-Csoft-float=yes",
"-Zbranch-protection=bti,pac-ret,leaf",
"-Zdwarf-version=5",
"-Zstack-protector=strong",
// Set flags we don't recognise but rustc supports next
// rustc flags
"--cfg",
"a",
"--check-cfg 'cfg(verbose)",
"-L",
"/usr/lib/foo",
"-l",
"static:+whole-archive=mylib",
"--crate-type=dylib",
"--crate-name=foo",
"--edition=2021",
"--emit=asm",
"--print=crate-name",
"-g",
"-O",
"-o",
"foooutput",
"--out-dir",
"foooutdir",
"--target",
"aarch64-unknown-linux-gnu",
"-W",
"missing-docs",
"-D",
"unused-variables",
"--force-warn",
"dead-code",
"-A",
"unused",
"-F",
"unused",
"--cap-lints",
"warn",
"--version",
"--verbose",
"-v",
"--extern",
"foocrate",
"--sysroot",
"fooroot",
"--error-format",
"human",
"--color",
"auto",
"--diagnostic-width",
"80",
"--remap-path-prefix",
"foo=bar",
"--json=artifact",
// Codegen flags
"-Car",
"-Ccodegen-units=1",
"-Ccollapse-macro-debuginfo=yes",
"-Cdebug-assertions=yes",
"-Cdebuginfo=1",
"-Cdefault-linker-libraries=yes",
"-Cdlltool=foo",
"-Cextra-filename=foo",
"-Cforce-unwind-tables=yes",
"-Cincremental=foodir",
"-Cinline-threshold=6",
"-Cinstrument-coverage",
"-Clink-arg=-foo",
"-Clink-args=-foo",
"-Clink-self-contained=yes",
"-Clinker=lld",
"-Clinker-flavor=ld.lld",
"-Clinker-plugin-lto=/path",
"-Cllvm-args=foo",
"-Cmetadata=foo",
"-Cno-prepopulate-passes",
"-Cno-stack-check",
"-Copt-level=3",
"-Coverflow-checks=yes",
"-Cpanic=abort",
"-Cpasses=foopass",
"-Cprefer-dynamic=yes",
"-Crelro-level=partial",
"-Cremark=all",
"-Crpath=yes",
"-Csave-temps=yes",
"-Csplit-debuginfo=packed",
"-Cstrip=symbols",
"-Csymbol-mangling-version=v0",
"-Ctarget-cpu=native",
"-Ctarget-feature=+sve",
// Unstable options
"-Ztune-cpu=machine",
];
check(
&flags.join("\u{1f}"),
&RustcCodegenFlags {
code_model: Some("tiny"),
control_flow_guard: Some("yes"),
embed_bitcode: Some(false),
force_frame_pointers: Some(true),
lto: Some("false"),
no_redzone: Some(true),
no_vectorize_loops: true,
no_vectorize_slp: true,
profile_generate: Some("fooprofile"),
profile_use: Some("fooprofile"),
relocation_model: Some("pic"),
soft_float: Some(true),
branch_protection: Some("bti,pac-ret,leaf"),
dwarf_version: Some(5),
stack_protector: Some("strong"),
linker_plugin_lto: Some(true),
},
);
}
}

4397
vendor/cc/src/lib.rs vendored Normal file

File diff suppressed because it is too large Load Diff

118
vendor/cc/src/parallel/async_executor.rs vendored Normal file
View File

@@ -0,0 +1,118 @@
use std::{
cell::Cell,
future::Future,
pin::Pin,
ptr,
task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
thread,
time::Duration,
};
use crate::Error;
const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(
// Cloning just returns a new no-op raw waker
|_| NOOP_RAW_WAKER,
// `wake` does nothing
|_| {},
// `wake_by_ref` does nothing
|_| {},
// Dropping does nothing as we don't allocate anything
|_| {},
);
const NOOP_RAW_WAKER: RawWaker = RawWaker::new(ptr::null(), &NOOP_WAKER_VTABLE);
#[derive(Default)]
pub(crate) struct YieldOnce(bool);
impl Future for YieldOnce {
type Output = ();
fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> {
let flag = &mut std::pin::Pin::into_inner(self).0;
if !*flag {
*flag = true;
Poll::Pending
} else {
Poll::Ready(())
}
}
}
/// Execute the futures and return when they are all done.
///
/// Here we use our own homebrew async executor since cc is used in the build
/// script of many popular projects, pulling in additional dependencies would
/// significantly slow down its compilation.
pub(crate) fn block_on<Fut1, Fut2>(
mut fut1: Fut1,
mut fut2: Fut2,
has_made_progress: &Cell<bool>,
) -> Result<(), Error>
where
Fut1: Future<Output = Result<(), Error>>,
Fut2: Future<Output = Result<(), Error>>,
{
// Shadows the future so that it can never be moved and is guaranteed
// to be pinned.
//
// The same trick used in `pin!` macro.
//
// TODO: Once MSRV is bumped to 1.68, replace this with `std::pin::pin!`
let mut fut1 = Some(unsafe { Pin::new_unchecked(&mut fut1) });
let mut fut2 = Some(unsafe { Pin::new_unchecked(&mut fut2) });
// TODO: Once `Waker::noop` stablised and our MSRV is bumped to the version
// which it is stablised, replace this with `Waker::noop`.
let waker = unsafe { Waker::from_raw(NOOP_RAW_WAKER) };
let mut context = Context::from_waker(&waker);
let mut backoff_cnt = 0;
loop {
has_made_progress.set(false);
if let Some(fut) = fut2.as_mut() {
if let Poll::Ready(res) = fut.as_mut().poll(&mut context) {
fut2 = None;
res?;
}
}
if let Some(fut) = fut1.as_mut() {
if let Poll::Ready(res) = fut.as_mut().poll(&mut context) {
fut1 = None;
res?;
}
}
if fut1.is_none() && fut2.is_none() {
return Ok(());
}
if !has_made_progress.get() {
if backoff_cnt > 3 {
// We have yielded at least three times without making'
// any progress, so we will sleep for a while.
let duration = Duration::from_millis(100 * (backoff_cnt - 3).min(10));
thread::sleep(duration);
} else {
// Given that we spawned a lot of compilation tasks, it is unlikely
// that OS cannot find other ready task to execute.
//
// If all of them are done, then we will yield them and spawn more,
// or simply return.
//
// Thus this will not be turned into a busy-wait loop and it will not
// waste CPU resource.
thread::yield_now();
}
}
backoff_cnt = if has_made_progress.get() {
0
} else {
backoff_cnt + 1
};
}
}

175
vendor/cc/src/parallel/command_runner.rs vendored Normal file
View File

@@ -0,0 +1,175 @@
use std::{
cell::Cell,
io::{self, Write as _},
process::{Child, Command},
};
use crate::{
parallel::{
async_executor::{block_on, YieldOnce},
job_token,
},
spawn, CargoOutput, Error, ErrorKind, StderrForwarder,
};
struct KillOnDrop(Child, StderrForwarder);
impl Drop for KillOnDrop {
fn drop(&mut self) {
let child = &mut self.0;
child.kill().ok();
}
}
fn cell_update<T, F>(cell: &Cell<T>, f: F)
where
T: Default,
F: FnOnce(T) -> T,
{
let old = cell.take();
let new = f(old);
cell.set(new);
}
fn try_wait_on_child(
cmd: &Command,
child: &mut Child,
mut stdout: impl io::Write,
stderr_forwarder: &mut StderrForwarder,
) -> Result<Option<()>, Error> {
stderr_forwarder.forward_available();
match child.try_wait() {
Ok(Some(status)) => {
stderr_forwarder.forward_all();
let _ = writeln!(stdout, "{}", status);
if status.success() {
Ok(Some(()))
} else {
Err(Error::new(
ErrorKind::ToolExecError,
format!("command did not execute successfully (status code {status}): {cmd:?}"),
))
}
}
Ok(None) => Ok(None),
Err(e) => {
stderr_forwarder.forward_all();
Err(Error::new(
ErrorKind::ToolExecError,
format!("failed to wait on spawned child process `{cmd:?}`: {e}"),
))
}
}
}
pub(crate) fn run_commands_in_parallel(
cargo_output: &CargoOutput,
cmds: &mut dyn Iterator<Item = Result<Command, Error>>,
) -> Result<(), Error> {
// Limit our parallelism globally with a jobserver.
let mut tokens = job_token::ActiveJobTokenServer::new();
// When compiling objects in parallel we do a few dirty tricks to speed
// things up:
//
// * First is that we use the `jobserver` crate to limit the parallelism
// of this build script. The `jobserver` crate will use a jobserver
// configured by Cargo for build scripts to ensure that parallelism is
// coordinated across C compilations and Rust compilations. Before we
// compile anything we make sure to wait until we acquire a token.
//
// Note that this jobserver is cached globally so we only used one per
// process and only worry about creating it once.
//
// * Next we use spawn the process to actually compile objects in
// parallel after we've acquired a token to perform some work
//
// With all that in mind we compile all objects in a loop here, after we
// acquire the appropriate tokens, Once all objects have been compiled
// we wait on all the processes and propagate the results of compilation.
let pendings = Cell::new(Vec::<(Command, KillOnDrop, job_token::JobToken)>::new());
let is_disconnected = Cell::new(false);
let has_made_progress = Cell::new(false);
let wait_future = async {
let mut error = None;
// Buffer the stdout
let mut stdout = io::BufWriter::with_capacity(128, io::stdout());
loop {
// If the other end of the pipe is already disconnected, then we're not gonna get any new jobs,
// so it doesn't make sense to reuse the tokens; in fact,
// releasing them as soon as possible (once we know that the other end is disconnected) is beneficial.
// Imagine that the last file built takes an hour to finish; in this scenario,
// by not releasing the tokens before that last file is done we would effectively block other processes from
// starting sooner - even though we only need one token for that last file, not N others that were acquired.
let mut pendings_is_empty = false;
cell_update(&pendings, |mut pendings| {
// Try waiting on them.
pendings.retain_mut(|(cmd, child, _token)| {
match try_wait_on_child(cmd, &mut child.0, &mut stdout, &mut child.1) {
Ok(Some(())) => {
// Task done, remove the entry
has_made_progress.set(true);
false
}
Ok(None) => true, // Task still not finished, keep the entry
Err(err) => {
// Task fail, remove the entry.
// Since we can only return one error, log the error to make
// sure users always see all the compilation failures.
has_made_progress.set(true);
if cargo_output.warnings {
let _ = writeln!(stdout, "cargo:warning={}", err);
}
error = Some(err);
false
}
}
});
pendings_is_empty = pendings.is_empty();
pendings
});
if pendings_is_empty && is_disconnected.get() {
break if let Some(err) = error {
Err(err)
} else {
Ok(())
};
}
YieldOnce::default().await;
}
};
let spawn_future = async {
for res in cmds {
let mut cmd = res?;
let token = tokens.acquire().await?;
let mut child = spawn(&mut cmd, cargo_output)?;
let mut stderr_forwarder = StderrForwarder::new(&mut child);
stderr_forwarder.set_non_blocking()?;
cell_update(&pendings, |mut pendings| {
pendings.push((cmd, KillOnDrop(child, stderr_forwarder), token));
pendings
});
has_made_progress.set(true);
}
is_disconnected.set(true);
Ok::<_, Error>(())
};
block_on(wait_future, spawn_future, &has_made_progress)
}

267
vendor/cc/src/parallel/job_token.rs vendored Normal file
View File

@@ -0,0 +1,267 @@
use std::marker::PhantomData;
use crate::{utilities::OnceLock, Error};
pub(crate) struct JobToken(PhantomData<()>);
impl JobToken {
fn new() -> Self {
Self(PhantomData)
}
}
impl Drop for JobToken {
fn drop(&mut self) {
match JobTokenServer::new() {
JobTokenServer::Inherited(jobserver) => jobserver.release_token_raw(),
JobTokenServer::InProcess(jobserver) => jobserver.release_token_raw(),
}
}
}
enum JobTokenServer {
Inherited(inherited_jobserver::JobServer),
InProcess(inprocess_jobserver::JobServer),
}
impl JobTokenServer {
/// This function returns a static reference to the jobserver because
/// - creating a jobserver from env is a bit fd-unsafe (e.g. the fd might
/// be closed by other jobserver users in the process) and better do it
/// at the start of the program.
/// - in case a jobserver cannot be created from env (e.g. it's not
/// present), we will create a global in-process only jobserver
/// that has to be static so that it will be shared by all cc
/// compilation.
fn new() -> &'static Self {
// TODO: Replace with a OnceLock once MSRV is 1.70
static JOBSERVER: OnceLock<JobTokenServer> = OnceLock::new();
JOBSERVER.get_or_init(|| {
unsafe { inherited_jobserver::JobServer::from_env() }
.map(Self::Inherited)
.unwrap_or_else(|| Self::InProcess(inprocess_jobserver::JobServer::new()))
})
}
}
pub(crate) enum ActiveJobTokenServer {
Inherited(inherited_jobserver::ActiveJobServer<'static>),
InProcess(&'static inprocess_jobserver::JobServer),
}
impl ActiveJobTokenServer {
pub(crate) fn new() -> Self {
match JobTokenServer::new() {
JobTokenServer::Inherited(inherited_jobserver) => {
Self::Inherited(inherited_jobserver.enter_active())
}
JobTokenServer::InProcess(inprocess_jobserver) => Self::InProcess(inprocess_jobserver),
}
}
pub(crate) async fn acquire(&mut self) -> Result<JobToken, Error> {
match self {
Self::Inherited(jobserver) => jobserver.acquire().await,
Self::InProcess(jobserver) => Ok(jobserver.acquire().await),
}
}
}
mod inherited_jobserver {
use super::JobToken;
use crate::{parallel::async_executor::YieldOnce, Error, ErrorKind};
use std::{
io, mem,
sync::{mpsc, Mutex, MutexGuard, PoisonError},
};
pub(super) struct JobServer {
/// Implicit token for this process which is obtained and will be
/// released in parent. Since `JobTokens` only give back what they got,
/// there should be at most one global implicit token in the wild.
///
/// Since Rust does not execute any `Drop` for global variables,
/// we can't just put it back to jobserver and then re-acquire it at
/// the end of the process.
///
/// Use `Mutex` to avoid race between acquire and release.
/// If an `AtomicBool` is used, then it's possible for:
/// - `release_token_raw`: Tries to set `global_implicit_token` to true, but it is already
/// set to `true`, continue to release it to jobserver
/// - `acquire` takes the global implicit token, set `global_implicit_token` to false
/// - `release_token_raw` now writes the token back into the jobserver, while
/// `global_implicit_token` is `false`
///
/// If the program exits here, then cc effectively increases parallelism by one, which is
/// incorrect, hence we use a `Mutex` here.
global_implicit_token: Mutex<bool>,
inner: jobserver::Client,
}
impl JobServer {
pub(super) unsafe fn from_env() -> Option<Self> {
jobserver::Client::from_env().map(|inner| Self {
inner,
global_implicit_token: Mutex::new(true),
})
}
fn get_global_implicit_token(&self) -> MutexGuard<'_, bool> {
self.global_implicit_token
.lock()
.unwrap_or_else(PoisonError::into_inner)
}
/// All tokens except for the global implicit token will be put back into the jobserver
/// immediately and they cannot be cached, since Rust does not call `Drop::drop` on
/// global variables.
pub(super) fn release_token_raw(&self) {
let mut global_implicit_token = self.get_global_implicit_token();
if *global_implicit_token {
// There's already a global implicit token, so this token must
// be released back into jobserver.
//
// `release_raw` should not block
let _ = self.inner.release_raw();
} else {
*global_implicit_token = true;
}
}
pub(super) fn enter_active(&self) -> ActiveJobServer<'_> {
ActiveJobServer {
jobserver: self,
helper_thread: None,
}
}
}
struct HelperThread {
inner: jobserver::HelperThread,
/// When rx is dropped, all the token stored within it will be dropped.
rx: mpsc::Receiver<io::Result<jobserver::Acquired>>,
}
impl HelperThread {
fn new(jobserver: &JobServer) -> Result<Self, Error> {
let (tx, rx) = mpsc::channel();
Ok(Self {
rx,
inner: jobserver.inner.clone().into_helper_thread(move |res| {
let _ = tx.send(res);
})?,
})
}
}
pub(crate) struct ActiveJobServer<'a> {
jobserver: &'a JobServer,
helper_thread: Option<HelperThread>,
}
impl ActiveJobServer<'_> {
pub(super) async fn acquire(&mut self) -> Result<JobToken, Error> {
let mut has_requested_token = false;
loop {
// Fast path
if mem::replace(&mut *self.jobserver.get_global_implicit_token(), false) {
break Ok(JobToken::new());
}
match self.jobserver.inner.try_acquire() {
Ok(Some(acquired)) => {
acquired.drop_without_releasing();
break Ok(JobToken::new());
}
Ok(None) => YieldOnce::default().await,
Err(err) if err.kind() == io::ErrorKind::Unsupported => {
// Fallback to creating a help thread with blocking acquire
let helper_thread = if let Some(thread) = self.helper_thread.as_ref() {
thread
} else {
self.helper_thread
.insert(HelperThread::new(self.jobserver)?)
};
match helper_thread.rx.try_recv() {
Ok(res) => {
let acquired = res?;
acquired.drop_without_releasing();
break Ok(JobToken::new());
}
Err(mpsc::TryRecvError::Disconnected) => break Err(Error::new(
ErrorKind::JobserverHelpThreadError,
"jobserver help thread has returned before ActiveJobServer is dropped",
)),
Err(mpsc::TryRecvError::Empty) => {
if !has_requested_token {
helper_thread.inner.request_token();
has_requested_token = true;
}
YieldOnce::default().await
}
}
}
Err(err) => break Err(err.into()),
}
}
}
}
}
mod inprocess_jobserver {
use super::JobToken;
use crate::parallel::async_executor::YieldOnce;
use std::{
env::var,
sync::atomic::{
AtomicU32,
Ordering::{AcqRel, Acquire},
},
};
pub(crate) struct JobServer(AtomicU32);
impl JobServer {
#[allow(clippy::disallowed_methods)]
pub(super) fn new() -> Self {
// Use `NUM_JOBS` if set (it's configured by Cargo) and otherwise
// just fall back to the number of cores on the local machine, or a reasonable
// default if that cannot be determined.
let parallelism = var("NUM_JOBS")
.ok()
.and_then(|j| j.parse::<u32>().ok())
.or_else(|| Some(std::thread::available_parallelism().ok()?.get() as u32))
.unwrap_or(4);
Self(AtomicU32::new(parallelism))
}
pub(super) async fn acquire(&self) -> JobToken {
loop {
let res = self
.0
.fetch_update(AcqRel, Acquire, |tokens| tokens.checked_sub(1));
if res.is_ok() {
break JobToken::new();
}
YieldOnce::default().await
}
}
pub(super) fn release_token_raw(&self) {
self.0.fetch_add(1, AcqRel);
}
}
}

6
vendor/cc/src/parallel/mod.rs vendored Normal file
View File

@@ -0,0 +1,6 @@
mod async_executor;
mod command_runner;
mod job_token;
pub(crate) mod stderr;
pub(crate) use command_runner::run_commands_in_parallel;

91
vendor/cc/src/parallel/stderr.rs vendored Normal file
View File

@@ -0,0 +1,91 @@
#![cfg_attr(target_family = "wasm", allow(unused))]
/// Helpers functions for [`ChildStderr`].
use std::{convert::TryInto, process::ChildStderr};
use crate::{Error, ErrorKind};
#[cfg(all(not(unix), not(windows), not(target_family = "wasm")))]
compile_error!("Only unix and windows support non-blocking pipes! For other OSes, disable the parallel feature.");
#[cfg(unix)]
fn get_flags(fd: std::os::unix::io::RawFd) -> Result<i32, Error> {
let flags = unsafe { libc::fcntl(fd, libc::F_GETFL, 0) };
if flags == -1 {
Err(Error::new(
ErrorKind::IOError,
format!(
"Failed to get flags for pipe {}: {}",
fd,
std::io::Error::last_os_error()
),
))
} else {
Ok(flags)
}
}
#[cfg(unix)]
fn set_flags(fd: std::os::unix::io::RawFd, flags: std::os::raw::c_int) -> Result<(), Error> {
if unsafe { libc::fcntl(fd, libc::F_SETFL, flags) } == -1 {
Err(Error::new(
ErrorKind::IOError,
format!(
"Failed to set flags for pipe {}: {}",
fd,
std::io::Error::last_os_error()
),
))
} else {
Ok(())
}
}
#[cfg(unix)]
pub fn set_non_blocking(pipe: &impl std::os::unix::io::AsRawFd) -> Result<(), Error> {
// On Unix, switch the pipe to non-blocking mode.
// On Windows, we have a different way to be non-blocking.
let fd = pipe.as_raw_fd();
let flags = get_flags(fd)?;
set_flags(fd, flags | libc::O_NONBLOCK)
}
pub fn bytes_available(stderr: &mut ChildStderr) -> Result<usize, Error> {
let mut bytes_available = 0;
#[cfg(windows)]
{
use ::find_msvc_tools::windows_sys::PeekNamedPipe;
use std::os::windows::io::AsRawHandle;
use std::ptr::null_mut;
if unsafe {
PeekNamedPipe(
stderr.as_raw_handle(),
null_mut(),
0,
null_mut(),
&mut bytes_available,
null_mut(),
)
} == 0
{
return Err(Error::new(
ErrorKind::IOError,
format!(
"PeekNamedPipe failed with {}",
std::io::Error::last_os_error()
),
));
}
}
#[cfg(unix)]
{
use std::os::unix::io::AsRawFd;
if unsafe { libc::ioctl(stderr.as_raw_fd(), libc::FIONREAD, &mut bytes_available) } != 0 {
return Err(Error::new(
ErrorKind::IOError,
format!("ioctl failed with {}", std::io::Error::last_os_error()),
));
}
}
Ok(bytes_available.try_into().unwrap())
}

42
vendor/cc/src/target.rs vendored Normal file
View File

@@ -0,0 +1,42 @@
//! Parsing of `rustc` target names to match the values exposed to Cargo
//! build scripts (`CARGO_CFG_*`).
mod apple;
mod generated;
mod llvm;
mod parser;
pub(crate) use apple::*;
pub(crate) use parser::TargetInfoParser;
/// Information specific to a `rustc` target.
///
/// See <https://doc.rust-lang.org/cargo/appendix/glossary.html#target>.
#[derive(Debug, PartialEq, Clone)]
pub(crate) struct TargetInfo<'a> {
/// The full architecture, including the subarchitecture.
///
/// This differs from `cfg!(target_arch)`, which only specifies the
/// overall architecture, which is too coarse for certain cases.
pub full_arch: &'a str,
/// The overall target architecture.
///
/// This is the same as the value of `cfg!(target_arch)`.
pub arch: &'a str,
/// The target vendor.
///
/// This is the same as the value of `cfg!(target_vendor)`.
pub vendor: &'a str,
/// The operating system, or `none` on bare-metal targets.
///
/// This is the same as the value of `cfg!(target_os)`.
pub os: &'a str,
/// The environment on top of the operating system.
///
/// This is the same as the value of `cfg!(target_env)`.
pub env: &'a str,
/// The ABI on top of the operating system.
///
/// This is the same as the value of `cfg!(target_abi)`.
pub abi: &'a str,
}

64
vendor/cc/src/target/apple.rs vendored Normal file
View File

@@ -0,0 +1,64 @@
use super::TargetInfo;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(crate) enum AppleEnv {
Simulator,
MacCatalyst,
}
pub(crate) use AppleEnv::*;
impl TargetInfo<'_> {
pub(crate) fn get_apple_env(&self) -> Option<AppleEnv> {
match (self.env, self.abi) {
("sim", _) | (_, "sim") => Some(Simulator),
("macabi", _) | (_, "macabi") => Some(MacCatalyst),
_ => None,
}
}
pub(crate) fn apple_sdk_name(&self) -> &'static str {
match (self.os, self.get_apple_env()) {
("macos", None) => "macosx",
("ios", None) => "iphoneos",
("ios", Some(Simulator)) => "iphonesimulator",
("ios", Some(MacCatalyst)) => "macosx",
("tvos", None) => "appletvos",
("tvos", Some(Simulator)) => "appletvsimulator",
("watchos", None) => "watchos",
("watchos", Some(Simulator)) => "watchsimulator",
("visionos", None) => "xros",
("visionos", Some(Simulator)) => "xrsimulator",
(os, _) => panic!("invalid Apple target OS {}", os),
}
}
pub(crate) fn apple_version_flag(&self, min_version: &str) -> String {
// There are many aliases for these, and `-mtargetos=` is preferred on Clang nowadays, but
// for compatibility with older Clang, we use the earliest supported name here.
//
// NOTE: GCC does not support `-miphoneos-version-min=` etc. (because it does not support
// iOS in general), but we specify them anyhow in case we actually have a Clang-like
// compiler disguised as a GNU-like compiler, or in case GCC adds support for these in the
// future.
//
// See also:
// https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mmacos-version-min
// https://clang.llvm.org/docs/AttributeReference.html#availability
// https://gcc.gnu.org/onlinedocs/gcc/Darwin-Options.html#index-mmacosx-version-min
match (self.os, self.get_apple_env()) {
("macos", None) => format!("-mmacosx-version-min={min_version}"),
("ios", None) => format!("-miphoneos-version-min={min_version}"),
("ios", Some(Simulator)) => format!("-mios-simulator-version-min={min_version}"),
("ios", Some(MacCatalyst)) => format!("-mtargetos=ios{min_version}-macabi"),
("tvos", None) => format!("-mappletvos-version-min={min_version}"),
("tvos", Some(Simulator)) => format!("-mappletvsimulator-version-min={min_version}"),
("watchos", None) => format!("-mwatchos-version-min={min_version}"),
("watchos", Some(Simulator)) => format!("-mwatchsimulator-version-min={min_version}"),
// `-mxros-version-min` does not exist
// https://github.com/llvm/llvm-project/issues/88271
("visionos", None) => format!("-mtargetos=xros{min_version}"),
("visionos", Some(Simulator)) => format!("-mtargetos=xros{min_version}-simulator"),
(os, _) => panic!("invalid Apple target OS {}", os),
}
}
}

315
vendor/cc/src/target/generated.rs vendored Normal file
View File

@@ -0,0 +1,315 @@
//! This file is generated code. Please edit the generator in
//! dev-tools/gen-target-info if you need to make changes, or see
//! src/target/llvm.rs if you need to configure a specific LLVM triple.
#[rustfmt::skip]
pub(crate) const LLVM_TARGETS: &[(&str, &str)] = &[
("aarch64-apple-darwin", "arm64-apple-macosx"),
("aarch64-apple-ios", "arm64-apple-ios"),
("aarch64-apple-ios-macabi", "arm64-apple-ios-macabi"),
("aarch64-apple-ios-sim", "arm64-apple-ios-simulator"),
("aarch64-apple-tvos", "arm64-apple-tvos"),
("aarch64-apple-tvos-sim", "arm64-apple-tvos-simulator"),
("aarch64-apple-visionos", "arm64-apple-xros"),
("aarch64-apple-visionos-sim", "arm64-apple-xros-simulator"),
("aarch64-apple-watchos", "arm64-apple-watchos"),
("aarch64-apple-watchos-sim", "arm64-apple-watchos-simulator"),
("aarch64-fuchsia", "aarch64-fuchsia"),
("aarch64-kmc-solid_asp3", "aarch64-unknown-none"),
("aarch64-linux-android", "aarch64-linux-android"),
("aarch64-nintendo-switch-freestanding", "aarch64-unknown-none"),
("aarch64-pc-windows-gnullvm", "aarch64-pc-windows-gnu"),
("aarch64-pc-windows-msvc", "aarch64-pc-windows-msvc"),
("aarch64-unknown-freebsd", "aarch64-unknown-freebsd"),
("aarch64-unknown-fuchsia", "aarch64-unknown-fuchsia"),
("aarch64-unknown-hermit", "aarch64-unknown-hermit"),
("aarch64-unknown-illumos", "aarch64-unknown-solaris2.11"),
("aarch64-unknown-linux-gnu", "aarch64-unknown-linux-gnu"),
("aarch64-unknown-linux-gnu_ilp32", "aarch64-unknown-linux-gnu_ilp32"),
("aarch64-unknown-linux-musl", "aarch64-unknown-linux-musl"),
("aarch64-unknown-linux-ohos", "aarch64-unknown-linux-ohos"),
("aarch64-unknown-managarm-mlibc", "aarch64-unknown-managarm-mlibc"),
("aarch64-unknown-netbsd", "aarch64-unknown-netbsd"),
("aarch64-unknown-none", "aarch64-unknown-none"),
("aarch64-unknown-none-softfloat", "aarch64-unknown-none"),
("aarch64-unknown-nto-qnx700", "aarch64-unknown-unknown"),
("aarch64-unknown-nto-qnx710", "aarch64-unknown-unknown"),
("aarch64-unknown-nto-qnx710_iosock", "aarch64-unknown-unknown"),
("aarch64-unknown-nto-qnx800", "aarch64-unknown-unknown"),
("aarch64-unknown-nuttx", "aarch64-unknown-none"),
("aarch64-unknown-openbsd", "aarch64-unknown-openbsd"),
("aarch64-unknown-redox", "aarch64-unknown-redox"),
("aarch64-unknown-teeos", "aarch64-unknown-none"),
("aarch64-unknown-trusty", "aarch64-unknown-unknown-musl"),
("aarch64-unknown-uefi", "aarch64-unknown-windows"),
("aarch64-uwp-windows-msvc", "aarch64-pc-windows-msvc"),
("aarch64-wrs-vxworks", "aarch64-unknown-linux-gnu"),
("aarch64_be-unknown-hermit", "aarch64_be-unknown-hermit"),
("aarch64_be-unknown-linux-gnu", "aarch64_be-unknown-linux-gnu"),
("aarch64_be-unknown-linux-gnu_ilp32", "aarch64_be-unknown-linux-gnu_ilp32"),
("aarch64_be-unknown-linux-musl", "aarch64_be-unknown-linux-musl"),
("aarch64_be-unknown-netbsd", "aarch64_be-unknown-netbsd"),
("aarch64_be-unknown-none-softfloat", "aarch64_be-unknown-none"),
("amdgcn-amd-amdhsa", "amdgcn-amd-amdhsa"),
("arm-linux-androideabi", "arm-linux-androideabi"),
("arm-unknown-linux-gnueabi", "arm-unknown-linux-gnueabi"),
("arm-unknown-linux-gnueabihf", "arm-unknown-linux-gnueabihf"),
("arm-unknown-linux-musleabi", "arm-unknown-linux-musleabi"),
("arm-unknown-linux-musleabihf", "arm-unknown-linux-musleabihf"),
("arm64_32-apple-watchos", "arm64_32-apple-watchos"),
("arm64e-apple-darwin", "arm64e-apple-macosx"),
("arm64e-apple-ios", "arm64e-apple-ios"),
("arm64e-apple-tvos", "arm64e-apple-tvos"),
("arm64ec-pc-windows-msvc", "arm64ec-pc-windows-msvc"),
("armeb-unknown-linux-gnueabi", "armeb-unknown-linux-gnueabi"),
("armebv7r-none-eabi", "armebv7r-none-eabi"),
("armebv7r-none-eabihf", "armebv7r-none-eabihf"),
("armv4t-none-eabi", "armv4t-none-eabi"),
("armv4t-unknown-linux-gnueabi", "armv4t-unknown-linux-gnueabi"),
("armv5te-none-eabi", "armv5te-none-eabi"),
("armv5te-unknown-linux-gnueabi", "armv5te-unknown-linux-gnueabi"),
("armv5te-unknown-linux-musleabi", "armv5te-unknown-linux-musleabi"),
("armv5te-unknown-linux-uclibceabi", "armv5te-unknown-linux-gnueabi"),
("armv6-unknown-freebsd", "armv6-unknown-freebsd-gnueabihf"),
("armv6-unknown-netbsd-eabihf", "armv6-unknown-netbsdelf-eabihf"),
("armv6k-nintendo-3ds", "armv6k-none-eabihf"),
("armv7-apple-ios", "armv7-apple-ios7.0.0"),
("armv7-linux-androideabi", "armv7-none-linux-android"),
("armv7-rtems-eabihf", "armv7-unknown-none-eabihf"),
("armv7-sony-vita-newlibeabihf", "thumbv7a-sony-vita-eabihf"),
("armv7-unknown-freebsd", "armv7-unknown-freebsd-gnueabihf"),
("armv7-unknown-linux-gnueabi", "armv7-unknown-linux-gnueabi"),
("armv7-unknown-linux-gnueabihf", "armv7-unknown-linux-gnueabihf"),
("armv7-unknown-linux-musleabi", "armv7-unknown-linux-musleabi"),
("armv7-unknown-linux-musleabihf", "armv7-unknown-linux-musleabihf"),
("armv7-unknown-linux-ohos", "armv7-unknown-linux-ohos"),
("armv7-unknown-linux-uclibceabi", "armv7-unknown-linux-gnueabi"),
("armv7-unknown-linux-uclibceabihf", "armv7-unknown-linux-gnueabihf"),
("armv7-unknown-netbsd-eabihf", "armv7-unknown-netbsdelf-eabihf"),
("armv7-unknown-trusty", "armv7-unknown-unknown-gnueabi"),
("armv7-wrs-vxworks-eabihf", "armv7-unknown-linux-gnueabihf"),
("armv7a-kmc-solid_asp3-eabi", "armv7a-none-eabi"),
("armv7a-kmc-solid_asp3-eabihf", "armv7a-none-eabihf"),
("armv7a-none-eabi", "armv7a-none-eabi"),
("armv7a-none-eabihf", "armv7a-none-eabihf"),
("armv7a-nuttx-eabi", "armv7a-none-eabi"),
("armv7a-nuttx-eabihf", "armv7a-none-eabihf"),
("armv7a-vex-v5", "armv7a-none-eabihf"),
("armv7k-apple-watchos", "armv7k-apple-watchos"),
("armv7r-none-eabi", "armv7r-none-eabi"),
("armv7r-none-eabihf", "armv7r-none-eabihf"),
("armv7s-apple-ios", "armv7s-apple-ios"),
("armv8r-none-eabihf", "armv8r-none-eabihf"),
("asmjs-unknown-emscripten", "wasm32-unknown-emscripten"),
("avr-none", "avr-unknown-unknown"),
("avr-unknown-gnu-atmega328", "avr-unknown-unknown"),
("bpfeb-unknown-none", "bpfeb"),
("bpfel-unknown-none", "bpfel"),
("csky-unknown-linux-gnuabiv2", "csky-unknown-linux-gnuabiv2"),
("csky-unknown-linux-gnuabiv2hf", "csky-unknown-linux-gnuabiv2"),
("hexagon-unknown-linux-musl", "hexagon-unknown-linux-musl"),
("hexagon-unknown-none-elf", "hexagon-unknown-none-elf"),
("i386-apple-ios", "i386-apple-ios-simulator"),
("i586-pc-windows-msvc", "i586-pc-windows-msvc"),
("i586-unknown-linux-gnu", "i586-unknown-linux-gnu"),
("i586-unknown-linux-musl", "i586-unknown-linux-musl"),
("i586-unknown-netbsd", "i586-unknown-netbsdelf"),
("i586-unknown-redox", "i586-unknown-redox"),
("i686-apple-darwin", "i686-apple-macosx"),
("i686-linux-android", "i686-linux-android"),
("i686-pc-nto-qnx700", "i586-pc-unknown"),
("i686-pc-windows-gnu", "i686-pc-windows-gnu"),
("i686-pc-windows-gnullvm", "i686-pc-windows-gnu"),
("i686-pc-windows-msvc", "i686-pc-windows-msvc"),
("i686-unknown-freebsd", "i686-unknown-freebsd"),
("i686-unknown-haiku", "i686-unknown-haiku"),
("i686-unknown-hurd-gnu", "i686-unknown-hurd-gnu"),
("i686-unknown-linux-gnu", "i686-unknown-linux-gnu"),
("i686-unknown-linux-musl", "i686-unknown-linux-musl"),
("i686-unknown-netbsd", "i686-unknown-netbsdelf"),
("i686-unknown-openbsd", "i686-unknown-openbsd"),
("i686-unknown-uefi", "i686-unknown-windows-gnu"),
("i686-uwp-windows-gnu", "i686-pc-windows-gnu"),
("i686-uwp-windows-msvc", "i686-pc-windows-msvc"),
("i686-win7-windows-gnu", "i686-pc-windows-gnu"),
("i686-win7-windows-msvc", "i686-pc-windows-msvc"),
("i686-wrs-vxworks", "i686-unknown-linux-gnu"),
("loongarch32-unknown-none", "loongarch32-unknown-none"),
("loongarch32-unknown-none-softfloat", "loongarch32-unknown-none"),
("loongarch64-unknown-linux-gnu", "loongarch64-unknown-linux-gnu"),
("loongarch64-unknown-linux-musl", "loongarch64-unknown-linux-musl"),
("loongarch64-unknown-linux-ohos", "loongarch64-unknown-linux-ohos"),
("loongarch64-unknown-none", "loongarch64-unknown-none"),
("loongarch64-unknown-none-softfloat", "loongarch64-unknown-none"),
("m68k-unknown-linux-gnu", "m68k-unknown-linux-gnu"),
("m68k-unknown-none-elf", "m68k"),
("mips-mti-none-elf", "mips"),
("mips-unknown-linux-gnu", "mips-unknown-linux-gnu"),
("mips-unknown-linux-musl", "mips-unknown-linux-musl"),
("mips-unknown-linux-uclibc", "mips-unknown-linux-gnu"),
("mips64-openwrt-linux-musl", "mips64-unknown-linux-musl"),
("mips64-unknown-linux-gnuabi64", "mips64-unknown-linux-gnuabi64"),
("mips64-unknown-linux-muslabi64", "mips64-unknown-linux-musl"),
("mips64el-unknown-linux-gnuabi64", "mips64el-unknown-linux-gnuabi64"),
("mips64el-unknown-linux-muslabi64", "mips64el-unknown-linux-musl"),
("mipsel-mti-none-elf", "mipsel"),
("mipsel-sony-psp", "mipsel-sony-psp"),
("mipsel-sony-psx", "mipsel-sony-psx"),
("mipsel-unknown-linux-gnu", "mipsel-unknown-linux-gnu"),
("mipsel-unknown-linux-musl", "mipsel-unknown-linux-musl"),
("mipsel-unknown-linux-uclibc", "mipsel-unknown-linux-gnu"),
("mipsel-unknown-netbsd", "mipsel-unknown-netbsd"),
("mipsel-unknown-none", "mipsel-unknown-none"),
("mipsisa32r6-unknown-linux-gnu", "mipsisa32r6-unknown-linux-gnu"),
("mipsisa32r6el-unknown-linux-gnu", "mipsisa32r6el-unknown-linux-gnu"),
("mipsisa64r6-unknown-linux-gnuabi64", "mipsisa64r6-unknown-linux-gnuabi64"),
("mipsisa64r6el-unknown-linux-gnuabi64", "mipsisa64r6el-unknown-linux-gnuabi64"),
("msp430-none-elf", "msp430-none-elf"),
("nvptx64-nvidia-cuda", "nvptx64-nvidia-cuda"),
("powerpc-unknown-freebsd", "powerpc-unknown-freebsd13.0"),
("powerpc-unknown-linux-gnu", "powerpc-unknown-linux-gnu"),
("powerpc-unknown-linux-gnuspe", "powerpc-unknown-linux-gnuspe"),
("powerpc-unknown-linux-musl", "powerpc-unknown-linux-musl"),
("powerpc-unknown-linux-muslspe", "powerpc-unknown-linux-muslspe"),
("powerpc-unknown-netbsd", "powerpc-unknown-netbsd"),
("powerpc-unknown-openbsd", "powerpc-unknown-openbsd"),
("powerpc-wrs-vxworks", "powerpc-unknown-linux-gnu"),
("powerpc-wrs-vxworks-spe", "powerpc-unknown-linux-gnuspe"),
("powerpc64-ibm-aix", "powerpc64-ibm-aix"),
("powerpc64-unknown-freebsd", "powerpc64-unknown-freebsd"),
("powerpc64-unknown-linux-gnu", "powerpc64-unknown-linux-gnu"),
("powerpc64-unknown-linux-musl", "powerpc64-unknown-linux-musl"),
("powerpc64-unknown-openbsd", "powerpc64-unknown-openbsd"),
("powerpc64-wrs-vxworks", "powerpc64-unknown-linux-gnu"),
("powerpc64le-unknown-freebsd", "powerpc64le-unknown-freebsd"),
("powerpc64le-unknown-linux-gnu", "powerpc64le-unknown-linux-gnu"),
("powerpc64le-unknown-linux-musl", "powerpc64le-unknown-linux-musl"),
("riscv32-wrs-vxworks", "riscv32-unknown-linux-gnu"),
("riscv32e-unknown-none-elf", "riscv32"),
("riscv32em-unknown-none-elf", "riscv32"),
("riscv32emc-unknown-none-elf", "riscv32"),
("riscv32gc-unknown-linux-gnu", "riscv32-unknown-linux-gnu"),
("riscv32gc-unknown-linux-musl", "riscv32-unknown-linux-musl"),
("riscv32i-unknown-none-elf", "riscv32"),
("riscv32im-risc0-zkvm-elf", "riscv32"),
("riscv32im-unknown-none-elf", "riscv32"),
("riscv32ima-unknown-none-elf", "riscv32"),
("riscv32imac-esp-espidf", "riscv32"),
("riscv32imac-unknown-none-elf", "riscv32"),
("riscv32imac-unknown-nuttx-elf", "riscv32"),
("riscv32imac-unknown-xous-elf", "riscv32"),
("riscv32imafc-esp-espidf", "riscv32"),
("riscv32imafc-unknown-none-elf", "riscv32"),
("riscv32imafc-unknown-nuttx-elf", "riscv32"),
("riscv32imc-esp-espidf", "riscv32"),
("riscv32imc-unknown-none-elf", "riscv32"),
("riscv32imc-unknown-nuttx-elf", "riscv32"),
("riscv64-linux-android", "riscv64-linux-android"),
("riscv64-wrs-vxworks", "riscv64-unknown-linux-gnu"),
("riscv64a23-unknown-linux-gnu", "riscv64-unknown-linux-gnu"),
("riscv64gc-unknown-freebsd", "riscv64-unknown-freebsd"),
("riscv64gc-unknown-fuchsia", "riscv64-unknown-fuchsia"),
("riscv64gc-unknown-hermit", "riscv64-unknown-hermit"),
("riscv64gc-unknown-linux-gnu", "riscv64-unknown-linux-gnu"),
("riscv64gc-unknown-linux-musl", "riscv64-unknown-linux-musl"),
("riscv64gc-unknown-managarm-mlibc", "riscv64-unknown-managarm-mlibc"),
("riscv64gc-unknown-netbsd", "riscv64-unknown-netbsd"),
("riscv64gc-unknown-none-elf", "riscv64"),
("riscv64gc-unknown-nuttx-elf", "riscv64"),
("riscv64gc-unknown-openbsd", "riscv64-unknown-openbsd"),
("riscv64imac-unknown-none-elf", "riscv64"),
("riscv64imac-unknown-nuttx-elf", "riscv64"),
("s390x-unknown-linux-gnu", "s390x-unknown-linux-gnu"),
("s390x-unknown-linux-musl", "s390x-unknown-linux-musl"),
("sparc-unknown-linux-gnu", "sparc-unknown-linux-gnu"),
("sparc-unknown-none-elf", "sparc-unknown-none-elf"),
("sparc64-unknown-linux-gnu", "sparc64-unknown-linux-gnu"),
("sparc64-unknown-netbsd", "sparc64-unknown-netbsd"),
("sparc64-unknown-openbsd", "sparc64-unknown-openbsd"),
("sparcv9-sun-solaris", "sparcv9-sun-solaris"),
("thumbv4t-none-eabi", "thumbv4t-none-eabi"),
("thumbv5te-none-eabi", "thumbv5te-none-eabi"),
("thumbv6m-none-eabi", "thumbv6m-none-eabi"),
("thumbv6m-nuttx-eabi", "thumbv6m-none-eabi"),
("thumbv7a-nuttx-eabi", "thumbv7a-none-eabi"),
("thumbv7a-nuttx-eabihf", "thumbv7a-none-eabihf"),
("thumbv7a-pc-windows-msvc", "thumbv7a-pc-windows-msvc"),
("thumbv7a-uwp-windows-msvc", "thumbv7a-pc-windows-msvc"),
("thumbv7em-none-eabi", "thumbv7em-none-eabi"),
("thumbv7em-none-eabihf", "thumbv7em-none-eabihf"),
("thumbv7em-nuttx-eabi", "thumbv7em-none-eabi"),
("thumbv7em-nuttx-eabihf", "thumbv7em-none-eabihf"),
("thumbv7m-none-eabi", "thumbv7m-none-eabi"),
("thumbv7m-nuttx-eabi", "thumbv7m-none-eabi"),
("thumbv7neon-linux-androideabi", "armv7-none-linux-android"),
("thumbv7neon-unknown-linux-gnueabihf", "armv7-unknown-linux-gnueabihf"),
("thumbv7neon-unknown-linux-musleabihf", "armv7-unknown-linux-musleabihf"),
("thumbv8m.base-none-eabi", "thumbv8m.base-none-eabi"),
("thumbv8m.base-nuttx-eabi", "thumbv8m.base-none-eabi"),
("thumbv8m.main-none-eabi", "thumbv8m.main-none-eabi"),
("thumbv8m.main-none-eabihf", "thumbv8m.main-none-eabihf"),
("thumbv8m.main-nuttx-eabi", "thumbv8m.main-none-eabi"),
("thumbv8m.main-nuttx-eabihf", "thumbv8m.main-none-eabihf"),
("wasm32-unknown-emscripten", "wasm32-unknown-emscripten"),
("wasm32-unknown-unknown", "wasm32-unknown-unknown"),
("wasm32-wali-linux-musl", "wasm32-wasi"),
("wasm32-wasi", "wasm32-wasi"),
("wasm32-wasip1", "wasm32-wasip1"),
("wasm32-wasip1-threads", "wasm32-wasi"),
("wasm32-wasip2", "wasm32-wasip2"),
("wasm32v1-none", "wasm32-unknown-unknown"),
("wasm64-unknown-unknown", "wasm64-unknown-unknown"),
("x86_64-apple-darwin", "x86_64-apple-macosx"),
("x86_64-apple-ios", "x86_64-apple-ios-simulator"),
("x86_64-apple-ios-macabi", "x86_64-apple-ios-macabi"),
("x86_64-apple-tvos", "x86_64-apple-tvos-simulator"),
("x86_64-apple-watchos-sim", "x86_64-apple-watchos-simulator"),
("x86_64-fortanix-unknown-sgx", "x86_64-elf"),
("x86_64-fuchsia", "x86_64-fuchsia"),
("x86_64-linux-android", "x86_64-linux-android"),
("x86_64-lynx-lynxos178", "x86_64-unknown-unknown-gnu"),
("x86_64-pc-cygwin", "x86_64-pc-cygwin"),
("x86_64-pc-nto-qnx710", "x86_64-pc-unknown"),
("x86_64-pc-nto-qnx710_iosock", "x86_64-pc-unknown"),
("x86_64-pc-nto-qnx800", "x86_64-pc-unknown"),
("x86_64-pc-solaris", "x86_64-pc-solaris"),
("x86_64-pc-windows-gnu", "x86_64-pc-windows-gnu"),
("x86_64-pc-windows-gnullvm", "x86_64-pc-windows-gnu"),
("x86_64-pc-windows-msvc", "x86_64-pc-windows-msvc"),
("x86_64-sun-solaris", "x86_64-pc-solaris"),
("x86_64-unikraft-linux-musl", "x86_64-unknown-linux-musl"),
("x86_64-unknown-dragonfly", "x86_64-unknown-dragonfly"),
("x86_64-unknown-freebsd", "x86_64-unknown-freebsd"),
("x86_64-unknown-fuchsia", "x86_64-unknown-fuchsia"),
("x86_64-unknown-haiku", "x86_64-unknown-haiku"),
("x86_64-unknown-hermit", "x86_64-unknown-hermit"),
("x86_64-unknown-hurd-gnu", "x86_64-unknown-hurd-gnu"),
("x86_64-unknown-illumos", "x86_64-pc-solaris"),
("x86_64-unknown-l4re-uclibc", "x86_64-unknown-l4re-gnu"),
("x86_64-unknown-linux-gnu", "x86_64-unknown-linux-gnu"),
("x86_64-unknown-linux-gnux32", "x86_64-unknown-linux-gnux32"),
("x86_64-unknown-linux-musl", "x86_64-unknown-linux-musl"),
("x86_64-unknown-linux-none", "x86_64-unknown-linux-none"),
("x86_64-unknown-linux-ohos", "x86_64-unknown-linux-ohos"),
("x86_64-unknown-managarm-mlibc", "x86_64-unknown-managarm-mlibc"),
("x86_64-unknown-motor", "x86_64-unknown-none-elf"),
("x86_64-unknown-netbsd", "x86_64-unknown-netbsd"),
("x86_64-unknown-none", "x86_64-unknown-none-elf"),
("x86_64-unknown-none-linuxkernel", "x86_64-unknown-none-elf"),
("x86_64-unknown-openbsd", "x86_64-unknown-openbsd"),
("x86_64-unknown-redox", "x86_64-unknown-redox"),
("x86_64-unknown-trusty", "x86_64-unknown-unknown-musl"),
("x86_64-unknown-uefi", "x86_64-unknown-windows"),
("x86_64-uwp-windows-gnu", "x86_64-pc-windows-gnu"),
("x86_64-uwp-windows-msvc", "x86_64-pc-windows-msvc"),
("x86_64-win7-windows-gnu", "x86_64-pc-windows-gnu"),
("x86_64-win7-windows-msvc", "x86_64-pc-windows-msvc"),
("x86_64-wrs-vxworks", "x86_64-unknown-linux-gnu"),
("x86_64h-apple-darwin", "x86_64h-apple-macosx"),
("xtensa-esp32-espidf", "xtensa-none-elf"),
("xtensa-esp32-none-elf", "xtensa-none-elf"),
("xtensa-esp32s2-espidf", "xtensa-none-elf"),
("xtensa-esp32s2-none-elf", "xtensa-none-elf"),
("xtensa-esp32s3-espidf", "xtensa-none-elf"),
("xtensa-esp32s3-none-elf", "xtensa-none-elf"),
];

322
vendor/cc/src/target/llvm.rs vendored Normal file
View File

@@ -0,0 +1,322 @@
use std::borrow::Cow;
use super::{generated, TargetInfo};
impl TargetInfo<'_> {
/// The LLVM/Clang target triple.
///
/// See <https://clang.llvm.org/docs/CrossCompilation.html#target-triple>.
///
/// Rust and Clang don't really agree on target naming, so we first try to
/// find the matching trible based on `rustc`'s output, but if no such
/// triple exists, we attempt to construct the triple from scratch.
///
/// NOTE: You should never need to match on this explicitly, use the
/// fields on [`TargetInfo`] instead.
pub(crate) fn llvm_target(
&self,
rustc_target: &str,
version: Option<&str>,
) -> Cow<'static, str> {
if rustc_target == "armv7-apple-ios" {
// FIXME(madsmtm): Unnecessary once we bump MSRV to Rust 1.74
return Cow::Borrowed("armv7-apple-ios");
} else if self.os == "uefi" {
// Override the UEFI LLVM targets.
//
// The rustc mappings (as of 1.82) for the UEFI targets are:
// * i686-unknown-uefi -> i686-unknown-windows-gnu
// * x86_64-unknown-uefi -> x86_64-unknown-windows
// * aarch64-unknown-uefi -> aarch64-unknown-windows
//
// However, in cc-rs all the UEFI targets use
// -windows-gnu. This has been the case since 2021 [1].
// * i686-unknown-uefi -> i686-unknown-windows-gnu
// * x86_64-unknown-uefi -> x86_64-unknown-windows-gnu
// * aarch64-unknown-uefi -> aarch64-unknown-windows-gnu
//
// For now, override the UEFI mapping to keep the behavior
// of cc-rs unchanged.
//
// TODO: as discussed in [2], it may be possible to switch
// to new UEFI targets added to clang, and regardless it
// would be good to have consistency between rustc and
// cc-rs.
//
// [1]: https://github.com/rust-lang/cc-rs/pull/623
// [2]: https://github.com/rust-lang/cc-rs/pull/1264
return Cow::Owned(format!("{}-unknown-windows-gnu", self.full_arch));
}
// If no version is requested, let's take the triple directly from
// `rustc` (the logic below is not yet good enough for most targets).
//
// FIXME(madsmtm): This should ideally be removed.
if version.is_none() {
if let Ok(index) = generated::LLVM_TARGETS
.binary_search_by_key(&rustc_target, |(rustc_target, _)| rustc_target)
{
let (_, llvm_target) = &generated::LLVM_TARGETS[index];
return Cow::Borrowed(llvm_target);
}
}
// Otherwise, attempt to construct the triple from the target info.
let arch = match self.full_arch {
riscv32 if riscv32.starts_with("riscv32") => "riscv32",
riscv64 if riscv64.starts_with("riscv64") => "riscv64",
"aarch64" if self.vendor == "apple" => "arm64",
"armv7" if self.vendor == "sony" => "thumbv7a", // FIXME
arch => arch,
};
let vendor = match self.vendor {
"kmc" | "nintendo" => "unknown",
"unknown" if self.os == "android" => "linux",
"uwp" => "pc",
"espressif" => "",
_ if self.arch == "msp430" => "",
vendor => vendor,
};
let os = match self.os {
"macos" => "macosx",
"visionos" => "xros",
"uefi" => "windows",
"solid_asp3" | "horizon" | "teeos" | "nuttx" | "espidf" => "none",
"nto" => "unknown", // FIXME
"trusty" => "unknown", // FIXME
os => os,
};
let version = version.unwrap_or("");
let env = match self.env {
"newlib" | "nto70" | "nto71" | "nto71_iosock" | "p1" | "p2" | "relibc" | "sgx"
| "uclibc" => "",
"sim" => "simulator",
env => env,
};
let abi = match self.abi {
"sim" => {
if env != "simulator" {
"simulator"
} else {
""
}
}
"llvm" | "softfloat" | "uwp" | "vec-extabi" => "",
"ilp32" => "_ilp32",
"abi64" => "",
abi => abi,
};
Cow::Owned(match (vendor, env, abi) {
("", "", "") => format!("{arch}-{os}{version}"),
("", env, abi) => format!("{arch}-{os}{version}-{env}{abi}"),
(vendor, "", "") => format!("{arch}-{vendor}-{os}{version}"),
(vendor, env, abi) => format!("{arch}-{vendor}-{os}{version}-{env}{abi}"),
})
}
}
#[cfg(test)]
mod tests {
use std::process::Command;
use crate::TargetInfo;
#[test]
fn test_old_ios_target() {
assert_eq!(
TargetInfo {
full_arch: "armv7",
arch: "armv7",
vendor: "apple",
os: "ios",
env: "",
abi: "",
}
.llvm_target("armv7-apple-ios", None),
"armv7-apple-ios"
);
}
#[test]
fn basic_llvm_triple_guessing() {
assert_eq!(
TargetInfo {
full_arch: "aarch64",
arch: "aarch64",
vendor: "unknown",
os: "linux",
env: "",
abi: "",
}
.llvm_target("invalid", None),
"aarch64-unknown-linux"
);
assert_eq!(
TargetInfo {
full_arch: "x86_64",
arch: "x86_64",
vendor: "unknown",
os: "linux",
env: "gnu",
abi: "",
}
.llvm_target("invalid", None),
"x86_64-unknown-linux-gnu"
);
assert_eq!(
TargetInfo {
full_arch: "x86_64",
arch: "x86_64",
vendor: "unknown",
os: "linux",
env: "gnu",
abi: "eabi",
}
.llvm_target("invalid", None),
"x86_64-unknown-linux-gnueabi"
);
assert_eq!(
TargetInfo {
full_arch: "x86_64",
arch: "x86_64",
vendor: "apple",
os: "macos",
env: "",
abi: "",
}
.llvm_target("invalid", None),
"x86_64-apple-macosx"
);
}
#[test]
fn llvm_version() {
assert_eq!(
TargetInfo {
full_arch: "aarch64",
arch: "aarch64",
vendor: "apple",
os: "ios",
env: "",
abi: "sim",
}
.llvm_target("aarch64-apple-ios-sim", Some("14.0")),
"arm64-apple-ios14.0-simulator"
);
assert_eq!(
TargetInfo {
full_arch: "aarch64",
arch: "aarch64",
vendor: "apple",
os: "visionos",
env: "",
abi: "",
}
.llvm_target("aarch64-apple-visionos", Some("2.0")),
"arm64-apple-xros2.0"
);
assert_eq!(
TargetInfo {
full_arch: "aarch64",
arch: "aarch64",
vendor: "apple",
os: "ios",
env: "",
abi: "macabi",
}
.llvm_target("aarch64-apple-ios-macabi", Some("13.1")),
"arm64-apple-ios13.1-macabi"
);
}
#[test]
fn uefi() {
assert_eq!(
TargetInfo {
full_arch: "i686",
arch: "x86",
vendor: "unknown",
os: "uefi",
env: "",
abi: "",
}
.llvm_target("i686-unknown-uefi", None),
"i686-unknown-windows-gnu"
);
assert_eq!(
TargetInfo {
full_arch: "x86_64",
arch: "x86_64",
vendor: "unknown",
os: "uefi",
env: "",
abi: "",
}
.llvm_target("x86_64-unknown-uefi", None),
"x86_64-unknown-windows-gnu"
);
assert_eq!(
TargetInfo {
full_arch: "aarch64",
arch: "aarch64",
vendor: "unknown",
os: "uefi",
env: "",
abi: "",
}
.llvm_target("aarch64-unknown-uefi", None),
"aarch64-unknown-windows-gnu"
);
}
#[test]
#[ignore = "not yet done"]
fn llvm_for_all_rustc_targets() {
let rustc = std::env::var("RUSTC").unwrap_or_else(|_| "rustc".to_string());
let target_list = Command::new(&rustc)
.arg("--print=target-list")
.output()
.unwrap()
.stdout;
let target_list = String::from_utf8(target_list).unwrap();
let mut has_failure = false;
for target in target_list.lines() {
let spec_json = Command::new(&rustc)
.arg("--target")
.arg(target)
.arg("-Zunstable-options")
.arg("--print=target-spec-json")
.env("RUSTC_BOOTSTRAP", "1") // Crimes
.output()
.unwrap()
.stdout;
let spec_json = String::from_utf8(spec_json).unwrap();
// JSON crimes
let expected = spec_json
.split_once("llvm-target\": \"")
.unwrap()
.1
.split_once("\"")
.unwrap()
.0;
let actual = TargetInfo::from_rustc_target(target)
.map(|target| target.llvm_target("invalid", None));
if Some(expected) != actual.as_deref().ok() {
eprintln!("failed comparing {target}:");
eprintln!(" expected: Ok({expected:?})");
eprintln!(" actual: {actual:?}");
eprintln!();
has_failure = true;
}
}
if has_failure {
panic!("failed comparing targets");
}
}
}

600
vendor/cc/src/target/parser.rs vendored Normal file
View File

@@ -0,0 +1,600 @@
use std::env;
use crate::{target::TargetInfo, utilities::OnceLock, Error, ErrorKind};
#[derive(Debug)]
struct TargetInfoParserInner {
full_arch: Box<str>,
arch: Box<str>,
vendor: Box<str>,
os: Box<str>,
env: Box<str>,
abi: Box<str>,
}
impl TargetInfoParserInner {
fn from_cargo_environment_variables() -> Result<Self, Error> {
// `TARGET` must be present.
//
// No need to emit `rerun-if-env-changed` for this,
// as it is controlled by Cargo itself.
#[allow(clippy::disallowed_methods)]
let target_name = env::var("TARGET").map_err(|err| {
Error::new(
ErrorKind::EnvVarNotFound,
format!("failed reading TARGET: {err}"),
)
})?;
// Parse the full architecture name from the target name.
let (full_arch, _rest) = target_name.split_once('-').ok_or(Error::new(
ErrorKind::InvalidTarget,
format!("target `{target_name}` only had a single component (at least two required)"),
))?;
let cargo_env = |name, fallback: Option<&str>| -> Result<Box<str>, Error> {
// No need to emit `rerun-if-env-changed` for these,
// as they are controlled by Cargo itself.
#[allow(clippy::disallowed_methods)]
match env::var(name) {
Ok(var) => Ok(var.into_boxed_str()),
Err(err) => match fallback {
Some(fallback) => Ok(fallback.into()),
None => Err(Error::new(
ErrorKind::EnvVarNotFound,
format!("did not find fallback information for target `{target_name}`, and failed reading {name}: {err}"),
)),
},
}
};
// Prefer to use `CARGO_ENV_*` if set, since these contain the most
// correct information relative to the current `rustc`, and makes it
// possible to support custom target JSON specs unknown to `rustc`.
//
// NOTE: If the user is using an older `rustc`, that data may be older
// than our pre-generated data, but we still prefer Cargo's view of
// the world, since at least `cc` won't differ from `rustc` in that
// case.
//
// These may not be set in case the user depended on being able to
// just set `TARGET` outside of build scripts; in those cases, fall
// back back to data from the known set of target names instead.
//
// See discussion in #1225 for further details.
let fallback_target = TargetInfo::from_rustc_target(&target_name).ok();
let ft = fallback_target.as_ref();
let arch = cargo_env("CARGO_CFG_TARGET_ARCH", ft.map(|t| t.arch))?;
let vendor = cargo_env("CARGO_CFG_TARGET_VENDOR", ft.map(|t| t.vendor))?;
let os = cargo_env("CARGO_CFG_TARGET_OS", ft.map(|t| t.os))?;
let env = cargo_env("CARGO_CFG_TARGET_ENV", ft.map(|t| t.env))?;
// `target_abi` was stabilized in Rust 1.78, which is higher than our
// MSRV, so it may not always be available; In that case, fall back to
// `""`, which is _probably_ correct for unknown target names.
let abi = cargo_env("CARGO_CFG_TARGET_ABI", ft.map(|t| t.abi))
.unwrap_or_else(|_| String::default().into_boxed_str());
Ok(Self {
full_arch: full_arch.to_string().into_boxed_str(),
arch,
vendor,
os,
env,
abi,
})
}
}
/// Parser for [`TargetInfo`], contains cached information.
#[derive(Default, Debug)]
pub(crate) struct TargetInfoParser(OnceLock<Result<TargetInfoParserInner, Error>>);
impl TargetInfoParser {
pub fn parse_from_cargo_environment_variables(&self) -> Result<TargetInfo<'_>, Error> {
match self
.0
.get_or_init(TargetInfoParserInner::from_cargo_environment_variables)
{
Ok(TargetInfoParserInner {
full_arch,
arch,
vendor,
os,
env,
abi,
}) => Ok(TargetInfo {
full_arch,
arch,
vendor,
os,
env,
abi,
}),
Err(e) => Err(e.clone()),
}
}
}
/// Parse the full architecture in the target name into the simpler
/// `cfg(target_arch = "...")` that `rustc` exposes.
fn parse_arch(full_arch: &str) -> Option<&str> {
// NOTE: Some of these don't necessarily match an existing target in
// `rustc`. They're parsed anyhow to be as forward-compatible as possible,
// while still being correct.
//
// See also:
// https://docs.rs/cfg-expr/0.18.0/cfg_expr/targets/index.html
// https://docs.rs/target-lexicon/0.13.2/target_lexicon/enum.Architecture.html
// https://gcc.gnu.org/onlinedocs/gcc/Submodel-Options.html
// `clang -print-targets`
Some(match full_arch {
arch if arch.starts_with("mipsisa32r6") => "mips32r6", // mipsisa32r6 | mipsisa32r6el
arch if arch.starts_with("mipsisa64r6") => "mips64r6", // mipsisa64r6 | mipsisa64r6el
arch if arch.starts_with("mips64") => "mips64", // mips64 | mips64el
arch if arch.starts_with("mips") => "mips", // mips | mipsel
arch if arch.starts_with("loongarch64") => "loongarch64",
arch if arch.starts_with("loongarch32") => "loongarch32",
arch if arch.starts_with("powerpc64") => "powerpc64", // powerpc64 | powerpc64le
arch if arch.starts_with("powerpc") => "powerpc",
arch if arch.starts_with("ppc64") => "powerpc64",
arch if arch.starts_with("ppc") => "powerpc",
arch if arch.starts_with("x86_64") => "x86_64", // x86_64 | x86_64h
arch if arch.starts_with("i") && arch.ends_with("86") => "x86", // i386 | i586 | i686
"arm64ec" => "arm64ec", // https://github.com/rust-lang/rust/issues/131172
arch if arch.starts_with("aarch64") => "aarch64", // arm64e | arm64_32
arch if arch.starts_with("arm64") => "aarch64", // aarch64 | aarch64_be
arch if arch.starts_with("arm") => "arm", // arm | armv7s | armeb | ...
arch if arch.starts_with("thumb") => "arm", // thumbv4t | thumbv7a | thumbv8m | ...
arch if arch.starts_with("riscv64") => "riscv64",
arch if arch.starts_with("riscv32") => "riscv32",
arch if arch.starts_with("wasm64") => "wasm64",
arch if arch.starts_with("wasm32") => "wasm32", // wasm32 | wasm32v1
"asmjs" => "wasm32",
arch if arch.starts_with("nvptx64") => "nvptx64",
arch if arch.starts_with("nvptx") => "nvptx",
arch if arch.starts_with("bpf") => "bpf", // bpfeb | bpfel
// https://github.com/bytecodealliance/wasmtime/tree/v30.0.1/pulley
arch if arch.starts_with("pulley64") => "pulley64",
arch if arch.starts_with("pulley32") => "pulley32",
// https://github.com/Clever-ISA/Clever-ISA
arch if arch.starts_with("clever") => "clever",
"sparc" | "sparcv7" | "sparcv8" => "sparc",
"sparc64" | "sparcv9" => "sparc64",
"amdgcn" => "amdgpu",
"avr" => "avr",
"csky" => "csky",
"hexagon" => "hexagon",
"m68k" => "m68k",
"msp430" => "msp430",
"r600" => "r600",
"s390x" => "s390x",
"xtensa" => "xtensa",
// Arches supported by gcc, but not LLVM.
arch if arch.starts_with("alpha") => "alpha", // DEC Alpha
"hppa" => "hppa", // https://en.wikipedia.org/wiki/PA-RISC, also known as HPPA
arch if arch.starts_with("sh") => "sh", // SuperH
_ => return None,
})
}
/// Parse environment and ABI from the last component of the target name.
fn parse_envabi(last_component: &str) -> Option<(&str, &str)> {
let (env, abi) = match last_component {
// Combined environment and ABI
// gnullvm | gnueabi | gnueabihf | gnuabiv2 | gnuabi64 | gnuspe | gnux32 | gnu_ilp32
env_and_abi if env_and_abi.starts_with("gnu") => {
let abi = env_and_abi.strip_prefix("gnu").unwrap();
let abi = abi.strip_prefix("_").unwrap_or(abi);
("gnu", abi)
}
// musl | musleabi | musleabihf | muslabi64 | muslspe
env_and_abi if env_and_abi.starts_with("musl") => {
("musl", env_and_abi.strip_prefix("musl").unwrap())
}
// uclibc | uclibceabi | uclibceabihf
env_and_abi if env_and_abi.starts_with("uclibc") => {
("uclibc", env_and_abi.strip_prefix("uclibc").unwrap())
}
// newlib | newlibeabihf
env_and_abi if env_and_abi.starts_with("newlib") => {
("newlib", env_and_abi.strip_prefix("newlib").unwrap())
}
// Environments
"msvc" => ("msvc", ""),
"ohos" => ("ohos", ""),
"qnx700" => ("nto70", ""),
"qnx710_iosock" => ("nto71_iosock", ""),
"qnx710" => ("nto71", ""),
"qnx800" => ("nto80", ""),
"sgx" => ("sgx", ""),
"threads" => ("threads", ""),
"mlibc" => ("mlibc", ""),
// ABIs
"abi64" => ("", "abi64"),
"abiv2" => ("", "spe"),
"eabi" => ("", "eabi"),
"eabihf" => ("", "eabihf"),
"macabi" => ("macabi", ""),
"sim" => ("sim", ""),
"softfloat" => ("", "softfloat"),
"spe" => ("", "spe"),
"x32" => ("", "x32"),
// Badly named targets, ELF is already known from target OS.
// Probably too late to fix now though.
"elf" => ("", ""),
// Undesirable to expose to user code (yet):
// https://github.com/rust-lang/rust/pull/131166#issuecomment-2389541917
"freestanding" => ("", ""),
_ => return None,
};
Some((env, abi))
}
impl<'a> TargetInfo<'a> {
pub(crate) fn from_rustc_target(target: &'a str) -> Result<Self, Error> {
// FIXME(madsmtm): This target should be renamed, cannot be parsed
// with the means we do below (since `none` must not be interpreted
// as an env/ABI).
if target == "x86_64-unknown-linux-none" {
return Ok(Self {
full_arch: "x86_64",
arch: "x86_64",
vendor: "unknown",
os: "linux",
env: "",
abi: "",
});
}
if target == "armv7a-vex-v5" {
return Ok(Self {
full_arch: "armv7a",
arch: "arm",
vendor: "vex",
os: "vexos",
env: "v5",
abi: "eabihf",
});
}
let mut components = target.split('-');
// Insist that the target name contains at least a valid architecture.
let full_arch = components.next().ok_or(Error::new(
ErrorKind::InvalidTarget,
"target was empty".to_string(),
))?;
let arch = parse_arch(full_arch).ok_or_else(|| {
Error::new(
ErrorKind::UnknownTarget,
format!("target `{target}` had an unknown architecture"),
)
})?;
// Newer target names have begun omitting the vendor, so the only
// component we know must be there is the OS name.
let components: Vec<_> = components.collect();
let (vendor, os, mut env, mut abi) = match &*components {
[] => {
return Err(Error::new(
ErrorKind::InvalidTarget,
format!("target `{target}` must have at least two components"),
))
}
// Two components; format is `arch-os`.
[os] => ("unknown", *os, "", ""),
// The three-component case is a bit tricky to handle, it could
// either have the format `arch-vendor-os` or `arch-os-env+abi`.
[vendor_or_os, os_or_envabi] => {
// We differentiate between these by checking if the last
// component is an env/ABI; if it isn't, then it's probably
// an OS instead.
if let Some((env, abi)) = parse_envabi(os_or_envabi) {
("unknown", *vendor_or_os, env, abi)
} else {
(*vendor_or_os, *os_or_envabi, "", "")
}
}
// Four components; format is `arch-vendor-os-env+abi`.
[vendor, os, envabi] => {
let (env, abi) = parse_envabi(envabi).ok_or_else(|| {
Error::new(
ErrorKind::UnknownTarget,
format!("unknown environment/ABI `{envabi}` in target `{target}`"),
)
})?;
(*vendor, *os, env, abi)
}
_ => {
return Err(Error::new(
ErrorKind::InvalidTarget,
format!("too many components in target `{target}`"),
))
}
};
// Part of the architecture name is carried over into the ABI.
match full_arch {
// https://github.com/rust-lang/compiler-team/issues/830
arch if arch.starts_with("riscv32e") => {
abi = "ilp32e";
}
_ => {}
}
// Various environment/ABIs are determined based on OS name.
match os {
"3ds" | "rtems" | "espidf" => env = "newlib",
"vxworks" => env = "gnu",
"redox" => env = "relibc",
"aix" => abi = "vec-extabi",
_ => {}
}
// Extra overrides for badly named targets.
match target {
// Actually simulator targets.
"i386-apple-ios" | "x86_64-apple-ios" | "x86_64-apple-tvos" => {
env = "sim";
}
// Name should've contained `muslabi64`.
"mips64-openwrt-linux-musl" => {
abi = "abi64";
}
// Specifies abi even though not in name.
"armv6-unknown-freebsd" | "armv6k-nintendo-3ds" | "armv7-unknown-freebsd" => {
abi = "eabihf";
}
// Specifies abi even though not in name.
"armv7-unknown-linux-ohos" | "armv7-unknown-trusty" => {
abi = "eabi";
}
_ => {}
}
let os = match os {
// Horizon is the common/internal OS name for 3DS and the Switch.
"3ds" | "switch" => "horizon",
// FIXME(madsmtm): macOS targets are badly named.
"darwin" => "macos",
// WASI targets contain the preview version in them too. Should've
// been `wasi-p1`/`wasi-p2`, but that's probably too late now.
os if os.starts_with("wasi") => {
env = os.strip_prefix("wasi").unwrap();
"wasi"
}
// FIXME(madsmtm): Badly named targets `*-linux-androideabi`,
// should be `*-android-eabi`.
"androideabi" => {
abi = "eabi";
"android"
}
os => os,
};
let vendor = match vendor {
// esp, esp32, esp32s2 etc.
vendor if vendor.starts_with("esp") => "espressif",
// FIXME(madsmtm): Badly named targets `*-linux-android*`,
// "linux" makes no sense as the vendor name.
"linux" if os == "android" || os == "androideabi" => "unknown",
// FIXME(madsmtm): Fix in `rustc` after
// https://github.com/rust-lang/compiler-team/issues/850.
"wali" => "unknown",
"lynx" => "unknown",
// Some Linux distributions set their name as the target vendor,
// so we have to assume that it can be an arbitary string.
vendor => vendor,
};
// Intentionally also marked as an ABI:
// https://github.com/rust-lang/rust/pull/86922
if vendor == "fortanix" {
abi = "fortanix";
}
if vendor == "uwp" {
abi = "uwp";
}
if ["powerpc64-unknown-linux-gnu", "powerpc64-wrs-vxworks"].contains(&target) {
abi = "elfv1";
}
if [
"powerpc64-unknown-freebsd",
"powerpc64-unknown-linux-musl",
"powerpc64-unknown-openbsd",
"powerpc64le-unknown-freebsd",
"powerpc64le-unknown-linux-gnu",
"powerpc64le-unknown-linux-musl",
]
.contains(&target)
{
abi = "elfv2";
}
Ok(Self {
full_arch,
arch,
vendor,
os,
env,
abi,
})
}
}
#[cfg(test)]
#[allow(unexpected_cfgs)]
mod tests {
use std::process::Command;
use super::TargetInfo;
use crate::ErrorKind;
// Test tier 1 targets.
#[test]
fn tier1() {
let targets = [
"aarch64-unknown-linux-gnu",
"aarch64-apple-darwin",
"i686-pc-windows-gnu",
"i686-pc-windows-msvc",
"i686-unknown-linux-gnu",
"x86_64-apple-darwin",
"x86_64-pc-windows-gnu",
"x86_64-pc-windows-msvc",
"x86_64-unknown-linux-gnu",
];
for target in targets {
// Check that they parse.
let _ = TargetInfo::from_rustc_target(target).unwrap();
}
}
// Various custom target names not (or no longer) known by `rustc`.
#[test]
fn parse_extra() {
let targets = [
"aarch64-unknown-none-gnu",
"aarch64-uwp-windows-gnu",
"arm-frc-linux-gnueabi",
"arm-unknown-netbsd-eabi",
"armv7neon-unknown-linux-gnueabihf",
"armv7neon-unknown-linux-musleabihf",
"thumbv7-unknown-linux-gnueabihf",
"thumbv7-unknown-linux-musleabihf",
"armv7-apple-ios",
"wasm32-wasi",
"x86_64-rumprun-netbsd",
"x86_64-unknown-linux",
"x86_64-alpine-linux-musl",
"x86_64-chimera-linux-musl",
"x86_64-foxkit-linux-musl",
"arm-poky-linux-gnueabi",
"x86_64-unknown-moturus",
"x86_64-unknown-managarm-mlibc",
];
for target in targets {
// Check that they parse.
let _ = TargetInfo::from_rustc_target(target).unwrap();
}
}
fn target_from_rustc_cfgs<'a>(target: &'a str, cfgs: &'a str) -> TargetInfo<'a> {
// Cannot determine full architecture from cfgs.
let (full_arch, _rest) = target.split_once('-').expect("target to have arch");
let mut target = TargetInfo {
full_arch,
arch: "invalid-none-set",
vendor: "invalid-none-set",
os: "invalid-none-set",
env: "invalid-none-set",
// Not set in older Rust versions
abi: "",
};
for cfg in cfgs.lines() {
if let Some((name, value)) = cfg.split_once('=') {
// Remove whitespace, if `rustc` decided to insert any.
let name = name.trim();
let value = value.trim();
// Remove quotes around value.
let value = value.strip_prefix('"').unwrap_or(value);
let value = value.strip_suffix('"').unwrap_or(value);
match name {
"target_arch" => target.arch = value,
"target_vendor" => target.vendor = value,
"target_os" => target.os = value,
"target_env" => target.env = value,
"target_abi" => target.abi = value,
_ => {}
}
} else {
// Skip cfgs like `debug_assertions` and `unix`.
}
}
if matches!(target.abi, "macabi" | "sim") {
assert_eq!(target.env, target.abi);
target.abi = "";
}
target
}
#[test]
fn unknown_env_determined_as_unknown() {
let err = TargetInfo::from_rustc_target("aarch64-unknown-linux-bogus").unwrap_err();
assert!(matches!(err.kind, ErrorKind::UnknownTarget));
}
// Used in .github/workflows/test-rustc-targets.yml
#[test]
#[cfg_attr(
not(rustc_target_test),
ignore = "must enable explicitly with --cfg=rustc_target_test"
)]
fn parse_rustc_targets() {
let rustc = std::env::var("RUSTC").unwrap_or_else(|_| "rustc".to_string());
let target_list = Command::new(&rustc)
.arg("--print=target-list")
.output()
.unwrap()
.stdout;
let target_list = String::from_utf8(target_list).unwrap();
let mut has_failure = false;
for target in target_list.lines() {
let cfgs = Command::new(&rustc)
.arg("--target")
.arg(target)
.arg("--print=cfg")
.output()
.unwrap()
.stdout;
let cfgs = String::from_utf8(cfgs).unwrap();
let expected = target_from_rustc_cfgs(target, &cfgs);
let actual = TargetInfo::from_rustc_target(target);
if Some(&expected) != actual.as_ref().ok() {
eprintln!("failed comparing {target}:");
eprintln!(" expected: Ok({expected:?})");
eprintln!(" actual: {actual:?}");
eprintln!();
has_failure = true;
}
}
if has_failure {
panic!("failed comparing targets");
}
}
}

86
vendor/cc/src/tempfile.rs vendored Normal file
View File

@@ -0,0 +1,86 @@
#![cfg_attr(target_family = "wasm", allow(unused))]
use std::{
collections::hash_map::RandomState,
fs::{remove_file, File, OpenOptions},
hash::{BuildHasher, Hasher},
io, os,
path::{Path, PathBuf},
};
#[cfg(not(any(unix, target_family = "wasm", windows)))]
compile_error!("Your system is not supported since cc cannot create named tempfile");
fn rand() -> u64 {
RandomState::new().build_hasher().finish()
}
fn tmpname(suffix: &str) -> String {
format!("{}{}", rand(), suffix)
}
fn create_named(path: &Path) -> io::Result<File> {
let mut open_options = OpenOptions::new();
open_options.read(true).write(true).create_new(true);
#[cfg(all(unix, not(target_os = "wasi")))]
<OpenOptions as os::unix::fs::OpenOptionsExt>::mode(&mut open_options, 0o600);
#[cfg(windows)]
<OpenOptions as os::windows::fs::OpenOptionsExt>::custom_flags(
&mut open_options,
::find_msvc_tools::windows_sys::FILE_ATTRIBUTE_TEMPORARY,
);
open_options.open(path)
}
pub(super) struct NamedTempfile {
path: PathBuf,
file: Option<File>,
}
impl NamedTempfile {
pub(super) fn new(base: &Path, suffix: &str) -> io::Result<Self> {
for _ in 0..10 {
let path = base.join(tmpname(suffix));
match create_named(&path) {
Ok(file) => {
return Ok(Self {
file: Some(file),
path,
})
}
Err(e) if e.kind() == io::ErrorKind::AlreadyExists => continue,
Err(e) => return Err(e),
};
}
Err(io::Error::new(
io::ErrorKind::AlreadyExists,
format!(
"too many temporary files exist in base `{}` with suffix `{}`",
base.display(),
suffix
),
))
}
pub(super) fn path(&self) -> &Path {
&self.path
}
pub(super) fn take_file(&mut self) -> Option<File> {
self.file.take()
}
}
impl Drop for NamedTempfile {
fn drop(&mut self) {
// On Windows you have to close all handle to it before
// removing the file.
self.file.take();
let _ = remove_file(&self.path);
}
}

564
vendor/cc/src/tool.rs vendored Normal file
View File

@@ -0,0 +1,564 @@
use crate::{
command_helpers::{run_output, spawn, CargoOutput},
run,
tempfile::NamedTempfile,
Error, ErrorKind, OutputKind,
};
use std::io::Read;
use std::{
borrow::Cow,
collections::HashMap,
env,
ffi::{OsStr, OsString},
io::Write,
path::{Path, PathBuf},
process::{Command, Stdio},
sync::RwLock,
};
pub(crate) type CompilerFamilyLookupCache = HashMap<Box<[Box<OsStr>]>, ToolFamily>;
/// Configuration used to represent an invocation of a C compiler.
///
/// This can be used to figure out what compiler is in use, what the arguments
/// to it are, and what the environment variables look like for the compiler.
/// This can be used to further configure other build systems (e.g. forward
/// along CC and/or CFLAGS) or the `to_command` method can be used to run the
/// compiler itself.
#[derive(Clone, Debug)]
#[allow(missing_docs)]
pub struct Tool {
pub(crate) path: PathBuf,
pub(crate) cc_wrapper_path: Option<PathBuf>,
pub(crate) cc_wrapper_args: Vec<OsString>,
pub(crate) args: Vec<OsString>,
pub(crate) env: Vec<(OsString, OsString)>,
pub(crate) family: ToolFamily,
pub(crate) cuda: bool,
pub(crate) removed_args: Vec<OsString>,
pub(crate) has_internal_target_arg: bool,
}
impl Tool {
pub(crate) fn from_find_msvc_tools(tool: ::find_msvc_tools::Tool) -> Self {
let mut cc_tool = Self::with_family(
tool.path().into(),
ToolFamily::Msvc {
clang_cl: tool.is_clang_cl(),
},
);
cc_tool.env = tool
.env()
.into_iter()
.map(|(k, v)| (k.clone(), v.clone()))
.collect();
cc_tool
}
pub(crate) fn new(
path: PathBuf,
cached_compiler_family: &RwLock<CompilerFamilyLookupCache>,
cargo_output: &CargoOutput,
out_dir: Option<&Path>,
) -> Self {
Self::with_features(
path,
vec![],
false,
cached_compiler_family,
cargo_output,
out_dir,
)
}
pub(crate) fn with_args(
path: PathBuf,
args: Vec<String>,
cached_compiler_family: &RwLock<CompilerFamilyLookupCache>,
cargo_output: &CargoOutput,
out_dir: Option<&Path>,
) -> Self {
Self::with_features(
path,
args,
false,
cached_compiler_family,
cargo_output,
out_dir,
)
}
/// Explicitly set the `ToolFamily`, skipping name-based detection.
pub(crate) fn with_family(path: PathBuf, family: ToolFamily) -> Self {
Self {
path,
cc_wrapper_path: None,
cc_wrapper_args: Vec::new(),
args: Vec::new(),
env: Vec::new(),
family,
cuda: false,
removed_args: Vec::new(),
has_internal_target_arg: false,
}
}
pub(crate) fn with_features(
path: PathBuf,
args: Vec<String>,
cuda: bool,
cached_compiler_family: &RwLock<CompilerFamilyLookupCache>,
cargo_output: &CargoOutput,
out_dir: Option<&Path>,
) -> Self {
fn is_zig_cc(path: &Path, cargo_output: &CargoOutput) -> bool {
run_output(
Command::new(path).arg("--version"),
// tool detection issues should always be shown as warnings
cargo_output,
)
.map(|o| String::from_utf8_lossy(&o).contains("ziglang"))
.unwrap_or_default()
|| {
match path.file_name().map(OsStr::to_string_lossy) {
Some(fname) => fname.contains("zig"),
_ => false,
}
}
}
fn guess_family_from_stdout(
stdout: &str,
path: &Path,
args: &[String],
cargo_output: &CargoOutput,
) -> Result<ToolFamily, Error> {
cargo_output.print_debug(&stdout);
// https://gitlab.kitware.com/cmake/cmake/-/blob/69a2eeb9dff5b60f2f1e5b425002a0fd45b7cadb/Modules/CMakeDetermineCompilerId.cmake#L267-271
// stdin is set to null to ensure that the help output is never paginated.
let accepts_cl_style_flags = run(
Command::new(path).args(args).arg("-?").stdin(Stdio::null()),
&{
// the errors are not errors!
let mut cargo_output = cargo_output.clone();
cargo_output.warnings = cargo_output.debug;
cargo_output.output = OutputKind::Discard;
cargo_output
},
)
.is_ok();
let clang = stdout.contains(r#""clang""#);
let gcc = stdout.contains(r#""gcc""#);
let emscripten = stdout.contains(r#""emscripten""#);
let vxworks = stdout.contains(r#""VxWorks""#);
match (clang, accepts_cl_style_flags, gcc, emscripten, vxworks) {
(clang_cl, true, _, false, false) => Ok(ToolFamily::Msvc { clang_cl }),
(true, _, _, _, false) | (_, _, _, true, false) => Ok(ToolFamily::Clang {
zig_cc: is_zig_cc(path, cargo_output),
}),
(false, false, true, _, false) | (_, _, _, _, true) => Ok(ToolFamily::Gnu),
(false, false, false, false, false) => {
cargo_output.print_warning(&"Compiler family detection failed since it does not define `__clang__`, `__GNUC__`, `__EMSCRIPTEN__` or `__VXWORKS__`, also does not accept cl style flag `-?`, fallback to treating it as GNU");
Err(Error::new(
ErrorKind::ToolFamilyMacroNotFound,
"Expects macro `__clang__`, `__GNUC__` or `__EMSCRIPTEN__`, `__VXWORKS__` or accepts cl style flag `-?`, but found none",
))
}
}
}
fn detect_family_inner(
path: &Path,
args: &[String],
cargo_output: &CargoOutput,
out_dir: Option<&Path>,
) -> Result<ToolFamily, Error> {
let out_dir = out_dir
.map(Cow::Borrowed)
.unwrap_or_else(|| Cow::Owned(env::temp_dir()));
// Ensure all the parent directories exist otherwise temp file creation
// will fail
std::fs::create_dir_all(&out_dir).map_err(|err| Error {
kind: ErrorKind::IOError,
message: format!("failed to create OUT_DIR '{}': {}", out_dir.display(), err)
.into(),
})?;
let mut tmp =
NamedTempfile::new(&out_dir, "detect_compiler_family.c").map_err(|err| Error {
kind: ErrorKind::IOError,
message: format!(
"failed to create detect_compiler_family.c temp file in '{}': {}",
out_dir.display(),
err
)
.into(),
})?;
let mut tmp_file = tmp.take_file().unwrap();
tmp_file.write_all(include_bytes!("detect_compiler_family.c"))?;
// Close the file handle *now*, otherwise the compiler may fail to open it on Windows
// (#1082). The file stays on disk and its path remains valid until `tmp` is dropped.
tmp_file.flush()?;
tmp_file.sync_data()?;
drop(tmp_file);
// When expanding the file, the compiler prints a lot of information to stderr
// that it is not an error, but related to expanding itself.
//
// cc would have to disable warning here to prevent generation of too many warnings.
let mut compiler_detect_output = cargo_output.clone();
compiler_detect_output.warnings = compiler_detect_output.debug;
let mut cmd = Command::new(path);
cmd.arg("-E").arg(tmp.path());
// The -Wslash-u-filename warning is normally part of stdout.
// But with clang-cl it can be part of stderr instead and exit with a
// non-zero exit code.
let mut captured_cargo_output = compiler_detect_output.clone();
captured_cargo_output.output = OutputKind::Capture;
captured_cargo_output.warnings = true;
let mut child = spawn(&mut cmd, &captured_cargo_output)?;
let mut out = vec![];
let mut err = vec![];
child.stdout.take().unwrap().read_to_end(&mut out)?;
child.stderr.take().unwrap().read_to_end(&mut err)?;
let status = child.wait()?;
let stdout = if [&out, &err]
.iter()
.any(|o| String::from_utf8_lossy(o).contains("-Wslash-u-filename"))
{
run_output(
Command::new(path).arg("-E").arg("--").arg(tmp.path()),
&compiler_detect_output,
)?
} else {
if !status.success() {
return Err(Error::new(
ErrorKind::ToolExecError,
format!(
"command did not execute successfully (status code {status}): {cmd:?}"
),
));
}
out
};
let stdout = String::from_utf8_lossy(&stdout);
guess_family_from_stdout(&stdout, path, args, cargo_output)
}
let detect_family = |path: &Path, args: &[String]| -> Result<ToolFamily, Error> {
let cache_key = [path.as_os_str()]
.iter()
.cloned()
.chain(args.iter().map(OsStr::new))
.map(Into::into)
.collect();
if let Some(family) = cached_compiler_family.read().unwrap().get(&cache_key) {
return Ok(*family);
}
let family = detect_family_inner(path, args, cargo_output, out_dir)?;
cached_compiler_family
.write()
.unwrap()
.insert(cache_key, family);
Ok(family)
};
let family = detect_family(&path, &args).unwrap_or_else(|e| {
cargo_output.print_warning(&format_args!(
"Compiler family detection failed due to error: {e}"
));
match path.file_name().map(OsStr::to_string_lossy) {
Some(fname) if fname.contains("clang-cl") => ToolFamily::Msvc { clang_cl: true },
Some(fname) if fname.ends_with("cl") || fname == "cl.exe" => {
ToolFamily::Msvc { clang_cl: false }
}
Some(fname) if fname.contains("clang") => {
let is_clang_cl = args
.iter()
.any(|a| a.strip_prefix("--driver-mode=") == Some("cl"));
if is_clang_cl {
ToolFamily::Msvc { clang_cl: true }
} else {
ToolFamily::Clang {
zig_cc: is_zig_cc(&path, cargo_output),
}
}
}
Some(fname) if fname.contains("zig") => ToolFamily::Clang { zig_cc: true },
_ => ToolFamily::Gnu,
}
});
Tool {
path,
cc_wrapper_path: None,
cc_wrapper_args: Vec::new(),
args: Vec::new(),
env: Vec::new(),
family,
cuda,
removed_args: Vec::new(),
has_internal_target_arg: false,
}
}
/// Add an argument to be stripped from the final command arguments.
pub(crate) fn remove_arg(&mut self, flag: OsString) {
self.removed_args.push(flag);
}
/// Push an "exotic" flag to the end of the compiler's arguments list.
///
/// Nvidia compiler accepts only the most common compiler flags like `-D`,
/// `-I`, `-c`, etc. Options meant specifically for the underlying
/// host C++ compiler have to be prefixed with `-Xcompiler`.
/// [Another possible future application for this function is passing
/// clang-specific flags to clang-cl, which otherwise accepts only
/// MSVC-specific options.]
pub(crate) fn push_cc_arg(&mut self, flag: OsString) {
if self.cuda {
self.args.push("-Xcompiler".into());
}
self.args.push(flag);
}
/// Checks if an argument or flag has already been specified or conflicts.
///
/// Currently only checks optimization flags.
pub(crate) 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()) && chars.next() != Some('-') {
return false;
}
// Check for existing optimization flags (-O, /O)
if chars.next() == Some('O') {
return self
.args()
.iter()
.any(|a| a.to_str().unwrap_or("").chars().nth(1) == Some('O'));
}
// TODO Check for existing -m..., -m...=..., /arch:... flags
false
}
/// Don't push optimization arg if it conflicts with existing args.
pub(crate) fn push_opt_unless_duplicate(&mut self, flag: OsString) {
if self.is_duplicate_opt_arg(&flag) {
eprintln!("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
/// command returned will already have the initial arguments and environment
/// variables configured.
pub fn to_command(&self) -> Command {
let mut cmd = match self.cc_wrapper_path {
Some(ref cc_wrapper_path) => {
let mut cmd = Command::new(cc_wrapper_path);
cmd.arg(&self.path);
cmd
}
None => Command::new(&self.path),
};
cmd.args(&self.cc_wrapper_args);
cmd.args(self.args.iter().filter(|a| !self.removed_args.contains(a)));
for (k, v) in self.env.iter() {
cmd.env(k, v);
}
cmd
}
/// Returns the path for this compiler.
///
/// Note that this may not be a path to a file on the filesystem, e.g. "cc",
/// but rather something which will be resolved when a process is spawned.
pub fn path(&self) -> &Path {
&self.path
}
/// Returns the default set of arguments to the compiler needed to produce
/// executables for the target this compiler generates.
pub fn args(&self) -> &[OsString] {
&self.args
}
/// Returns the set of environment variables needed for this compiler to
/// operate.
///
/// This is typically only used for MSVC compilers currently.
pub fn env(&self) -> &[(OsString, OsString)] {
&self.env
}
/// Returns the compiler command in format of CC environment variable.
/// Or empty string if CC env was not present
///
/// This is typically used by configure script
pub fn cc_env(&self) -> OsString {
match self.cc_wrapper_path {
Some(ref cc_wrapper_path) => {
let mut cc_env = cc_wrapper_path.as_os_str().to_owned();
cc_env.push(" ");
cc_env.push(self.path.to_path_buf().into_os_string());
for arg in self.cc_wrapper_args.iter() {
cc_env.push(" ");
cc_env.push(arg);
}
cc_env
}
None => OsString::from(""),
}
}
/// Returns the compiler flags in format of CFLAGS environment variable.
/// Important here - this will not be CFLAGS from env, its internal gcc's flags to use as CFLAGS
/// This is typically used by configure script
pub fn cflags_env(&self) -> OsString {
let mut flags = OsString::new();
for (i, arg) in self.args.iter().enumerate() {
if i > 0 {
flags.push(" ");
}
flags.push(arg);
}
flags
}
/// Whether the tool is GNU Compiler Collection-like.
pub fn is_like_gnu(&self) -> bool {
self.family == ToolFamily::Gnu
}
/// Whether the tool is Clang-like.
pub fn is_like_clang(&self) -> bool {
matches!(self.family, ToolFamily::Clang { .. })
}
/// Whether the tool is AppleClang under .xctoolchain
#[cfg(target_vendor = "apple")]
pub(crate) fn is_xctoolchain_clang(&self) -> bool {
let path = self.path.to_string_lossy();
path.contains(".xctoolchain/")
}
#[cfg(not(target_vendor = "apple"))]
pub(crate) fn is_xctoolchain_clang(&self) -> bool {
false
}
/// Whether the tool is MSVC-like.
pub fn is_like_msvc(&self) -> bool {
matches!(self.family, ToolFamily::Msvc { .. })
}
/// Whether the tool is `clang-cl`-based MSVC-like.
pub fn is_like_clang_cl(&self) -> bool {
matches!(self.family, ToolFamily::Msvc { clang_cl: true })
}
/// Supports using `--` delimiter to separate arguments and path to source files.
pub(crate) fn supports_path_delimiter(&self) -> bool {
// homebrew clang and zig-cc does not support this while stock version does
matches!(self.family, ToolFamily::Msvc { clang_cl: true }) && !self.cuda
}
}
/// 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, PartialEq)]
pub 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 { zig_cc: bool },
/// Tool is the MSVC cl.exe.
Msvc { clang_cl: bool },
}
impl ToolFamily {
/// What the flag to request debug info for this family of tools look like
pub(crate) fn add_debug_flags(&self, cmd: &mut Tool, dwarf_version: Option<u32>) {
match *self {
ToolFamily::Msvc { .. } => {
cmd.push_cc_arg("-Z7".into());
}
ToolFamily::Gnu | ToolFamily::Clang { .. } => {
cmd.push_cc_arg(
dwarf_version
.map_or_else(|| "-g".into(), |v| format!("-gdwarf-{v}"))
.into(),
);
}
}
}
/// What the flag to force frame pointers.
pub(crate) fn add_force_frame_pointer(&self, cmd: &mut Tool) {
match *self {
ToolFamily::Gnu | ToolFamily::Clang { .. } => {
cmd.push_cc_arg("-fno-omit-frame-pointer".into());
}
_ => (),
}
}
/// What the flags to enable all warnings
pub(crate) fn warnings_flags(&self) -> &'static str {
match *self {
ToolFamily::Msvc { .. } => "-W4",
ToolFamily::Gnu | ToolFamily::Clang { .. } => "-Wall",
}
}
/// What the flags to enable extra warnings
pub(crate) fn extra_warnings_flags(&self) -> Option<&'static str> {
match *self {
ToolFamily::Msvc { .. } => None,
ToolFamily::Gnu | ToolFamily::Clang { .. } => Some("-Wextra"),
}
}
/// What the flag to turn warning into errors
pub(crate) fn warnings_to_errors_flag(&self) -> &'static str {
match *self {
ToolFamily::Msvc { .. } => "-WX",
ToolFamily::Gnu | ToolFamily::Clang { .. } => "-Werror",
}
}
pub(crate) fn verbose_stderr(&self) -> bool {
matches!(*self, ToolFamily::Clang { .. })
}
}

130
vendor/cc/src/utilities.rs vendored Normal file
View File

@@ -0,0 +1,130 @@
use std::{
cell::UnsafeCell,
ffi::OsStr,
fmt::{self, Write},
marker::PhantomData,
mem::MaybeUninit,
panic::{RefUnwindSafe, UnwindSafe},
path::Path,
sync::Once,
};
pub(super) struct JoinOsStrs<'a, T> {
pub(super) slice: &'a [T],
pub(super) delimiter: char,
}
impl<T> fmt::Display for JoinOsStrs<'_, T>
where
T: AsRef<OsStr>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let len = self.slice.len();
for (index, os_str) in self.slice.iter().enumerate() {
// TODO: Use OsStr::display once it is stablised,
// Path and OsStr has the same `Display` impl
write!(f, "{}", Path::new(os_str).display())?;
if index + 1 < len {
f.write_char(self.delimiter)?;
}
}
Ok(())
}
}
pub(super) struct OptionOsStrDisplay<T>(pub(super) Option<T>);
impl<T> fmt::Display for OptionOsStrDisplay<T>
where
T: AsRef<OsStr>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// TODO: Use OsStr::display once it is stablised
// Path and OsStr has the same `Display` impl
if let Some(os_str) = self.0.as_ref() {
write!(f, "Some({})", Path::new(os_str).display())
} else {
f.write_str("None")
}
}
}
pub(crate) struct OnceLock<T> {
once: Once,
value: UnsafeCell<MaybeUninit<T>>,
_marker: PhantomData<T>,
}
impl<T> Default for OnceLock<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> OnceLock<T> {
pub(crate) const fn new() -> Self {
Self {
once: Once::new(),
value: UnsafeCell::new(MaybeUninit::uninit()),
_marker: PhantomData,
}
}
#[inline]
fn is_initialized(&self) -> bool {
self.once.is_completed()
}
unsafe fn get_unchecked(&self) -> &T {
debug_assert!(self.is_initialized());
#[allow(clippy::needless_borrow)]
#[allow(unused_unsafe)]
unsafe {
(&*self.value.get()).assume_init_ref()
}
}
pub(crate) fn get_or_init(&self, f: impl FnOnce() -> T) -> &T {
self.once.call_once(|| {
unsafe { &mut *self.value.get() }.write(f());
});
unsafe { self.get_unchecked() }
}
pub(crate) fn get(&self) -> Option<&T> {
if self.is_initialized() {
// Safe b/c checked is_initialized
Some(unsafe { self.get_unchecked() })
} else {
None
}
}
}
impl<T: fmt::Debug> fmt::Debug for OnceLock<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut d = f.debug_tuple("OnceLock");
match self.get() {
Some(v) => d.field(v),
None => d.field(&format_args!("<uninit>")),
};
d.finish()
}
}
unsafe impl<T: Sync + Send> Sync for OnceLock<T> {}
unsafe impl<T: Send> Send for OnceLock<T> {}
impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceLock<T> {}
impl<T: UnwindSafe> UnwindSafe for OnceLock<T> {}
impl<T> Drop for OnceLock<T> {
#[inline]
fn drop(&mut self) {
if self.once.is_completed() {
// SAFETY: The cell is initialized and being dropped, so it can't
// be accessed again.
unsafe { self.value.get_mut().assume_init_drop() };
}
}
}