Skip to content

Commit adeb701

Browse files
mmastracclaude
andcommitted
feat: allow caching all Rust crate types via SCCACHE_RUST_CRATE_TYPE_ALLOW_HASH
When the SCCACHE_RUST_CRATE_TYPE_ALLOW_HASH environment variable is set, all crate types (bin, dylib, cdylib, proc-macro) become cacheable. The env var value is hashed into the cache key only when unsupported crate types are present, so machines with different linker setups get separate cache entries. This enables per-machine binary crate caching by setting the env var to a machine-specific value (e.g., a hash of the linker toolchain). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 8261038 commit adeb701

1 file changed

Lines changed: 29 additions & 14 deletions

File tree

src/compiler/rust.rs

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ pub struct RustCompilation {
228228
pub struct CrateTypes {
229229
rlib: bool,
230230
staticlib: bool,
231+
others: Vec<String>,
231232
}
232233

233234
/// Emit types that we will cache.
@@ -1075,6 +1076,7 @@ fn parse_arguments(arguments: &[OsString], cwd: &Path) -> CompilerArguments<Pars
10751076
let mut crate_types = CrateTypes {
10761077
rlib: false,
10771078
staticlib: false,
1079+
others: vec![],
10781080
};
10791081
let mut extra_filename = None;
10801082
let mut externs = vec![];
@@ -1125,10 +1127,16 @@ fn parse_arguments(arguments: &[OsString], cwd: &Path) -> CompilerArguments<Pars
11251127
})) => {
11261128
// We can't cache non-rlib/staticlib crates, because rustc invokes the
11271129
// system linker to link them, and we don't know about all the linker inputs.
1130+
// However, if SCCACHE_RUST_CRATE_TYPE_ALLOW_HASH is set, we allow caching
1131+
// all crate types. The env var value is hashed into the cache key so that
1132+
// machines with different linker setups get separate cache entries.
11281133
if !others.is_empty() {
1129-
let others: Vec<&str> = others.iter().map(String::as_str).collect();
1130-
let others_string = others.join(",");
1131-
cannot_cache!("crate-type", others_string)
1134+
if std::env::var("SCCACHE_RUST_CRATE_TYPE_ALLOW_HASH").is_err() {
1135+
let others: Vec<&str> = others.iter().map(String::as_str).collect();
1136+
let others_string = others.join(",");
1137+
cannot_cache!("crate-type", others_string)
1138+
}
1139+
crate_types.others.extend(others.iter().cloned());
11321140
}
11331141
crate_types.rlib |= rlib;
11341142
crate_types.staticlib |= staticlib;
@@ -1235,10 +1243,12 @@ fn parse_arguments(arguments: &[OsString], cwd: &Path) -> CompilerArguments<Pars
12351243
// If it's not an rlib and not a staticlib then crate-type wasn't passed,
12361244
// so it will usually be inferred as a binary, though the `#![crate_type`
12371245
// annotation may dictate otherwise - either way, we don't know what to do.
1238-
if let CrateTypes {
1239-
rlib: false,
1240-
staticlib: false,
1241-
} = crate_types
1246+
// Unless SCCACHE_RUST_CRATE_TYPE_ALLOW_HASH is set, in which case we
1247+
// allow caching regardless.
1248+
if !crate_types.rlib
1249+
&& !crate_types.staticlib
1250+
&& crate_types.others.is_empty()
1251+
&& std::env::var("SCCACHE_RUST_CRATE_TYPE_ALLOW_HASH").is_err()
12421252
{
12431253
cannot_cache!("crate-type", "No crate-type passed".to_owned())
12441254
}
@@ -1540,6 +1550,15 @@ where
15401550
cwd.hash(&mut HashToDigest { digest: &mut m });
15411551
// 10. The version of the compiler.
15421552
self.version.hash(&mut HashToDigest { digest: &mut m });
1553+
// 11. SCCACHE_RUST_CRATE_TYPE_ALLOW_HASH, if set and we have unsupported
1554+
// crate types: differentiates cache entries for machines with different
1555+
// linker setups.
1556+
if !self.parsed_args.crate_types.others.is_empty() {
1557+
if let Ok(val) = std::env::var("SCCACHE_RUST_CRATE_TYPE_ALLOW_HASH") {
1558+
m.update(b"SCCACHE_RUST_CRATE_TYPE_ALLOW_HASH=");
1559+
m.update(val.as_bytes());
1560+
}
1561+
}
15431562

15441563
// Turn arguments into a simple Vec<OsString> to calculate outputs.
15451564
let flat_os_string_arguments: Vec<OsString> = os_string_arguments
@@ -2161,13 +2180,8 @@ impl pkg::InputsPackager for RustInputsPackager {
21612180

21622181
// If we're just creating an rlib then the only thing inspected inside dependency rlibs is the
21632182
// metadata, in which case we can create a trimmed rlib (which is actually a .a) with the metadata
2164-
let can_trim_rlibs = matches!(
2165-
crate_types,
2166-
CrateTypes {
2167-
rlib: true,
2168-
staticlib: false,
2169-
}
2170-
);
2183+
let can_trim_rlibs =
2184+
crate_types.rlib && !crate_types.staticlib && crate_types.others.is_empty();
21712185

21722186
let mut builder = tar::Builder::new(wtr);
21732187

@@ -3477,6 +3491,7 @@ proc_macro false
34773491
crate_types: CrateTypes {
34783492
rlib: true,
34793493
staticlib: false,
3494+
others: vec![],
34803495
},
34813496
dep_info: None,
34823497
emit,

0 commit comments

Comments
 (0)