Load proc-macros for rustc_private crates

This commit is contained in:
Lukas Wirth 2023-03-08 12:41:38 +01:00
parent ecc32c2f85
commit c9786484c5
3 changed files with 98 additions and 22 deletions

View file

@ -15,13 +15,13 @@ use std::{
use cargo_metadata::{camino::Utf8Path, Message};
use la_arena::ArenaMap;
use paths::AbsPathBuf;
use paths::{AbsPath, AbsPathBuf};
use rustc_hash::FxHashMap;
use semver::Version;
use serde::Deserialize;
use crate::{
cfg_flag::CfgFlag, CargoConfig, CargoFeatures, CargoWorkspace, InvocationLocation,
cfg_flag::CfgFlag, utf8_stdout, CargoConfig, CargoFeatures, CargoWorkspace, InvocationLocation,
InvocationStrategy, Package,
};
@ -250,7 +250,7 @@ impl WorkspaceBuildScripts {
if tracing::enabled!(tracing::Level::INFO) {
for package in workspace.packages() {
let package_build_data = &mut outputs[package];
let package_build_data = &outputs[package];
if !package_build_data.is_unchanged() {
tracing::info!(
"{}: {:?}",
@ -378,6 +378,80 @@ impl WorkspaceBuildScripts {
pub(crate) fn get_output(&self, idx: Package) -> Option<&BuildScriptOutput> {
self.outputs.get(idx)
}
pub(crate) fn rustc_crates(
rustc: &CargoWorkspace,
current_dir: &AbsPath,
extra_env: &FxHashMap<String, String>,
) -> Self {
let mut bs = WorkspaceBuildScripts::default();
for p in rustc.packages() {
bs.outputs.insert(p, BuildScriptOutput::default());
}
let res = (|| {
let target_libdir = (|| {
let mut cargo_config = Command::new(toolchain::cargo());
cargo_config.envs(extra_env);
cargo_config
.current_dir(current_dir)
.args(["rustc", "-Z", "unstable-options", "--print", "target-libdir"])
.env("RUSTC_BOOTSTRAP", "1");
if let Ok(it) = utf8_stdout(cargo_config) {
return Ok(it);
}
let mut cmd = Command::new(toolchain::rustc());
cmd.envs(extra_env);
cmd.args(["--print", "target-libdir"]);
utf8_stdout(cmd)
})()?;
let target_libdir = AbsPathBuf::try_from(PathBuf::from(target_libdir))
.map_err(|_| anyhow::format_err!("target-libdir was not an absolute path"))?;
tracing::info!("Loading rustc proc-macro paths from {}", target_libdir.display());
let proc_macro_dylibs: Vec<(String, AbsPathBuf)> = std::fs::read_dir(target_libdir)?
.filter_map(|entry| {
let dir_entry = entry.ok()?;
if dir_entry.file_type().ok()?.is_file() {
let path = dir_entry.path();
tracing::info!("p{:?}", path);
let extension = path.extension()?;
if extension == "dll" || extension == "so" {
let name = path.file_stem()?.to_str()?.split_once('-')?.0.to_owned();
let path = AbsPathBuf::try_from(path).ok()?;
return Some((name, path));
}
}
None
})
.collect();
for p in rustc.packages() {
if let Some((_, path)) =
proc_macro_dylibs.iter().find(|(name, _)| *name == rustc[p].name)
{
bs.outputs[p].proc_macro_dylib_path = Some(path.clone());
}
}
if tracing::enabled!(tracing::Level::INFO) {
for package in rustc.packages() {
let package_build_data = &bs.outputs[package];
if !package_build_data.is_unchanged() {
tracing::info!(
"{}: {:?}",
rustc[package].manifest.parent().display(),
package_build_data,
);
}
}
}
Ok(())
})();
if let Err::<_, anyhow::Error>(e) = res {
bs.error = Some(e.to_string());
}
bs
}
}
// FIXME: Find a better way to know if it is a dylib.