Skip to main content

cargo_xwin/
cache.rs

1use std::path::PathBuf;
2
3use crate::compiler::clang::Clang;
4use crate::compiler::clang_cl::ClangCl;
5use crate::options::XWinOptions;
6use anyhow::Result;
7use clap::{Parser, Subcommand};
8use fs_err as fs;
9
10/// Manage xwin cache
11#[derive(Debug, Parser)]
12pub struct Cache {
13    #[command(subcommand)]
14    pub subcommand: CacheSubcommand,
15}
16
17#[derive(Debug, Subcommand)]
18pub enum CacheSubcommand {
19    /// Pre-cache xwin (MS CRT) for clang-cl backend
20    Xwin(CacheXwin),
21    /// Pre-cache windows-msvc-sysroot for clang backend
22    WindowsMsvcSysroot(CacheWindowsMsvcSysroot),
23}
24
25/// Pre-cache xwin (MS CRT) for clang-cl backend
26#[derive(Debug, Parser)]
27pub struct CacheXwin {
28    #[command(flatten)]
29    pub xwin_options: XWinOptions,
30}
31
32/// Pre-cache windows-msvc-sysroot for clang backend
33#[derive(Debug, Parser)]
34pub struct CacheWindowsMsvcSysroot {
35    /// Cache directory for windows-msvc-sysroot
36    #[arg(long, env = "XWIN_CACHE_DIR")]
37    pub cache_dir: Option<PathBuf>,
38}
39
40/// Get the default cache directory for cargo-xwin
41fn get_default_cache_dir() -> PathBuf {
42    dirs::cache_dir()
43        .unwrap_or_else(|| std::env::current_dir().expect("Failed to get current dir"))
44        .join(env!("CARGO_PKG_NAME"))
45}
46
47/// Prepare and canonicalize a cache directory
48fn prepare_cache_dir(cache_dir: Option<PathBuf>) -> Result<PathBuf> {
49    let cache_dir = cache_dir.unwrap_or_else(get_default_cache_dir);
50    fs::create_dir_all(&cache_dir)?;
51    cache_dir.canonicalize().map_err(Into::into)
52}
53
54/// Prepare the xwin cache subdirectory
55pub fn prepare_xwin_cache_dir(base_cache_dir: PathBuf) -> Result<PathBuf> {
56    let xwin_cache_dir = base_cache_dir.join("xwin");
57    fs::create_dir_all(&xwin_cache_dir)?;
58    xwin_cache_dir.canonicalize().map_err(Into::into)
59}
60
61impl Cache {
62    pub fn execute(self) -> Result<()> {
63        match self.subcommand {
64            CacheSubcommand::Xwin(xwin) => xwin.execute(),
65            CacheSubcommand::WindowsMsvcSysroot(sysroot) => sysroot.execute(),
66        }
67    }
68}
69
70impl CacheXwin {
71    pub fn execute(self) -> Result<()> {
72        let cache_dir = prepare_cache_dir(self.xwin_options.xwin_cache_dir.clone())?;
73        let xwin_cache_dir = prepare_xwin_cache_dir(cache_dir)?;
74
75        println!("📦 Pre-caching Microsoft CRT and Windows SDK...");
76        println!("📁 Cache directory: {}", xwin_cache_dir.display());
77
78        let clang_cl = ClangCl::new(&self.xwin_options);
79        clang_cl.setup_msvc_crt(xwin_cache_dir)?;
80
81        println!("✅ xwin cache setup completed successfully!");
82        Ok(())
83    }
84}
85
86impl CacheWindowsMsvcSysroot {
87    pub fn execute(self) -> Result<()> {
88        let cache_dir = prepare_cache_dir(self.cache_dir.clone())?;
89
90        println!("📦 Pre-caching windows-msvc-sysroot...");
91        println!("📁 Cache directory: {}", cache_dir.display());
92
93        let clang = Clang::new();
94        let sysroot_dir = clang.setup_msvc_sysroot(cache_dir)?;
95
96        println!("✅ windows-msvc-sysroot cache setup completed successfully!");
97        println!("📁 Sysroot location: {}", sysroot_dir.display());
98        Ok(())
99    }
100}