// build.rs -- Compile-time detection of optional build tools. // // Sets cfg flags that integration tests use to gracefully skip when // tools are missing instead of panicking with scary error messages. // // has_cmake cmake is in PATH // has_cpp_compiler g++, clang++, or cl is in PATH // has_git git is in PATH // has_arduino_cli arduino-cli is in PATH // // Usage in tests: // #[cfg_attr(not(has_cmake), ignore = "cmake not found")] 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") .stdout(Stdio::null()) .stderr(Stdio::null()) .status() .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)"); println!("cargo::rustc-check-cfg=cfg(has_arduino_cli)"); if has_tool("cmake") { println!("cargo:rustc-cfg=has_cmake"); } if has_cpp_compiler() { println!("cargo:rustc-cfg=has_cpp_compiler"); } if has_tool("git") { println!("cargo:rustc-cfg=has_git"); } if has_tool("arduino-cli") { println!("cargo:rustc-cfg=has_arduino_cli"); } }