Skip to main content

cubecl_runtime/config/
cache.rs

1use etcetera::BaseStrategy;
2
3/// Cache location options.
4#[derive(Default, Clone, Debug, serde::Serialize, serde::Deserialize)]
5pub enum CacheConfig {
6    /// Stores cache in the current working directory.
7    #[serde(rename = "local")]
8    Local,
9
10    /// Stores cache in the project's `target` directory (default).
11    #[default]
12    #[serde(rename = "target")]
13    Target,
14
15    /// Stores cache in the system's local configuration directory.
16    #[serde(rename = "global")]
17    Global,
18
19    /// Stores cache in a user-specified file path.
20    #[serde(rename = "file")]
21    File(std::path::PathBuf),
22}
23
24impl CacheConfig {
25    /// Returns the root directory for the cache.
26    pub fn root(&self) -> std::path::PathBuf {
27        match self {
28            Self::Local => std::env::current_dir().unwrap(),
29            Self::Target => {
30                let dir_original =
31                    std::env::current_dir().unwrap_or_else(|_| std::path::PathBuf::from("/"));
32                let mut dir = dir_original.clone();
33
34                // Search for Cargo.toml in parent directories to locate project root.
35                loop {
36                    if let Ok(true) = std::fs::exists(dir.join("Cargo.toml")) {
37                        return dir.join("target");
38                    }
39
40                    if !dir.pop() {
41                        break;
42                    }
43                }
44
45                // No Cargo.toml anywhere above cwd — this is a bundled or
46                // installed application (Tauri, GUI app, CLI installed via
47                // cargo install, etc.) running outside a workspace. The
48                // previous fallback of `dir_original.join("target")` became
49                // `/target` when cwd was `/`, which fails on most platforms
50                // with EROFS (read-only system volume on macOS, root-owned
51                // on Linux) and cascaded a `CacheFile::new` directory
52                // failure into the whole autotune pipeline. Use the
53                // platform-appropriate user cache directory instead.
54                if let Ok(strategy) = etcetera::choose_base_strategy() {
55                    return strategy.cache_dir().join("cubecl");
56                }
57                dir_original.join("target")
58            }
59            Self::Global => etcetera::choose_base_strategy()
60                .expect("a configuration directory should exist")
61                .config_dir(),
62            Self::File(path_buf) => path_buf.clone(),
63        }
64    }
65}