Skip to content

Commit

Permalink
Support finding windows tools on non-Windows host
Browse files Browse the repository at this point in the history
  • Loading branch information
cavivie committed Nov 28, 2023
1 parent 2d6a3b2 commit c34105e
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 20 deletions.
9 changes: 4 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ mod vs_instances;
#[cfg(windows)]
mod windows_sys;

pub mod windows_registry;
pub mod windows_helper;

/// A builder for compilation of a native library.
///
Expand Down Expand Up @@ -2187,7 +2187,7 @@ impl Build {
} else {
"ml.exe"
};
let mut cmd = windows_registry::find(&target, tool).unwrap_or_else(|| self.cmd(tool));
let mut cmd = windows_helper::find(&target, tool).unwrap_or_else(|| self.cmd(tool));
cmd.arg("-nologo"); // undocumented, yet working with armasm[64]
for directory in self.include_directories.iter() {
cmd.arg("-I").arg(&**directory);
Expand Down Expand Up @@ -2540,7 +2540,7 @@ impl Build {
traditional
};

let cl_exe = windows_registry::find_tool(&target, "cl.exe");
let cl_exe = windows_helper::find_tool(&target, "cl.exe");

let tool_opt: Option<Tool> = self
.env_tool(env)
Expand Down Expand Up @@ -3008,7 +3008,7 @@ impl Build {

if lib.is_empty() {
name = String::from("lib.exe");
match windows_registry::find(&target, "lib.exe") {
match windows_helper::find(&target, "lib.exe") {
Some(t) => t,
None => self.cmd("lib.exe"),
}
Expand Down Expand Up @@ -3543,7 +3543,6 @@ impl Tool {
Self::with_features(path, clang_driver, false)
}

#[cfg(windows)]
/// Explicitly set the `ToolFamily`, skipping name-based detection.
fn with_family(path: PathBuf, family: ToolFamily) -> Self {
Self {
Expand Down
89 changes: 74 additions & 15 deletions src/windows_registry.rs → src/windows_helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,21 @@
// 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.
//! 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.
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.
/// Attempts to find a tool within an MSVC installation:
/// 1. On Windows host, using the Windows registry as a point to search from;
/// 2. On non-Windows host, using related environment variables 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.
Expand All @@ -39,13 +40,6 @@ pub fn find(target: &str, tool: &str) -> Option<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.
Expand All @@ -54,12 +48,13 @@ pub fn find_tool(target: &str, tool: &str) -> Option<Tool> {
}

// 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.
// cl.exe and lib.exe.
if tool.contains("msbuild") {
return impl_::find_msbuild(target);
}

// 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);
}
Expand Down Expand Up @@ -152,6 +147,7 @@ pub fn find_vs_version() -> Result<VsVers, String> {
}
}

/// Windows Implementation.
#[cfg(windows)]
mod impl_ {
use crate::com;
Expand Down Expand Up @@ -882,6 +878,7 @@ mod impl_ {
}
}

// To find devenv we probe for it manually with dedicated registry keys.
pub fn find_devenv(target: &str) -> Option<Tool> {
find_devenv_vs15(&target)
}
Expand All @@ -890,6 +887,7 @@ mod impl_ {
find_tool_in_vs15_path(r"Common7\IDE\devenv.exe", target)
}

// To find msbuild we probe for it manually with dedicated registry keys.
// 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
Expand Down Expand Up @@ -927,3 +925,64 @@ mod impl_ {
})
}
}

/// Non-Windows Implementation.
#[cfg(not(windows))]
mod impl_ {
use std::{env, ffi::OsString};

use super::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`.
pub fn find_msbuild(_target: &str) -> 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`.
pub fn find_devenv(_target: &str) -> Option<Tool> {
None
}

/// 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.
let _vc_install_dir = env::var_os("VCINSTALLDIR")?;
let vs_install_dir = env::var_os("VSINSTALLDIR")?;

let search = |path: OsString| {
env::split_paths(&path)
.map(|p| p.join(tool))
.find(|p| p.exists())
};

search(vs_install_dir)
.or_else(|| {
// Fallback to simply using the current environment.
env::var_os("PATH").and_then(search)
})
.map(|path| Tool::with_family(path.into(), MSVC_FAMILY))
}

pub fn find_msvc_15plus(_tool: &str, _target: &str) -> 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.
pub fn find_msvc_14(_tool: &str, _target: &str) -> Option<Tool> {
None
}

// For MSVC 12 we need to find the Windows 8.1 SDK.
pub fn find_msvc_12(_tool: &str, _target: &str) -> Option<Tool> {
None
}

// For MSVC 11 we need to find the Windows 8 SDK.
pub fn find_msvc_11(_tool: &str, _target: &str) -> Option<Tool> {
None
}
}

0 comments on commit c34105e

Please sign in to comment.