From 1863aa284773a20854971560bccc7902232b60e7 Mon Sep 17 00:00:00 2001 From: Geoffry Song Date: Sat, 22 Jun 2019 13:48:52 -0700 Subject: [PATCH 1/2] Fix exponentiality in depend_on_deps_of_deps. --- src/cargo/core/compiler/job_queue.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/cargo/core/compiler/job_queue.rs b/src/cargo/core/compiler/job_queue.rs index 12a720b16c9..1b999be7f42 100644 --- a/src/cargo/core/compiler/job_queue.rs +++ b/src/cargo/core/compiler/job_queue.rs @@ -154,12 +154,12 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> { let dependencies = cx.dep_targets(unit); let mut queue_deps = dependencies .iter() + .cloned() .filter(|unit| { // Binaries aren't actually needed to *compile* tests, just to run // them, so we don't include this dependency edge in the job graph. !unit.target.is_test() || !unit.target.is_bin() }) - .cloned() .map(|dep| { // Handle the case here where our `unit -> dep` dependency may // only require the metadata, not the full compilation to @@ -172,7 +172,7 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> { }; (dep, artifact) }) - .collect::>(); + .collect::>(); // This is somewhat tricky, but we may need to synthesize some // dependencies for this target if it requires full upstream @@ -196,19 +196,18 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> { // `Metadata` propagate upwards `All` dependencies to anything that // transitively contains the `Metadata` edge. if unit.requires_upstream_objects() { - for dep in dependencies.iter() { + for dep in dependencies { depend_on_deps_of_deps(cx, &mut queue_deps, dep); } fn depend_on_deps_of_deps<'a>( cx: &Context<'a, '_>, - deps: &mut Vec<(Unit<'a>, Artifact)>, - unit: &Unit<'a>, + deps: &mut HashMap, Artifact>, + unit: Unit<'a>, ) { - for dep in cx.dep_targets(unit) { - if cx.only_requires_rmeta(unit, &dep) { - deps.push((dep, Artifact::All)); - depend_on_deps_of_deps(cx, deps, &dep); + for dep in cx.dep_targets(&unit) { + if deps.insert(dep, Artifact::All).is_none() { + depend_on_deps_of_deps(cx, deps, dep); } } } From 15e08029f1b333c3e726f49a8d871d4552f6990c Mon Sep 17 00:00:00 2001 From: Geoffry Song Date: Mon, 24 Jun 2019 13:18:24 -0700 Subject: [PATCH 2/2] Add a test for build pipelining with a complex build graph. --- tests/testsuite/build.rs | 61 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/tests/testsuite/build.rs b/tests/testsuite/build.rs index 4ffcaf70bff..e1fae224237 100644 --- a/tests/testsuite/build.rs +++ b/tests/testsuite/build.rs @@ -4583,6 +4583,67 @@ fn pipelining_works() { .run(); } +#[cargo_test] +fn pipelining_big_graph() { + if !crate::support::is_nightly() { + return; + } + + // Create a crate graph of the form {a,b}{0..19}, where {a,b}(n) depend on {a,b}(n+1) + // Then have `foo`, a binary crate, depend on the whole thing. + let mut project = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + [dependencies] + a1 = { path = "a1" } + b1 = { path = "b1" } + "#, + ) + .file("src/main.rs", "fn main(){}"); + + for n in 0..30 { + for x in &["a", "b"] { + project = project + .file( + &format!("{x}{n}/Cargo.toml", x = x, n = n), + &format!( + r#" + [package] + name = "{x}{n}" + version = "0.1.0" + [dependencies] + a{np1} = {{ path = "../a{np1}" }} + b{np1} = {{ path = "../b{np1}" }} + "#, + x = x, + n = n, + np1 = n + 1 + ), + ) + .file(&format!("{x}{n}/src/lib.rs", x = x, n = n), ""); + } + } + + let foo = project + .file("a30/Cargo.toml", &basic_lib_manifest("a30")) + .file( + "a30/src/lib.rs", + r#"compile_error!("don't actually build me");"#, + ) + .file("b30/Cargo.toml", &basic_lib_manifest("b30")) + .file("b30/src/lib.rs", "") + .build(); + foo.cargo("build -p foo") + .env("CARGO_BUILD_PIPELINING", "true") + .with_status(101) + .with_stderr_contains("[ERROR] Could not compile `a30`[..]") + .run(); +} + #[cargo_test] fn forward_rustc_output() { let foo = project()