summaryrefslogtreecommitdiffstats
path: root/src/bootstrap/metadata.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bootstrap/metadata.rs')
-rw-r--r--src/bootstrap/metadata.rs75
1 files changed, 57 insertions, 18 deletions
diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs
index bba4d65e8..8f2c3faca 100644
--- a/src/bootstrap/metadata.rs
+++ b/src/bootstrap/metadata.rs
@@ -5,40 +5,43 @@ use serde_derive::Deserialize;
use crate::cache::INTERNER;
use crate::util::output;
-use crate::{Build, Crate};
+use crate::{t, Build, Crate};
-#[derive(Deserialize)]
+/// For more information, see the output of
+/// <https://doc.rust-lang.org/nightly/cargo/commands/cargo-metadata.html>
+#[derive(Debug, Deserialize)]
struct Output {
packages: Vec<Package>,
}
-#[derive(Deserialize)]
+/// For more information, see the output of
+/// <https://doc.rust-lang.org/nightly/cargo/commands/cargo-metadata.html>
+#[derive(Debug, Deserialize)]
struct Package {
name: String,
source: Option<String>,
manifest_path: String,
dependencies: Vec<Dependency>,
+ targets: Vec<Target>,
}
-#[derive(Deserialize)]
+/// For more information, see the output of
+/// <https://doc.rust-lang.org/nightly/cargo/commands/cargo-metadata.html>
+#[derive(Debug, Deserialize)]
struct Dependency {
name: String,
source: Option<String>,
}
+#[derive(Debug, Deserialize)]
+struct Target {
+ kind: Vec<String>,
+}
+
+/// Collects and stores package metadata of each workspace members into `build`,
+/// by executing `cargo metadata` commands.
pub fn build(build: &mut Build) {
- // Run `cargo metadata` to figure out what crates we're testing.
- let mut cargo = Command::new(&build.initial_cargo);
- cargo
- .arg("metadata")
- .arg("--format-version")
- .arg("1")
- .arg("--no-deps")
- .arg("--manifest-path")
- .arg(build.src.join("Cargo.toml"));
- let output = output(&mut cargo);
- let output: Output = serde_json::from_str(&output).unwrap();
- for package in output.packages {
+ for package in workspace_members(build) {
if package.source.is_none() {
let name = INTERNER.intern_string(package.name);
let mut path = PathBuf::from(package.manifest_path);
@@ -49,11 +52,47 @@ pub fn build(build: &mut Build) {
.filter(|dep| dep.source.is_none())
.map(|dep| INTERNER.intern_string(dep.name))
.collect();
- let krate = Crate { name, deps, path };
+ let has_lib = package.targets.iter().any(|t| t.kind.iter().any(|k| k == "lib"));
+ let krate = Crate { name, deps, path, has_lib };
let relative_path = krate.local_path(build);
build.crates.insert(name, krate);
let existing_path = build.crate_paths.insert(relative_path, name);
- assert!(existing_path.is_none(), "multiple crates with the same path");
+ assert!(
+ existing_path.is_none(),
+ "multiple crates with the same path: {}",
+ existing_path.unwrap()
+ );
}
}
}
+
+/// Invokes `cargo metadata` to get package metadata of each workspace member.
+///
+/// Note that `src/tools/cargo` is no longer a workspace member but we still
+/// treat it as one here, by invoking an additional `cargo metadata` command.
+fn workspace_members(build: &Build) -> impl Iterator<Item = Package> {
+ let collect_metadata = |manifest_path| {
+ let mut cargo = Command::new(&build.initial_cargo);
+ cargo
+ .arg("metadata")
+ .arg("--format-version")
+ .arg("1")
+ .arg("--no-deps")
+ .arg("--manifest-path")
+ .arg(build.src.join(manifest_path));
+ let metadata_output = output(&mut cargo);
+ let Output { packages, .. } = t!(serde_json::from_str(&metadata_output));
+ packages
+ };
+
+ // Collects `metadata.packages` from all workspaces.
+ let packages = collect_metadata("Cargo.toml");
+ let cargo_packages = collect_metadata("src/tools/cargo/Cargo.toml");
+ let ra_packages = collect_metadata("src/tools/rust-analyzer/Cargo.toml");
+ let bootstrap_packages = collect_metadata("src/bootstrap/Cargo.toml");
+
+ // We only care about the root package from `src/tool/cargo` workspace.
+ let cargo_package = cargo_packages.into_iter().find(|pkg| pkg.name == "cargo").into_iter();
+
+ packages.into_iter().chain(cargo_package).chain(ra_packages).chain(bootstrap_packages)
+}