1use std::path::{Path, PathBuf};
2use std::process::Command;
3
4use anyhow::Result;
5use clap::{
6 Parser, ValueEnum,
7 builder::{PossibleValuesParser, TypedValueParser as _},
8};
9use fs_err as fs;
10
11#[derive(Clone, Debug, Default, ValueEnum)]
13pub enum CrossCompiler {
14 #[default]
16 ClangCl,
17 Clang,
19}
20
21#[derive(Clone, Debug, Parser)]
23pub struct XWinOptions {
24 #[arg(long, env = "XWIN_CROSS_COMPILER", default_value = "clang-cl")]
26 pub cross_compiler: CrossCompiler,
27
28 #[arg(long, env = "XWIN_CACHE_DIR", hide = true)]
30 pub xwin_cache_dir: Option<PathBuf>,
31
32 #[arg(
34 long,
35 env = "XWIN_ARCH",
36 value_parser = PossibleValuesParser::new(["x86", "x86_64", "aarch", "aarch64"])
37 .map(|s| s.parse::<xwin::Arch>().unwrap()),
38 value_delimiter = ',',
39 default_values_t = vec![xwin::Arch::X86_64, xwin::Arch::Aarch64],
40 hide = true,
41 )]
42 pub xwin_arch: Vec<xwin::Arch>,
43
44 #[arg(
46 long,
47 env = "XWIN_VARIANT",
48 value_parser = PossibleValuesParser::new(["desktop", "onecore", "spectre"])
49 .map(|s| s.parse::<xwin::Variant>().unwrap()),
50 value_delimiter = ',',
51 default_values_t = vec![xwin::Variant::Desktop],
52 hide = true,
53 )]
54 pub xwin_variant: Vec<xwin::Variant>,
55
56 #[arg(long, env = "XWIN_VERSION", default_value = "17")]
59 pub xwin_version: u8,
60
61 #[arg(long, env = "XWIN_SDK_VERSION")]
64 pub xwin_sdk_version: Option<String>,
65 #[arg(long, env = "XWIN_CRT_VERSION")]
68 pub xwin_crt_version: Option<String>,
69
70 #[arg(long, env = "XWIN_INCLUDE_ATL")]
72 pub xwin_include_atl: bool,
73
74 #[arg(long, env = "XWIN_INCLUDE_DEBUG_LIBS", hide = true)]
76 pub xwin_include_debug_libs: bool,
77
78 #[arg(long, env = "XWIN_INCLUDE_DEBUG_SYMBOLS", hide = true)]
80 pub xwin_include_debug_symbols: bool,
81
82 #[arg(long, env = "XWIN_HTTP_RETRIES", default_value = "3")]
84 pub xwin_http_retries: u32,
85}
86
87impl Default for XWinOptions {
88 fn default() -> Self {
89 Self {
90 xwin_cache_dir: None,
91 xwin_arch: vec![xwin::Arch::X86_64, xwin::Arch::Aarch64],
92 xwin_variant: vec![xwin::Variant::Desktop],
93 xwin_version: 17,
94 xwin_sdk_version: None,
95 xwin_crt_version: None,
96 xwin_include_atl: false,
97 xwin_include_debug_libs: false,
98 xwin_include_debug_symbols: false,
99 cross_compiler: CrossCompiler::ClangCl,
100 xwin_http_retries: 3,
101 }
102 }
103}
104
105impl XWinOptions {
106 pub fn apply_command_env(
107 &self,
108 manifest_path: Option<&Path>,
109 cargo: &cargo_options::CommonOptions,
110 cmd: &mut Command,
111 ) -> Result<()> {
112 let cache_dir = {
113 let cache_dir = self.xwin_cache_dir.clone().unwrap_or_else(|| {
114 dirs::cache_dir()
115 .unwrap_or_else(|| std::env::current_dir().expect("Failed to get current dir"))
116 .join(env!("CARGO_PKG_NAME"))
117 });
118 fs::create_dir_all(&cache_dir)?;
119 cache_dir.canonicalize()?
120 };
121 match self.cross_compiler {
122 CrossCompiler::ClangCl => {
123 let clang_cl = crate::compiler::clang_cl::ClangCl::new(self);
124 clang_cl.apply_command_env(manifest_path, cargo, cache_dir, cmd)?;
125 }
126 CrossCompiler::Clang => {
127 let clang = crate::compiler::clang::Clang::new();
128 clang.apply_command_env(manifest_path, cargo, cache_dir, cmd)?;
129 }
130 }
131 Ok(())
132 }
133}