summaryrefslogtreecommitdiff
path: root/vendor/cc/src/windows
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/cc/src/windows')
-rw-r--r--vendor/cc/src/windows/com.rs110
-rw-r--r--vendor/cc/src/windows/find_tools.rs1238
-rw-r--r--vendor/cc/src/windows/mod.rs22
-rw-r--r--vendor/cc/src/windows/registry.rs191
-rw-r--r--vendor/cc/src/windows/setup_config.rs283
-rw-r--r--vendor/cc/src/windows/vs_instances.rs199
-rw-r--r--vendor/cc/src/windows/winapi.rs146
-rw-r--r--vendor/cc/src/windows/windows_link.rs19
-rw-r--r--vendor/cc/src/windows/windows_sys.rs139
9 files changed, 0 insertions, 2347 deletions
diff --git a/vendor/cc/src/windows/com.rs b/vendor/cc/src/windows/com.rs
deleted file mode 100644
index 0391b5af..00000000
--- a/vendor/cc/src/windows/com.rs
+++ /dev/null
@@ -1,110 +0,0 @@
-// 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.
-
-use crate::windows::{
- winapi::{IUnknown, Interface},
- windows_sys::{
- CoInitializeEx, SysFreeString, SysStringLen, BSTR, COINIT_MULTITHREADED, HRESULT, S_FALSE,
- S_OK,
- },
-};
-use std::{
- convert::TryInto,
- ffi::OsString,
- ops::Deref,
- os::windows::ffi::OsStringExt,
- ptr::{null, null_mut},
- slice::from_raw_parts,
-};
-
-pub fn initialize() -> Result<(), HRESULT> {
- let err = unsafe { CoInitializeEx(null(), COINIT_MULTITHREADED.try_into().unwrap()) };
- 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)
- }
- /// 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) };
- }
-}
diff --git a/vendor/cc/src/windows/find_tools.rs b/vendor/cc/src/windows/find_tools.rs
deleted file mode 100644
index ec7c786c..00000000
--- a/vendor/cc/src/windows/find_tools.rs
+++ /dev/null
@@ -1,1238 +0,0 @@
-// 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 looking for windows-specific tools:
-//! 1. On Windows host, probe the Windows Registry if needed;
-//! 2. On non-Windows host, check specified environment variables.
-
-#![allow(clippy::upper_case_acronyms)]
-
-use std::{
- env,
- ffi::{OsStr, OsString},
- ops::Deref,
- path::PathBuf,
- process::Command,
- sync::Arc,
-};
-
-use crate::Tool;
-use crate::ToolFamily;
-
-const MSVC_FAMILY: ToolFamily = ToolFamily::Msvc { clang_cl: false };
-
-/// The target provided by the user.
-#[derive(Copy, Clone, PartialEq, Eq)]
-enum TargetArch {
- X86,
- X64,
- Arm,
- Arm64,
- Arm64ec,
-}
-impl TargetArch {
- /// Parse the `TargetArch` from a str. Returns `None` if the arch is unrecognized.
- fn new(arch: &str) -> Option<Self> {
- // NOTE: Keep up to date with docs in [`find`].
- match arch {
- "x64" | "x86_64" => Some(Self::X64),
- "arm64" | "aarch64" => Some(Self::Arm64),
- "arm64ec" => Some(Self::Arm64ec),
- "x86" | "i686" | "i586" => Some(Self::X86),
- "arm" | "thumbv7a" => Some(Self::Arm),
- _ => None,
- }
- }
-
- #[cfg(windows)]
- /// Gets the Visual Studio name for the architecture.
- fn as_vs_arch(&self) -> &'static str {
- match self {
- Self::X64 => "x64",
- Self::Arm64 | Self::Arm64ec => "arm64",
- Self::X86 => "x86",
- Self::Arm => "arm",
- }
- }
-}
-
-pub(crate) enum Env {
- Owned(OsString),
- Arced(Arc<OsStr>),
-}
-
-impl AsRef<OsStr> for Env {
- fn as_ref(&self) -> &OsStr {
- self.deref()
- }
-}
-
-impl Deref for Env {
- type Target = OsStr;
-
- fn deref(&self) -> &Self::Target {
- match self {
- Env::Owned(os_str) => os_str,
- Env::Arced(os_str) => os_str,
- }
- }
-}
-
-impl From<Env> for PathBuf {
- fn from(env: Env) -> Self {
- match env {
- Env::Owned(os_str) => PathBuf::from(os_str),
- Env::Arced(os_str) => PathBuf::from(os_str.deref()),
- }
- }
-}
-
-pub(crate) trait EnvGetter {
- fn get_env(&self, name: &'static str) -> Option<Env>;
-}
-
-struct StdEnvGetter;
-
-impl EnvGetter for StdEnvGetter {
- #[allow(clippy::disallowed_methods)]
- fn get_env(&self, name: &'static str) -> Option<Env> {
- env::var_os(name).map(Env::Owned)
- }
-}
-
-/// Attempts to find a tool within an MSVC installation using the Windows
-/// registry as a point to search from.
-///
-/// The `arch_or_target` argument is the architecture or the Rust target name
-/// that the tool should work for (e.g. compile or link for). The supported
-/// architecture names are:
-/// - `"x64"` or `"x86_64"`
-/// - `"arm64"` or `"aarch64"`
-/// - `"arm64ec"`
-/// - `"x86"`, `"i586"` or `"i686"`
-/// - `"arm"` or `"thumbv7a"`
-///
-/// 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 (if a
-/// full target name was specified).
-pub fn find(arch_or_target: &str, tool: &str) -> Option<Command> {
- find_tool(arch_or_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.
-pub fn find_tool(arch_or_target: &str, tool: &str) -> Option<Tool> {
- let full_arch = if let Some((full_arch, rest)) = arch_or_target.split_once("-") {
- // The logic is all tailored for MSVC, if the target is not that then
- // bail out early.
- if !rest.contains("msvc") {
- return None;
- }
- full_arch
- } else {
- arch_or_target
- };
- find_tool_inner(full_arch, tool, &StdEnvGetter)
-}
-
-pub(crate) fn find_tool_inner(
- full_arch: &str,
- tool: &str,
- env_getter: &dyn EnvGetter,
-) -> Option<Tool> {
- // We only need the arch.
- let target = TargetArch::new(full_arch)?;
-
- // Looks like msbuild isn't located in the same location as other tools like
- // cl.exe and lib.exe.
- if tool.contains("msbuild") {
- return impl_::find_msbuild(target, env_getter);
- }
-
- // Looks like devenv isn't located in the same location as other tools like
- // cl.exe and lib.exe.
- if tool.contains("devenv") {
- return impl_::find_devenv(target, env_getter);
- }
-
- // 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.
-
- impl_::find_msvc_environment(tool, target, env_getter)
- .or_else(|| impl_::find_msvc_15plus(tool, target, env_getter))
- .or_else(|| impl_::find_msvc_14(tool, target, env_getter))
-}
-
-/// A version of Visual Studio
-#[derive(Debug, PartialEq, Eq, Copy, Clone)]
-#[non_exhaustive]
-pub enum VsVers {
- /// Visual Studio 12 (2013)
- #[deprecated(
- note = "Visual Studio 12 is no longer supported. cc will never return this value."
- )]
- 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.
-#[allow(clippy::disallowed_methods)]
-pub fn find_vs_version() -> Result<VsVers, String> {
- fn has_msbuild_version(version: &str) -> bool {
- impl_::has_msbuild_version(version, &StdEnvGetter)
- }
-
- match std::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),
- 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 has_msbuild_version("17.0") {
- Ok(VsVers::Vs17)
- } else if has_msbuild_version("16.0") {
- Ok(VsVers::Vs16)
- } else if has_msbuild_version("15.0") {
- Ok(VsVers::Vs15)
- } else if has_msbuild_version("14.0") {
- Ok(VsVers::Vs14)
- } else {
- Err("\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\
- "
- .to_string())
- }
- }
- }
-}
-
-/// Windows Implementation.
-#[cfg(windows)]
-mod impl_ {
- use crate::windows::com;
- use crate::windows::registry::{RegistryKey, LOCAL_MACHINE};
- use crate::windows::setup_config::SetupConfiguration;
- use crate::windows::vs_instances::{VsInstances, VswhereInstance};
- use crate::windows::windows_sys::{
- GetMachineTypeAttributes, GetProcAddress, LoadLibraryA, UserEnabled, HMODULE,
- IMAGE_FILE_MACHINE_AMD64, MACHINE_ATTRIBUTES, S_OK,
- };
- 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 std::sync::atomic::{AtomicBool, Ordering};
- use std::sync::Once;
-
- use super::{EnvGetter, TargetArch, MSVC_FAMILY};
- use crate::Tool;
-
- struct MsvcTool {
- tool: PathBuf,
- libs: Vec<PathBuf>,
- path: Vec<PathBuf>,
- include: Vec<PathBuf>,
- }
-
- struct LibraryHandle(HMODULE);
-
- impl LibraryHandle {
- fn new(name: &[u8]) -> Option<Self> {
- let handle = unsafe { LoadLibraryA(name.as_ptr() as _) };
- (!handle.is_null()).then_some(Self(handle))
- }
-
- /// Get a function pointer to a function in the library.
- /// # SAFETY
- ///
- /// The caller must ensure that the function signature matches the actual function.
- /// The easiest way to do this is to add an entry to `windows_sys_no_link.list` and use the
- /// generated function for `func_signature`.
- ///
- /// The function returned cannot be used after the handle is dropped.
- unsafe fn get_proc_address<F>(&self, name: &[u8]) -> Option<F> {
- let symbol = GetProcAddress(self.0, name.as_ptr() as _);
- symbol.map(|symbol| mem::transmute_copy(&symbol))
- }
- }
-
- type GetMachineTypeAttributesFuncType =
- unsafe extern "system" fn(u16, *mut MACHINE_ATTRIBUTES) -> i32;
- const _: () = {
- // Ensure that our hand-written signature matches the actual function signature.
- // We can't use `GetMachineTypeAttributes` outside of a const scope otherwise we'll end up statically linking to
- // it, which will fail to load on older versions of Windows.
- let _: GetMachineTypeAttributesFuncType = GetMachineTypeAttributes;
- };
-
- fn is_amd64_emulation_supported_inner() -> Option<bool> {
- // GetMachineTypeAttributes is only available on Win11 22000+, so dynamically load it.
- let kernel32 = LibraryHandle::new(b"kernel32.dll\0")?;
- // SAFETY: GetMachineTypeAttributesFuncType is checked to match the real function signature.
- let get_machine_type_attributes = unsafe {
- kernel32
- .get_proc_address::<GetMachineTypeAttributesFuncType>(b"GetMachineTypeAttributes\0")
- }?;
- let mut attributes = Default::default();
- if unsafe { get_machine_type_attributes(IMAGE_FILE_MACHINE_AMD64, &mut attributes) } == S_OK
- {
- Some((attributes & UserEnabled) != 0)
- } else {
- Some(false)
- }
- }
-
- fn is_amd64_emulation_supported() -> bool {
- // TODO: Replace with a OnceLock once MSRV is 1.70.
- static LOAD_VALUE: Once = Once::new();
- static IS_SUPPORTED: AtomicBool = AtomicBool::new(false);
-
- // Using Relaxed ordering since the Once is providing synchronization.
- LOAD_VALUE.call_once(|| {
- IS_SUPPORTED.store(
- is_amd64_emulation_supported_inner().unwrap_or(false),
- Ordering::Relaxed,
- );
- });
- IS_SUPPORTED.load(Ordering::Relaxed)
- }
-
- impl MsvcTool {
- fn new(tool: PathBuf) -> MsvcTool {
- MsvcTool {
- tool,
- libs: Vec::new(),
- path: Vec::new(),
- include: Vec::new(),
- }
- }
-
- fn into_tool(self, env_getter: &dyn EnvGetter) -> Tool {
- let MsvcTool {
- tool,
- libs,
- path,
- include,
- } = self;
- let mut tool = Tool::with_family(tool, MSVC_FAMILY);
- add_env(&mut tool, "LIB", libs, env_getter);
- add_env(&mut tool, "PATH", path, env_getter);
- add_env(&mut tool, "INCLUDE", include, env_getter);
- tool
- }
- }
-
- /// Checks to see if the target's arch matches the VS environment. Returns `None` if the
- /// environment is unknown.
- fn is_vscmd_target(target: TargetArch, env_getter: &dyn EnvGetter) -> Option<bool> {
- is_vscmd_target_env(target, env_getter).or_else(|| is_vscmd_target_cl(target, env_getter))
- }
-
- /// 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.
- fn is_vscmd_target_env(target: TargetArch, env_getter: &dyn EnvGetter) -> Option<bool> {
- let vscmd_arch = env_getter.get_env("VSCMD_ARG_TGT_ARCH")?;
- Some(target.as_vs_arch() == vscmd_arch.as_ref())
- }
-
- /// Checks if the cl.exe target matches the given target's arch. Returns `None` if anything
- /// fails.
- fn is_vscmd_target_cl(target: TargetArch, env_getter: &dyn EnvGetter) -> Option<bool> {
- let cmd_target = vscmd_target_cl(env_getter)?;
- Some(target.as_vs_arch() == cmd_target)
- }
-
- /// Detect the target architecture of `cl.exe` in the current path, and return `None` if this
- /// fails for any reason.
- fn vscmd_target_cl(env_getter: &dyn EnvGetter) -> Option<&'static str> {
- let cl_exe = env_getter.get_env("PATH").and_then(|path| {
- env::split_paths(&path)
- .map(|p| p.join("cl.exe"))
- .find(|p| p.exists())
- })?;
- let mut cl = Command::new(cl_exe);
- cl.stderr(std::process::Stdio::piped())
- .stdout(std::process::Stdio::null());
-
- let out = cl.output().ok()?;
- let cl_arch = out
- .stderr
- .split(|&b| b == b'\n' || b == b'\r')
- .next()?
- .rsplit(|&b| b == b' ')
- .next()?;
-
- match cl_arch {
- b"x64" => Some("x64"),
- b"x86" => Some("x86"),
- b"ARM64" => Some("arm64"),
- b"ARM" => Some("arm"),
- _ => None,
- }
- }
-
- /// Attempt to find the tool using environment variables set by vcvars.
- pub(super) fn find_msvc_environment(
- tool: &str,
- target: TargetArch,
- env_getter: &dyn EnvGetter,
- ) -> Option<Tool> {
- // Early return if the environment isn't one that is known to have compiler toolsets in PATH
- // `VCINSTALLDIR` is set from vcvarsall.bat (developer command prompt)
- // `VSTEL_MSBuildProjectFullPath` is set by msbuild when invoking custom build steps
- // NOTE: `VisualStudioDir` used to be used but this isn't set when invoking msbuild from the commandline
- if env_getter.get_env("VCINSTALLDIR").is_none()
- && env_getter.get_env("VSTEL_MSBuildProjectFullPath").is_none()
- {
- return None;
- }
-
- // 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, env_getter) == Some(false) {
- // We will only get here with versions 15+.
- let vs_install_dir: PathBuf = env_getter.get_env("VSINSTALLDIR")?.into();
- tool_from_vs15plus_instance(tool, target, &vs_install_dir, env_getter)
- } else {
- // Fallback to simply using the current environment.
- env_getter
- .get_env("PATH")
- .and_then(|path| {
- env::split_paths(&path)
- .map(|p| p.join(tool))
- .find(|p| p.exists())
- })
- .map(|path| Tool::with_family(path, MSVC_FAMILY))
- }
- }
-
- fn find_msbuild_vs17(target: TargetArch, env_getter: &dyn EnvGetter) -> Option<Tool> {
- find_tool_in_vs16plus_path(r"MSBuild\Current\Bin\MSBuild.exe", target, "17", env_getter)
- }
-
- #[allow(bare_trait_objects)]
- fn vs16plus_instances(
- target: TargetArch,
- version: &'static str,
- env_getter: &dyn EnvGetter,
- ) -> Box<Iterator<Item = PathBuf>> {
- let instances = if let Some(instances) = vs15plus_instances(target, env_getter) {
- 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))
- || installation_name.starts_with(&format!("VisualStudioPreview/{}.", version))
- {
- Some(instance.installation_path()?)
- } else {
- None
- }
- }))
- }
-
- fn find_tool_in_vs16plus_path(
- tool: &str,
- target: TargetArch,
- version: &'static str,
- env_getter: &dyn EnvGetter,
- ) -> Option<Tool> {
- vs16plus_instances(target, version, env_getter)
- .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 == TargetArch::X64 {
- tool.env.push(("Platform".into(), "X64".into()));
- }
- if matches!(target, TargetArch::Arm64 | TargetArch::Arm64ec) {
- tool.env.push(("Platform".into(), "ARM64".into()));
- }
- Some(tool)
- })
- .next()
- }
-
- fn find_msbuild_vs16(target: TargetArch, env_getter: &dyn EnvGetter) -> Option<Tool> {
- find_tool_in_vs16plus_path(r"MSBuild\Current\Bin\MSBuild.exe", target, "16", env_getter)
- }
-
- // 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: TargetArch, env_getter: &dyn EnvGetter) -> Option<VsInstances> {
- vs15plus_instances_using_com()
- .or_else(|| vs15plus_instances_using_vswhere(target, env_getter))
- }
-
- 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: TargetArch,
- env_getter: &dyn EnvGetter,
- ) -> Option<VsInstances> {
- let program_files_path = env_getter
- .get_env("ProgramFiles(x86)")
- .or_else(|| env_getter.get_env("ProgramFiles"))?;
-
- let program_files_path = Path::new(program_files_path.as_ref());
-
- let vswhere_path =
- program_files_path.join(r"Microsoft Visual Studio\Installer\vswhere.exe");
-
- if !vswhere_path.exists() {
- return None;
- }
-
- let tools_arch = match target {
- TargetArch::X86 | TargetArch::X64 => Some("x86.x64"),
- TargetArch::Arm => Some("ARM"),
- TargetArch::Arm64 | TargetArch::Arm64ec => Some("ARM64"),
- };
-
- 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(super) fn find_msvc_15plus(
- tool: &str,
- target: TargetArch,
- env_getter: &dyn EnvGetter,
- ) -> Option<Tool> {
- let iter = vs15plus_instances(target, env_getter)?;
- 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, env_getter)?;
- 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: TargetArch,
- env_getter: &dyn EnvGetter,
- ) -> Option<Tool> {
- let mut path = match vs15plus_instances(target, env_getter) {
- Some(instances) => instances
- .into_iter()
- .filter_map(|instance| instance.installation_path())
- .map(|path| path.join(tool))
- .find(|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 == TargetArch::X64 {
- tool.env.push(("Platform".into(), "X64".into()));
- } else if matches!(target, TargetArch::Arm64 | TargetArch::Arm64ec) {
- tool.env.push(("Platform".into(), "ARM64".into()));
- }
- tool
- })
- }
-
- fn tool_from_vs15plus_instance(
- tool: &str,
- target: TargetArch,
- instance_path: &Path,
- env_getter: &dyn EnvGetter,
- ) -> Option<Tool> {
- let (root_path, bin_path, host_dylib_path, lib_path, alt_lib_path, include_path) =
- vs15plus_vc_paths(target, instance_path, env_getter)?;
- 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);
- if let Some(alt_lib_path) = alt_lib_path {
- tool.libs.push(alt_lib_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, env_getter)?;
-
- Some(tool.into_tool(env_getter))
- }
-
- fn vs15plus_vc_paths(
- target_arch: TargetArch,
- instance_path: &Path,
- env_getter: &dyn EnvGetter,
- ) -> Option<(PathBuf, PathBuf, PathBuf, PathBuf, Option<PathBuf>, PathBuf)> {
- let version = vs15plus_vc_read_version(instance_path)?;
-
- let hosts = match host_arch() {
- X86 => &["X86"],
- X86_64 => &["X64"],
- // Starting with VS 17.4, there is a natively hosted compiler on ARM64:
- // https://devblogs.microsoft.com/visualstudio/arm64-visual-studio-is-officially-here/
- // On older versions of VS, we use x64 if running under emulation is supported,
- // otherwise use x86.
- AARCH64 => {
- if is_amd64_emulation_supported() {
- &["ARM64", "X64", "X86"][..]
- } else {
- &["ARM64", "X86"]
- }
- }
- _ => return None,
- };
- let target_dir = target_arch.as_vs_arch();
- // The directory layout here is MSVC/bin/Host$host/$target/
- let path = instance_path.join(r"VC\Tools\MSVC").join(version);
- // We use the first available host architecture that can build for the target
- let (host_path, host) = hosts.iter().find_map(|&x| {
- let candidate = path.join("bin").join(format!("Host{}", x));
- if candidate.join(target_dir).exists() {
- Some((candidate, x))
- } else {
- None
- }
- })?;
- // This is the path to the toolchain for a particular target, running
- // on a given host
- let bin_path = host_path.join(target_dir);
- // 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 = host_path.join(host.to_lowercase());
- let lib_fragment = if use_spectre_mitigated_libs(env_getter) {
- r"lib\spectre"
- } else {
- "lib"
- };
- let lib_path = path.join(lib_fragment).join(target_dir);
- let alt_lib_path =
- (target_arch == TargetArch::Arm64ec).then(|| path.join(lib_fragment).join("arm64ec"));
- let include_path = path.join("include");
- Some((
- path,
- bin_path,
- host_dylib_path,
- lib_path,
- alt_lib_path,
- include_path,
- ))
- }
-
- fn vs15plus_vc_read_version(dir: &Path) -> Option<String> {
- // Try to open the default version file.
- let mut version_path: PathBuf =
- dir.join(r"VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt");
- let mut version_file = if let Ok(f) = File::open(&version_path) {
- f
- } else {
- // If the default doesn't exist, search for other version files.
- // These are in the form Microsoft.VCToolsVersion.v143.default.txt
- // where `143` is any three decimal digit version number.
- // This sorts versions by lexical order and selects the highest version.
- let mut version_file = String::new();
- version_path.pop();
- for file in version_path.read_dir().ok()? {
- let name = file.ok()?.file_name();
- let name = name.to_str()?;
- if name.starts_with("Microsoft.VCToolsVersion.v")
- && name.ends_with(".default.txt")
- && name > &version_file
- {
- version_file.replace_range(.., name);
- }
- }
- if version_file.is_empty() {
- return None;
- }
- version_path.push(version_file);
- File::open(version_path).ok()?
- };
-
- // Get the version string from the file we found.
- let mut version = String::new();
- version_file.read_to_string(&mut version).ok()?;
- version.truncate(version.trim_end().len());
- Some(version)
- }
-
- fn use_spectre_mitigated_libs(env_getter: &dyn EnvGetter) -> bool {
- env_getter
- .get_env("VSCMD_ARG_VCVARS_SPECTRE")
- .map(|env| env.as_ref() == "spectre")
- .unwrap_or_default()
- }
-
- fn atl_paths(target: TargetArch, path: &Path) -> Option<(PathBuf, PathBuf)> {
- let atl_path = path.join("atlmfc");
- let sub = target.as_vs_arch();
- 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(super) fn find_msvc_14(
- tool: &str,
- target: TargetArch,
- env_getter: &dyn EnvGetter,
- ) -> Option<Tool> {
- let vcdir = get_vc_dir("14.0")?;
- let mut tool = get_tool(tool, &vcdir, target)?;
- add_sdks(&mut tool, target, env_getter)?;
- Some(tool.into_tool(env_getter))
- }
-
- fn add_sdks(tool: &mut MsvcTool, target: TargetArch, env_getter: &dyn EnvGetter) -> Option<()> {
- let sub = target.as_vs_arch();
- 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(env_getter) {
- 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(())
- }
-
- fn add_env(
- tool: &mut Tool,
- env: &'static str,
- paths: Vec<PathBuf>,
- env_getter: &dyn EnvGetter,
- ) {
- let prev = env_getter.get_env(env);
- let prev = prev.as_ref().map(AsRef::as_ref).unwrap_or_default();
- 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: TargetArch) -> Option<MsvcTool> {
- bin_subdir(target)
- .into_iter()
- .map(|(sub, host)| {
- (
- path.join("bin").join(sub).join(tool),
- path.join("bin").join(host),
- )
- })
- .filter(|(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(env_getter: &dyn EnvGetter) -> Option<(PathBuf, String)> {
- if let (Some(root), Some(version)) = (
- env_getter.get_env("WindowsSdkDir"),
- env_getter
- .get_env("WindowsSDKVersion")
- .as_ref()
- .and_then(|version| version.as_ref().to_str()),
- ) {
- return Some((
- PathBuf::from(root),
- 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()
- .find(|dir| dir.join("um").join("x64").join("kernel32.lib").is_file())?;
- 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())
- }
-
- 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: TargetArch) -> Vec<(&'static str, &'static str)> {
- match (target, host_arch()) {
- (TargetArch::X86, X86) => vec![("", "")],
- (TargetArch::X86, X86_64) => vec![("amd64_x86", "amd64"), ("", "")],
- (TargetArch::X64, X86) => vec![("x86_amd64", "")],
- (TargetArch::X64, X86_64) => vec![("amd64", "amd64"), ("x86_amd64", "")],
- (TargetArch::Arm, X86) => vec![("x86_arm", "")],
- (TargetArch::Arm, X86_64) => vec![("amd64_arm", "amd64"), ("x86_arm", "")],
- _ => vec![],
- }
- }
-
- // MSVC's x86 libraries are not in a subfolder
- fn vc_lib_subdir(target: TargetArch) -> &'static str {
- match target {
- TargetArch::X86 => "",
- TargetArch::X64 => "amd64",
- TargetArch::Arm => "arm",
- TargetArch::Arm64 | TargetArch::Arm64ec => "arm64",
- }
- }
-
- #[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_start_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
- }
-
- #[inline(always)]
- pub(super) fn has_msbuild_version(version: &str, env_getter: &dyn EnvGetter) -> bool {
- match version {
- "17.0" => {
- find_msbuild_vs17(TargetArch::X64, env_getter).is_some()
- || find_msbuild_vs17(TargetArch::X86, env_getter).is_some()
- || find_msbuild_vs17(TargetArch::Arm64, env_getter).is_some()
- }
- "16.0" => {
- find_msbuild_vs16(TargetArch::X64, env_getter).is_some()
- || find_msbuild_vs16(TargetArch::X86, env_getter).is_some()
- || find_msbuild_vs16(TargetArch::Arm64, env_getter).is_some()
- }
- "15.0" => {
- find_msbuild_vs15(TargetArch::X64, env_getter).is_some()
- || find_msbuild_vs15(TargetArch::X86, env_getter).is_some()
- || find_msbuild_vs15(TargetArch::Arm64, env_getter).is_some()
- }
- "14.0" => LOCAL_MACHINE
- .open(&OsString::from(format!(
- "SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\{}",
- version
- )))
- .is_ok(),
- _ => false,
- }
- }
-
- pub(super) fn find_devenv(target: TargetArch, env_getter: &dyn EnvGetter) -> Option<Tool> {
- find_devenv_vs15(target, env_getter)
- }
-
- fn find_devenv_vs15(target: TargetArch, env_getter: &dyn EnvGetter) -> Option<Tool> {
- find_tool_in_vs15_path(r"Common7\IDE\devenv.exe", target, env_getter)
- }
-
- // see http://stackoverflow.com/questions/328017/path-to-msbuild
- pub(super) fn find_msbuild(target: TargetArch, env_getter: &dyn EnvGetter) -> Option<Tool> {
- // VS 15 (2017) changed how to locate msbuild
- if let Some(r) = find_msbuild_vs17(target, env_getter) {
- Some(r)
- } else if let Some(r) = find_msbuild_vs16(target, env_getter) {
- return Some(r);
- } else if let Some(r) = find_msbuild_vs15(target, env_getter) {
- return Some(r);
- } else {
- find_old_msbuild(target)
- }
- }
-
- fn find_msbuild_vs15(target: TargetArch, env_getter: &dyn EnvGetter) -> Option<Tool> {
- find_tool_in_vs15_path(r"MSBuild\15.0\Bin\MSBuild.exe", target, env_getter)
- }
-
- fn find_old_msbuild(target: TargetArch) -> 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 == TargetArch::X64 {
- tool.env.push(("Platform".into(), "X64".into()));
- }
- tool
- })
- }
-}
-
-/// Non-Windows Implementation.
-#[cfg(not(windows))]
-mod impl_ {
- use std::{env, ffi::OsStr};
-
- use super::{EnvGetter, TargetArch, MSVC_FAMILY};
- use crate::Tool;
-
- /// Finding msbuild.exe tool under unix system is not currently supported.
- /// Maybe can check it using an environment variable looks like `MSBUILD_BIN`.
- #[inline(always)]
- pub(super) fn find_msbuild(_target: TargetArch, _: &dyn EnvGetter) -> Option<Tool> {
- None
- }
-
- // Finding devenv.exe tool under unix system is not currently supported.
- // Maybe can check it using an environment variable looks like `DEVENV_BIN`.
- #[inline(always)]
- pub(super) fn find_devenv(_target: TargetArch, _: &dyn EnvGetter) -> Option<Tool> {
- None
- }
-
- /// Attempt to find the tool using environment variables set by vcvars.
- pub(super) fn find_msvc_environment(
- tool: &str,
- _target: TargetArch,
- env_getter: &dyn EnvGetter,
- ) -> Option<Tool> {
- // Early return if the environment doesn't contain a VC install.
- let vc_install_dir = env_getter.get_env("VCINSTALLDIR")?;
- let vs_install_dir = env_getter.get_env("VSINSTALLDIR")?;
-
- let get_tool = |install_dir: &OsStr| {
- env::split_paths(install_dir)
- .map(|p| p.join(tool))
- .find(|p| p.exists())
- .map(|path| Tool::with_family(path, MSVC_FAMILY))
- };
-
- // Take the path of tool for the vc install directory.
- get_tool(vc_install_dir.as_ref())
- // Take the path of tool for the vs install directory.
- .or_else(|| get_tool(vs_install_dir.as_ref()))
- // Take the path of tool for the current path environment.
- .or_else(|| {
- env_getter
- .get_env("PATH")
- .as_ref()
- .map(|path| path.as_ref())
- .and_then(get_tool)
- })
- }
-
- #[inline(always)]
- pub(super) fn find_msvc_15plus(
- _tool: &str,
- _target: TargetArch,
- _: &dyn EnvGetter,
- ) -> Option<Tool> {
- None
- }
-
- // For MSVC 14 we need to find the Universal CRT as well as either
- // the Windows 10 SDK or Windows 8.1 SDK.
- #[inline(always)]
- pub(super) fn find_msvc_14(
- _tool: &str,
- _target: TargetArch,
- _: &dyn EnvGetter,
- ) -> Option<Tool> {
- None
- }
-
- #[inline(always)]
- pub(super) fn has_msbuild_version(_version: &str, _: &dyn EnvGetter) -> bool {
- false
- }
-}
diff --git a/vendor/cc/src/windows/mod.rs b/vendor/cc/src/windows/mod.rs
deleted file mode 100644
index 07b3e7b1..00000000
--- a/vendor/cc/src/windows/mod.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-//! These modules are all glue to support reading the MSVC version from
-//! the registry and from COM interfaces.
-
-// This is used in the crate's public API, so don't use #[cfg(windows)]
-pub mod find_tools;
-
-#[cfg(windows)]
-mod windows_link;
-#[cfg(windows)]
-pub(crate) mod windows_sys;
-
-#[cfg(windows)]
-mod registry;
-#[cfg(windows)]
-#[macro_use]
-mod winapi;
-#[cfg(windows)]
-mod com;
-#[cfg(windows)]
-mod setup_config;
-#[cfg(windows)]
-mod vs_instances;
diff --git a/vendor/cc/src/windows/registry.rs b/vendor/cc/src/windows/registry.rs
deleted file mode 100644
index 83983032..00000000
--- a/vendor/cc/src/windows/registry.rs
+++ /dev/null
@@ -1,191 +0,0 @@
-// 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::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);
-
-#[allow(clippy::upper_case_acronyms)]
-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();
- }
- 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)))
- }
- })
- }
-}
diff --git a/vendor/cc/src/windows/setup_config.rs b/vendor/cc/src/windows/setup_config.rs
deleted file mode 100644
index 5739ecf7..00000000
--- a/vendor/cc/src/windows/setup_config.rs
+++ /dev/null
@@ -1,283 +0,0 @@
-// 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::windows::{
- 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) }))
- }
-}
diff --git a/vendor/cc/src/windows/vs_instances.rs b/vendor/cc/src/windows/vs_instances.rs
deleted file mode 100644
index 3e6eeed9..00000000
--- a/vendor/cc/src/windows/vs_instances.rs
+++ /dev/null
@@ -1,199 +0,0 @@
-use std::borrow::Cow;
-use std::collections::HashMap;
-use std::convert::TryFrom;
-use std::io::BufRead;
-use std::path::PathBuf;
-
-use crate::windows::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()
- .map_while(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());
- }
-}
diff --git a/vendor/cc/src/windows/winapi.rs b/vendor/cc/src/windows/winapi.rs
deleted file mode 100644
index 09965daa..00000000
--- a/vendor/cc/src/windows/winapi.rs
+++ /dev/null
@@ -1,146 +0,0 @@
-// 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, clippy::upper_case_acronyms)]
-
-use std::os::raw;
-
-pub type wchar_t = u16;
-
-pub use crate::windows::windows_sys::{FILETIME, GUID, HRESULT, SAFEARRAY};
-
-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::windows::winapi::GUID = $crate::windows::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::windows::winapi::Interface for $interface {
- #[inline]
- fn uuidof() -> $crate::windows::winapi::GUID {
- $crate::windows::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,
-}}
diff --git a/vendor/cc/src/windows/windows_link.rs b/vendor/cc/src/windows/windows_link.rs
deleted file mode 100644
index d08affe0..00000000
--- a/vendor/cc/src/windows/windows_link.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-//! Provides the `link!` macro used by the generated windows bindings.
-//!
-//! This is a simple wrapper around an `extern` block with a `#[link]` attribute.
-//! It's very roughly equivalent to the windows-targets crate.
-
-macro_rules! link_macro {
- ($library:literal $abi:literal $($link_name:literal)? $(#[$doc:meta])? fn $($function:tt)*) => (
- // Note: the windows-targets crate uses a pre-built Windows.lib import library which we don't
- // have in this repo. So instead we always link kernel32.lib and add the rest of the import
- // libraries below by using an empty extern block. This works because extern blocks are not
- // connected to the library given in the #[link] attribute.
- #[link(name = "kernel32")]
- extern $abi {
- $(#[link_name=$link_name])?
- pub fn $($function)*;
- }
- )
-}
-pub(crate) use link_macro as link;
diff --git a/vendor/cc/src/windows/windows_sys.rs b/vendor/cc/src/windows/windows_sys.rs
deleted file mode 100644
index c871727d..00000000
--- a/vendor/cc/src/windows/windows_sys.rs
+++ /dev/null
@@ -1,139 +0,0 @@
-// 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.62.1
-
-#![allow(
- non_snake_case,
- non_upper_case_globals,
- non_camel_case_types,
- dead_code,
- clippy::all
-)]
-
-windows_link::link!("ole32.dll" "system" fn CoCreateInstance(rclsid : *const GUID, punkouter : * mut core::ffi::c_void, dwclscontext : CLSCTX, riid : *const GUID, ppv : *mut *mut core::ffi::c_void) -> HRESULT);
-windows_link::link!("ole32.dll" "system" fn CoInitializeEx(pvreserved : *const core::ffi::c_void, dwcoinit : u32) -> HRESULT);
-windows_link::link!("kernel32.dll" "system" fn FreeLibrary(hlibmodule : HMODULE) -> BOOL);
-windows_link::link!("kernel32.dll" "system" fn GetMachineTypeAttributes(machine : u16, machinetypeattributes : *mut MACHINE_ATTRIBUTES) -> HRESULT);
-windows_link::link!("kernel32.dll" "system" fn GetProcAddress(hmodule : HMODULE, lpprocname : PCSTR) -> FARPROC);
-windows_link::link!("kernel32.dll" "system" fn LoadLibraryA(lplibfilename : PCSTR) -> HMODULE);
-windows_link::link!("kernel32.dll" "system" fn OpenSemaphoreA(dwdesiredaccess : u32, binherithandle : BOOL, lpname : PCSTR) -> HANDLE);
-windows_link::link!("kernel32.dll" "system" fn PeekNamedPipe(hnamedpipe : HANDLE, lpbuffer : *mut core::ffi::c_void, nbuffersize : u32, lpbytesread : *mut u32, lptotalbytesavail : *mut u32, lpbytesleftthismessage : *mut u32) -> BOOL);
-windows_link::link!("advapi32.dll" "system" fn RegCloseKey(hkey : HKEY) -> WIN32_ERROR);
-windows_link::link!("advapi32.dll" "system" fn RegEnumKeyExW(hkey : HKEY, dwindex : u32, lpname : PWSTR, lpcchname : *mut u32, lpreserved : *const u32, lpclass : PWSTR, lpcchclass : *mut u32, lpftlastwritetime : *mut FILETIME) -> WIN32_ERROR);
-windows_link::link!("advapi32.dll" "system" fn RegOpenKeyExW(hkey : HKEY, lpsubkey : PCWSTR, uloptions : u32, samdesired : REG_SAM_FLAGS, phkresult : *mut HKEY) -> WIN32_ERROR);
-windows_link::link!("advapi32.dll" "system" fn RegQueryValueExW(hkey : HKEY, lpvaluename : PCWSTR, lpreserved : *const u32, lptype : *mut REG_VALUE_TYPE, lpdata : *mut u8, lpcbdata : *mut u32) -> WIN32_ERROR);
-windows_link::link!("kernel32.dll" "system" fn ReleaseSemaphore(hsemaphore : HANDLE, lreleasecount : i32, lppreviouscount : *mut i32) -> BOOL);
-windows_link::link!("oleaut32.dll" "system" fn SysFreeString(bstrstring : BSTR));
-windows_link::link!("oleaut32.dll" "system" fn SysStringLen(pbstr : BSTR) -> u32);
-windows_link::link!("kernel32.dll" "system" fn WaitForSingleObject(hhandle : HANDLE, dwmilliseconds : u32) -> WAIT_EVENT);
-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;
-pub const FALSE: BOOL = 0i32;
-pub type FARPROC = Option<unsafe extern "system" fn() -> isize>;
-#[repr(C)]
-#[derive(Clone, Copy, Default)]
-pub struct FILETIME {
- pub dwLowDateTime: u32,
- pub dwHighDateTime: u32,
-}
-pub const FILE_ATTRIBUTE_TEMPORARY: FILE_FLAGS_AND_ATTRIBUTES = 256u32;
-pub type FILE_FLAGS_AND_ATTRIBUTES = u32;
-#[repr(C)]
-#[derive(Clone, Copy)]
-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(),
- }
- }
-}
-pub type HANDLE = *mut core::ffi::c_void;
-pub type HINSTANCE = *mut core::ffi::c_void;
-pub type HKEY = *mut core::ffi::c_void;
-pub const HKEY_LOCAL_MACHINE: HKEY = -2147483646i32 as _;
-pub type HMODULE = *mut core::ffi::c_void;
-pub type HRESULT = i32;
-pub type IMAGE_FILE_MACHINE = u16;
-pub const IMAGE_FILE_MACHINE_AMD64: IMAGE_FILE_MACHINE = 34404u16;
-pub const IID_IUnknown: GUID = GUID::from_u128(0x00000000_0000_0000_c000_000000000046);
-#[repr(C)]
-pub struct IUnknown_Vtbl {
- pub QueryInterface: unsafe extern "system" fn(
- this: *mut core::ffi::c_void,
- iid: *const GUID,
- interface: *mut *mut core::ffi::c_void,
- ) -> HRESULT,
- pub AddRef: unsafe extern "system" fn(this: *mut core::ffi::c_void) -> u32,
- pub Release: unsafe extern "system" fn(this: *mut core::ffi::c_void) -> u32,
-}
-pub const KEY_READ: REG_SAM_FLAGS = 131097u32;
-pub const KEY_WOW64_32KEY: REG_SAM_FLAGS = 512u32;
-pub type MACHINE_ATTRIBUTES = i32;
-pub type PCSTR = *const u8;
-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)]
-#[derive(Clone, Copy)]
-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 Default for SAFEARRAY {
- fn default() -> Self {
- unsafe { core::mem::zeroed() }
- }
-}
-#[repr(C)]
-#[derive(Clone, Copy, Default)]
-pub struct SAFEARRAYBOUND {
- pub cElements: u32,
- pub lLbound: i32,
-}
-pub const SEMAPHORE_MODIFY_STATE: SYNCHRONIZATION_ACCESS_RIGHTS = 2u32;
-pub type SYNCHRONIZATION_ACCESS_RIGHTS = u32;
-pub const S_FALSE: HRESULT = 0x1_u32 as _;
-pub const S_OK: HRESULT = 0x0_u32 as _;
-pub type THREAD_ACCESS_RIGHTS = u32;
-pub const THREAD_SYNCHRONIZE: THREAD_ACCESS_RIGHTS = 1048576u32;
-pub const UserEnabled: MACHINE_ATTRIBUTES = 1i32;
-pub const WAIT_ABANDONED: WAIT_EVENT = 128u32;
-pub type WAIT_EVENT = u32;
-pub const WAIT_FAILED: WAIT_EVENT = 4294967295u32;
-pub const WAIT_OBJECT_0: WAIT_EVENT = 0u32;
-pub const WAIT_TIMEOUT: WAIT_EVENT = 258u32;
-pub type WIN32_ERROR = u32;
-
-#[link(name = "advapi32")]
-#[link(name = "ole32")]
-#[link(name = "oleaut32")]
-extern "C" {}
-use super::windows_link;