bootstrap/core/
metadata.rs1use std::collections::BTreeMap;
9use std::path::PathBuf;
10
11use serde_derive::Deserialize;
12
13use crate::utils::exec::command;
14use crate::{Build, Crate, t};
15
16#[derive(Debug, Deserialize)]
19struct Output {
20 packages: Vec<Package>,
21}
22
23#[derive(Debug, Deserialize)]
26struct Package {
27 name: String,
28 source: Option<String>,
29 manifest_path: String,
30 dependencies: Vec<Dependency>,
31 features: BTreeMap<String, Vec<String>>,
32}
33
34#[derive(Debug, Deserialize)]
37struct Dependency {
38 name: String,
39 source: Option<String>,
40}
41
42pub fn build(build: &mut Build) {
45 for package in workspace_members(build) {
46 if package.source.is_none() {
47 let name = package.name;
48 let mut path = PathBuf::from(package.manifest_path);
49 path.pop();
50 let deps = package
51 .dependencies
52 .into_iter()
53 .filter(|dep| dep.source.is_none())
54 .map(|dep| dep.name)
55 .collect();
56 let krate = Crate {
57 name: name.clone(),
58 deps,
59 path,
60 features: package.features.keys().cloned().collect(),
61 };
62 let relative_path = krate.local_path(build);
63 build.crates.insert(name.clone(), krate);
64 let existing_path = build.crate_paths.insert(relative_path, name);
65 assert!(
66 existing_path.is_none(),
67 "multiple crates with the same path: {}",
68 existing_path.unwrap()
69 );
70 }
71 }
72}
73
74fn workspace_members(build: &Build) -> Vec<Package> {
79 let collect_metadata = |manifest_path| {
80 let mut cargo = command(&build.initial_cargo);
81 cargo
82 .env("RUSTC_BOOTSTRAP", "1")
85 .arg("metadata")
86 .arg("--format-version")
87 .arg("1")
88 .arg("--no-deps")
89 .arg("--manifest-path")
90 .arg(build.src.join(manifest_path));
91 let metadata_output = cargo.run_always().run_capture_stdout(build).stdout();
92 let Output { packages, .. } = t!(serde_json::from_str(&metadata_output));
93 packages
94 };
95
96 let mut packages = vec![];
98 packages.extend(collect_metadata("Cargo.toml"));
99 packages.extend(collect_metadata("library/Cargo.toml"));
100 packages
101}