Skip to content

Commit 147e2da

Browse files
committed
rustbuild: Use cargo metadata to learn about DAG
This updates the commit to use workspaces to use `cargo metadata` instead of hardcoded lists about what to test. This should help us be resilient to updates in the future on behalf of the crate DAG and minimize the amount of files that need to be touched.
1 parent 9ca382f commit 147e2da

File tree

2 files changed

+91
-74
lines changed

2 files changed

+91
-74
lines changed

src/Cargo.lock

+21-13
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/bootstrap/check.rs

+70-61
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,44 @@
1313
//! This file implements the various regression test suites that we execute on
1414
//! our CI.
1515
16+
use std::collections::{HashMap, HashSet};
1617
use std::env;
17-
use std::fs::{self, File};
18-
use std::io::prelude::*;
18+
use std::fs;
1919
use std::path::{PathBuf, Path};
2020
use std::process::Command;
2121

2222
use build_helper::output;
23+
use rustc_serialize::json;
2324

2425
use {Build, Compiler, Mode};
2526
use util::{self, dylib_path, dylib_path_var};
2627

2728
const ADB_TEST_DIR: &'static str = "/data/tmp";
2829

30+
#[derive(RustcDecodable)]
31+
struct Output {
32+
packages: Vec<Package>,
33+
resolve: Resolve,
34+
}
35+
36+
#[derive(RustcDecodable)]
37+
struct Package {
38+
id: String,
39+
name: String,
40+
source: Option<String>,
41+
}
42+
43+
#[derive(RustcDecodable)]
44+
struct Resolve {
45+
nodes: Vec<ResolveNode>,
46+
}
47+
48+
#[derive(RustcDecodable)]
49+
struct ResolveNode {
50+
id: String,
51+
dependencies: Vec<String>,
52+
}
53+
2954
/// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler.
3055
///
3156
/// This tool in `src/tools` will verify the validity of all our links in the
@@ -263,90 +288,74 @@ fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) {
263288
/// It essentially is the driver for running `cargo test`.
264289
///
265290
/// Currently this runs all tests for a DAG by passing a bunch of `-p foo`
266-
/// arguments, and those arguments are discovered from `Cargo.lock`.
291+
/// arguments, and those arguments are discovered from `cargo metadata`.
267292
pub fn krate(build: &Build,
268293
compiler: &Compiler,
269294
target: &str,
270295
mode: Mode) {
271-
let (name, path, features, excluded) = match mode {
296+
let (name, path, features, root) = match mode {
272297
Mode::Libstd => {
273-
let excluded = vec![
274-
"alloc_jemalloc", "arena", "bootstrap", "cargotest", "compiletest",
275-
"error_index_generator", "flate", "fmt_macros", "getopts", "graphviz",
276-
"linkchecker", "log", "proc_macro", "rbml", "rustbook", "rustc", "rustc-main",
277-
"rustc_back", "rustc_bitflags", "rustc_borrowck", "rustc_const_eval",
278-
"rustc_const_math", "rustc_data_structures", "rustc_driver", "rustc_errors",
279-
"rustc_incremental", "rustc_lint", "rustc_llvm", "rustc_metadata", "rustc_mir",
280-
"rustc_passes", "rustc_platform_intrinsics", "rustc_plugin", "rustc_privacy",
281-
"rustc_resolve", "rustc_save_analysis", "rustc_trans", "rustc_typeck", "rustdoc",
282-
"serialize", "syntax", "syntax_ext", "syntax_pos", "term", "test", "test_shim",
283-
"tidy", "unwind",
284-
];
285-
("libstd", "src/rustc/std_shim", build.std_features(), excluded)
298+
("libstd", "src/rustc/std_shim", build.std_features(), "std_shim")
286299
}
287300
Mode::Libtest => {
288-
let excluded = vec![
289-
"alloc", "alloc_jemalloc", "alloc_system", "arena", "bootstrap", "build_helper",
290-
"cargotest", "collections", "compiletest", "core", "error_index_generator",
291-
"flate", "fmt_macros", "graphviz", "libc", "linkchecker", "log", "panic_abort",
292-
"panic_unwind", "proc_macro", "rand", "rbml", "rustbook", "rustc", "rustc-main",
293-
"rustc_back", "rustc_bitflags", "rustc_borrowck", "rustc_const_eval",
294-
"rustc_const_math", "rustc_data_structures", "rustc_driver", "rustc_errors",
295-
"rustc_incremental", "rustc_lint", "rustc_llvm", "rustc_metadata", "rustc_mir",
296-
"rustc_passes", "rustc_platform_intrinsics", "rustc_plugin", "rustc_privacy",
297-
"rustc_resolve", "rustc_save_analysis", "rustc_trans", "rustc_typeck",
298-
"rustc_unicode", "rustdoc", "serialize", "std", "std_shim", "syntax", "syntax_ext",
299-
"syntax_pos", "tidy", "unwind",
300-
];
301-
("libtest", "src/rustc/test_shim", String::new(), excluded)
301+
("libtest", "src/rustc/test_shim", String::new(), "test_shim")
302302
}
303303
Mode::Librustc => {
304-
let excluded = vec![
305-
"alloc", "alloc_jemalloc", "alloc_system", "bootstrap", "cargotest", "collections",
306-
"compiletest", "core", "error_index_generator", "getopts", "libc", "linkchecker",
307-
"panic_abort", "panic_unwind", "rand", "rustbook", "rustc_unicode", "std",
308-
"std_shim", "term", "test", "test_shim", "tidy", "unwind",
309-
];
310-
("librustc", "src/rustc", build.rustc_features(), excluded)
304+
("librustc", "src/rustc", build.rustc_features(), "rustc-main")
311305
}
312306
_ => panic!("can only test libraries"),
313307
};
314308
println!("Testing {} stage{} ({} -> {})", name, compiler.stage,
315309
compiler.host, target);
316310

311+
// Run `cargo metadata` to figure out what crates we're testing.
312+
//
313+
// Down below we're going to call `cargo test`, but to test the right set
314+
// of packages we're going to have to know what `-p` arguments to pass it
315+
// to know what crates to test. Here we run `cargo metadata` to learn about
316+
// the dependency graph and what `-p` arguments there are.
317+
let mut cargo = Command::new(&build.cargo);
318+
cargo.arg("metadata")
319+
.arg("--manifest-path").arg(build.src.join(path).join("Cargo.toml"));
320+
let output = output(&mut cargo);
321+
let output: Output = json::decode(&output).unwrap();
322+
let id2pkg = output.packages.iter()
323+
.map(|pkg| (&pkg.id, pkg))
324+
.collect::<HashMap<_, _>>();
325+
let id2deps = output.resolve.nodes.iter()
326+
.map(|node| (&node.id, &node.dependencies))
327+
.collect::<HashMap<_, _>>();
328+
317329
// Build up the base `cargo test` command.
330+
//
331+
// Pass in some standard flags then iterate over the graph we've discovered
332+
// in `cargo metadata` with the maps above and figure out what `-p`
333+
// arguments need to get passed.
318334
let mut cargo = build.cargo(compiler, mode, target, "test");
319335
cargo.arg("--manifest-path")
320336
.arg(build.src.join(path).join("Cargo.toml"))
321337
.arg("--features").arg(features);
322338

323-
// Generate a list of `-p` arguments to pass to the `cargo test` invocation
324-
// by crawling the corresponding Cargo.lock file.
325-
let lockfile = build.src.join("src").join("Cargo.lock");
326-
let mut contents = String::new();
327-
t!(t!(File::open(&lockfile)).read_to_string(&mut contents));
328-
let mut lines = contents.lines();
329-
while let Some(line) = lines.next() {
330-
let prefix = "name = \"";
331-
if !line.starts_with(prefix) {
339+
let mut visited = HashSet::new();
340+
let root_pkg = output.packages.iter().find(|p| p.name == root).unwrap();
341+
let mut next = vec![&root_pkg.id];
342+
while let Some(id) = next.pop() {
343+
// Skip any packages with sources listed, as these come from crates.io
344+
// and we shouldn't be testing them.
345+
if id2pkg[id].source.is_some() {
332346
continue
333347
}
334-
lines.next(); // skip `version = ...`
335-
336-
// skip crates.io or otherwise non-path crates
337-
if let Some(line) = lines.next() {
338-
if line.starts_with("source") {
339-
continue
340-
}
348+
// Right now jemalloc is our only target-specific crate in the sense
349+
// that it's not present on all platforms. Custom skip it here for now,
350+
// but if we add more this probably wants to get more generalized.
351+
if !id.contains("jemalloc") {
352+
cargo.arg("-p").arg(&id2pkg[id].name);
341353
}
342-
343-
let crate_name = &line[prefix.len()..line.len() - 1];
344-
345-
if excluded.contains(&crate_name) {
346-
continue
354+
for dep in id2deps[id] {
355+
if visited.insert(dep) {
356+
next.push(dep);
357+
}
347358
}
348-
349-
cargo.arg("-p").arg(crate_name);
350359
}
351360

352361
// The tests are going to run with the *target* libraries, so we need to

0 commit comments

Comments
 (0)