in src/compiler/rust.rs [2379:2440]
fn new_with_check(executable: PathBuf, env_vars: &[(OsString, OsString)]) -> Result<Self> {
let temp_dir = tempfile::Builder::new()
.prefix("sccache-rlibreader")
.tempdir()
.context("Could not create temporary directory for rlib output")?;
let temp_rlib = temp_dir.path().join("x.rlib");
let mut cmd = process::Command::new(&executable);
cmd.arg("--crate-type=rlib")
.arg("-o")
.arg(&temp_rlib)
.arg("-")
.env_clear()
.envs(env_vars.to_vec());
let process::Output {
status,
stdout,
stderr,
} = cmd.output()?;
if !stdout.is_empty() {
bail!(
"rustc stdout non-empty when compiling a minimal rlib: {:?}",
String::from_utf8_lossy(&stdout)
)
}
if !stderr.is_empty() {
bail!(
"rustc stderr non-empty when compiling a minimal rlib: {:?}",
String::from_utf8_lossy(&stderr)
)
}
if !status.success() {
bail!(
"Failed to compile a minimal rlib with {}",
executable.display()
)
}
// The goal of this cache is to avoid repeated lookups when building a single project. Let's budget 3MB.
// Allowing for a 100 byte path, 50 dependencies per rlib and 20 characters per crate name, this roughly
// approximates to `path_size + path + vec_size + num_deps * (systemtime_size + string_size + crate_name_len)`
// ` 3*8 + 100 + 3*8 + 50 * ( 8 + 3*8 + 20 )`
// `2748` bytes per crate
// Allowing for possible overhead of up to double (for unused space in allocated memory), this means we
// can cache information from about 570 rlibs - easily enough for a single project.
const CACHE_SIZE: u64 = 3 * 1024 * 1024;
let cache = LruCache::with_meter(CACHE_SIZE, DepsSize);
let rustc_version = Self::get_rustc_version(&executable, env_vars)?;
let rlib_dep_reader = RlibDepReader {
cache: Mutex::new(cache),
executable,
ls_arg: Self::get_correct_ls_arg(rustc_version),
};
if let Err(e) = rlib_dep_reader.discover_rlib_deps(env_vars, &temp_rlib) {
bail!("Failed to read deps from minimal rlib: {}", e)
}
Ok(rlib_dep_reader)
}