Skip to content

Commit 82950f6

Browse files
weihangloMuscraftehuss
committed
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 <[email protected]> Co-authored-by: Eric Huss <[email protected]>
1 parent 4c77771 commit 82950f6

File tree

1 file changed

+44
-15
lines changed

1 file changed

+44
-15
lines changed

src/bootstrap/metadata.rs

+44-15
Original file line numberDiff line numberDiff line change
@@ -7,38 +7,35 @@ use crate::cache::INTERNER;
77
use crate::util::output;
88
use crate::{Build, Crate};
99

10-
#[derive(Deserialize)]
10+
/// For more information, see the output of
11+
/// <https://doc.rust-lang.org/nightly/cargo/commands/cargo-metadata.html>
12+
#[derive(Debug, Deserialize)]
1113
struct Output {
1214
packages: Vec<Package>,
1315
}
1416

15-
#[derive(Deserialize)]
17+
/// For more information, see the output of
18+
/// <https://doc.rust-lang.org/nightly/cargo/commands/cargo-metadata.html>
19+
#[derive(Debug, Deserialize)]
1620
struct Package {
1721
name: String,
1822
source: Option<String>,
1923
manifest_path: String,
2024
dependencies: Vec<Dependency>,
2125
}
2226

23-
#[derive(Deserialize)]
27+
/// For more information, see the output of
28+
/// <https://doc.rust-lang.org/nightly/cargo/commands/cargo-metadata.html>
29+
#[derive(Debug, Deserialize)]
2430
struct Dependency {
2531
name: String,
2632
source: Option<String>,
2733
}
2834

35+
/// Collects and stores package metadata of each workspace members into `build`,
36+
/// by executing `cargo metadata` commands.
2937
pub fn build(build: &mut Build) {
30-
// Run `cargo metadata` to figure out what crates we're testing.
31-
let mut cargo = Command::new(&build.initial_cargo);
32-
cargo
33-
.arg("metadata")
34-
.arg("--format-version")
35-
.arg("1")
36-
.arg("--no-deps")
37-
.arg("--manifest-path")
38-
.arg(build.src.join("Cargo.toml"));
39-
let output = output(&mut cargo);
40-
let output: Output = serde_json::from_str(&output).unwrap();
41-
for package in output.packages {
38+
for package in workspace_members(build) {
4239
if package.source.is_none() {
4340
let name = INTERNER.intern_string(package.name);
4441
let mut path = PathBuf::from(package.manifest_path);
@@ -57,3 +54,35 @@ pub fn build(build: &mut Build) {
5754
}
5855
}
5956
}
57+
58+
/// Invokes `cargo metadata` to get package metadata of each workspace member.
59+
///
60+
/// Note that `src/tools/cargo` is no longer a workspace member but we still
61+
/// treat it as one here, by invoking an additional `cargo metadata` command.
62+
fn workspace_members(build: &Build) -> impl Iterator<Item = Package> {
63+
let cmd_metadata = |manifest_path| {
64+
let mut cargo = Command::new(&build.initial_cargo);
65+
cargo
66+
.arg("metadata")
67+
.arg("--format-version")
68+
.arg("1")
69+
.arg("--no-deps")
70+
.arg("--manifest-path")
71+
.arg(manifest_path);
72+
cargo
73+
};
74+
75+
// Collects `metadata.packages` from the root workspace.
76+
let root_manifest_path = build.src.join("Cargo.toml");
77+
let root_output = output(&mut cmd_metadata(&root_manifest_path));
78+
let Output { packages, .. } = serde_json::from_str(&root_output).unwrap();
79+
80+
// Collects `metadata.packages` from src/tools/cargo separately.
81+
let cargo_manifest_path = build.src.join("src/tools/cargo/Cargo.toml");
82+
let cargo_output = output(&mut cmd_metadata(&cargo_manifest_path));
83+
let Output { packages: cargo_packages, .. } = serde_json::from_str(&cargo_output).unwrap();
84+
85+
// We only care about the root package from `src/tool/cargo` workspace.
86+
let cargo_package = cargo_packages.into_iter().find(|pkg| pkg.name == "cargo").into_iter();
87+
packages.into_iter().chain(cargo_package)
88+
}

0 commit comments

Comments
 (0)