Initial vendor packages

Signed-off-by: Valentin Popov <valentin@popov.link>
This commit is contained in:
2024-01-08 01:21:28 +04:00
parent 5ecd8cf2cb
commit 1b6a04ca55
7309 changed files with 2160054 additions and 0 deletions

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

@ -0,0 +1 @@
{"files":{"Cargo.lock":"f36b5fb99e6a2272cb5ad088fb7e21baa135c5335f9babfd3d6e79cd915d5082","Cargo.toml":"2be00f2836c949a6ff7120610ee0191a6d12d50f141aafd6622d4c2e932f0d71","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"fe18a56553aa54cbef39b659e98340ddf4dbb18f156e7b34a8be25d97e4d123f","src/bin/gcc-shim.rs":"36dc4e447428e73c548cc7106ca1e8f282c098463b014e13a729a44445de4880","src/com.rs":"cf188faf2651f613ee5c38fd6af29188ff4b0c3036b615874bce0e3b6e61a96f","src/lib.rs":"cdf0c6dc4e12ad313fb93ab42f994e26c7e5aaeb07ca61620032d8f4014dacd0","src/os_pipe.rs":"5b950b491b93226885c34a9070387c081f50029fdf19770bb983bca2a64aa705","src/os_pipe/unix.rs":"64a765352b3e94c4590d11f99824dc60a887fe5bc61eba81398aab1180908f55","src/os_pipe/windows.rs":"fa35d5b6adb83a8442ec06b08f3d30631ac7b8513f3cf8b3986d27b7ee58cf93","src/registry.rs":"d888d22abd8a32a61562529274b2d5d2f9e5a3bfa754589d6beb04b740144771","src/setup_config.rs":"5fee84b80d089ae4a92f10080b072ea2bb32c2edbcdc759cb9072e380404fc46","src/vs_instances.rs":"2d3f8278a803b0e7052f4eeb1979b29f963dd0143f4458e2cb5f33c4e5f0963b","src/winapi.rs":"132a7c23d57911db0bef03446cd106e7f75818096132522219d72b9d2a8f247f","src/windows_registry.rs":"c58ae361caf3b6f13dff515e25b3a7e5cf443bb9470d2d347784b5872c3de06d","src/windows_sys.rs":"ff7cdf4450db85c8704dfd3aa765dd62da24f0650825457094405af82958f688","tests/cc_env.rs":"e02b3b0824ad039b47e4462c5ef6dbe6c824c28e7953af94a0f28f7b5158042e","tests/cflags.rs":"57f06eb5ce1557e5b4a032d0c4673e18fbe6f8d26c1deb153126e368b96b41b3","tests/cxxflags.rs":"c2c6c6d8a0d7146616fa1caed26876ee7bc9fcfffd525eb4743593cade5f3371","tests/support/mod.rs":"a3c8d116973bb16066bf6ec4de5143183f97de7aad085d85f8118a2eaac3e1e0","tests/test.rs":"bab74eb7e7a383cb5da4143e74c26ddfa3e7162b5f46c1d46a722250e925444d"},"package":"f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"}

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

@ -0,0 +1,111 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.83"
dependencies = [
"jobserver",
"libc",
"tempfile",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "fastrand"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
dependencies = [
"instant",
]
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if",
]
[[package]]
name = "jobserver"
version = "0.1.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b"
dependencies = [
"libc",
]
[[package]]
name = "libc"
version = "0.2.134"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb"
[[package]]
name = "redox_syscall"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [
"bitflags",
]
[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
"winapi",
]
[[package]]
name = "tempfile"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
dependencies = [
"cfg-if",
"fastrand",
"libc",
"redox_syscall",
"remove_dir_all",
"winapi",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

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

@ -0,0 +1,43 @@
# 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"
name = "cc"
version = "1.0.83"
authors = ["Alex Crichton <alex@alexcrichton.com>"]
exclude = ["/.github"]
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"
[dependencies.jobserver]
version = "0.1.16"
optional = true
[dev-dependencies.tempfile]
version = "3"
[features]
parallel = ["jobserver"]
[target."cfg(unix)".dependencies.libc]
version = "0.2.62"
default-features = false

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.

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

@ -0,0 +1,233 @@
# cc-rs
A library to compile C/C++/assembly into a Rust library/application.
[Documentation](https://docs.rs/cc)
A simple library meant to be used as a build dependency with Cargo packages in
order to build a set of C/C++ files into a static archive. This crate calls out
to the most relevant compiler for a platform, for example using `cl` on MSVC.
## Using cc-rs
First, you'll want to both add a build script for your crate (`build.rs`) and
also add this crate to your `Cargo.toml` via:
```toml
[build-dependencies]
cc = "1.0"
```
Next up, you'll want to write a build script like so:
```rust,no_run
// build.rs
fn main() {
cc::Build::new()
.file("foo.c")
.file("bar.c")
.compile("foo");
}
```
And that's it! Running `cargo build` should take care of the rest and your Rust
application will now have the C files `foo.c` and `bar.c` compiled into a file
named `libfoo.a`. If the C files contain
```c
void foo_function(void) { ... }
```
and
```c
int32_t bar_function(int32_t x) { ... }
```
you can call them from Rust by declaring them in
your Rust code like so:
```rust,no_run
extern "C" {
fn foo_function();
fn bar_function(x: i32) -> i32;
}
pub fn call() {
unsafe {
foo_function();
bar_function(42);
}
}
fn main() {
// ...
}
```
See [the Rustonomicon](https://doc.rust-lang.org/nomicon/ffi.html) for more details.
## External configuration via environment variables
To control the programs and flags used for building, the builder can set a
number of different environment variables.
* `CFLAGS` - a series of space separated flags passed to compilers. Note that
individual flags cannot currently contain spaces, so doing
something like: `-L=foo\ bar` is not possible.
* `CC` - the actual C compiler used. Note that this is used as an exact
executable name, so (for example) no extra flags can be passed inside
this variable, and the builder must ensure that there aren't any
trailing spaces. This compiler must understand the `-c` flag. For
certain `TARGET`s, it also is assumed to know about other flags (most
common is `-fPIC`).
* `AR` - the `ar` (archiver) executable to use to build the static library.
* `CRATE_CC_NO_DEFAULTS` - the default compiler flags may cause conflicts in
some cross compiling scenarios. Setting this variable
will disable the generation of default compiler
flags.
* `CXX...` - see [C++ Support](#c-support).
Furthermore, projects using this crate may specify custom environment variables
to be inspected, for example via the `Build::try_flags_from_environment`
function. Consult the projects own documentation or its use of the `cc` crate
for any additional variables it may use.
Each of these variables can also be supplied with certain prefixes and suffixes,
in the following prioritized order:
1. `<var>_<target>` - for example, `CC_x86_64-unknown-linux-gnu`
2. `<var>_<target_with_underscores>` - for example, `CC_x86_64_unknown_linux_gnu`
3. `<build-kind>_<var>` - for example, `HOST_CC` or `TARGET_CFLAGS`
4. `<var>` - a plain `CC`, `AR` as above.
If none of these variables exist, cc-rs uses built-in defaults.
In addition to the above optional environment variables, `cc-rs` has some
functions with hard requirements on some variables supplied by [cargo's
build-script driver][cargo] that it has the `TARGET`, `OUT_DIR`, `OPT_LEVEL`,
and `HOST` variables.
[cargo]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#inputs-to-the-build-script
## Optional features
### Parallel
Currently cc-rs supports parallel compilation (think `make -jN`) but this
feature is turned off by default. To enable cc-rs to compile C/C++ in parallel,
you can change your dependency to:
```toml
[build-dependencies]
cc = { version = "1.0", features = ["parallel"] }
```
By default cc-rs will limit parallelism to `$NUM_JOBS`, or if not present it
will limit it to the number of cpus on the machine. If you are using cargo,
use `-jN` option of `build`, `test` and `run` commands as `$NUM_JOBS`
is supplied by cargo.
## Compile-time Requirements
To work properly this crate needs access to a C compiler when the build script
is being run. This crate does not ship a C compiler with it. The compiler
required varies per platform, but there are three broad categories:
* Unix platforms require `cc` to be the C compiler. This can be found by
installing cc/clang on Linux distributions and Xcode on macOS, for example.
* Windows platforms targeting MSVC (e.g. your target triple ends in `-msvc`)
require Visual Studio to be installed. `cc-rs` attempts to locate it, and
if it fails, `cl.exe` is expected to be available in `PATH`. This can be
set up by running the appropriate developer tools shell.
* Windows platforms targeting MinGW (e.g. your target triple ends in `-gnu`)
require `cc` to be available in `PATH`. We recommend the
[MinGW-w64](https://www.mingw-w64.org/) distribution, which is using the
[Win-builds](http://win-builds.org/) installation system.
You may also acquire it via
[MSYS2](https://www.msys2.org/), as explained [here][msys2-help]. Make sure
to install the appropriate architecture corresponding to your installation of
rustc. GCC from older [MinGW](http://www.mingw.org/) project is compatible
only with 32-bit rust compiler.
[msys2-help]: https://github.com/rust-lang/rust#building-on-windows
## C++ support
`cc-rs` supports C++ libraries compilation by using the `cpp` method on
`Build`:
```rust,no_run
fn main() {
cc::Build::new()
.cpp(true) // Switch to C++ library compilation.
.file("foo.cpp")
.compile("foo");
}
```
For C++ libraries, the `CXX` and `CXXFLAGS` environment variables are used instead of `CC` and `CFLAGS`.
The C++ standard library may be linked to the crate target. By default it's `libc++` for macOS, FreeBSD, and OpenBSD, `libc++_shared` for Android, nothing for MSVC, and `libstdc++` for anything else. It can be changed in one of two ways:
1. by using the `cpp_link_stdlib` method on `Build`:
```rust,no-run
fn main() {
cc::Build::new()
.cpp(true)
.file("foo.cpp")
.cpp_link_stdlib("stdc++") // use libstdc++
.compile("foo");
}
```
2. by setting the `CXXSTDLIB` environment variable.
In particular, for Android you may want to [use `c++_static` if you have at most one shared library](https://developer.android.com/ndk/guides/cpp-support).
Remember that C++ does name mangling so `extern "C"` might be required to enable Rust linker to find your functions.
## CUDA C++ support
`cc-rs` also supports compiling CUDA C++ libraries by using the `cuda` method
on `Build`:
```rust,no_run
fn main() {
cc::Build::new()
// Switch to CUDA C++ library compilation using NVCC.
.cuda(true)
.cudart("static")
// Generate code for Maxwell (GTX 970, 980, 980 Ti, Titan X).
.flag("-gencode").flag("arch=compute_52,code=sm_52")
// Generate code for Maxwell (Jetson TX1).
.flag("-gencode").flag("arch=compute_53,code=sm_53")
// Generate code for Pascal (GTX 1070, 1080, 1080 Ti, Titan Xp).
.flag("-gencode").flag("arch=compute_61,code=sm_61")
// Generate code for Pascal (Tesla P100).
.flag("-gencode").flag("arch=compute_60,code=sm_60")
// Generate code for Pascal (Jetson TX2).
.flag("-gencode").flag("arch=compute_62,code=sm_62")
// Generate code in parallel
.flag("-t0")
.file("bar.cu")
.compile("bar");
}
```
## 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.

70
vendor/cc/src/bin/gcc-shim.rs vendored Normal file
View File

@ -0,0 +1,70 @@
#![cfg_attr(test, allow(dead_code))]
use std::env;
use std::fs::File;
use std::io::{self, prelude::*};
use std::path::PathBuf;
fn main() {
let mut args = env::args();
let program = args.next().expect("Unexpected empty args");
let out_dir = PathBuf::from(
env::var_os("GCCTEST_OUT_DIR")
.unwrap_or_else(|| panic!("{}: GCCTEST_OUT_DIR not found", program)),
);
// Find the first nonexistent candidate file to which the program's args can be written.
let candidate = (0..).find_map(|i| {
let candidate = out_dir.join(format!("out{}", i));
if candidate.exists() {
// If the file exists, commands have already run. Try again.
None
} else {
Some(candidate)
}
}).unwrap_or_else(|| panic!("Cannot find the first nonexistent candidate file to which the program's args can be written under out_dir '{}'", out_dir.display()));
// Create a file and record the args passed to the command.
let f = File::create(&candidate).unwrap_or_else(|e| {
panic!(
"{}: can't create candidate: {}, error: {}",
program,
candidate.display(),
e
)
});
let mut f = io::BufWriter::new(f);
(|| {
for arg in args {
writeln!(f, "{}", arg)?;
}
f.flush()?;
let mut f = f.into_inner()?;
f.flush()?;
f.sync_all()
})()
.unwrap_or_else(|e| {
panic!(
"{}: can't write to candidate: {}, error: {}",
program,
candidate.display(),
e
)
});
// Create a file used by some tests.
let path = &out_dir.join("libfoo.a");
File::create(path).unwrap_or_else(|e| {
panic!(
"{}: can't create libfoo.a: {}, error: {}",
program,
path.display(),
e
)
});
}

156
vendor/cc/src/com.rs vendored Normal file
View File

@ -0,0 +1,156 @@
// Copyright © 2017 winapi-rs developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// All files in the project carrying such notice may not be copied, modified, or distributed
// except according to those terms.
#![allow(unused)]
use crate::{
winapi::{IUnknown, Interface},
windows_sys::{
CoInitializeEx, SysFreeString, SysStringLen, BSTR, COINIT_MULTITHREADED, HRESULT, S_FALSE,
S_OK,
},
};
use std::{
ffi::{OsStr, OsString},
mem::ManuallyDrop,
ops::Deref,
os::windows::ffi::{OsStrExt, OsStringExt},
ptr::{null, null_mut},
slice::from_raw_parts,
};
pub fn initialize() -> Result<(), HRESULT> {
let err = unsafe { CoInitializeEx(null(), COINIT_MULTITHREADED) };
if err != S_OK && err != S_FALSE {
// S_FALSE just means COM is already initialized
Err(err)
} else {
Ok(())
}
}
pub struct ComPtr<T>(*mut T)
where
T: Interface;
impl<T> ComPtr<T>
where
T: Interface,
{
/// Creates a `ComPtr` to wrap a raw pointer.
/// It takes ownership over the pointer which means it does __not__ call `AddRef`.
/// `T` __must__ be a COM interface that inherits from `IUnknown`.
pub unsafe fn from_raw(ptr: *mut T) -> ComPtr<T> {
assert!(!ptr.is_null());
ComPtr(ptr)
}
/// Casts up the inheritance chain
pub fn up<U>(self) -> ComPtr<U>
where
T: Deref<Target = U>,
U: Interface,
{
ComPtr(self.into_raw() as *mut U)
}
/// Extracts the raw pointer.
/// You are now responsible for releasing it yourself.
pub fn into_raw(self) -> *mut T {
ManuallyDrop::new(self).0
}
/// For internal use only.
fn as_unknown(&self) -> &IUnknown {
unsafe { &*(self.0 as *mut IUnknown) }
}
/// Performs QueryInterface fun.
pub fn cast<U>(&self) -> Result<ComPtr<U>, i32>
where
U: Interface,
{
let mut obj = null_mut();
let err = unsafe { self.as_unknown().QueryInterface(&U::uuidof(), &mut obj) };
if err < 0 {
return Err(err);
}
Ok(unsafe { ComPtr::from_raw(obj as *mut U) })
}
}
impl<T> Deref for ComPtr<T>
where
T: Interface,
{
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.0 }
}
}
impl<T> Clone for ComPtr<T>
where
T: Interface,
{
fn clone(&self) -> Self {
unsafe {
self.as_unknown().AddRef();
ComPtr::from_raw(self.0)
}
}
}
impl<T> Drop for ComPtr<T>
where
T: Interface,
{
fn drop(&mut self) {
unsafe {
self.as_unknown().Release();
}
}
}
pub struct BStr(BSTR);
impl BStr {
pub unsafe fn from_raw(s: BSTR) -> BStr {
BStr(s)
}
pub fn to_osstring(&self) -> OsString {
let len = unsafe { SysStringLen(self.0) };
let slice = unsafe { from_raw_parts(self.0, len as usize) };
OsStringExt::from_wide(slice)
}
}
impl Drop for BStr {
fn drop(&mut self) {
unsafe { SysFreeString(self.0) };
}
}
pub trait ToWide {
fn to_wide(&self) -> Vec<u16>;
fn to_wide_null(&self) -> Vec<u16>;
}
impl<T> ToWide for T
where
T: AsRef<OsStr>,
{
fn to_wide(&self) -> Vec<u16> {
self.as_ref().encode_wide().collect()
}
fn to_wide_null(&self) -> Vec<u16> {
self.as_ref().encode_wide().chain(Some(0)).collect()
}
}
pub trait FromWide
where
Self: Sized,
{
fn from_wide(wide: &[u16]) -> Self;
fn from_wide_null(wide: &[u16]) -> Self {
let len = wide.iter().take_while(|&&c| c != 0).count();
Self::from_wide(&wide[..len])
}
}
impl FromWide for OsString {
fn from_wide(wide: &[u16]) -> OsString {
OsStringExt::from_wide(wide)
}
}

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

File diff suppressed because it is too large Load Diff

28
vendor/cc/src/os_pipe.rs vendored Normal file
View File

@ -0,0 +1,28 @@
//! Adapted from:
//! - https://doc.rust-lang.org/src/std/sys/unix/pipe.rs.html
//! - https://doc.rust-lang.org/src/std/sys/unix/fd.rs.html#385
//! - https://github.com/rust-lang/rust/blob/master/library/std/src/sys/mod.rs#L57
//! - https://github.com/oconnor663/os_pipe.rs
use std::fs::File;
/// Open a new pipe and return a pair of [`File`] objects for the reader and writer.
///
/// This corresponds to the `pipe2` library call on Posix and the
/// `CreatePipe` library call on Windows (though these implementation
/// details might change). These pipes are non-inheritable, so new child
/// processes won't receive a copy of them unless they're explicitly
/// passed as stdin/stdout/stderr.
pub fn pipe() -> std::io::Result<(File, File)> {
sys::pipe()
}
#[cfg(unix)]
#[path = "os_pipe/unix.rs"]
mod sys;
#[cfg(windows)]
#[path = "os_pipe/windows.rs"]
mod sys;
#[cfg(all(not(unix), not(windows)))]
compile_error!("Only unix and windows support os_pipe!");

121
vendor/cc/src/os_pipe/unix.rs vendored Normal file
View File

@ -0,0 +1,121 @@
use std::{
fs::File,
io,
os::{raw::c_int, unix::io::FromRawFd},
};
pub(super) fn pipe() -> io::Result<(File, File)> {
let mut fds = [0; 2];
// The only known way right now to create atomically set the CLOEXEC flag is
// to use the `pipe2` syscall. This was added to Linux in 2.6.27, glibc 2.9
// and musl 0.9.3, and some other targets also have it.
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd",
target_os = "redox"
))]
{
unsafe {
cvt(libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC))?;
}
}
#[cfg(not(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd",
target_os = "redox"
)))]
{
unsafe {
cvt(libc::pipe(fds.as_mut_ptr()))?;
}
cloexec::set_cloexec(fds[0])?;
cloexec::set_cloexec(fds[1])?;
}
unsafe { Ok((File::from_raw_fd(fds[0]), File::from_raw_fd(fds[1]))) }
}
fn cvt(t: c_int) -> io::Result<c_int> {
if t == -1 {
Err(io::Error::last_os_error())
} else {
Ok(t)
}
}
#[cfg(not(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd",
target_os = "redox"
)))]
mod cloexec {
use super::{c_int, cvt, io};
#[cfg(not(any(
target_env = "newlib",
target_os = "solaris",
target_os = "illumos",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "l4re",
target_os = "linux",
target_os = "haiku",
target_os = "redox",
target_os = "vxworks",
target_os = "nto",
)))]
pub(super) fn set_cloexec(fd: c_int) -> io::Result<()> {
unsafe {
cvt(libc::ioctl(fd, libc::FIOCLEX))?;
}
Ok(())
}
#[cfg(any(
all(
target_env = "newlib",
not(any(target_os = "espidf", target_os = "horizon"))
),
target_os = "solaris",
target_os = "illumos",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "l4re",
target_os = "linux",
target_os = "haiku",
target_os = "redox",
target_os = "vxworks",
target_os = "nto",
))]
pub(super) fn set_cloexec(fd: c_int) -> io::Result<()> {
unsafe {
let previous = cvt(libc::fcntl(fd, libc::F_GETFD))?;
let new = previous | libc::FD_CLOEXEC;
if new != previous {
cvt(libc::fcntl(fd, libc::F_SETFD, new))?;
}
}
Ok(())
}
// FD_CLOEXEC is not supported in ESP-IDF and Horizon OS but there's no need to,
// because neither supports spawning processes.
#[cfg(any(target_os = "espidf", target_os = "horizon"))]
pub(super) fn set_cloexec(_fd: c_int) -> io::Result<()> {
Ok(())
}
}

