diff --git a/build.rs b/build.rs index a011aad..8d7f976 100644 --- a/build.rs +++ b/build.rs @@ -13,6 +13,8 @@ use std::process::{Command, Stdio}; +/// Check if a tool is available by running it with --version. +/// Works for most tools (cmake, git, g++, clang++, arduino-cli). fn has_tool(name: &str) -> bool { Command::new(name) .arg("--version") @@ -22,7 +24,57 @@ fn has_tool(name: &str) -> bool { .is_ok() } +/// Check if a C++ compiler is available. +/// +/// g++ and clang++ respond to --version normally. MSVC's cl.exe does +/// not -- it rejects --version and returns an error. On Windows we +/// fall back to checking PATH via `where cl`. On Unix, cmake cannot +/// discover MSVC so we only check g++ and clang++. +fn has_cpp_compiler() -> bool { + if has_tool("g++") || has_tool("clang++") { + return true; + } + + // cl.exe doesn't support --version; check PATH directly on Windows. + // On a regular command prompt cl may not be in PATH, but cmake can + // still find MSVC via the Visual Studio registry. We check `where` + // as a best-effort signal. + #[cfg(windows)] + { + let found = Command::new("where") + .arg("cl") + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .status() + .map(|s| s.success()) + .unwrap_or(false); + if found { + return true; + } + + // Last resort: cmake can discover MSVC even when cl is not in + // PATH. Check if any Visual Studio installation exists by + // looking for vswhere, which ships with VS 2017+. + let vswhere = Command::new("cmd") + .args(["/C", "where", "vswhere"]) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .status() + .map(|s| s.success()) + .unwrap_or(false); + if vswhere { + return true; + } + } + + #[cfg(not(windows))] + let _ = (); // silence unused warning + + false +} + fn main() { + // Declare custom cfg names so rustc doesn't warn about them. println!("cargo::rustc-check-cfg=cfg(has_cmake)"); println!("cargo::rustc-check-cfg=cfg(has_cpp_compiler)"); println!("cargo::rustc-check-cfg=cfg(has_git)"); @@ -31,7 +83,7 @@ fn main() { if has_tool("cmake") { println!("cargo:rustc-cfg=has_cmake"); } - if has_tool("g++") || has_tool("clang++") || has_tool("cl") { + if has_cpp_compiler() { println!("cargo:rustc-cfg=has_cpp_compiler"); } if has_tool("git") {