in src/compiler/rust.rs [2492:2552]
fn discover_rlib_deps(
&self,
env_vars: &[(OsString, OsString)],
rlib: &Path,
) -> Result<Vec<String>> {
let rlib_mtime = fs::metadata(rlib)
.and_then(|m| m.modified())
.context("Unable to get rlib modified time")?;
{
let mut cache = self.cache.lock().unwrap();
if let Some(deps_detail) = cache.get(rlib) {
if rlib_mtime == deps_detail.mtime {
return Ok(deps_detail.deps.clone());
}
}
}
trace!("Discovering dependencies of {}", rlib.display());
let mut cmd = process::Command::new(&self.executable);
cmd.args(["-Z", &self.ls_arg])
.arg(rlib)
.env_clear()
.envs(env_vars.to_vec())
.env("RUSTC_BOOTSTRAP", "1"); // TODO: this is fairly naughty
let process::Output {
status,
stdout,
stderr,
} = cmd.output()?;
if !status.success() {
bail!(format!("Failed to list deps of {}", rlib.display()))
}
if !stderr.is_empty() {
bail!(
"rustc -Z ls stderr non-empty: {:?}",
String::from_utf8_lossy(&stderr)
)
}
let stdout = String::from_utf8(stdout).context("Error parsing rustc -Z ls output")?;
let deps: Vec<_> = parse_rustc_z_ls(&stdout)
.map(|deps| deps.into_iter().map(|dep| dep.to_owned()).collect())?;
{
// This will behave poorly if the rlib is changing under our feet, but in that case rustc
// will also do the wrong thing, so the user has bigger issues to deal with.
let mut cache = self.cache.lock().unwrap();
cache.insert(
rlib.to_owned(),
RlibDepsDetail {
deps: deps.clone(),
mtime: rlib_mtime,
},
);
}
Ok(deps)
}