about summary refs log tree commit diff
path: root/src/bootstrap
diff options
context:
space:
mode:
authorWeihang Lo <me@weihanglo.tw>2023-03-14 10:23:14 +0000
committerWeihang Lo <me@weihanglo.tw>2023-04-16 19:32:20 +0100
commit82950f6895638b7fe5e80a961cb03fca27436629 (patch)
treef55d08ac181dba741ac74984c4ed711b5698519a /src/bootstrap
parent4c777710c6f5996e0967fe5b9d2924684c646626 (diff)
downloadrust-82950f6895638b7fe5e80a961cb03fca27436629.tar.gz
rust-82950f6895638b7fe5e80a961cb03fca27436629.zip
bootstrap: treat src/tools/cargo as a workspace member
We remove `src/tools/cargo` from rust-lang/rust root workspace, but
some underlying mechanism still needs it to be a member. for example,
`./x.py doc`. This little hack make cargo's metadata available by
invoking an extra `cargo metadata` for cargo the package itself.

Co-authored-by: Scott Schafer <schaferjscott@gmail.com>
Co-authored-by: Eric Huss <eric@huss.org>
Diffstat (limited to 'src/bootstrap')
-rw-r--r--src/bootstrap/metadata.rs59
1 files changed, 44 insertions, 15 deletions
diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs
index bba4d65e8c3..597aefadcfe 100644
--- a/src/bootstrap/metadata.rs
+++ b/src/bootstrap/metadata.rs
@@ -7,12 +7,16 @@ use crate::cache::INTERNER;
 use crate::util::output;
 use crate::{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>,
@@ -20,25 +24,18 @@ struct Package {
     dependencies: Vec<Dependency>,
 }
 
-#[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>,
 }
 
+/// 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);
@@ -57,3 +54,35 @@ pub fn build(build: &mut Build) {
         }
     }
 }
+
+/// 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 cmd_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(manifest_path);
+        cargo
+    };
+
+    // Collects `metadata.packages` from the root workspace.
+    let root_manifest_path = build.src.join("Cargo.toml");
+    let root_output = output(&mut cmd_metadata(&root_manifest_path));
+    let Output { packages, .. } = serde_json::from_str(&root_output).unwrap();
+
+    // Collects `metadata.packages` from src/tools/cargo separately.
+    let cargo_manifest_path = build.src.join("src/tools/cargo/Cargo.toml");
+    let cargo_output = output(&mut cmd_metadata(&cargo_manifest_path));
+    let Output { packages: cargo_packages, .. } = serde_json::from_str(&cargo_output).unwrap();
+
+    // 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)
+}