use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::PathBuf;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[allow(clippy::upper_case_acronyms)]
pub enum CompilerType {
MSVC,
ClangCL,
Clang,
GCC,
}
#[allow(dead_code)]
impl CompilerType {
pub fn is_msvc_compatible(&self) -> bool {
matches!(self, CompilerType::MSVC | CompilerType::ClangCL)
}
pub fn uses_msvc_flags(&self) -> bool {
matches!(self, CompilerType::MSVC | CompilerType::ClangCL)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Toolchain {
pub compiler_type: CompilerType,
pub cc_path: PathBuf,
pub cxx_path: PathBuf,
pub linker_path: PathBuf,
pub version: String,
pub msvc_toolset_version: Option<String>,
pub windows_sdk_version: Option<String>,
pub vs_install_path: Option<PathBuf>,
pub env_vars: HashMap<String, String>,
}
#[allow(dead_code)]
impl Toolchain {
pub fn new_simple(compiler_type: CompilerType, cxx_path: PathBuf, version: String) -> Self {
let cc_path = if cxx_path.to_string_lossy().contains("++") {
PathBuf::from(cxx_path.to_string_lossy().replace("++", ""))
} else {
cxx_path.clone()
};
Self {
compiler_type,
cc_path,
cxx_path: cxx_path.clone(),
linker_path: cxx_path,
version,
msvc_toolset_version: None,
windows_sdk_version: None,
vs_install_path: None,
env_vars: HashMap::new(),
}
}
pub fn get_cxx_compiler(&self) -> &PathBuf {
&self.cxx_path
}
pub fn get_cc_compiler(&self) -> &PathBuf {
&self.cc_path
}
pub fn needs_env_setup(&self) -> bool {
!self.env_vars.is_empty()
}
pub fn fingerprint(&self) -> String {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let mut hasher = DefaultHasher::new();
self.cxx_path.hash(&mut hasher);
self.version.hash(&mut hasher);
if let Some(ref v) = self.msvc_toolset_version {
v.hash(&mut hasher);
}
if let Some(ref v) = self.windows_sdk_version {
v.hash(&mut hasher);
}
format!("{:x}", hasher.finish())
}
}
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct VSInstallation {
pub install_path: PathBuf,
pub display_name: String,
pub version: String,
pub product_id: String, }
#[derive(Debug)]
pub enum ToolchainError {
NotFound(String),
#[cfg(windows)]
VsWhereError(String),
#[cfg(windows)]
VcVarsError(String),
IoError(std::io::Error),
}
impl std::fmt::Display for ToolchainError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ToolchainError::NotFound(msg) => write!(f, "Toolchain not found: {}", msg),
#[cfg(windows)]
ToolchainError::VsWhereError(msg) => write!(f, "vswhere error: {}", msg),
#[cfg(windows)]
ToolchainError::VcVarsError(msg) => write!(f, "vcvars error: {}", msg),
ToolchainError::IoError(e) => write!(f, "IO error: {}", e),
}
}
}
impl std::error::Error for ToolchainError {}
impl From<std::io::Error> for ToolchainError {
fn from(e: std::io::Error) -> Self {
ToolchainError::IoError(e)
}
}