24
vendor/cc/src/os_pipe/windows.rs vendored Normal file
View File

@ -0,0 +1,24 @@
use crate::windows_sys::{CreatePipe, INVALID_HANDLE_VALUE};
use std::{fs::File, io, os::windows::prelude::*, ptr};
/// NOTE: These pipes do not support IOCP.
///
/// If IOCP is needed, then you might want to emulate
/// anonymous pipes with CreateNamedPipe, as Rust's stdlib does.
pub(super) fn pipe() -> io::Result<(File, File)> {
let mut read_pipe = INVALID_HANDLE_VALUE;
let mut write_pipe = INVALID_HANDLE_VALUE;
let ret = unsafe { CreatePipe(&mut read_pipe, &mut write_pipe, ptr::null_mut(), 0) };
if ret == 0 {
Err(io::Error::last_os_error())
} else {
unsafe {
Ok((
File::from_raw_handle(read_pipe as RawHandle),
File::from_raw_handle(write_pipe as RawHandle),
))
}
}
}

190
vendor/cc/src/registry.rs vendored Normal file
View File

@ -0,0 +1,190 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use crate::windows_sys::{
RegCloseKey, RegEnumKeyExW, RegOpenKeyExW, RegQueryValueExW, ERROR_NO_MORE_ITEMS,
ERROR_SUCCESS, HKEY, HKEY_LOCAL_MACHINE, KEY_READ, KEY_WOW64_32KEY, REG_SZ,
};
use std::{
ffi::{OsStr, OsString},
io,
ops::RangeFrom,
os::windows::prelude::*,
ptr::null_mut,
};
/// Must never be `HKEY_PERFORMANCE_DATA`.
pub(crate) struct RegistryKey(Repr);
type DWORD = u32;
struct OwnedKey(HKEY);
/// Note: must not encode `HKEY_PERFORMANCE_DATA` or one of its subkeys.
enum Repr {
/// `HKEY_LOCAL_MACHINE`.
LocalMachine,
/// A subkey of `HKEY_LOCAL_MACHINE`.
Owned(OwnedKey),
}
pub struct Iter<'a> {
idx: RangeFrom<DWORD>,
key: &'a RegistryKey,
}
unsafe impl Sync for Repr {}
unsafe impl Send for Repr {}
pub(crate) const LOCAL_MACHINE: RegistryKey = RegistryKey(Repr::LocalMachine);
impl RegistryKey {
fn raw(&self) -> HKEY {
match self.0 {
Repr::LocalMachine => HKEY_LOCAL_MACHINE,
Repr::Owned(ref val) => val.0,
}
}
/// Open a sub-key of `self`.
pub fn open(&self, key: &OsStr) -> io::Result<RegistryKey> {
let key = key.encode_wide().chain(Some(0)).collect::<Vec<_>>();
let mut ret = null_mut();
let err = unsafe {
RegOpenKeyExW(
self.raw(),
key.as_ptr(),
0,
KEY_READ | KEY_WOW64_32KEY,
&mut ret,
)
};
if err == ERROR_SUCCESS {
Ok(RegistryKey(Repr::Owned(OwnedKey(ret))))
} else {
Err(io::Error::from_raw_os_error(err as i32))
}
}
pub fn iter(&self) -> Iter {
Iter {
idx: 0..,
key: self,
}
}
pub fn query_str(&self, name: &str) -> io::Result<OsString> {
let name: &OsStr = name.as_ref();
let name = name.encode_wide().chain(Some(0)).collect::<Vec<_>>();
let mut len = 0;
let mut kind = 0;
unsafe {
let err = RegQueryValueExW(
self.raw(),
name.as_ptr(),
null_mut(),
&mut kind,
null_mut(),
&mut len,
);
if err != ERROR_SUCCESS {
return Err(io::Error::from_raw_os_error(err as i32));
}
if kind != REG_SZ {
return Err(io::Error::new(
io::ErrorKind::Other,
"registry key wasn't a string",
));
}
// The length here is the length in bytes, but we're using wide
// characters so we need to be sure to halve it for the length
// passed in.
assert!(len % 2 == 0, "impossible wide string size: {} bytes", len);
let vlen = len as usize / 2;
// Defensively initialized, see comment about
// `HKEY_PERFORMANCE_DATA` below.
let mut v = vec![0u16; vlen];
let err = RegQueryValueExW(
self.raw(),
name.as_ptr(),
null_mut(),
null_mut(),
v.as_mut_ptr() as *mut _,
&mut len,
);
// We don't check for `ERROR_MORE_DATA` (which would if the value
// grew between the first and second call to `RegQueryValueExW`),
// both because it's extremely unlikely, and this is a bit more
// defensive more defensive against weird types of registry keys.
if err != ERROR_SUCCESS {
return Err(io::Error::from_raw_os_error(err as i32));
}
// The length is allowed to change, but should still be even, as
// well as smaller.
assert!(len % 2 == 0, "impossible wide string size: {} bytes", len);
// If the length grew but returned a success code, it *probably*
// indicates we're `HKEY_PERFORMANCE_DATA` or a subkey(?). We
// consider this UB, since those keys write "undefined" or
// "unpredictable" values to len, and need to use a completely
// different loop structure. This should be impossible (and enforce
// it in the API to the best of our ability), but to mitigate the
// damage we do some smoke-checks on the len, and ensure `v` has
// been fully initialized (rather than trusting the result of
// `RegQueryValueExW`).
let actual_len = len as usize / 2;
assert!(actual_len <= v.len());
v.truncate(actual_len);
// Some registry keys may have a terminating nul character, but
// we're not interested in that, so chop it off if it's there.
if !v.is_empty() && v[v.len() - 1] == 0 {
v.pop();
}
return Ok(OsString::from_wide(&v));
}
}
}
impl Drop for OwnedKey {
fn drop(&mut self) {
unsafe {
RegCloseKey(self.0);
}
}
}
impl<'a> Iterator for Iter<'a> {
type Item = io::Result<OsString>;
fn next(&mut self) -> Option<io::Result<OsString>> {
self.idx.next().and_then(|i| unsafe {
let mut v = Vec::with_capacity(256);
let mut len = v.capacity() as DWORD;
let ret = RegEnumKeyExW(
self.key.raw(),
i,
v.as_mut_ptr(),
&mut len,
null_mut(),
null_mut(),
null_mut(),
null_mut(),
);
if ret == ERROR_NO_MORE_ITEMS {
None
} else if ret != ERROR_SUCCESS {
Some(Err(io::Error::from_raw_os_error(ret as i32)))
} else {
v.set_len(len as usize);
Some(Ok(OsString::from_wide(&v)))
}
})
}
}

