5878: Prepare to share sysroot lowering code between Cargo & ProjectJSON
 r=matklad a=matklad

bors r+
🤖

Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
bors[bot] 2020-08-25 15:54:05 +00:00 committed by GitHub
commit 3f721683de
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 73 additions and 105 deletions

View file

@ -335,45 +335,8 @@ impl ProjectWorkspace {
let mut cfg_options = CfgOptions::default(); let mut cfg_options = CfgOptions::default();
cfg_options.extend(get_rustc_cfg_options(target)); cfg_options.extend(get_rustc_cfg_options(target));
let sysroot_crates: FxHashMap<_, _> = sysroot let (public_deps, libproc_macro) =
.crates() sysroot_to_crate_graph(&mut crate_graph, sysroot, &cfg_options, load);
.filter_map(|krate| {
let file_id = load(&sysroot[krate].root)?;
let env = Env::default();
let proc_macro = vec![];
let name = sysroot[krate].name.clone();
let crate_id = crate_graph.add_crate_root(
file_id,
Edition::Edition2018,
Some(name),
cfg_options.clone(),
env,
proc_macro,
);
Some((krate, crate_id))
})
.collect();
for from in sysroot.crates() {
for &to in sysroot[from].deps.iter() {
let name = &sysroot[to].name;
if let (Some(&from), Some(&to)) =
(sysroot_crates.get(&from), sysroot_crates.get(&to))
{
if crate_graph.add_dep(from, CrateName::new(name).unwrap(), to).is_err()
{
log::error!("cyclic dependency between sysroot crates")
}
}
}
}
let libcore = sysroot.core().and_then(|it| sysroot_crates.get(&it).copied());
let liballoc = sysroot.alloc().and_then(|it| sysroot_crates.get(&it).copied());
let libstd = sysroot.std().and_then(|it| sysroot_crates.get(&it).copied());
let libproc_macro =
sysroot.proc_macro().and_then(|it| sysroot_crates.get(&it).copied());
let mut pkg_to_lib_crate = FxHashMap::default(); let mut pkg_to_lib_crate = FxHashMap::default();
let mut pkg_crates = FxHashMap::default(); let mut pkg_crates = FxHashMap::default();
@ -424,14 +387,11 @@ impl ProjectWorkspace {
} }
if cargo[tgt].is_proc_macro { if cargo[tgt].is_proc_macro {
if let Some(proc_macro) = libproc_macro { if let Some(proc_macro) = libproc_macro {
if crate_graph if let Err(_) = crate_graph.add_dep(
.add_dep( crate_id,
crate_id, CrateName::new("proc_macro").unwrap(),
CrateName::new("proc_macro").unwrap(), proc_macro,
proc_macro, ) {
)
.is_err()
{
log::error!( log::error!(
"cyclic dependency on proc_macro for {}", "cyclic dependency on proc_macro for {}",
&cargo[pkg].name &cargo[pkg].name
@ -447,52 +407,22 @@ impl ProjectWorkspace {
// Set deps to the core, std and to the lib target of the current package // Set deps to the core, std and to the lib target of the current package
for &from in pkg_crates.get(&pkg).into_iter().flatten() { for &from in pkg_crates.get(&pkg).into_iter().flatten() {
if let Some((to, name)) = lib_tgt.clone() { if let Some((to, name)) = lib_tgt.clone() {
if to != from // For root projects with dashes in their name,
&& crate_graph // cargo metadata does not do any normalization,
.add_dep( // so we do it ourselves currently
from, let name = CrateName::normalize_dashes(&name);
// For root projects with dashes in their name, if to != from && crate_graph.add_dep(from, name, to).is_err() {
// cargo metadata does not do any normalization, log::error!(
// so we do it ourselves currently "cyclic dependency between targets of {}",
CrateName::normalize_dashes(&name), &cargo[pkg].name
to, )
)
.is_err()
{
{
log::error!(
"cyclic dependency between targets of {}",
&cargo[pkg].name
)
}
} }
} }
// core is added as a dependency before std in order to for (name, krate) in public_deps.iter() {
// mimic rustcs dependency order if let Err(_) = crate_graph.add_dep(from, name.clone(), *krate) {
if let Some(core) = libcore {
if crate_graph
.add_dep(from, CrateName::new("core").unwrap(), core)
.is_err()
{
log::error!("cyclic dependency on core for {}", &cargo[pkg].name) log::error!("cyclic dependency on core for {}", &cargo[pkg].name)
} }
} }
if let Some(alloc) = liballoc {
if crate_graph
.add_dep(from, CrateName::new("alloc").unwrap(), alloc)
.is_err()
{
log::error!("cyclic dependency on alloc for {}", &cargo[pkg].name)
}
}
if let Some(std) = libstd {
if crate_graph
.add_dep(from, CrateName::new("std").unwrap(), std)
.is_err()
{
log::error!("cyclic dependency on std for {}", &cargo[pkg].name)
}
}
} }
} }
@ -500,12 +430,10 @@ impl ProjectWorkspace {
// target of downstream. // target of downstream.
for pkg in cargo.packages() { for pkg in cargo.packages() {
for dep in cargo[pkg].dependencies.iter() { for dep in cargo[pkg].dependencies.iter() {
let name = CrateName::new(&dep.name).unwrap();
if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) { if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
for &from in pkg_crates.get(&pkg).into_iter().flatten() { for &from in pkg_crates.get(&pkg).into_iter().flatten() {
if crate_graph if let Err(_) = crate_graph.add_dep(from, name.clone(), to) {
.add_dep(from, CrateName::new(&dep.name).unwrap(), to)
.is_err()
{
log::error!( log::error!(
"cyclic dependency {} -> {}", "cyclic dependency {} -> {}",
&cargo[pkg].name, &cargo[pkg].name,
@ -563,3 +491,49 @@ fn utf8_stdout(mut cmd: Command) -> Result<String> {
let stdout = String::from_utf8(output.stdout)?; let stdout = String::from_utf8(output.stdout)?;
Ok(stdout.trim().to_string()) Ok(stdout.trim().to_string())
} }
fn sysroot_to_crate_graph(
crate_graph: &mut CrateGraph,
sysroot: &Sysroot,
cfg_options: &CfgOptions,
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
) -> (Vec<(CrateName, CrateId)>, Option<CrateId>) {
let sysroot_crates: FxHashMap<_, _> = sysroot
.crates()
.filter_map(|krate| {
let file_id = load(&sysroot[krate].root)?;
let env = Env::default();
let proc_macro = vec![];
let name = sysroot[krate].name.clone();
let crate_id = crate_graph.add_crate_root(
file_id,
Edition::Edition2018,
Some(name),
cfg_options.clone(),
env,
proc_macro,
);
Some((krate, crate_id))
})
.collect();
for from in sysroot.crates() {
for &to in sysroot[from].deps.iter() {
let name = CrateName::new(&sysroot[to].name).unwrap();
if let (Some(&from), Some(&to)) = (sysroot_crates.get(&from), sysroot_crates.get(&to)) {
if let Err(_) = crate_graph.add_dep(from, name, to) {
log::error!("cyclic dependency between sysroot crates")
}
}
}
}
let public_deps = sysroot
.public_deps()
.map(|(name, idx)| (CrateName::new(name).unwrap(), sysroot_crates[&idx]))
.collect::<Vec<_>>();
let libproc_macro = sysroot.proc_macro().and_then(|it| sysroot_crates.get(&it).copied());
(public_deps, libproc_macro)
}

View file

@ -34,16 +34,10 @@ impl ops::Index<SysrootCrate> for Sysroot {
} }
impl Sysroot { impl Sysroot {
pub fn core(&self) -> Option<SysrootCrate> { pub fn public_deps(&self) -> impl Iterator<Item = (&'static str, SysrootCrate)> + '_ {
self.by_name("core") // core is added as a dependency before std in order to
} // mimic rustcs dependency order
vec!["core", "alloc", "std"].into_iter().filter_map(move |it| Some((it, self.by_name(it)?)))
pub fn alloc(&self) -> Option<SysrootCrate> {
self.by_name("alloc")
}
pub fn std(&self) -> Option<SysrootCrate> {
self.by_name("std")
} }
pub fn proc_macro(&self) -> Option<SysrootCrate> { pub fn proc_macro(&self) -> Option<SysrootCrate> {
@ -81,7 +75,7 @@ impl Sysroot {
} }
} }
if let Some(std) = sysroot.std() { if let Some(std) = sysroot.by_name("std") {
for dep in STD_DEPS.trim().lines() { for dep in STD_DEPS.trim().lines() {
if let Some(dep) = sysroot.by_name(dep) { if let Some(dep) = sysroot.by_name(dep) {
sysroot.crates[std].deps.push(dep) sysroot.crates[std].deps.push(dep)
@ -89,8 +83,8 @@ impl Sysroot {
} }
} }
if let Some(alloc) = sysroot.alloc() { if let Some(alloc) = sysroot.by_name("alloc") {
if let Some(core) = sysroot.core() { if let Some(core) = sysroot.by_name("core") {
sysroot.crates[alloc].deps.push(core); sysroot.crates[alloc].deps.push(core);
} }
} }