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    /// Update the cache
32    #[arg(long)]
33    pub update: bool,
34}
35
36/// Pre-cache windows-msvc-sysroot for clang backend
37#[derive(Debug, Parser)]
38pub struct CacheWindowsMsvcSysroot {
39    /// Cache directory for windows-msvc-sysroot
40    #[arg(long, env = "XWIN_CACHE_DIR")]
41    pub cache_dir: Option<PathBuf>,
42}
43
44/// Get the default cache directory for cargo-xwin
45fn get_default_cache_dir() -> PathBuf {
46    dirs::cache_dir()
47        .unwrap_or_else(|| std::env::current_dir().expect("Failed to get current dir"))
48        .join(env!("CARGO_PKG_NAME"))
49}
50
51/// Prepare and canonicalize a cache directory
52fn prepare_cache_dir(cache_dir: Option<PathBuf>) -> Result<PathBuf> {
53    let cache_dir = cache_dir.unwrap_or_else(get_default_cache_dir);
54    fs::create_dir_all(&cache_dir)?;
55    cache_dir.canonicalize().map_err(Into::into)
56}
57
58/// Prepare the xwin cache subdirectory
59pub fn prepare_xwin_cache_dir(base_cache_dir: PathBuf) -> Result<PathBuf> {
60    let xwin_cache_dir = base_cache_dir.join("xwin");
61    fs::create_dir_all(&xwin_cache_dir)?;
62    xwin_cache_dir.canonicalize().map_err(Into::into)
63}
64
65impl Cache {
66    pub fn execute(self) -> Result<()> {
67        match self.subcommand {
68            CacheSubcommand::Xwin(xwin) => xwin.execute(),
69            CacheSubcommand::WindowsMsvcSysroot(sysroot) => sysroot.execute(),
70        }
71    }
72}
73
74impl CacheXwin {
75    pub fn execute(self) -> Result<()> {
76        let cache_dir = prepare_cache_dir(self.xwin_options.xwin_cache_dir.clone())?;
77        let xwin_cache_dir = prepare_xwin_cache_dir(cache_dir)?;
78
79        println!("📦 Pre-caching Microsoft CRT and Windows SDK...");
80        println!("📁 Cache directory: {}", xwin_cache_dir.display());
81
82        let clang_cl = ClangCl::new(&self.xwin_options);
83        clang_cl.setup_msvc_crt(xwin_cache_dir, self.update)?;
84
85        println!("✅ xwin cache setup completed successfully!");
86        Ok(())
87    }
88}
89
90impl CacheWindowsMsvcSysroot {
91    pub fn execute(self) -> Result<()> {
92        let cache_dir = prepare_cache_dir(self.cache_dir.clone())?;
93
94        println!("📦 Pre-caching windows-msvc-sysroot...");
95        println!("📁 Cache directory: {}", cache_dir.display());
96
97        let clang = Clang::new();
98        let sysroot_dir = clang.setup_msvc_sysroot(cache_dir)?;
99
100        println!("✅ windows-msvc-sysroot cache setup completed successfully!");
101        println!("📁 Sysroot location: {}", sysroot_dir.display());
102        Ok(())
103    }
104}