283
vendor/cc/src/setup_config.rs vendored Normal file
View File

@ -0,0 +1,283 @@
// Copyright © 2017 winapi-rs developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// All files in the project carrying such notice may not be copied, modified, or distributed
// except according to those terms.
#![allow(bad_style)]
#![allow(unused)]
use crate::{
com::{BStr, ComPtr},
winapi::{
IUnknown, IUnknownVtbl, Interface, LCID, LPCOLESTR, LPCWSTR, LPFILETIME, LPSAFEARRAY,
PULONGLONG, ULONG,
},
windows_sys::{CoCreateInstance, BSTR, CLSCTX_ALL, HRESULT, S_FALSE},
};
use std::{
ffi::OsString,
ptr::{null, null_mut},
};
// Bindings to the Setup.Configuration stuff
pub type InstanceState = u32;
pub const eNone: InstanceState = 0;
pub const eLocal: InstanceState = 1;
pub const eRegistered: InstanceState = 2;
pub const eNoRebootRequired: InstanceState = 4;
pub const eComplete: InstanceState = -1i32 as u32;
RIDL! {#[uuid(0xb41463c3, 0x8866, 0x43b5, 0xbc, 0x33, 0x2b, 0x06, 0x76, 0xf7, 0xf4, 0x2e)]
interface ISetupInstance(ISetupInstanceVtbl): IUnknown(IUnknownVtbl) {
fn GetInstanceId(
pbstrInstanceId: *mut BSTR,
) -> HRESULT,
fn GetInstallDate(
pInstallDate: LPFILETIME,
) -> HRESULT,
fn GetInstallationName(
pbstrInstallationName: *mut BSTR,
) -> HRESULT,
fn GetInstallationPath(
pbstrInstallationPath: *mut BSTR,
) -> HRESULT,
fn GetInstallationVersion(
pbstrInstallationVersion: *mut BSTR,
) -> HRESULT,
fn GetDisplayName(
lcid: LCID,
pbstrDisplayName: *mut BSTR,
) -> HRESULT,
fn GetDescription(
lcid: LCID,
pbstrDescription: *mut BSTR,
) -> HRESULT,
fn ResolvePath(
pwszRelativePath: LPCOLESTR,
pbstrAbsolutePath: *mut BSTR,
) -> HRESULT,
}}
RIDL! {#[uuid(0x89143c9a, 0x05af, 0x49b0, 0xb7, 0x17, 0x72, 0xe2, 0x18, 0xa2, 0x18, 0x5c)]
interface ISetupInstance2(ISetupInstance2Vtbl): ISetupInstance(ISetupInstanceVtbl) {
fn GetState(
pState: *mut InstanceState,
) -> HRESULT,
fn GetPackages(
ppsaPackages: *mut LPSAFEARRAY,
) -> HRESULT,
fn GetProduct(
ppPackage: *mut *mut ISetupPackageReference,
) -> HRESULT,
fn GetProductPath(
pbstrProductPath: *mut BSTR,
) -> HRESULT,
}}
RIDL! {#[uuid(0x6380bcff, 0x41d3, 0x4b2e, 0x8b, 0x2e, 0xbf, 0x8a, 0x68, 0x10, 0xc8, 0x48)]
interface IEnumSetupInstances(IEnumSetupInstancesVtbl): IUnknown(IUnknownVtbl) {
fn Next(
celt: ULONG,
rgelt: *mut *mut ISetupInstance,
pceltFetched: *mut ULONG,
) -> HRESULT,
fn Skip(
celt: ULONG,
) -> HRESULT,
fn Reset() -> HRESULT,
fn Clone(
ppenum: *mut *mut IEnumSetupInstances,
) -> HRESULT,
}}
RIDL! {#[uuid(0x42843719, 0xdb4c, 0x46c2, 0x8e, 0x7c, 0x64, 0xf1, 0x81, 0x6e, 0xfd, 0x5b)]
interface ISetupConfiguration(ISetupConfigurationVtbl): IUnknown(IUnknownVtbl) {
fn EnumInstances(
ppEnumInstances: *mut *mut IEnumSetupInstances,
) -> HRESULT,
fn GetInstanceForCurrentProcess(
ppInstance: *mut *mut ISetupInstance,
) -> HRESULT,
fn GetInstanceForPath(
wzPath: LPCWSTR,
ppInstance: *mut *mut ISetupInstance,
) -> HRESULT,
}}
RIDL! {#[uuid(0x26aab78c, 0x4a60, 0x49d6, 0xaf, 0x3b, 0x3c, 0x35, 0xbc, 0x93, 0x36, 0x5d)]
interface ISetupConfiguration2(ISetupConfiguration2Vtbl):
ISetupConfiguration(ISetupConfigurationVtbl) {
fn EnumAllInstances(
ppEnumInstances: *mut *mut IEnumSetupInstances,
) -> HRESULT,
}}
RIDL! {#[uuid(0xda8d8a16, 0xb2b6, 0x4487, 0xa2, 0xf1, 0x59, 0x4c, 0xcc, 0xcd, 0x6b, 0xf5)]
interface ISetupPackageReference(ISetupPackageReferenceVtbl): IUnknown(IUnknownVtbl) {
fn GetId(
pbstrId: *mut BSTR,
) -> HRESULT,
fn GetVersion(
pbstrVersion: *mut BSTR,
) -> HRESULT,
fn GetChip(
pbstrChip: *mut BSTR,
) -> HRESULT,
fn GetLanguage(
pbstrLanguage: *mut BSTR,
) -> HRESULT,
fn GetBranch(
pbstrBranch: *mut BSTR,
) -> HRESULT,
fn GetType(
pbstrType: *mut BSTR,
) -> HRESULT,
fn GetUniqueId(
pbstrUniqueId: *mut BSTR,
) -> HRESULT,
}}
RIDL! {#[uuid(0x42b21b78, 0x6192, 0x463e, 0x87, 0xbf, 0xd5, 0x77, 0x83, 0x8f, 0x1d, 0x5c)]
interface ISetupHelper(ISetupHelperVtbl): IUnknown(IUnknownVtbl) {
fn ParseVersion(
pwszVersion: LPCOLESTR,
pullVersion: PULONGLONG,
) -> HRESULT,
fn ParseVersionRange(
pwszVersionRange: LPCOLESTR,
pullMinVersion: PULONGLONG,
pullMaxVersion: PULONGLONG,
) -> HRESULT,
}}
DEFINE_GUID! {CLSID_SetupConfiguration,
0x177f0c4a, 0x1cd3, 0x4de7, 0xa3, 0x2c, 0x71, 0xdb, 0xbb, 0x9f, 0xa3, 0x6d}
// Safe wrapper around the COM interfaces
pub struct SetupConfiguration(ComPtr<ISetupConfiguration>);
impl SetupConfiguration {
pub fn new() -> Result<SetupConfiguration, i32> {
let mut obj = null_mut();
let err = unsafe {
CoCreateInstance(
&CLSID_SetupConfiguration,
null_mut(),
CLSCTX_ALL,
&ISetupConfiguration::uuidof(),
&mut obj,
)
};
if err < 0 {
return Err(err);
}
let obj = unsafe { ComPtr::from_raw(obj as *mut ISetupConfiguration) };
Ok(SetupConfiguration(obj))
}
pub fn get_instance_for_current_process(&self) -> Result<SetupInstance, i32> {
let mut obj = null_mut();
let err = unsafe { self.0.GetInstanceForCurrentProcess(&mut obj) };
if err < 0 {
return Err(err);
}
Ok(unsafe { SetupInstance::from_raw(obj) })
}
pub fn enum_instances(&self) -> Result<EnumSetupInstances, i32> {
let mut obj = null_mut();
let err = unsafe { self.0.EnumInstances(&mut obj) };
if err < 0 {
return Err(err);
}
Ok(unsafe { EnumSetupInstances::from_raw(obj) })
}
pub fn enum_all_instances(&self) -> Result<EnumSetupInstances, i32> {
let mut obj = null_mut();
let this = self.0.cast::<ISetupConfiguration2>()?;
let err = unsafe { this.EnumAllInstances(&mut obj) };
if err < 0 {
return Err(err);
}
Ok(unsafe { EnumSetupInstances::from_raw(obj) })
}
}
pub struct SetupInstance(ComPtr<ISetupInstance>);
impl SetupInstance {
pub unsafe fn from_raw(obj: *mut ISetupInstance) -> SetupInstance {
SetupInstance(ComPtr::from_raw(obj))
}
pub fn instance_id(&self) -> Result<OsString, i32> {
let mut s = null();
let err = unsafe { self.0.GetInstanceId(&mut s) };
let bstr = unsafe { BStr::from_raw(s) };
if err < 0 {
return Err(err);
}
Ok(bstr.to_osstring())
}
pub fn installation_name(&self) -> Result<OsString, i32> {
let mut s = null();
let err = unsafe { self.0.GetInstallationName(&mut s) };
let bstr = unsafe { BStr::from_raw(s) };
if err < 0 {
return Err(err);
}
Ok(bstr.to_osstring())
}
pub fn installation_path(&self) -> Result<OsString, i32> {
let mut s = null();
let err = unsafe { self.0.GetInstallationPath(&mut s) };
let bstr = unsafe { BStr::from_raw(s) };
if err < 0 {
return Err(err);
}
Ok(bstr.to_osstring())
}
pub fn installation_version(&self) -> Result<OsString, i32> {
let mut s = null();
let err = unsafe { self.0.GetInstallationVersion(&mut s) };
let bstr = unsafe { BStr::from_raw(s) };
if err < 0 {
return Err(err);
}
Ok(bstr.to_osstring())
}
pub fn product_path(&self) -> Result<OsString, i32> {
let mut s = null();
let this = self.0.cast::<ISetupInstance2>()?;
let err = unsafe { this.GetProductPath(&mut s) };
let bstr = unsafe { BStr::from_raw(s) };
if err < 0 {
return Err(err);
}
Ok(bstr.to_osstring())
}
}
pub struct EnumSetupInstances(ComPtr<IEnumSetupInstances>);
impl EnumSetupInstances {
pub unsafe fn from_raw(obj: *mut IEnumSetupInstances) -> EnumSetupInstances {
EnumSetupInstances(ComPtr::from_raw(obj))
}
}
impl Iterator for EnumSetupInstances {
type Item = Result<SetupInstance, i32>;
fn next(&mut self) -> Option<Result<SetupInstance, i32>> {
let mut obj = null_mut();
let err = unsafe { self.0.Next(1, &mut obj, null_mut()) };
if err < 0 {
return Some(Err(err));
}
if err == S_FALSE {
return None;
}
Some(Ok(unsafe { SetupInstance::from_raw(obj) }))
}
}

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

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

