use std::path::{Path, PathBuf};
use std::process::Command;
use anyhow::Result;
use clap::{
Parser, ValueEnum,
builder::{PossibleValuesParser, TypedValueParser as _},
};
use fs_err as fs;
#[derive(Clone, Debug, Default, ValueEnum)]
pub enum CrossCompiler {
#[default]
ClangCl,
Clang,
}
#[derive(Clone, Debug, Parser)]
pub struct XWinOptions {
#[arg(long, env = "XWIN_CROSS_COMPILER", default_value = "clang-cl")]
pub cross_compiler: CrossCompiler,
#[arg(long, env = "XWIN_CACHE_DIR", hide = true)]
pub xwin_cache_dir: Option<PathBuf>,
#[arg(
long,
env = "XWIN_ARCH",
value_parser = PossibleValuesParser::new(["x86", "x86_64", "aarch", "aarch64"])
.map(|s| s.parse::<xwin::Arch>().unwrap()),
value_delimiter = ',',
default_values_t = vec![xwin::Arch::X86_64, xwin::Arch::Aarch64],
hide = true,
)]
pub xwin_arch: Vec<xwin::Arch>,
#[arg(
long,
env = "XWIN_VARIANT",
value_parser = PossibleValuesParser::new(["desktop", "onecore", /*"store",*/ "spectre"])
.map(|s| s.parse::<xwin::Variant>().unwrap()),
value_delimiter = ',',
default_values_t = vec![xwin::Variant::Desktop],
hide = true,
)]
pub xwin_variant: Vec<xwin::Variant>,
#[arg(long, env = "XWIN_VERSION", default_value = "17")]
pub xwin_version: u8,
#[arg(long, env = "XWIN_SDK_VERSION")]
pub xwin_sdk_version: Option<String>,
#[arg(long, env = "XWIN_CRT_VERSION")]
pub xwin_crt_version: Option<String>,
#[arg(long, env = "XWIN_INCLUDE_ATL")]
pub xwin_include_atl: bool,
#[arg(long, env = "XWIN_INCLUDE_DEBUG_LIBS", hide = true)]
pub xwin_include_debug_libs: bool,
#[arg(long, env = "XWIN_INCLUDE_DEBUG_SYMBOLS", hide = true)]
pub xwin_include_debug_symbols: bool,
#[arg(long, env = "XWIN_HTTP_RETRIES", default_value = "3")]
pub xwin_http_retries: u32,
}
impl Default for XWinOptions {
fn default() -> Self {
Self {
xwin_cache_dir: None,
xwin_arch: vec![xwin::Arch::X86_64, xwin::Arch::Aarch64],
xwin_variant: vec![xwin::Variant::Desktop],
xwin_version: 17,
xwin_sdk_version: None,
xwin_crt_version: None,
xwin_include_atl: false,
xwin_include_debug_libs: false,
xwin_include_debug_symbols: false,
cross_compiler: CrossCompiler::ClangCl,
xwin_http_retries: 3,
}
}
}
impl XWinOptions {
pub fn apply_command_env(
&self,
manifest_path: Option<&Path>,
cargo: &cargo_options::CommonOptions,
cmd: &mut Command,
) -> Result<()> {
let cache_dir = {
let cache_dir = self.xwin_cache_dir.clone().unwrap_or_else(|| {
dirs::cache_dir()
.unwrap_or_else(|| std::env::current_dir().expect("Failed to get current dir"))
.join(env!("CARGO_PKG_NAME"))
});
fs::create_dir_all(&cache_dir)?;
cache_dir.canonicalize()?
};
match self.cross_compiler {
CrossCompiler::ClangCl => {
let clang_cl = crate::compiler::clang_cl::ClangCl::new(self);
clang_cl.apply_command_env(manifest_path, cargo, cache_dir, cmd)?;
}
CrossCompiler::Clang => {
let clang = crate::compiler::clang::Clang::new();
clang.apply_command_env(manifest_path, cargo, cache_dir, cmd)?;
}
}
Ok(())
}
}