146
vendor/cc/src/winapi.rs vendored Normal file
View File

@ -0,0 +1,146 @@
// Copyright © 2015-2017 winapi-rs developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// All files in the project carrying such notice may not be copied, modified, or distributed
// except according to those terms.
#![allow(bad_style)]
use std::os::raw;
pub type wchar_t = u16;
pub use crate::windows_sys::{FILETIME, GUID, HRESULT, SAFEARRAY, SAFEARRAYBOUND};
pub type REFIID = *const IID;
pub type IID = GUID;
pub type ULONG = raw::c_ulong;
pub type DWORD = u32;
pub type LPFILETIME = *mut FILETIME;
pub type OLECHAR = WCHAR;
pub type WCHAR = wchar_t;
pub type LPCOLESTR = *const OLECHAR;
pub type LCID = DWORD;
pub type LPCWSTR = *const WCHAR;
pub type PULONGLONG = *mut ULONGLONG;
pub type ULONGLONG = u64;
pub trait Interface {
fn uuidof() -> GUID;
}
pub type LPSAFEARRAY = *mut SAFEARRAY;
macro_rules! DEFINE_GUID {
(
$name:ident, $l:expr, $w1:expr, $w2:expr,
$b1:expr, $b2:expr, $b3:expr, $b4:expr, $b5:expr, $b6:expr, $b7:expr, $b8:expr
) => {
pub const $name: $crate::winapi::GUID = $crate::winapi::GUID {
data1: $l,
data2: $w1,
data3: $w2,
data4: [$b1, $b2, $b3, $b4, $b5, $b6, $b7, $b8],
};
};
}
macro_rules! RIDL {
(#[uuid($($uuid:expr),+)]
interface $interface:ident ($vtbl:ident) {$(
fn $method:ident($($p:ident : $t:ty,)*) -> $rtr:ty,
)+}) => (
#[repr(C)]
pub struct $vtbl {
$(pub $method: unsafe extern "system" fn(
This: *mut $interface,
$($p: $t),*
) -> $rtr,)+
}
#[repr(C)]
pub struct $interface {
pub lpVtbl: *const $vtbl,
}
RIDL!{@impl $interface {$(fn $method($($p: $t,)*) -> $rtr,)+}}
RIDL!{@uuid $interface $($uuid),+}
);
(#[uuid($($uuid:expr),+)]
interface $interface:ident ($vtbl:ident) : $pinterface:ident ($pvtbl:ident) {
}) => (
#[repr(C)]
pub struct $vtbl {
pub parent: $pvtbl,
}
#[repr(C)]
pub struct $interface {
pub lpVtbl: *const $vtbl,
}
RIDL!{@deref $interface $pinterface}
RIDL!{@uuid $interface $($uuid),+}
);
(#[uuid($($uuid:expr),+)]
interface $interface:ident ($vtbl:ident) : $pinterface:ident ($pvtbl:ident) {$(
fn $method:ident($($p:ident : $t:ty,)*) -> $rtr:ty,
)+}) => (
#[repr(C)]
pub struct $vtbl {
pub parent: $pvtbl,
$(pub $method: unsafe extern "system" fn(
This: *mut $interface,
$($p: $t,)*
) -> $rtr,)+
}
#[repr(C)]
pub struct $interface {
pub lpVtbl: *const $vtbl,
}
RIDL!{@impl $interface {$(fn $method($($p: $t,)*) -> $rtr,)+}}
RIDL!{@deref $interface $pinterface}
RIDL!{@uuid $interface $($uuid),+}
);
(@deref $interface:ident $pinterface:ident) => (
impl ::std::ops::Deref for $interface {
type Target = $pinterface;
#[inline]
fn deref(&self) -> &$pinterface {
unsafe { &*(self as *const $interface as *const $pinterface) }
}
}
);
(@impl $interface:ident {$(
fn $method:ident($($p:ident : $t:ty,)*) -> $rtr:ty,
)+}) => (
impl $interface {
$(#[inline] pub unsafe fn $method(&self, $($p: $t,)*) -> $rtr {
((*self.lpVtbl).$method)(self as *const _ as *mut _, $($p,)*)
})+
}
);
(@uuid $interface:ident
$l:expr, $w1:expr, $w2:expr,
$b1:expr, $b2:expr, $b3:expr, $b4:expr, $b5:expr, $b6:expr, $b7:expr, $b8:expr
) => (
impl $crate::winapi::Interface for $interface {
#[inline]
fn uuidof() -> $crate::winapi::GUID {
$crate::winapi::GUID {
data1: $l,
data2: $w1,
data3: $w2,
data4: [$b1, $b2, $b3, $b4, $b5, $b6, $b7, $b8],
}
}
}
);
}
RIDL! {#[uuid(0x00000000, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)]
interface IUnknown(IUnknownVtbl) {
fn QueryInterface(
riid: REFIID,
ppvObject: *mut *mut raw::c_void,
) -> HRESULT,
fn AddRef() -> ULONG,
fn Release() -> ULONG,
}}

896
vendor/cc/src/windows_registry.rs vendored Normal file
View File

@ -0,0 +1,896 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! A helper module to probe the Windows Registry when looking for
//! windows-specific tools.
use std::process::Command;
use crate::Tool;
#[cfg(windows)]
use crate::ToolFamily;
#[cfg(windows)]
const MSVC_FAMILY: ToolFamily = ToolFamily::Msvc { clang_cl: false };
/// Attempts to find a tool within an MSVC installation using the Windows
/// registry as a point to search from.
///
/// The `target` argument is the target that the tool should work for (e.g.
/// compile or link for) and the `tool` argument is the tool to find (e.g.
/// `cl.exe` or `link.exe`).
///
/// This function will return `None` if the tool could not be found, or it will
/// return `Some(cmd)` which represents a command that's ready to execute the
/// tool with the appropriate environment variables set.
///
/// Note that this function always returns `None` for non-MSVC targets.
pub fn find(target: &str, tool: &str) -> Option<Command> {
find_tool(target, tool).map(|c| c.to_command())
}
/// Similar to the `find` function above, this function will attempt the same
/// operation (finding a MSVC tool in a local install) but instead returns a
/// `Tool` which may be introspected.
#[cfg(not(windows))]
pub fn find_tool(_target: &str, _tool: &str) -> Option<Tool> {
None
}
/// Documented above.
#[cfg(windows)]
pub fn find_tool(target: &str, tool: &str) -> Option<Tool> {
// This logic is all tailored for MSVC, if we're not that then bail out
// early.
if !target.contains("msvc") {
return None;
}
// Looks like msbuild isn't located in the same location as other tools like
// cl.exe and lib.exe. To handle this we probe for it manually with
// dedicated registry keys.
if tool.contains("msbuild") {
return impl_::find_msbuild(target);
}
if tool.contains("devenv") {
return impl_::find_devenv(target);
}
// Ok, if we're here, now comes the fun part of the probing. Default shells
// or shells like MSYS aren't really configured to execute `cl.exe` and the
// various compiler tools shipped as part of Visual Studio. Here we try to
// first find the relevant tool, then we also have to be sure to fill in
// environment variables like `LIB`, `INCLUDE`, and `PATH` to ensure that
// the tool is actually usable.
return impl_::find_msvc_environment(tool, target)
.or_else(|| impl_::find_msvc_15plus(tool, target))
.or_else(|| impl_::find_msvc_14(tool, target))
.or_else(|| impl_::find_msvc_12(tool, target))
.or_else(|| impl_::find_msvc_11(tool, target));
}
/// A version of Visual Studio
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[non_exhaustive]
pub enum VsVers {
/// Visual Studio 12 (2013)
Vs12,
/// Visual Studio 14 (2015)
Vs14,
/// Visual Studio 15 (2017)
Vs15,
/// Visual Studio 16 (2019)
Vs16,
/// Visual Studio 17 (2022)
Vs17,
}
/// Find the most recent installed version of Visual Studio
///
/// This is used by the cmake crate to figure out the correct
/// generator.
#[cfg(not(windows))]
pub fn find_vs_version() -> Result<VsVers, String> {
Err("not windows".to_string())
}
/// Documented above
#[cfg(windows)]
pub fn find_vs_version() -> Result<VsVers, String> {
use std::env;
match env::var("VisualStudioVersion") {
Ok(version) => match &version[..] {
"17.0" => Ok(VsVers::Vs17),
"16.0" => Ok(VsVers::Vs16),
"15.0" => Ok(VsVers::Vs15),
"14.0" => Ok(VsVers::Vs14),
"12.0" => Ok(VsVers::Vs12),
vers => Err(format!(
"\n\n\
unsupported or unknown VisualStudio version: {}\n\
if another version is installed consider running \
the appropriate vcvars script before building this \
crate\n\
",
vers
)),
},
_ => {
// Check for the presence of a specific registry key
// that indicates visual studio is installed.
if impl_::has_msbuild_version("17.0") {
Ok(VsVers::Vs17)
} else if impl_::has_msbuild_version("16.0") {
Ok(VsVers::Vs16)
} else if impl_::has_msbuild_version("15.0") {
Ok(VsVers::Vs15)
} else if impl_::has_msbuild_version("14.0") {
Ok(VsVers::Vs14)
} else if impl_::has_msbuild_version("12.0") {
Ok(VsVers::Vs12)
} else {
Err(format!(
"\n\n\
couldn't determine visual studio generator\n\
if VisualStudio is installed, however, consider \
running the appropriate vcvars script before building \
this crate\n\
"
))
}
}
}
}
#[cfg(windows)]
mod impl_ {
use crate::com;
use crate::registry::{RegistryKey, LOCAL_MACHINE};
use crate::setup_config::SetupConfiguration;
use crate::vs_instances::{VsInstances, VswhereInstance};
use std::convert::TryFrom;
use std::env;
use std::ffi::OsString;
use std::fs::File;
use std::io::Read;
use std::iter;
use std::mem;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str::FromStr;
use super::MSVC_FAMILY;
use crate::Tool;
struct MsvcTool {
tool: PathBuf,
libs: Vec<PathBuf>,
path: Vec<PathBuf>,
include: Vec<PathBuf>,
}
impl MsvcTool {
fn new(tool: PathBuf) -> MsvcTool {
MsvcTool {
tool: tool,
libs: Vec::new(),
path: Vec::new(),
include: Vec::new(),
}
}
fn into_tool(self) -> Tool {
let MsvcTool {
tool,
libs,
path,
include,
} = self;
let mut tool = Tool::with_family(tool.into(), MSVC_FAMILY);
add_env(&mut tool, "LIB", libs);
add_env(&mut tool, "PATH", path);
add_env(&mut tool, "INCLUDE", include);
tool
}
}
/// Checks to see if the `VSCMD_ARG_TGT_ARCH` environment variable matches the
/// given target's arch. Returns `None` if the variable does not exist.
#[cfg(windows)]
fn is_vscmd_target(target: &str) -> Option<bool> {
let vscmd_arch = env::var("VSCMD_ARG_TGT_ARCH").ok()?;
// Convert the Rust target arch to its VS arch equivalent.
let arch = match target.split("-").next() {
Some("x86_64") => "x64",
Some("aarch64") => "arm64",
Some("i686") | Some("i586") => "x86",
Some("thumbv7a") => "arm",
// An unrecognized arch.
_ => return Some(false),
};
Some(vscmd_arch == arch)
}
/// Attempt to find the tool using environment variables set by vcvars.
pub fn find_msvc_environment(tool: &str, target: &str) -> Option<Tool> {
// Early return if the environment doesn't contain a VC install.
if env::var_os("VCINSTALLDIR").is_none() {
return None;
}
let vs_install_dir = env::var_os("VSINSTALLDIR")?.into();
// If the vscmd target differs from the requested target then
// attempt to get the tool using the VS install directory.
if is_vscmd_target(target) == Some(false) {
// We will only get here with versions 15+.
tool_from_vs15plus_instance(tool, target, &vs_install_dir)
} else {
// Fallback to simply using the current environment.
env::var_os("PATH")
.and_then(|path| {
env::split_paths(&path)
.map(|p| p.join(tool))
.find(|p| p.exists())
})
.map(|path| Tool::with_family(path.into(), MSVC_FAMILY))
}
}
fn find_msbuild_vs17(target: &str) -> Option<Tool> {
find_tool_in_vs16plus_path(r"MSBuild\Current\Bin\MSBuild.exe", target, "17")
}
#[allow(bare_trait_objects)]
fn vs16plus_instances(target: &str, version: &'static str) -> Box<Iterator<Item = PathBuf>> {
let instances = if let Some(instances) = vs15plus_instances(target) {
instances
} else {
return Box::new(iter::empty());
};
Box::new(instances.into_iter().filter_map(move |instance| {
let installation_name = instance.installation_name()?;
if installation_name.starts_with(&format!("VisualStudio/{}.", version)) {
Some(instance.installation_path()?)
} else if installation_name.starts_with(&format!("VisualStudioPreview/{}.", version)) {
Some(instance.installation_path()?)
} else {
None
}
}))
}
fn find_tool_in_vs16plus_path(tool: &str, target: &str, version: &'static str) -> Option<Tool> {
vs16plus_instances(target, version)
.filter_map(|path| {
let path = path.join(tool);
if !path.is_file() {
return None;
}
let mut tool = Tool::with_family(path, MSVC_FAMILY);
if target.contains("x86_64") {
tool.env.push(("Platform".into(), "X64".into()));
}
if target.contains("aarch64") {
tool.env.push(("Platform".into(), "ARM64".into()));
}
Some(tool)
})
.next()
}
fn find_msbuild_vs16(target: &str) -> Option<Tool> {
find_tool_in_vs16plus_path(r"MSBuild\Current\Bin\MSBuild.exe", target, "16")
}
// In MSVC 15 (2017) MS once again changed the scheme for locating
// the tooling. Now we must go through some COM interfaces, which
// is super fun for Rust.
//
// Note that much of this logic can be found [online] wrt paths, COM, etc.
//
// [online]: https://blogs.msdn.microsoft.com/vcblog/2017/03/06/finding-the-visual-c-compiler-tools-in-visual-studio-2017/
//
// Returns MSVC 15+ instances (15, 16 right now), the order should be consider undefined.
//
// However, on ARM64 this method doesn't work because VS Installer fails to register COM component on ARM64.
// Hence, as the last resort we try to use vswhere.exe to list available instances.
fn vs15plus_instances(target: &str) -> Option<VsInstances> {
vs15plus_instances_using_com().or_else(|| vs15plus_instances_using_vswhere(target))
}
fn vs15plus_instances_using_com() -> Option<VsInstances> {
com::initialize().ok()?;
let config = SetupConfiguration::new().ok()?;
let enum_setup_instances = config.enum_all_instances().ok()?;
Some(VsInstances::ComBased(enum_setup_instances))
}
fn vs15plus_instances_using_vswhere(target: &str) -> Option<VsInstances> {
let program_files_path: PathBuf = env::var("ProgramFiles(x86)")
.or_else(|_| env::var("ProgramFiles"))
.ok()?
.into();
let vswhere_path =
program_files_path.join(r"Microsoft Visual Studio\Installer\vswhere.exe");
if !vswhere_path.exists() {
return None;
}
let arch = target.split('-').next().unwrap();
let tools_arch = match arch {
"i586" | "i686" | "x86_64" => Some("x86.x64"),
"arm" | "thumbv7a" => Some("ARM"),
"aarch64" => Some("ARM64"),
_ => None,
};
let vswhere_output = Command::new(vswhere_path)
.args(&[
"-latest",
"-products",
"*",
"-requires",
&format!("Microsoft.VisualStudio.Component.VC.Tools.{}", tools_arch?),
"-format",
"text",
"-nologo",
])
.stderr(std::process::Stdio::inherit())
.output()
.ok()?;
let vs_instances =
VsInstances::VswhereBased(VswhereInstance::try_from(&vswhere_output.stdout).ok()?);
Some(vs_instances)
}
// Inspired from official microsoft/vswhere ParseVersionString
// i.e. at most four u16 numbers separated by '.'
fn parse_version(version: &str) -> Option<Vec<u16>> {
version
.split('.')
.map(|chunk| u16::from_str(chunk).ok())
.collect()
}
pub fn find_msvc_15plus(tool: &str, target: &str) -> Option<Tool> {
let iter = vs15plus_instances(target)?;
iter.into_iter()
.filter_map(|instance| {
let version = parse_version(&instance.installation_version()?)?;
let instance_path = instance.installation_path()?;
let tool = tool_from_vs15plus_instance(tool, target, &instance_path)?;
Some((version, tool))
})
.max_by(|(a_version, _), (b_version, _)| a_version.cmp(b_version))
.map(|(_version, tool)| tool)
}
// While the paths to Visual Studio 2017's devenv and MSBuild could
// potentially be retrieved from the registry, finding them via
// SetupConfiguration has shown to be [more reliable], and is preferred
// according to Microsoft. To help head off potential regressions though,
// we keep the registry method as a fallback option.
//
// [more reliable]: https://github.com/rust-lang/cc-rs/pull/331
fn find_tool_in_vs15_path(tool: &str, target: &str) -> Option<Tool> {
let mut path = match vs15plus_instances(target) {
Some(instances) => instances
.into_iter()
.filter_map(|instance| instance.installation_path())
.map(|path| path.join(tool))
.find(|ref path| path.is_file()),
None => None,
};
if path.is_none() {
let key = r"SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7";
path = LOCAL_MACHINE
.open(key.as_ref())
.ok()
.and_then(|key| key.query_str("15.0").ok())
.map(|path| PathBuf::from(path).join(tool))
.and_then(|path| if path.is_file() { Some(path) } else { None });
}
path.map(|path| {
let mut tool = Tool::with_family(path, MSVC_FAMILY);
if target.contains("x86_64") {
tool.env.push(("Platform".into(), "X64".into()));
}
if target.contains("aarch64") {
tool.env.push(("Platform".into(), "ARM64".into()));
}
tool
})
}
fn tool_from_vs15plus_instance(
tool: &str,
target: &str,
instance_path: &PathBuf,
) -> Option<Tool> {
let (root_path, bin_path, host_dylib_path, lib_path, include_path) =
vs15plus_vc_paths(target, instance_path)?;
let tool_path = bin_path.join(tool);
if !tool_path.exists() {
return None;
};
let mut tool = MsvcTool::new(tool_path);
tool.path.push(bin_path.clone());
tool.path.push(host_dylib_path);
tool.libs.push(lib_path);
tool.include.push(include_path);
if let Some((atl_lib_path, atl_include_path)) = atl_paths(target, &root_path) {
tool.libs.push(atl_lib_path);
tool.include.push(atl_include_path);
}
add_sdks(&mut tool, target)?;
Some(tool.into_tool())
}
fn vs15plus_vc_paths(
target: &str,
instance_path: &PathBuf,
) -> Option<(PathBuf, PathBuf, PathBuf, PathBuf, PathBuf)> {
let version_path =
instance_path.join(r"VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt");
let mut version_file = File::open(version_path).ok()?;
let mut version = String::new();
version_file.read_to_string(&mut version).ok()?;
let version = version.trim();
let host = match host_arch() {
X86 => "X86",
X86_64 => "X64",
// There is no natively hosted compiler on ARM64.
// Instead, use the x86 toolchain under emulation (there is no x64 emulation).
AARCH64 => "X86",
_ => return None,
};
let target = lib_subdir(target)?;
// The directory layout here is MSVC/bin/Host$host/$target/
let path = instance_path.join(r"VC\Tools\MSVC").join(version);
// This is the path to the toolchain for a particular target, running
// on a given host
let bin_path = path
.join("bin")
.join(&format!("Host{}", host))
.join(&target);
// But! we also need PATH to contain the target directory for the host
// architecture, because it contains dlls like mspdb140.dll compiled for
// the host architecture.
let host_dylib_path = path
.join("bin")
.join(&format!("Host{}", host))
.join(&host.to_lowercase());
let lib_path = path.join("lib").join(&target);
let include_path = path.join("include");
Some((path, bin_path, host_dylib_path, lib_path, include_path))
}
fn atl_paths(target: &str, path: &Path) -> Option<(PathBuf, PathBuf)> {
let atl_path = path.join("atlmfc");
let sub = lib_subdir(target)?;
if atl_path.exists() {
Some((atl_path.join("lib").join(sub), atl_path.join("include")))
} else {
None
}
}
// For MSVC 14 we need to find the Universal CRT as well as either
// the Windows 10 SDK or Windows 8.1 SDK.
pub fn find_msvc_14(tool: &str, target: &str) -> Option<Tool> {
let vcdir = get_vc_dir("14.0")?;
let mut tool = get_tool(tool, &vcdir, target)?;
add_sdks(&mut tool, target)?;
Some(tool.into_tool())
}
fn add_sdks(tool: &mut MsvcTool, target: &str) -> Option<()> {
let sub = lib_subdir(target)?;
let (ucrt, ucrt_version) = get_ucrt_dir()?;
let host = match host_arch() {
X86 => "x86",
X86_64 => "x64",
AARCH64 => "arm64",
_ => return None,
};
tool.path
.push(ucrt.join("bin").join(&ucrt_version).join(host));
let ucrt_include = ucrt.join("include").join(&ucrt_version);
tool.include.push(ucrt_include.join("ucrt"));
let ucrt_lib = ucrt.join("lib").join(&ucrt_version);
tool.libs.push(ucrt_lib.join("ucrt").join(sub));
if let Some((sdk, version)) = get_sdk10_dir() {
tool.path.push(sdk.join("bin").join(host));
let sdk_lib = sdk.join("lib").join(&version);
tool.libs.push(sdk_lib.join("um").join(sub));
let sdk_include = sdk.join("include").join(&version);
tool.include.push(sdk_include.join("um"));
tool.include.push(sdk_include.join("cppwinrt"));
tool.include.push(sdk_include.join("winrt"));
tool.include.push(sdk_include.join("shared"));
} else if let Some(sdk) = get_sdk81_dir() {
tool.path.push(sdk.join("bin").join(host));
let sdk_lib = sdk.join("lib").join("winv6.3");
tool.libs.push(sdk_lib.join("um").join(sub));
let sdk_include = sdk.join("include");
tool.include.push(sdk_include.join("um"));
tool.include.push(sdk_include.join("winrt"));
tool.include.push(sdk_include.join("shared"));
}
Some(())
}
// For MSVC 12 we need to find the Windows 8.1 SDK.
pub fn find_msvc_12(tool: &str, target: &str) -> Option<Tool> {
let vcdir = get_vc_dir("12.0")?;
let mut tool = get_tool(tool, &vcdir, target)?;
let sub = lib_subdir(target)?;
let sdk81 = get_sdk81_dir()?;
tool.path.push(sdk81.join("bin").join(sub));
let sdk_lib = sdk81.join("lib").join("winv6.3");
tool.libs.push(sdk_lib.join("um").join(sub));
let sdk_include = sdk81.join("include");
tool.include.push(sdk_include.join("shared"));
tool.include.push(sdk_include.join("um"));
tool.include.push(sdk_include.join("winrt"));
Some(tool.into_tool())
}
// For MSVC 11 we need to find the Windows 8 SDK.
pub fn find_msvc_11(tool: &str, target: &str) -> Option<Tool> {
let vcdir = get_vc_dir("11.0")?;
let mut tool = get_tool(tool, &vcdir, target)?;
let sub = lib_subdir(target)?;
let sdk8 = get_sdk8_dir()?;
tool.path.push(sdk8.join("bin").join(sub));
let sdk_lib = sdk8.join("lib").join("win8");
tool.libs.push(sdk_lib.join("um").join(sub));
let sdk_include = sdk8.join("include");
tool.include.push(sdk_include.join("shared"));
tool.include.push(sdk_include.join("um"));
tool.include.push(sdk_include.join("winrt"));
Some(tool.into_tool())
}
fn add_env(tool: &mut Tool, env: &str, paths: Vec<PathBuf>) {
let prev = env::var_os(env).unwrap_or(OsString::new());
let prev = env::split_paths(&prev);
let new = paths.into_iter().chain(prev);
tool.env
.push((env.to_string().into(), env::join_paths(new).unwrap()));
}
// Given a possible MSVC installation directory, we look for the linker and
// then add the MSVC library path.
fn get_tool(tool: &str, path: &Path, target: &str) -> Option<MsvcTool> {
bin_subdir(target)
.into_iter()
.map(|(sub, host)| {
(
path.join("bin").join(sub).join(tool),
path.join("bin").join(host),
)
})
.filter(|&(ref path, _)| path.is_file())
.map(|(path, host)| {
let mut tool = MsvcTool::new(path);
tool.path.push(host);
tool
})
.filter_map(|mut tool| {
let sub = vc_lib_subdir(target)?;
tool.libs.push(path.join("lib").join(sub));
tool.include.push(path.join("include"));
let atlmfc_path = path.join("atlmfc");
if atlmfc_path.exists() {
tool.libs.push(atlmfc_path.join("lib").join(sub));
tool.include.push(atlmfc_path.join("include"));
}
Some(tool)
})
.next()
}
// To find MSVC we look in a specific registry key for the version we are
// trying to find.
fn get_vc_dir(ver: &str) -> Option<PathBuf> {
let key = r"SOFTWARE\Microsoft\VisualStudio\SxS\VC7";
let key = LOCAL_MACHINE.open(key.as_ref()).ok()?;
let path = key.query_str(ver).ok()?;
Some(path.into())
}
// To find the Universal CRT we look in a specific registry key for where
// all the Universal CRTs are located and then sort them asciibetically to
// find the newest version. While this sort of sorting isn't ideal, it is
// what vcvars does so that's good enough for us.
//
// Returns a pair of (root, version) for the ucrt dir if found
fn get_ucrt_dir() -> Option<(PathBuf, String)> {
let key = r"SOFTWARE\Microsoft\Windows Kits\Installed Roots";
let key = LOCAL_MACHINE.open(key.as_ref()).ok()?;
let root = key.query_str("KitsRoot10").ok()?;
let readdir = Path::new(&root).join("lib").read_dir().ok()?;
let max_libdir = readdir
.filter_map(|dir| dir.ok())
.map(|dir| dir.path())
.filter(|dir| {
dir.components()
.last()
.and_then(|c| c.as_os_str().to_str())
.map(|c| c.starts_with("10.") && dir.join("ucrt").is_dir())
.unwrap_or(false)
})
.max()?;
let version = max_libdir.components().last().unwrap();
let version = version.as_os_str().to_str().unwrap().to_string();
Some((root.into(), version))
}
// Vcvars finds the correct version of the Windows 10 SDK by looking
// for the include `um\Windows.h` because sometimes a given version will
// only have UCRT bits without the rest of the SDK. Since we only care about
// libraries and not includes, we instead look for `um\x64\kernel32.lib`.
// Since the 32-bit and 64-bit libraries are always installed together we
// only need to bother checking x64, making this code a tiny bit simpler.
// Like we do for the Universal CRT, we sort the possibilities
// asciibetically to find the newest one as that is what vcvars does.
// Before doing that, we check the "WindowsSdkDir" and "WindowsSDKVersion"
// environment variables set by vcvars to use the environment sdk version
// if one is already configured.
fn get_sdk10_dir() -> Option<(PathBuf, String)> {
if let (Ok(root), Ok(version)) = (env::var("WindowsSdkDir"), env::var("WindowsSDKVersion"))
{
return Some((root.into(), version.trim_end_matches('\\').to_string()));
}
let key = r"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0";
let key = LOCAL_MACHINE.open(key.as_ref()).ok()?;
let root = key.query_str("InstallationFolder").ok()?;
let readdir = Path::new(&root).join("lib").read_dir().ok()?;
let mut dirs = readdir
.filter_map(|dir| dir.ok())
.map(|dir| dir.path())
.collect::<Vec<_>>();
dirs.sort();
let dir = dirs
.into_iter()
.rev()
.filter(|dir| dir.join("um").join("x64").join("kernel32.lib").is_file())
.next()?;
let version = dir.components().last().unwrap();
let version = version.as_os_str().to_str().unwrap().to_string();
Some((root.into(), version))
}
// Interestingly there are several subdirectories, `win7` `win8` and
// `winv6.3`. Vcvars seems to only care about `winv6.3` though, so the same
// applies to us. Note that if we were targeting kernel mode drivers
// instead of user mode applications, we would care.
fn get_sdk81_dir() -> Option<PathBuf> {
let key = r"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.1";
let key = LOCAL_MACHINE.open(key.as_ref()).ok()?;
let root = key.query_str("InstallationFolder").ok()?;
Some(root.into())
}
fn get_sdk8_dir() -> Option<PathBuf> {
let key = r"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.0";
let key = LOCAL_MACHINE.open(key.as_ref()).ok()?;
let root = key.query_str("InstallationFolder").ok()?;
Some(root.into())
}
const PROCESSOR_ARCHITECTURE_INTEL: u16 = 0;
const PROCESSOR_ARCHITECTURE_AMD64: u16 = 9;
const PROCESSOR_ARCHITECTURE_ARM64: u16 = 12;
const X86: u16 = PROCESSOR_ARCHITECTURE_INTEL;
const X86_64: u16 = PROCESSOR_ARCHITECTURE_AMD64;
const AARCH64: u16 = PROCESSOR_ARCHITECTURE_ARM64;
// When choosing the tool to use, we have to choose the one which matches
// the target architecture. Otherwise we end up in situations where someone
// on 32-bit Windows is trying to cross compile to 64-bit and it tries to
// invoke the native 64-bit compiler which won't work.
//
// For the return value of this function, the first member of the tuple is
// the folder of the tool we will be invoking, while the second member is
// the folder of the host toolchain for that tool which is essential when
// using a cross linker. We return a Vec since on x64 there are often two
// linkers that can target the architecture we desire. The 64-bit host
// linker is preferred, and hence first, due to 64-bit allowing it more
// address space to work with and potentially being faster.
fn bin_subdir(target: &str) -> Vec<(&'static str, &'static str)> {
let arch = target.split('-').next().unwrap();
match (arch, host_arch()) {
("i586", X86) | ("i686", X86) => vec![("", "")],
("i586", X86_64) | ("i686", X86_64) => vec![("amd64_x86", "amd64"), ("", "")],
("x86_64", X86) => vec![("x86_amd64", "")],
("x86_64", X86_64) => vec![("amd64", "amd64"), ("x86_amd64", "")],
("arm", X86) | ("thumbv7a", X86) => vec![("x86_arm", "")],
("arm", X86_64) | ("thumbv7a", X86_64) => vec![("amd64_arm", "amd64"), ("x86_arm", "")],
_ => vec![],
}
}
fn lib_subdir(target: &str) -> Option<&'static str> {
let arch = target.split('-').next().unwrap();
match arch {
"i586" | "i686" => Some("x86"),
"x86_64" => Some("x64"),
"arm" | "thumbv7a" => Some("arm"),
"aarch64" => Some("arm64"),
_ => None,
}
}
// MSVC's x86 libraries are not in a subfolder
fn vc_lib_subdir(target: &str) -> Option<&'static str> {
let arch = target.split('-').next().unwrap();
match arch {
"i586" | "i686" => Some(""),
"x86_64" => Some("amd64"),
"arm" | "thumbv7a" => Some("arm"),
"aarch64" => Some("arm64"),
_ => None,
}
}
#[allow(bad_style)]
fn host_arch() -> u16 {
type DWORD = u32;
type WORD = u16;
type LPVOID = *mut u8;
type DWORD_PTR = usize;
#[repr(C)]
struct SYSTEM_INFO {
wProcessorArchitecture: WORD,
_wReserved: WORD,
_dwPageSize: DWORD,
_lpMinimumApplicationAddress: LPVOID,
_lpMaximumApplicationAddress: LPVOID,
_dwActiveProcessorMask: DWORD_PTR,
_dwNumberOfProcessors: DWORD,
_dwProcessorType: DWORD,
_dwAllocationGranularity: DWORD,
_wProcessorLevel: WORD,
_wProcessorRevision: WORD,
}
extern "system" {
fn GetNativeSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
}
unsafe {
let mut info = mem::zeroed();
GetNativeSystemInfo(&mut info);
info.wProcessorArchitecture
}
}
// Given a registry key, look at all the sub keys and find the one which has
// the maximal numeric value.
//
// Returns the name of the maximal key as well as the opened maximal key.
fn max_version(key: &RegistryKey) -> Option<(OsString, RegistryKey)> {
let mut max_vers = 0;
let mut max_key = None;
for subkey in key.iter().filter_map(|k| k.ok()) {
let val = subkey
.to_str()
.and_then(|s| s.trim_left_matches("v").replace(".", "").parse().ok());
let val = match val {
Some(s) => s,
None => continue,
};
if val > max_vers {
if let Ok(k) = key.open(&subkey) {
max_vers = val;
max_key = Some((subkey, k));
}
}
}
max_key
}
pub fn has_msbuild_version(version: &str) -> bool {
match version {
"17.0" => {
find_msbuild_vs17("x86_64-pc-windows-msvc").is_some()
|| find_msbuild_vs17("i686-pc-windows-msvc").is_some()
|| find_msbuild_vs17("aarch64-pc-windows-msvc").is_some()
}
"16.0" => {
find_msbuild_vs16("x86_64-pc-windows-msvc").is_some()
|| find_msbuild_vs16("i686-pc-windows-msvc").is_some()
|| find_msbuild_vs16("aarch64-pc-windows-msvc").is_some()
}
"15.0" => {
find_msbuild_vs15("x86_64-pc-windows-msvc").is_some()
|| find_msbuild_vs15("i686-pc-windows-msvc").is_some()
|| find_msbuild_vs15("aarch64-pc-windows-msvc").is_some()
}
"12.0" | "14.0" => LOCAL_MACHINE
.open(&OsString::from(format!(
"SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\{}",
version
)))
.is_ok(),
_ => false,
}
}
pub fn find_devenv(target: &str) -> Option<Tool> {
find_devenv_vs15(&target)
}
fn find_devenv_vs15(target: &str) -> Option<Tool> {
find_tool_in_vs15_path(r"Common7\IDE\devenv.exe", target)
}
// see http://stackoverflow.com/questions/328017/path-to-msbuild
pub fn find_msbuild(target: &str) -> Option<Tool> {
// VS 15 (2017) changed how to locate msbuild
if let Some(r) = find_msbuild_vs17(target) {
return Some(r);
} else if let Some(r) = find_msbuild_vs16(target) {
return Some(r);
} else if let Some(r) = find_msbuild_vs15(target) {
return Some(r);
} else {
find_old_msbuild(target)
}
}
fn find_msbuild_vs15(target: &str) -> Option<Tool> {
find_tool_in_vs15_path(r"MSBuild\15.0\Bin\MSBuild.exe", target)
}
fn find_old_msbuild(target: &str) -> Option<Tool> {
let key = r"SOFTWARE\Microsoft\MSBuild\ToolsVersions";
LOCAL_MACHINE
.open(key.as_ref())
.ok()
.and_then(|key| {
max_version(&key).and_then(|(_vers, key)| key.query_str("MSBuildToolsPath").ok())
})
.map(|path| {
let mut path = PathBuf::from(path);
path.push("MSBuild.exe");
let mut tool = Tool::with_family(path, MSVC_FAMILY);
if target.contains("x86_64") {
tool.env.push(("Platform".into(), "X64".into()));
}
tool
})
}
}

198
vendor/cc/src/windows_sys.rs vendored Normal file
View File

@ -0,0 +1,198 @@
// This file is autogenerated.
//
// To add bindings, edit windows_sys.lst then run:
//
// ```
// cd generate-windows-sys/
// cargo run
// ```
// Bindings generated by `windows-bindgen` 0.49.0
#![allow(
non_snake_case,
non_upper_case_globals,
non_camel_case_types,
dead_code,
clippy::all
)]
#[link(name = "advapi32")]
extern "system" {
pub fn RegCloseKey(hkey: HKEY) -> WIN32_ERROR;
}
#[link(name = "advapi32")]
extern "system" {
pub fn RegEnumKeyExW(
hkey: HKEY,
dwindex: u32,
lpname: PWSTR,
lpcchname: *mut u32,
lpreserved: *const u32,
lpclass: PWSTR,
lpcchclass: *mut u32,
lpftlastwritetime: *mut FILETIME,
) -> WIN32_ERROR;
}
#[link(name = "advapi32")]
extern "system" {
pub fn RegOpenKeyExW(
hkey: HKEY,
lpsubkey: PCWSTR,
uloptions: u32,
samdesired: REG_SAM_FLAGS,
phkresult: *mut HKEY,
) -> WIN32_ERROR;
}
#[link(name = "advapi32")]
extern "system" {
pub fn RegQueryValueExW(
hkey: HKEY,
lpvaluename: PCWSTR,
lpreserved: *const u32,
lptype: *mut REG_VALUE_TYPE,
lpdata: *mut u8,
lpcbdata: *mut u32,
) -> WIN32_ERROR;
}
#[link(name = "kernel32")]
extern "system" {
pub fn CreatePipe(
hreadpipe: *mut HANDLE,
hwritepipe: *mut HANDLE,
lppipeattributes: *const SECURITY_ATTRIBUTES,
nsize: u32,
) -> BOOL;
}
#[link(name = "ole32")]
extern "system" {
pub fn CoCreateInstance(
rclsid: *const GUID,
punkouter: IUnknown,
dwclscontext: CLSCTX,
riid: *const GUID,
ppv: *mut *mut ::core::ffi::c_void,
) -> HRESULT;
}
#[link(name = "ole32")]
extern "system" {
pub fn CoInitializeEx(pvreserved: *const ::core::ffi::c_void, dwcoinit: COINIT) -> HRESULT;
}
#[link(name = "oleaut32")]
extern "system" {
pub fn SysFreeString(bstrstring: BSTR) -> ();
}
#[link(name = "oleaut32")]
extern "system" {
pub fn SysStringLen(pbstr: BSTR) -> u32;
}
pub type ADVANCED_FEATURE_FLAGS = u16;
pub type BOOL = i32;
pub type BSTR = *const u16;
pub type CLSCTX = u32;
pub const CLSCTX_ALL: CLSCTX = 23u32;
pub type COINIT = i32;
pub const COINIT_MULTITHREADED: COINIT = 0i32;
pub const ERROR_NO_MORE_ITEMS: WIN32_ERROR = 259u32;
pub const ERROR_SUCCESS: WIN32_ERROR = 0u32;
#[repr(C)]
pub struct FILETIME {
pub dwLowDateTime: u32,
pub dwHighDateTime: u32,
}
impl ::core::marker::Copy for FILETIME {}
impl ::core::clone::Clone for FILETIME {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
pub struct GUID {
pub data1: u32,
pub data2: u16,
pub data3: u16,
pub data4: [u8; 8],
}
impl GUID {
pub const fn from_u128(uuid: u128) -> Self {
Self {
data1: (uuid >> 96) as u32,
data2: (uuid >> 80 & 0xffff) as u16,
data3: (uuid >> 64 & 0xffff) as u16,
data4: (uuid as u64).to_be_bytes(),
}
}
}
impl ::core::marker::Copy for GUID {}
impl ::core::clone::Clone for GUID {
fn clone(&self) -> Self {
*self
}
}
pub type HANDLE = *mut ::core::ffi::c_void;
pub type HKEY = *mut ::core::ffi::c_void;
pub const HKEY_LOCAL_MACHINE: HKEY = invalid_mut(-2147483646i32 as _);
pub type HRESULT = i32;
pub const INVALID_HANDLE_VALUE: HANDLE = invalid_mut(-1i32 as _);
pub type IUnknown = *mut ::core::ffi::c_void;
pub const KEY_READ: REG_SAM_FLAGS = 131097u32;
pub const KEY_WOW64_32KEY: REG_SAM_FLAGS = 512u32;
pub type PCWSTR = *const u16;
pub type PWSTR = *mut u16;
pub type REG_SAM_FLAGS = u32;
pub const REG_SZ: REG_VALUE_TYPE = 1u32;
pub type REG_VALUE_TYPE = u32;
#[repr(C)]
pub struct SAFEARRAY {
pub cDims: u16,
pub fFeatures: ADVANCED_FEATURE_FLAGS,
pub cbElements: u32,
pub cLocks: u32,
pub pvData: *mut ::core::ffi::c_void,
pub rgsabound: [SAFEARRAYBOUND; 1],
}
impl ::core::marker::Copy for SAFEARRAY {}
impl ::core::clone::Clone for SAFEARRAY {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
pub struct SAFEARRAYBOUND {
pub cElements: u32,
pub lLbound: i32,
}
impl ::core::marker::Copy for SAFEARRAYBOUND {}
impl ::core::clone::Clone for SAFEARRAYBOUND {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
pub struct SECURITY_ATTRIBUTES {
pub nLength: u32,
pub lpSecurityDescriptor: *mut ::core::ffi::c_void,
pub bInheritHandle: BOOL,
}
impl ::core::marker::Copy for SECURITY_ATTRIBUTES {}
impl ::core::clone::Clone for SECURITY_ATTRIBUTES {
fn clone(&self) -> Self {
*self
}
}
pub const S_FALSE: HRESULT = 1i32;
pub const S_OK: HRESULT = 0i32;
pub type WIN32_ERROR = u32;
/// Adapted from
/// [`core::ptr::invalid_mut()`](https://doc.rust-lang.org/src/core/ptr/mod.rs.html#600-607).
///
/// This function should actually use `core::mem::transmute` but due to msrv
/// we use `as` casting instead.
///
/// Once msrv is bumped to 1.56, replace this with `core::mem::transmute` since
/// it is const stablised in 1.56
///
/// NOTE that once supports `strict_provenance` we would also have to update
/// this.
const fn invalid_mut<T>(addr: usize) -> *mut T {
addr as *mut T
}

118
vendor/cc/tests/cc_env.rs vendored Normal file
View File

@ -0,0 +1,118 @@
use std::env;
use std::ffi::OsString;
use std::path::Path;
mod support;
use crate::support::Test;
#[test]
fn main() {
ccache();
distcc();
ccache_spaces();
ccache_env_flags();
leading_spaces();
extra_flags();
path_to_ccache();
more_spaces();
}
fn ccache() {
let test = Test::gnu();
env::set_var("CC", "ccache cc");
let compiler = test.gcc().file("foo.c").get_compiler();
assert_eq!(compiler.path(), Path::new("cc"));
}
fn ccache_spaces() {
let test = Test::gnu();
test.shim("ccache");
env::set_var("CC", "ccache cc");
let compiler = test.gcc().file("foo.c").get_compiler();
assert_eq!(compiler.path(), Path::new("cc"));
}
fn distcc() {
let test = Test::gnu();
test.shim("distcc");
env::set_var("CC", "distcc cc");
let compiler = test.gcc().file("foo.c").get_compiler();
assert_eq!(compiler.path(), Path::new("cc"));
}
fn ccache_env_flags() {
let test = Test::gnu();
test.shim("ccache");
env::set_var("CC", "ccache lol-this-is-not-a-compiler");
let compiler = test.gcc().file("foo.c").get_compiler();
assert_eq!(compiler.path(), Path::new("lol-this-is-not-a-compiler"));
assert_eq!(
compiler.cc_env(),
OsString::from("ccache lol-this-is-not-a-compiler")
);
assert!(
compiler
.cflags_env()
.into_string()
.unwrap()
.contains("ccache")
== false
);
assert!(
compiler
.cflags_env()
.into_string()
.unwrap()
.contains(" lol-this-is-not-a-compiler")
== false
);
env::set_var("CC", "");
}
fn leading_spaces() {
let test = Test::gnu();
test.shim("ccache");
env::set_var("CC", " test ");
let compiler = test.gcc().file("foo.c").get_compiler();
assert_eq!(compiler.path(), Path::new("test"));
env::set_var("CC", "");
}
fn extra_flags() {
let test = Test::gnu();
test.shim("ccache");
env::set_var("CC", "ccache cc -m32");
let compiler = test.gcc().file("foo.c").get_compiler();
assert_eq!(compiler.path(), Path::new("cc"));
}
fn path_to_ccache() {
let test = Test::gnu();
test.shim("ccache");
env::set_var("CC", "/path/to/ccache.exe cc -m32");
let compiler = test.gcc().file("foo.c").get_compiler();
assert_eq!(compiler.path(), Path::new("cc"));
assert_eq!(
compiler.cc_env(),
OsString::from("/path/to/ccache.exe cc -m32"),
);
}
fn more_spaces() {
let test = Test::gnu();
test.shim("ccache");
env::set_var("CC", "cc -m32");
let compiler = test.gcc().file("foo.c").get_compiler();
assert_eq!(compiler.path(), Path::new("cc"));
}

15
vendor/cc/tests/cflags.rs vendored Normal file
View File

@ -0,0 +1,15 @@
mod support;
use crate::support::Test;
use std::env;
/// This test is in its own module because it modifies the environment and would affect other tests
/// when run in parallel with them.
#[test]
fn gnu_no_warnings_if_cflags() {
env::set_var("CFLAGS", "-arbitrary");
let test = Test::gnu();
test.gcc().file("foo.c").compile("foo");
test.cmd(0).must_not_have("-Wall").must_not_have("-Wextra");
}

15
vendor/cc/tests/cxxflags.rs vendored Normal file
View File

@ -0,0 +1,15 @@
mod support;
use crate::support::Test;
use std::env;
/// This test is in its own module because it modifies the environment and would affect other tests
/// when run in parallel with them.
#[test]
fn gnu_no_warnings_if_cxxflags() {
env::set_var("CXXFLAGS", "-arbitrary");
let test = Test::gnu();
test.gcc().file("foo.cpp").cpp(true).compile("foo");
test.cmd(0).must_not_have("-Wall").must_not_have("-Wextra");
}

172
vendor/cc/tests/support/mod.rs vendored Normal file
View File

@ -0,0 +1,172 @@
#![allow(dead_code)]
use std::env;
use std::ffi::{OsStr, OsString};
use std::fs::{self, File};
use std::io;
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use cc;
use tempfile::{Builder, TempDir};
pub struct Test {
pub td: TempDir,
pub gcc: PathBuf,
pub msvc: bool,
}
pub struct Execution {
args: Vec<String>,
}
impl Test {
pub fn new() -> Test {
// This is ugly: `sccache` needs to introspect the compiler it is
// executing, as it adjusts its behavior depending on the
// language/compiler. This crate's test driver uses mock compilers that
// are obviously not supported by sccache, so the tests fail if
// RUSTC_WRAPPER is set. rust doesn't build test dependencies with
// the `test` feature enabled, so we can't conditionally disable the
// usage of `sccache` if running in a test environment, at least not
// without setting an environment variable here and testing for it
// there. Explicitly deasserting RUSTC_WRAPPER here seems to be the
// lesser of the two evils.
env::remove_var("RUSTC_WRAPPER");
let mut gcc = PathBuf::from(env::current_exe().unwrap());
gcc.pop();
if gcc.ends_with("deps") {
gcc.pop();
}
let td = Builder::new().prefix("gcc-test").tempdir_in(&gcc).unwrap();
gcc.push(format!("gcc-shim{}", env::consts::EXE_SUFFIX));
Test {
td: td,
gcc: gcc,
msvc: false,
}
}
pub fn gnu() -> Test {
let t = Test::new();
t.shim("cc").shim("c++").shim("ar");
t
}
pub fn msvc() -> Test {
let mut t = Test::new();
t.shim("cl").shim("lib.exe");
t.msvc = true;
t
}
pub fn shim(&self, name: &str) -> &Test {
let name = if name.ends_with(env::consts::EXE_SUFFIX) {
name.to_string()
} else {
format!("{}{}", name, env::consts::EXE_SUFFIX)
};
link_or_copy(&self.gcc, self.td.path().join(name)).unwrap();
self
}
pub fn gcc(&self) -> cc::Build {
let mut cfg = cc::Build::new();
let target = if self.msvc {
"x86_64-pc-windows-msvc"
} else {
"x86_64-unknown-linux-gnu"
};
cfg.target(target)
.host(target)
.opt_level(2)
.debug(false)
.out_dir(self.td.path())
.__set_env("PATH", self.path())
.__set_env("GCCTEST_OUT_DIR", self.td.path());
if self.msvc {
cfg.compiler(self.td.path().join("cl"));
cfg.archiver(self.td.path().join("lib.exe"));
}
cfg
}
fn path(&self) -> OsString {
let mut path = env::split_paths(&env::var_os("PATH").unwrap()).collect::<Vec<_>>();
path.insert(0, self.td.path().to_owned());
env::join_paths(path).unwrap()
}
pub fn cmd(&self, i: u32) -> Execution {
let mut s = String::new();
File::open(self.td.path().join(format!("out{}", i)))
.unwrap()
.read_to_string(&mut s)
.unwrap();
Execution {
args: s.lines().map(|s| s.to_string()).collect(),
}
}
}
impl Execution {
pub fn must_have<P: AsRef<OsStr>>(&self, p: P) -> &Execution {
if !self.has(p.as_ref()) {
panic!("didn't find {:?} in {:?}", p.as_ref(), self.args);
} else {
self
}
}
pub fn must_not_have<P: AsRef<OsStr>>(&self, p: P) -> &Execution {
if self.has(p.as_ref()) {
panic!("found {:?}", p.as_ref());
} else {
self
}
}
pub fn has(&self, p: &OsStr) -> bool {
self.args.iter().any(|arg| OsStr::new(arg) == p)
}
pub fn must_have_in_order(&self, before: &str, after: &str) -> &Execution {
let before_position = self
.args
.iter()
.rposition(|x| OsStr::new(x) == OsStr::new(before));
let after_position = self
.args
.iter()
.rposition(|x| OsStr::new(x) == OsStr::new(after));
match (before_position, after_position) {
(Some(b), Some(a)) if b < a => {}
(b, a) => panic!(
"{:?} (last position: {:?}) did not appear before {:?} (last position: {:?})",
before, b, after, a
),
};
self
}
}
/// Hard link an executable or copy it if that fails.
///
/// We first try to hard link an executable to save space. If that fails (as on Windows with
/// different mount points, issue #60), we copy.
#[cfg(not(target_os = "macos"))]
fn link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> {
let from = from.as_ref();
let to = to.as_ref();
fs::hard_link(from, to).or_else(|_| fs::copy(from, to).map(|_| ()))
}
/// Copy an executable.
///
/// On macOS, hard linking the executable leads to strange failures (issue #419), so we just copy.
#[cfg(target_os = "macos")]
fn link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> {
fs::copy(from, to).map(|_| ())
}

477
vendor/cc/tests/test.rs vendored Normal file
View File

@ -0,0 +1,477 @@
use crate::support::Test;
mod support;
// Some tests check that a flag is *not* present. These tests might fail if the flag is set in the
// CFLAGS or CXXFLAGS environment variables. This function clears the CFLAGS and CXXFLAGS
// variables to make sure that the tests can run correctly.
fn reset_env() {
std::env::set_var("CFLAGS", "");
std::env::set_var("CXXFLAGS", "");
}
#[test]
fn gnu_smoke() {
reset_env();
let test = Test::gnu();
test.gcc().file("foo.c").compile("foo");
test.cmd(0)
.must_have("-O2")
.must_have("foo.c")
.must_not_have("-gdwarf-4")
.must_have("-c")
.must_have("-ffunction-sections")
.must_have("-fdata-sections");
test.cmd(1).must_have(test.td.path().join("foo.o"));
}
#[test]
fn gnu_opt_level_1() {
reset_env();
let test = Test::gnu();
test.gcc().opt_level(1).file("foo.c").compile("foo");
test.cmd(0).must_have("-O1").must_not_have("-O2");
}
#[test]
fn gnu_opt_level_s() {
reset_env();
let test = Test::gnu();
test.gcc().opt_level_str("s").file("foo.c").compile("foo");
test.cmd(0)
.must_have("-Os")
.must_not_have("-O1")
.must_not_have("-O2")
.must_not_have("-O3")
.must_not_have("-Oz");
}
#[test]
fn gnu_debug() {
let test = Test::gnu();
test.gcc().debug(true).file("foo.c").compile("foo");
test.cmd(0).must_have("-gdwarf-4");
let test = Test::gnu();
test.gcc()
.target("x86_64-apple-darwin")
.debug(true)
.file("foo.c")
.compile("foo");
test.cmd(0).must_have("-gdwarf-2");
}
#[test]
fn gnu_debug_fp_auto() {
let test = Test::gnu();
test.gcc().debug(true).file("foo.c").compile("foo");
test.cmd(0).must_have("-gdwarf-4");
test.cmd(0).must_have("-fno-omit-frame-pointer");
}
#[test]
fn gnu_debug_fp() {
let test = Test::gnu();
test.gcc().debug(true).file("foo.c").compile("foo");
test.cmd(0).must_have("-gdwarf-4");
test.cmd(0).must_have("-fno-omit-frame-pointer");
}
#[test]
fn gnu_debug_nofp() {
reset_env();
let test = Test::gnu();
test.gcc()
.debug(true)
.force_frame_pointer(false)
.file("foo.c")
.compile("foo");
test.cmd(0).must_have("-gdwarf-4");
test.cmd(0).must_not_have("-fno-omit-frame-pointer");
let test = Test::gnu();
test.gcc()
.force_frame_pointer(false)
.debug(true)
.file("foo.c")
.compile("foo");
test.cmd(0).must_have("-gdwarf-4");
test.cmd(0).must_not_have("-fno-omit-frame-pointer");
}
#[test]
fn gnu_warnings_into_errors() {
let test = Test::gnu();
test.gcc()
.warnings_into_errors(true)
.file("foo.c")
.compile("foo");
test.cmd(0).must_have("-Werror");
}
#[test]
fn gnu_warnings() {
let test = Test::gnu();
test.gcc()
.warnings(true)
.flag("-Wno-missing-field-initializers")
.file("foo.c")
.compile("foo");
test.cmd(0).must_have("-Wall").must_have("-Wextra");
}
#[test]
fn gnu_extra_warnings0() {
reset_env();
let test = Test::gnu();
test.gcc()
.warnings(true)
.extra_warnings(false)
.flag("-Wno-missing-field-initializers")
.file("foo.c")
.compile("foo");
test.cmd(0).must_have("-Wall").must_not_have("-Wextra");
}
#[test]
fn gnu_extra_warnings1() {
reset_env();
let test = Test::gnu();
test.gcc()
.warnings(false)
.extra_warnings(true)
.flag("-Wno-missing-field-initializers")
.file("foo.c")
.compile("foo");
test.cmd(0).must_not_have("-Wall").must_have("-Wextra");
}
#[test]
fn gnu_warnings_overridable() {
reset_env();
let test = Test::gnu();
test.gcc()
.warnings(true)
.flag("-Wno-missing-field-initializers")
.file("foo.c")
.compile("foo");
test.cmd(0)
.must_have_in_order("-Wall", "-Wno-missing-field-initializers");
}
#[test]
fn gnu_x86_64() {
for vendor in &["unknown-linux-gnu", "apple-darwin"] {
let target = format!("x86_64-{}", vendor);
let test = Test::gnu();
test.gcc()
.target(&target)
.host(&target)
.file("foo.c")
.compile("foo");
test.cmd(0).must_have("-fPIC").must_have("-m64");
}
}
#[test]
fn gnu_x86_64_no_pic() {
reset_env();
for vendor in &["unknown-linux-gnu", "apple-darwin"] {
let target = format!("x86_64-{}", vendor);
let test = Test::gnu();
test.gcc()
.pic(false)
.target(&target)
.host(&target)
.file("foo.c")
.compile("foo");
test.cmd(0).must_not_have("-fPIC");
}
}
#[test]
fn gnu_i686() {
for vendor in &["unknown-linux-gnu", "apple-darwin"] {
let target = format!("i686-{}", vendor);
let test = Test::gnu();
test.gcc()
.target(&target)
.host(&target)
.file("foo.c")
.compile("foo");
test.cmd(0).must_have("-m32");
}
}
#[test]
fn gnu_i686_pic() {
for vendor in &["unknown-linux-gnu", "apple-darwin"] {
let target = format!("i686-{}", vendor);
let test = Test::gnu();
test.gcc()
.pic(true)
.target(&target)
.host(&target)
.file("foo.c")
.compile("foo");
test.cmd(0).must_have("-fPIC");
}
}
#[test]
fn gnu_x86_64_no_plt() {
let target = "x86_64-unknown-linux-gnu";
let test = Test::gnu();
test.gcc()
.pic(true)
.use_plt(false)
.target(&target)
.host(&target)
.file("foo.c")
.compile("foo");
test.cmd(0).must_have("-fno-plt");
}
#[test]
fn gnu_set_stdlib() {
reset_env();
let test = Test::gnu();
test.gcc()
.cpp_set_stdlib(Some("foo"))
.file("foo.c")
.compile("foo");
test.cmd(0).must_not_have("-stdlib=foo");
}
#[test]
fn gnu_include() {
let test = Test::gnu();
test.gcc().include("foo/bar").file("foo.c").compile("foo");
test.cmd(0).must_have("-I").must_have("foo/bar");
}
#[test]
fn gnu_define() {
let test = Test::gnu();
test.gcc()
.define("FOO", "bar")
.define("BAR", None)
.file("foo.c")
.compile("foo");
test.cmd(0).must_have("-DFOO=bar").must_have("-DBAR");
}
#[test]
fn gnu_compile_assembly() {
let test = Test::gnu();
test.gcc().file("foo.S").compile("foo");
test.cmd(0).must_have("foo.S");
}
#[test]
fn gnu_shared() {
reset_env();
let test = Test::gnu();
test.gcc()
.file("foo.c")
.shared_flag(true)
.static_flag(false)
.compile("foo");
test.cmd(0).must_have("-shared").must_not_have("-static");
}
#[test]
fn gnu_flag_if_supported() {
reset_env();
if cfg!(windows) {
return;
}
let test = Test::gnu();
test.gcc()
.file("foo.c")
.flag("-v")
.flag_if_supported("-Wall")
.flag_if_supported("-Wflag-does-not-exist")
.flag_if_supported("-std=c++11")
.compile("foo");
test.cmd(0)
.must_have("-v")
.must_have("-Wall")
.must_not_have("-Wflag-does-not-exist")
.must_not_have("-std=c++11");
}
#[test]
fn gnu_flag_if_supported_cpp() {
if cfg!(windows) {
return;
}
let test = Test::gnu();
test.gcc()
.cpp(true)
.file("foo.cpp")
.flag_if_supported("-std=c++11")
.compile("foo");
test.cmd(0).must_have("-std=c++11");
}
#[test]
fn gnu_static() {
reset_env();
let test = Test::gnu();
test.gcc()
.file("foo.c")
.shared_flag(false)
.static_flag(true)
.compile("foo");
test.cmd(0).must_have("-static").must_not_have("-shared");
}
#[test]
fn gnu_no_dash_dash() {
let test = Test::gnu();
test.gcc().file("foo.c").compile("foo");
test.cmd(0).must_not_have("--");
}
#[test]
fn gnu_std_c() {
let test = Test::gnu();
test.gcc().file("foo.c").std("c11").compile("foo");
test.cmd(0).must_have("-std=c11");
}
#[test]
fn msvc_smoke() {
reset_env();
let test = Test::msvc();
test.gcc().file("foo.c").compile("foo");
test.cmd(0)
.must_have("-O2")
.must_have("foo.c")
.must_not_have("-Z7")
.must_have("-c")
.must_have("-MD");
test.cmd(1).must_have(test.td.path().join("foo.o"));
}
#[test]
fn msvc_opt_level_0() {
reset_env();
let test = Test::msvc();
test.gcc().opt_level(0).file("foo.c").compile("foo");
test.cmd(0).must_not_have("-O2");
}
#[test]
fn msvc_debug() {
let test = Test::msvc();
test.gcc().debug(true).file("foo.c").compile("foo");
test.cmd(0).must_have("-Z7");
}
#[test]
fn msvc_include() {
let test = Test::msvc();
test.gcc().include("foo/bar").file("foo.c").compile("foo");
test.cmd(0).must_have("-I").must_have("foo/bar");
}
#[test]
fn msvc_define() {
let test = Test::msvc();
test.gcc()
.define("FOO", "bar")
.define("BAR", None)
.file("foo.c")
.compile("foo");
test.cmd(0).must_have("-DFOO=bar").must_have("-DBAR");
}
#[test]
fn msvc_static_crt() {
let test = Test::msvc();
test.gcc().static_crt(true).file("foo.c").compile("foo");
test.cmd(0).must_have("-MT");
}
#[test]
fn msvc_no_static_crt() {
let test = Test::msvc();
test.gcc().static_crt(false).file("foo.c").compile("foo");
test.cmd(0).must_have("-MD");
}
#[test]
fn msvc_no_dash_dash() {
let test = Test::msvc();
test.gcc().file("foo.c").compile("foo");
test.cmd(0).must_not_have("--");
}
#[test]
fn msvc_std_c() {
let test = Test::msvc();
test.gcc().file("foo.c").std("c11").compile("foo");
test.cmd(0).must_have("-std:c11");
}
// Disable this test with the parallel feature because the execution
// order is not deterministic.
#[cfg(not(feature = "parallel"))]
#[test]
fn asm_flags() {
let test = Test::gnu();
test.gcc()
.file("foo.c")
.file("x86_64.asm")
.file("x86_64.S")
.asm_flag("--abc")
.compile("foo");
test.cmd(0).must_not_have("--abc");
test.cmd(1).must_have("--abc");
test.cmd(2).must_have("--abc");
}