1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Definition of steps of the build system.
13 //! This is where some of the real meat of rustbuild is located, in how we
14 //! define targets and the dependencies amongst them. This file can sort of be
15 //! viewed as just defining targets in a makefile which shell out to predefined
16 //! functions elsewhere about how to execute the target.
18 //! The primary function here you're likely interested in is the `build_rules`
19 //! function. This will create a `Rules` structure which basically just lists
20 //! everything that rustbuild can do. Each rule has a human-readable name, a
21 //! path associated with it, some dependencies, and then a closure of how to
22 //! actually perform the rule.
24 //! All steps below are defined in self-contained units, so adding a new target
25 //! to the build system should just involve adding the meta information here
26 //! along with the actual implementation elsewhere. You can find more comments
27 //! about how to define rules themselves below.
29 use std::collections::{HashMap, HashSet};
32 use check::{self, TestKind};
36 use flags::Subcommand;
39 use {Compiler, Build, Mode};
41 pub fn run(build: &Build) {
42 let rules = build_rules(build);
43 let steps = rules.plan();
47 pub fn build_rules<'a>(build: &'a Build) -> Rules {
48 let mut rules = Rules::new(build);
50 // This is the first rule that we're going to define for rustbuild, which is
51 // used to compile LLVM itself. All rules are added through the `rules`
52 // structure created above and are configured through a builder-style
55 // First up we see the `build` method. This represents a rule that's part of
56 // the top-level `build` subcommand. For example `./x.py build` is what this
57 // is associating with. Note that this is normally only relevant if you flag
58 // a rule as `default`, which we'll talk about later.
60 // Next up we'll see two arguments to this method:
62 // * `llvm` - this is the "human readable" name of this target. This name is
63 // not accessed anywhere outside this file itself (e.g. not in
64 // the CLI nor elsewhere in rustbuild). The purpose of this is to
65 // easily define dependencies between rules. That is, other rules
66 // will depend on this with the name "llvm".
67 // * `src/llvm` - this is the relevant path to the rule that we're working
68 // with. This path is the engine behind how commands like
69 // `./x.py build src/llvm` work. This should typically point
70 // to the relevant component, but if there's not really a
71 // path to be assigned here you can pass something like
72 // `path/to/nowhere` to ignore it.
74 // After we create the rule with the `build` method we can then configure
75 // various aspects of it. For example this LLVM rule uses `.host(true)` to
76 // flag that it's a rule only for host targets. In other words, LLVM isn't
77 // compiled for targets configured through `--target` (e.g. those we're just
78 // building a standard library for).
80 // Next up the `dep` method will add a dependency to this rule. The closure
81 // is yielded the step that represents executing the `llvm` rule itself
82 // (containing information like stage, host, target, ...) and then it must
83 // return a target that the step depends on. Here LLVM is actually
84 // interesting where a cross-compiled LLVM depends on the host LLVM, but
85 // otherwise it has no dependencies.
87 // To handle this we do a bit of dynamic dispatch to see what the dependency
88 // is. If we're building a LLVM for the build triple, then we don't actually
89 // have any dependencies! To do that we return a dependency on the `Step::noop()`
90 // target which does nothing.
92 // If we're build a cross-compiled LLVM, however, we need to assemble the
93 // libraries from the previous compiler. This step has the same name as
94 // ours (llvm) but we want it for a different target, so we use the
95 // builder-style methods on `Step` to configure this target to the build
98 // Finally, to finish off this rule, we define how to actually execute it.
99 // That logic is all defined in the `native` module so we just delegate to
100 // the relevant function there. The argument to the closure passed to `run`
101 // is a `Step` (defined below) which encapsulates information like the
102 // stage, target, host, etc.
103 rules.build("llvm", "src/llvm")
106 if s.target == build.config.build {
109 s.target(&build.config.build)
112 .run(move |s| native::llvm(build, s.target));
114 // Ok! After that example rule that's hopefully enough to explain what's
115 // going on here. You can check out the API docs below and also see a bunch
116 // more examples of rules directly below as well.
118 // the compiler with no target libraries ready to go
119 rules.build("rustc", "src/rustc")
120 .dep(|s| s.name("create-sysroot").target(s.host))
126 .host(&build.config.build)
130 .run(move |s| compile::assemble_rustc(build, s.stage, s.target));
132 // Helper for loading an entire DAG of crates, rooted at `name`
133 let krates = |name: &str| {
134 let mut ret = Vec::new();
135 let mut list = vec![name];
136 let mut visited = HashSet::new();
137 while let Some(krate) = list.pop() {
138 let default = krate == name;
139 let krate = &build.crates[krate];
140 let path = krate.path.strip_prefix(&build.src).unwrap();
141 ret.push((krate, path.to_str().unwrap(), default));
142 for dep in krate.deps.iter() {
143 if visited.insert(dep) && dep != "build_helper" {
151 // ========================================================================
152 // Crate compilations
154 // Tools used during the build system but not shipped
155 rules.build("create-sysroot", "path/to/nowhere")
156 .run(move |s| compile::create_sysroot(build, &s.compiler()));
158 // These rules are "pseudo rules" that don't actually do any work
159 // themselves, but represent a complete sysroot with the relevant compiler
160 // linked into place.
162 // That is, depending on "libstd" means that when the rule is completed then
163 // the `stage` sysroot for the compiler `host` will be available with a
164 // standard library built for `target` linked in place. Not all rules need
165 // the compiler itself to be available, just the standard library, so
166 // there's a distinction between the two.
167 rules.build("libstd", "src/libstd")
168 .dep(|s| s.name("rustc").target(s.host))
169 .dep(|s| s.name("libstd-link"));
170 rules.build("libtest", "src/libtest")
171 .dep(|s| s.name("libstd"))
172 .dep(|s| s.name("libtest-link"))
174 rules.build("librustc", "src/librustc")
175 .dep(|s| s.name("libtest"))
176 .dep(|s| s.name("librustc-link"))
180 // Helper method to define the rules to link a crate into its place in the
183 // The logic here is a little subtle as there's a few cases to consider.
184 // Not all combinations of (stage, host, target) actually require something
185 // to be compiled, but rather libraries could get propagated from a
186 // different location. For example:
188 // * Any crate with a `host` that's not the build triple will not actually
189 // compile something. A different `host` means that the build triple will
190 // actually compile the libraries, and then we'll copy them over from the
191 // build triple to the `host` directory.
193 // * Some crates aren't even compiled by the build triple, but may be copied
194 // from previous stages. For example if we're not doing a full bootstrap
195 // then we may just depend on the stage1 versions of libraries to be
196 // available to get linked forward.
198 // * Finally, there are some cases, however, which do indeed comiple crates
199 // and link them into place afterwards.
201 // The rule definition below mirrors these three cases. The `dep` method
202 // calculates the correct dependency which either comes from stage1, a
203 // different compiler, or from actually building the crate itself (the `dep`
204 // rule). The `run` rule then mirrors these three cases and links the cases
205 // forward into the compiler sysroot specified from the correct location.
206 fn crate_rule<'a, 'b>(build: &'a Build,
207 rules: &'b mut Rules<'a>,
210 link: fn(&Build, &Compiler, &Compiler, &str))
211 -> RuleBuilder<'a, 'b> {
212 let mut rule = rules.build(&krate, "path/to/nowhere");
214 if build.force_use_stage1(&s.compiler(), s.target) {
215 s.host(&build.config.build).stage(1)
216 } else if s.host == build.config.build {
219 s.host(&build.config.build)
223 if build.force_use_stage1(&s.compiler(), s.target) {
225 &s.stage(1).host(&build.config.build).compiler(),
228 } else if s.host == build.config.build {
229 link(build, &s.compiler(), &s.compiler(), s.target)
232 &s.host(&build.config.build).compiler(),
240 // Similar to the `libstd`, `libtest`, and `librustc` rules above, except
241 // these rules only represent the libraries being available in the sysroot,
242 // not the compiler itself. This is done as not all rules need a compiler in
243 // the sysroot, but may just need the libraries.
245 // All of these rules use the helper definition above.
249 "build-crate-std_shim",
251 .dep(|s| s.name("startup-objects"))
252 .dep(|s| s.name("create-sysroot").target(s.host));
256 "build-crate-test_shim",
258 .dep(|s| s.name("libstd-link"));
262 "build-crate-rustc-main",
264 .dep(|s| s.name("libtest-link"));
266 for (krate, path, _default) in krates("std_shim") {
267 rules.build(&krate.build_step, path)
268 .dep(|s| s.name("startup-objects"))
269 .dep(move |s| s.name("rustc").host(&build.config.build).target(s.host))
270 .run(move |s| compile::std(build, s.target, &s.compiler()));
272 for (krate, path, _default) in krates("test_shim") {
273 rules.build(&krate.build_step, path)
274 .dep(|s| s.name("libstd-link"))
275 .run(move |s| compile::test(build, s.target, &s.compiler()));
277 for (krate, path, _default) in krates("rustc-main") {
278 rules.build(&krate.build_step, path)
279 .dep(|s| s.name("libtest-link"))
280 .dep(move |s| s.name("llvm").host(&build.config.build).stage(0))
281 .run(move |s| compile::rustc(build, s.target, &s.compiler()));
284 rules.build("startup-objects", "src/rtstartup")
285 .dep(|s| s.name("create-sysroot").target(s.host))
286 .run(move |s| compile::build_startup_objects(build, &s.compiler(), s.target));
288 // ========================================================================
291 // Various unit tests and tests suites we can run
293 let mut suite = |name, path, mode, dir| {
294 rules.test(name, path)
295 .dep(|s| s.name("libtest"))
296 .dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
297 .dep(|s| s.name("test-helpers"))
298 .dep(|s| s.name("emulator-copy-libs"))
299 .default(mode != "pretty") // pretty tests don't run everywhere
301 check::compiletest(build, &s.compiler(), s.target, mode, dir)
305 suite("check-rpass", "src/test/run-pass", "run-pass", "run-pass");
306 suite("check-cfail", "src/test/compile-fail", "compile-fail", "compile-fail");
307 suite("check-pfail", "src/test/parse-fail", "parse-fail", "parse-fail");
308 suite("check-rfail", "src/test/run-fail", "run-fail", "run-fail");
309 suite("check-rpass-valgrind", "src/test/run-pass-valgrind",
310 "run-pass-valgrind", "run-pass-valgrind");
311 suite("check-mir-opt", "src/test/mir-opt", "mir-opt", "mir-opt");
312 if build.config.codegen_tests {
313 suite("check-codegen", "src/test/codegen", "codegen", "codegen");
315 suite("check-codegen-units", "src/test/codegen-units", "codegen-units",
317 suite("check-incremental", "src/test/incremental", "incremental",
321 if build.config.build.contains("msvc") {
322 // nothing to do for debuginfo tests
324 rules.test("check-debuginfo-lldb", "src/test/debuginfo-lldb")
325 .dep(|s| s.name("libtest"))
326 .dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
327 .dep(|s| s.name("test-helpers"))
328 .dep(|s| s.name("debugger-scripts"))
329 .run(move |s| check::compiletest(build, &s.compiler(), s.target,
330 "debuginfo-lldb", "debuginfo"));
331 rules.test("check-debuginfo-gdb", "src/test/debuginfo-gdb")
332 .dep(|s| s.name("libtest"))
333 .dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
334 .dep(|s| s.name("test-helpers"))
335 .dep(|s| s.name("debugger-scripts"))
336 .dep(|s| s.name("emulator-copy-libs"))
337 .run(move |s| check::compiletest(build, &s.compiler(), s.target,
338 "debuginfo-gdb", "debuginfo"));
339 let mut rule = rules.test("check-debuginfo", "src/test/debuginfo");
341 if build.config.build.contains("apple") {
342 rule.dep(|s| s.name("check-debuginfo-lldb"));
344 rule.dep(|s| s.name("check-debuginfo-gdb"));
348 rules.test("debugger-scripts", "src/etc/lldb_batchmode.py")
349 .run(move |s| dist::debugger_scripts(build, &build.sysroot(&s.compiler()),
353 let mut suite = |name, path, mode, dir| {
354 rules.test(name, path)
355 .dep(|s| s.name("librustc"))
356 .dep(|s| s.name("test-helpers"))
357 .dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
358 .default(mode != "pretty")
361 check::compiletest(build, &s.compiler(), s.target, mode, dir)
365 suite("check-ui", "src/test/ui", "ui", "ui");
366 suite("check-rpass-full", "src/test/run-pass-fulldeps",
367 "run-pass", "run-pass-fulldeps");
368 suite("check-rfail-full", "src/test/run-fail-fulldeps",
369 "run-fail", "run-fail-fulldeps");
370 suite("check-cfail-full", "src/test/compile-fail-fulldeps",
371 "compile-fail", "compile-fail-fulldeps");
372 suite("check-rmake", "src/test/run-make", "run-make", "run-make");
373 suite("check-rustdoc", "src/test/rustdoc", "rustdoc", "rustdoc");
374 suite("check-pretty", "src/test/pretty", "pretty", "pretty");
375 suite("check-pretty-rpass", "src/test/run-pass/pretty", "pretty",
377 suite("check-pretty-rfail", "src/test/run-fail/pretty", "pretty",
379 suite("check-pretty-valgrind", "src/test/run-pass-valgrind/pretty", "pretty",
380 "run-pass-valgrind");
381 suite("check-pretty-rpass-full", "src/test/run-pass-fulldeps/pretty",
382 "pretty", "run-pass-fulldeps");
383 suite("check-pretty-rfail-full", "src/test/run-fail-fulldeps/pretty",
384 "pretty", "run-fail-fulldeps");
387 for (krate, path, _default) in krates("std_shim") {
388 rules.test(&krate.test_step, path)
389 .dep(|s| s.name("libtest"))
390 .dep(|s| s.name("emulator-copy-libs"))
391 .run(move |s| check::krate(build, &s.compiler(), s.target,
392 Mode::Libstd, TestKind::Test,
395 rules.test("check-std-all", "path/to/nowhere")
396 .dep(|s| s.name("libtest"))
397 .dep(|s| s.name("emulator-copy-libs"))
399 .run(move |s| check::krate(build, &s.compiler(), s.target,
400 Mode::Libstd, TestKind::Test, None));
403 for (krate, path, _default) in krates("std_shim") {
404 rules.bench(&krate.bench_step, path)
405 .dep(|s| s.name("libtest"))
406 .dep(|s| s.name("emulator-copy-libs"))
407 .run(move |s| check::krate(build, &s.compiler(), s.target,
408 Mode::Libstd, TestKind::Bench,
411 rules.bench("bench-std-all", "path/to/nowhere")
412 .dep(|s| s.name("libtest"))
413 .dep(|s| s.name("emulator-copy-libs"))
415 .run(move |s| check::krate(build, &s.compiler(), s.target,
416 Mode::Libstd, TestKind::Bench, None));
418 for (krate, path, _default) in krates("test_shim") {
419 rules.test(&krate.test_step, path)
420 .dep(|s| s.name("libtest"))
421 .dep(|s| s.name("emulator-copy-libs"))
422 .run(move |s| check::krate(build, &s.compiler(), s.target,
423 Mode::Libtest, TestKind::Test,
426 rules.test("check-test-all", "path/to/nowhere")
427 .dep(|s| s.name("libtest"))
428 .dep(|s| s.name("emulator-copy-libs"))
430 .run(move |s| check::krate(build, &s.compiler(), s.target,
431 Mode::Libtest, TestKind::Test, None));
432 for (krate, path, _default) in krates("rustc-main") {
433 rules.test(&krate.test_step, path)
434 .dep(|s| s.name("librustc"))
435 .dep(|s| s.name("emulator-copy-libs"))
437 .run(move |s| check::krate(build, &s.compiler(), s.target,
438 Mode::Librustc, TestKind::Test,
441 rules.test("check-rustc-all", "path/to/nowhere")
442 .dep(|s| s.name("librustc"))
443 .dep(|s| s.name("emulator-copy-libs"))
446 .run(move |s| check::krate(build, &s.compiler(), s.target,
447 Mode::Librustc, TestKind::Test, None));
449 rules.test("check-linkchecker", "src/tools/linkchecker")
450 .dep(|s| s.name("tool-linkchecker").stage(0))
451 .dep(|s| s.name("default:doc"))
454 .run(move |s| check::linkcheck(build, s.target));
455 rules.test("check-cargotest", "src/tools/cargotest")
456 .dep(|s| s.name("tool-cargotest").stage(0))
457 .dep(|s| s.name("librustc"))
459 .run(move |s| check::cargotest(build, s.stage, s.target));
460 rules.test("check-tidy", "src/tools/tidy")
461 .dep(|s| s.name("tool-tidy").stage(0))
465 .run(move |s| check::tidy(build, s.target));
466 rules.test("check-error-index", "src/tools/error_index_generator")
467 .dep(|s| s.name("libstd"))
468 .dep(|s| s.name("tool-error-index").host(s.host).stage(0))
471 .run(move |s| check::error_index(build, &s.compiler()));
472 rules.test("check-docs", "src/doc")
473 .dep(|s| s.name("libtest"))
476 .run(move |s| check::docs(build, &s.compiler()));
477 rules.test("check-distcheck", "distcheck")
478 .dep(|s| s.name("dist-src"))
479 .run(move |_| check::distcheck(build));
482 rules.build("test-helpers", "src/rt/rust_test_helpers.c")
483 .run(move |s| native::test_helpers(build, s.target));
485 // Some test suites are run inside emulators, and most of our test binaries
486 // are linked dynamically which means we need to ship the standard library
487 // and such to the emulator ahead of time. This step represents this and is
488 // a dependency of all test suites.
490 // Most of the time this step is a noop (the `check::emulator_copy_libs`
491 // only does work if necessary). For some steps such as shipping data to
492 // QEMU we have to build our own tools so we've got conditional dependencies
493 // on those programs as well. Note that the QEMU client is built for the
494 // build target (us) and the server is built for the target.
495 rules.test("emulator-copy-libs", "path/to/nowhere")
496 .dep(|s| s.name("libtest"))
498 if build.qemu_rootfs(s.target).is_some() {
499 s.name("tool-qemu-test-client").target(s.host).stage(0)
505 if build.qemu_rootfs(s.target).is_some() {
506 s.name("tool-qemu-test-server")
511 .run(move |s| check::emulator_copy_libs(build, &s.compiler(), s.target));
513 rules.test("check-bootstrap", "src/bootstrap")
517 .run(move |_| check::bootstrap(build));
519 // ========================================================================
522 // Tools used during the build system but not shipped
523 rules.build("tool-rustbook", "src/tools/rustbook")
524 .dep(|s| s.name("librustc"))
525 .run(move |s| compile::tool(build, s.stage, s.target, "rustbook"));
526 rules.build("tool-error-index", "src/tools/error_index_generator")
527 .dep(|s| s.name("librustc"))
528 .run(move |s| compile::tool(build, s.stage, s.target, "error_index_generator"));
529 rules.build("tool-tidy", "src/tools/tidy")
530 .dep(|s| s.name("libstd"))
531 .run(move |s| compile::tool(build, s.stage, s.target, "tidy"));
532 rules.build("tool-linkchecker", "src/tools/linkchecker")
533 .dep(|s| s.name("libstd"))
534 .run(move |s| compile::tool(build, s.stage, s.target, "linkchecker"));
535 rules.build("tool-cargotest", "src/tools/cargotest")
536 .dep(|s| s.name("libstd"))
537 .run(move |s| compile::tool(build, s.stage, s.target, "cargotest"));
538 rules.build("tool-compiletest", "src/tools/compiletest")
539 .dep(|s| s.name("libtest"))
540 .run(move |s| compile::tool(build, s.stage, s.target, "compiletest"));
541 rules.build("tool-build-manifest", "src/tools/build-manifest")
542 .dep(|s| s.name("libstd"))
543 .run(move |s| compile::tool(build, s.stage, s.target, "build-manifest"));
544 rules.build("tool-qemu-test-server", "src/tools/qemu-test-server")
545 .dep(|s| s.name("libstd"))
546 .run(move |s| compile::tool(build, s.stage, s.target, "qemu-test-server"));
547 rules.build("tool-qemu-test-client", "src/tools/qemu-test-client")
548 .dep(|s| s.name("libstd"))
549 .run(move |s| compile::tool(build, s.stage, s.target, "qemu-test-client"));
551 // ========================================================================
552 // Documentation targets
553 rules.doc("doc-book", "src/doc/book")
555 s.name("tool-rustbook")
556 .host(&build.config.build)
557 .target(&build.config.build)
560 .default(build.config.docs)
561 .run(move |s| doc::rustbook(build, s.target, "book"));
562 rules.doc("doc-nomicon", "src/doc/nomicon")
564 s.name("tool-rustbook")
565 .host(&build.config.build)
566 .target(&build.config.build)
569 .default(build.config.docs)
570 .run(move |s| doc::rustbook(build, s.target, "nomicon"));
571 rules.doc("doc-standalone", "src/doc")
574 .host(&build.config.build)
575 .target(&build.config.build)
578 .default(build.config.docs)
579 .run(move |s| doc::standalone(build, s.target));
580 rules.doc("doc-error-index", "src/tools/error_index_generator")
581 .dep(move |s| s.name("tool-error-index").target(&build.config.build).stage(0))
582 .dep(move |s| s.name("librustc-link"))
583 .default(build.config.docs)
585 .run(move |s| doc::error_index(build, s.target));
586 for (krate, path, default) in krates("std_shim") {
587 rules.doc(&krate.doc_step, path)
588 .dep(|s| s.name("libstd-link"))
589 .default(default && build.config.docs)
590 .run(move |s| doc::std(build, s.stage, s.target));
592 for (krate, path, default) in krates("test_shim") {
593 rules.doc(&krate.doc_step, path)
594 .dep(|s| s.name("libtest-link"))
595 .default(default && build.config.compiler_docs)
596 .run(move |s| doc::test(build, s.stage, s.target));
598 for (krate, path, default) in krates("rustc-main") {
599 rules.doc(&krate.doc_step, path)
600 .dep(|s| s.name("librustc-link"))
602 .default(default && build.config.compiler_docs)
603 .run(move |s| doc::rustc(build, s.stage, s.target));
606 // ========================================================================
607 // Distribution targets
608 rules.dist("dist-rustc", "src/librustc")
609 .dep(move |s| s.name("rustc").host(&build.config.build))
611 .only_host_build(true)
613 .run(move |s| dist::rustc(build, s.stage, s.target));
614 rules.dist("dist-std", "src/libstd")
616 // We want to package up as many target libraries as possible
617 // for the `rust-std` package, so if this is a host target we
618 // depend on librustc and otherwise we just depend on libtest.
619 if build.config.host.iter().any(|t| t == s.target) {
620 s.name("librustc-link")
622 s.name("libtest-link")
626 .only_host_build(true)
627 .run(move |s| dist::std(build, &s.compiler(), s.target));
628 rules.dist("dist-mingw", "path/to/nowhere")
630 .only_host_build(true)
632 if s.target.contains("pc-windows-gnu") {
633 dist::mingw(build, s.target)
636 rules.dist("dist-src", "src")
640 .only_host_build(true)
641 .run(move |_| dist::rust_src(build));
642 rules.dist("dist-docs", "src/doc")
644 .only_host_build(true)
645 .dep(|s| s.name("default:doc"))
646 .run(move |s| dist::docs(build, s.stage, s.target));
647 rules.dist("dist-analysis", "analysis")
648 .dep(|s| s.name("dist-std"))
650 .only_host_build(true)
651 .run(move |s| dist::analysis(build, &s.compiler(), s.target));
652 rules.dist("install", "path/to/nowhere")
653 .dep(|s| s.name("default:dist"))
654 .run(move |s| install::install(build, s.stage, s.target));
655 rules.dist("dist-cargo", "cargo")
657 .only_host_build(true)
658 .run(move |s| dist::cargo(build, s.stage, s.target));
659 rules.dist("dist-extended", "extended")
660 .default(build.config.extended)
662 .only_host_build(true)
663 .dep(|d| d.name("dist-std"))
664 .dep(|d| d.name("dist-rustc"))
665 .dep(|d| d.name("dist-mingw"))
666 .dep(|d| d.name("dist-docs"))
667 .dep(|d| d.name("dist-cargo"))
668 .run(move |s| dist::extended(build, s.stage, s.target));
670 rules.dist("dist-sign", "hash-and-sign")
673 .only_host_build(true)
674 .dep(move |s| s.name("tool-build-manifest").target(&build.config.build).stage(0))
675 .run(move |_| dist::hash_and_sign(build));
681 #[derive(PartialEq, Eq, Hash, Clone, Debug)]
683 /// Human readable name of the rule this step is executing. Possible names
684 /// are all defined above in `build_rules`.
687 /// The stage this step is executing in. This is typically 0, 1, or 2.
690 /// This step will likely involve a compiler, and the target that compiler
691 /// itself is built for is called the host, this variable. Typically this is
692 /// the target of the build machine itself.
695 /// The target that this step represents generating. If you're building a
696 /// standard library for a new suite of targets, for example, this'll be set
697 /// to those targets.
702 fn noop() -> Step<'a> {
703 Step { name: "", stage: 0, host: "", target: "" }
706 /// Creates a new step which is the same as this, except has a new name.
707 fn name(&self, name: &'a str) -> Step<'a> {
708 Step { name: name, ..*self }
711 /// Creates a new step which is the same as this, except has a new stage.
712 fn stage(&self, stage: u32) -> Step<'a> {
713 Step { stage: stage, ..*self }
716 /// Creates a new step which is the same as this, except has a new host.
717 fn host(&self, host: &'a str) -> Step<'a> {
718 Step { host: host, ..*self }
721 /// Creates a new step which is the same as this, except has a new target.
722 fn target(&self, target: &'a str) -> Step<'a> {
723 Step { target: target, ..*self }
726 /// Returns the `Compiler` structure that this step corresponds to.
727 fn compiler(&self) -> Compiler<'a> {
728 Compiler::new(self.stage, self.host)
733 /// The human readable name of this target, defined in `build_rules`.
736 /// The path associated with this target, used in the `./x.py` driver for
737 /// easy and ergonomic specification of what to do.
740 /// The "kind" of top-level command that this rule is associated with, only
741 /// relevant if this is a default rule.
744 /// List of dependencies this rule has. Each dependency is a function from a
745 /// step that's being executed to another step that should be executed.
746 deps: Vec<Box<Fn(&Step<'a>) -> Step<'a> + 'a>>,
748 /// How to actually execute this rule. Takes a step with contextual
749 /// information and then executes it.
750 run: Box<Fn(&Step<'a>) + 'a>,
752 /// Whether or not this is a "default" rule. That basically means that if
753 /// you run, for example, `./x.py test` whether it's included or not.
756 /// Whether or not this is a "host" rule, or in other words whether this is
757 /// only intended for compiler hosts and not for targets that are being
761 /// Whether this rule is only for steps where the host is the build triple,
762 /// not anything in hosts or targets.
763 only_host_build: bool,
765 /// Whether this rule is only for the build triple, not anything in hosts or
780 fn new(name: &'a str, path: &'a str, kind: Kind) -> Rule<'a> {
784 run: Box::new(|_| ()),
789 only_host_build: false,
795 /// Builder pattern returned from the various methods on `Rules` which will add
796 /// the rule to the internal list on `Drop`.
797 struct RuleBuilder<'a: 'b, 'b> {
798 rules: &'b mut Rules<'a>,
802 impl<'a, 'b> RuleBuilder<'a, 'b> {
803 fn dep<F>(&mut self, f: F) -> &mut Self
804 where F: Fn(&Step<'a>) -> Step<'a> + 'a,
806 self.rule.deps.push(Box::new(f));
810 fn run<F>(&mut self, f: F) -> &mut Self
811 where F: Fn(&Step<'a>) + 'a,
813 self.rule.run = Box::new(f);
817 fn default(&mut self, default: bool) -> &mut Self {
818 self.rule.default = default;
822 fn host(&mut self, host: bool) -> &mut Self {
823 self.rule.host = host;
827 fn only_build(&mut self, only_build: bool) -> &mut Self {
828 self.rule.only_build = only_build;
832 fn only_host_build(&mut self, only_host_build: bool) -> &mut Self {
833 self.rule.only_host_build = only_host_build;
838 impl<'a, 'b> Drop for RuleBuilder<'a, 'b> {
840 let rule = mem::replace(&mut self.rule, Rule::new("", "", Kind::Build));
841 let prev = self.rules.rules.insert(rule.name, rule);
842 if let Some(prev) = prev {
843 panic!("duplicate rule named: {}", prev.name);
848 pub struct Rules<'a> {
851 rules: HashMap<&'a str, Rule<'a>>,
855 fn new(build: &'a Build) -> Rules<'a> {
859 stage: build.flags.stage.unwrap_or(2),
860 target: &build.config.build,
861 host: &build.config.build,
864 rules: HashMap::new(),
868 /// Creates a new rule of `Kind::Build` with the specified human readable
869 /// name and path associated with it.
871 /// The builder returned should be configured further with information such
872 /// as how to actually run this rule.
873 fn build<'b>(&'b mut self, name: &'a str, path: &'a str)
874 -> RuleBuilder<'a, 'b> {
875 self.rule(name, path, Kind::Build)
878 /// Same as `build`, but for `Kind::Test`.
879 fn test<'b>(&'b mut self, name: &'a str, path: &'a str)
880 -> RuleBuilder<'a, 'b> {
881 self.rule(name, path, Kind::Test)
884 /// Same as `build`, but for `Kind::Bench`.
885 fn bench<'b>(&'b mut self, name: &'a str, path: &'a str)
886 -> RuleBuilder<'a, 'b> {
887 self.rule(name, path, Kind::Bench)
890 /// Same as `build`, but for `Kind::Doc`.
891 fn doc<'b>(&'b mut self, name: &'a str, path: &'a str)
892 -> RuleBuilder<'a, 'b> {
893 self.rule(name, path, Kind::Doc)
896 /// Same as `build`, but for `Kind::Dist`.
897 fn dist<'b>(&'b mut self, name: &'a str, path: &'a str)
898 -> RuleBuilder<'a, 'b> {
899 self.rule(name, path, Kind::Dist)
902 fn rule<'b>(&'b mut self,
905 kind: Kind) -> RuleBuilder<'a, 'b> {
908 rule: Rule::new(name, path, kind),
912 /// Verify the dependency graph defined by all our rules are correct, e.g.
913 /// everything points to a valid something else.
915 for rule in self.rules.values() {
916 for dep in rule.deps.iter() {
917 let dep = dep(&self.sbuild.name(rule.name));
918 if self.rules.contains_key(&dep.name) || dep.name.starts_with("default:") {
921 if dep == Step::noop() {
926 invalid rule dependency graph detected, was a rule added and maybe typo'd?
928 `{}` depends on `{}` which does not exist
930 ", rule.name, dep.name);
935 pub fn print_help(&self, command: &str) {
936 let kind = match command {
937 "build" => Kind::Build,
939 "test" => Kind::Test,
940 "bench" => Kind::Bench,
941 "dist" => Kind::Dist,
944 let rules = self.rules.values().filter(|r| r.kind == kind);
945 let rules = rules.filter(|r| !r.path.contains("nowhere"));
946 let mut rules = rules.collect::<Vec<_>>();
947 rules.sort_by_key(|r| r.path);
949 println!("Available paths:\n");
951 print!(" ./x.py {} {}", command, rule.path);
957 /// Construct the top-level build steps that we're going to be executing,
958 /// given the subcommand that our build is performing.
959 fn plan(&self) -> Vec<Step<'a>> {
960 // Ok, the logic here is pretty subtle, and involves quite a few
961 // conditionals. The basic idea here is to:
963 // 1. First, filter all our rules to the relevant ones. This means that
964 // the command specified corresponds to one of our `Kind` variants,
965 // and we filter all rules based on that.
967 // 2. Next, we determine which rules we're actually executing. If a
968 // number of path filters were specified on the command line we look
969 // for those, otherwise we look for anything tagged `default`.
971 // 3. Finally, we generate some steps with host and target information.
973 // The last step is by far the most complicated and subtle. The basic
974 // thinking here is that we want to take the cartesian product of
975 // specified hosts and targets and build rules with that. The list of
976 // hosts and targets, if not specified, come from the how this build was
977 // configured. If the rule we're looking at is a host-only rule the we
978 // ignore the list of targets and instead consider the list of hosts
979 // also the list of targets.
981 // Once the host and target lists are generated we take the cartesian
982 // product of the two and then create a step based off them. Note that
983 // the stage each step is associated was specified with the `--step`
984 // flag on the command line.
985 let (kind, paths) = match self.build.flags.cmd {
986 Subcommand::Build { ref paths } => (Kind::Build, &paths[..]),
987 Subcommand::Doc { ref paths } => (Kind::Doc, &paths[..]),
988 Subcommand::Test { ref paths, test_args: _ } => (Kind::Test, &paths[..]),
989 Subcommand::Bench { ref paths, test_args: _ } => (Kind::Bench, &paths[..]),
990 Subcommand::Dist { ref paths, install } => {
992 return vec![self.sbuild.name("install")]
994 (Kind::Dist, &paths[..])
997 Subcommand::Clean => panic!(),
1000 self.rules.values().filter(|rule| rule.kind == kind).filter(|rule| {
1001 (paths.len() == 0 && rule.default) || paths.iter().any(|path| {
1002 path.ends_with(rule.path)
1004 }).flat_map(|rule| {
1005 let hosts = if rule.only_host_build || rule.only_build {
1006 &self.build.config.host[..1]
1007 } else if self.build.flags.host.len() > 0 {
1008 &self.build.flags.host
1010 &self.build.config.host
1012 let targets = if self.build.flags.target.len() > 0 {
1013 &self.build.flags.target
1015 &self.build.config.target
1017 // Determine the actual targets participating in this rule.
1018 // NOTE: We should keep the full projection from build triple to
1019 // the hosts for the dist steps, now that the hosts array above is
1020 // truncated to avoid duplication of work in that case. Therefore
1021 // the original non-shadowed hosts array is used below.
1022 let arr = if rule.host {
1023 // If --target was specified but --host wasn't specified,
1024 // don't run any host-only tests. Also, respect any `--host`
1025 // overrides as done for `hosts`.
1026 if self.build.flags.host.len() > 0 {
1027 &self.build.flags.host[..]
1028 } else if self.build.flags.target.len() > 0 {
1030 } else if rule.only_build {
1031 &self.build.config.host[..1]
1033 &self.build.config.host[..]
1039 hosts.iter().flat_map(move |host| {
1040 arr.iter().map(move |target| {
1041 self.sbuild.name(rule.name).target(target).host(host)
1047 /// Execute all top-level targets indicated by `steps`.
1049 /// This will take the list returned by `plan` and then execute each step
1050 /// along with all required dependencies as it goes up the chain.
1051 fn run(&self, steps: &[Step<'a>]) {
1052 self.build.verbose("bootstrap top targets:");
1053 for step in steps.iter() {
1054 self.build.verbose(&format!("\t{:?}", step));
1057 // Using `steps` as the top-level targets, make a topological ordering
1058 // of what we need to do.
1059 let order = self.expand(steps);
1061 // Print out what we're doing for debugging
1062 self.build.verbose("bootstrap build plan:");
1063 for step in order.iter() {
1064 self.build.verbose(&format!("\t{:?}", step));
1067 // And finally, iterate over everything and execute it.
1068 for step in order.iter() {
1069 if self.build.flags.keep_stage.map_or(false, |s| step.stage <= s) {
1070 self.build.verbose(&format!("keeping step {:?}", step));
1073 self.build.verbose(&format!("executing step {:?}", step));
1074 (self.rules[step.name].run)(step);
1078 /// From the top level targets `steps` generate a topological ordering of
1079 /// all steps needed to run those steps.
1080 fn expand(&self, steps: &[Step<'a>]) -> Vec<Step<'a>> {
1081 let mut order = Vec::new();
1082 let mut added = HashSet::new();
1083 added.insert(Step::noop());
1084 for step in steps.iter().cloned() {
1085 self.fill(step, &mut order, &mut added);
1090 /// Performs topological sort of dependencies rooted at the `step`
1091 /// specified, pushing all results onto the `order` vector provided.
1093 /// In other words, when this method returns, the `order` vector will
1094 /// contain a list of steps which if executed in order will eventually
1095 /// complete the `step` specified as well.
1097 /// The `added` set specified here is the set of steps that are already
1098 /// present in `order` (and hence don't need to be added again).
1101 order: &mut Vec<Step<'a>>,
1102 added: &mut HashSet<Step<'a>>) {
1103 if !added.insert(step.clone()) {
1106 for dep in self.rules[step.name].deps.iter() {
1107 let dep = dep(&step);
1108 if dep.name.starts_with("default:") {
1109 let kind = match &dep.name[8..] {
1111 "dist" => Kind::Dist,
1112 kind => panic!("unknown kind: `{}`", kind),
1114 let host = self.build.config.host.iter().any(|h| h == dep.target);
1115 let rules = self.rules.values().filter(|r| r.default);
1116 for rule in rules.filter(|r| r.kind == kind && (!r.host || host)) {
1117 self.fill(dep.name(rule.name), order, added);
1120 self.fill(dep, order, added);
1136 ($($a:expr),*) => (vec![$($a.to_string()),*])
1139 fn build(args: &[&str],
1140 extra_host: &[&str],
1141 extra_target: &[&str]) -> Build {
1142 let mut args = args.iter().map(|s| s.to_string()).collect::<Vec<_>>();
1143 args.push("--build".to_string());
1144 args.push("A".to_string());
1145 let flags = Flags::parse(&args);
1147 let mut config = Config::default();
1149 config.build = "A".to_string();
1150 config.host = vec![config.build.clone()];
1151 config.host.extend(extra_host.iter().map(|s| s.to_string()));
1152 config.target = config.host.clone();
1153 config.target.extend(extra_target.iter().map(|s| s.to_string()));
1155 let mut build = Build::new(flags, config);
1156 let cwd = env::current_dir().unwrap();
1157 build.crates.insert("std_shim".to_string(), ::Crate {
1158 name: "std_shim".to_string(),
1160 path: cwd.join("src/std_shim"),
1161 doc_step: "doc-std_shim".to_string(),
1162 build_step: "build-crate-std_shim".to_string(),
1163 test_step: "test-std_shim".to_string(),
1164 bench_step: "bench-std_shim".to_string(),
1166 build.crates.insert("test_shim".to_string(), ::Crate {
1167 name: "test_shim".to_string(),
1169 path: cwd.join("src/test_shim"),
1170 doc_step: "doc-test_shim".to_string(),
1171 build_step: "build-crate-test_shim".to_string(),
1172 test_step: "test-test_shim".to_string(),
1173 bench_step: "bench-test_shim".to_string(),
1175 build.crates.insert("rustc-main".to_string(), ::Crate {
1176 name: "rustc-main".to_string(),
1178 path: cwd.join("src/rustc-main"),
1179 doc_step: "doc-rustc-main".to_string(),
1180 build_step: "build-crate-rustc-main".to_string(),
1181 test_step: "test-rustc-main".to_string(),
1182 bench_step: "bench-rustc-main".to_string(),
1188 fn dist_baseline() {
1189 let build = build(&["dist"], &[], &[]);
1190 let rules = super::build_rules(&build);
1191 let plan = rules.plan();
1192 println!("rules: {:#?}", plan);
1193 assert!(plan.iter().all(|s| s.stage == 2));
1194 assert!(plan.iter().all(|s| s.host == "A" ));
1195 assert!(plan.iter().all(|s| s.target == "A" ));
1197 let step = super::Step {
1200 host: &build.config.build,
1201 target: &build.config.build,
1204 assert!(plan.contains(&step.name("dist-docs")));
1205 assert!(plan.contains(&step.name("dist-mingw")));
1206 assert!(plan.contains(&step.name("dist-rustc")));
1207 assert!(plan.contains(&step.name("dist-std")));
1208 assert!(plan.contains(&step.name("dist-src")));
1212 fn dist_with_targets() {
1213 let build = build(&["dist"], &[], &["B"]);
1214 let rules = super::build_rules(&build);
1215 let plan = rules.plan();
1216 println!("rules: {:#?}", plan);
1217 assert!(plan.iter().all(|s| s.stage == 2));
1218 assert!(plan.iter().all(|s| s.host == "A" ));
1220 let step = super::Step {
1223 host: &build.config.build,
1224 target: &build.config.build,
1227 assert!(plan.contains(&step.name("dist-docs")));
1228 assert!(plan.contains(&step.name("dist-mingw")));
1229 assert!(plan.contains(&step.name("dist-rustc")));
1230 assert!(plan.contains(&step.name("dist-std")));
1231 assert!(plan.contains(&step.name("dist-src")));
1233 assert!(plan.contains(&step.target("B").name("dist-docs")));
1234 assert!(plan.contains(&step.target("B").name("dist-mingw")));
1235 assert!(!plan.contains(&step.target("B").name("dist-rustc")));
1236 assert!(plan.contains(&step.target("B").name("dist-std")));
1237 assert!(!plan.contains(&step.target("B").name("dist-src")));
1241 fn dist_with_hosts() {
1242 let build = build(&["dist"], &["B"], &[]);
1243 let rules = super::build_rules(&build);
1244 let plan = rules.plan();
1245 println!("rules: {:#?}", plan);
1246 assert!(plan.iter().all(|s| s.stage == 2));
1248 let step = super::Step {
1251 host: &build.config.build,
1252 target: &build.config.build,
1255 assert!(!plan.iter().any(|s| s.host == "B"));
1257 assert!(plan.contains(&step.name("dist-docs")));
1258 assert!(plan.contains(&step.name("dist-mingw")));
1259 assert!(plan.contains(&step.name("dist-rustc")));
1260 assert!(plan.contains(&step.name("dist-std")));
1261 assert!(plan.contains(&step.name("dist-src")));
1263 assert!(plan.contains(&step.target("B").name("dist-docs")));
1264 assert!(plan.contains(&step.target("B").name("dist-mingw")));
1265 assert!(plan.contains(&step.target("B").name("dist-rustc")));
1266 assert!(plan.contains(&step.target("B").name("dist-std")));
1267 assert!(!plan.contains(&step.target("B").name("dist-src")));
1271 fn dist_with_targets_and_hosts() {
1272 let build = build(&["dist"], &["B"], &["C"]);
1273 let rules = super::build_rules(&build);
1274 let plan = rules.plan();
1275 println!("rules: {:#?}", plan);
1276 assert!(plan.iter().all(|s| s.stage == 2));
1278 let step = super::Step {
1281 host: &build.config.build,
1282 target: &build.config.build,
1285 assert!(!plan.iter().any(|s| s.host == "B"));
1286 assert!(!plan.iter().any(|s| s.host == "C"));
1288 assert!(plan.contains(&step.name("dist-docs")));
1289 assert!(plan.contains(&step.name("dist-mingw")));
1290 assert!(plan.contains(&step.name("dist-rustc")));
1291 assert!(plan.contains(&step.name("dist-std")));
1292 assert!(plan.contains(&step.name("dist-src")));
1294 assert!(plan.contains(&step.target("B").name("dist-docs")));
1295 assert!(plan.contains(&step.target("B").name("dist-mingw")));
1296 assert!(plan.contains(&step.target("B").name("dist-rustc")));
1297 assert!(plan.contains(&step.target("B").name("dist-std")));
1298 assert!(!plan.contains(&step.target("B").name("dist-src")));
1300 assert!(plan.contains(&step.target("C").name("dist-docs")));
1301 assert!(plan.contains(&step.target("C").name("dist-mingw")));
1302 assert!(!plan.contains(&step.target("C").name("dist-rustc")));
1303 assert!(plan.contains(&step.target("C").name("dist-std")));
1304 assert!(!plan.contains(&step.target("C").name("dist-src")));
1308 fn dist_target_with_target_flag() {
1309 let build = build(&["dist", "--target=C"], &["B"], &["C"]);
1310 let rules = super::build_rules(&build);
1311 let plan = rules.plan();
1312 println!("rules: {:#?}", plan);
1313 assert!(plan.iter().all(|s| s.stage == 2));
1315 let step = super::Step {
1318 host: &build.config.build,
1319 target: &build.config.build,
1322 assert!(!plan.iter().any(|s| s.target == "A"));
1323 assert!(!plan.iter().any(|s| s.target == "B"));
1324 assert!(!plan.iter().any(|s| s.host == "B"));
1325 assert!(!plan.iter().any(|s| s.host == "C"));
1327 assert!(plan.contains(&step.target("C").name("dist-docs")));
1328 assert!(plan.contains(&step.target("C").name("dist-mingw")));
1329 assert!(!plan.contains(&step.target("C").name("dist-rustc")));
1330 assert!(plan.contains(&step.target("C").name("dist-std")));
1331 assert!(!plan.contains(&step.target("C").name("dist-src")));
1335 fn dist_host_with_target_flag() {
1336 let build = build(&["dist", "--host=B", "--target=B"], &["B"], &["C"]);
1337 let rules = super::build_rules(&build);
1338 let plan = rules.plan();
1339 println!("rules: {:#?}", plan);
1340 assert!(plan.iter().all(|s| s.stage == 2));
1342 let step = super::Step {
1345 host: &build.config.build,
1346 target: &build.config.build,
1349 assert!(!plan.iter().any(|s| s.target == "A"));
1350 assert!(!plan.iter().any(|s| s.target == "C"));
1351 assert!(!plan.iter().any(|s| s.host == "B"));
1352 assert!(!plan.iter().any(|s| s.host == "C"));
1354 assert!(plan.contains(&step.target("B").name("dist-docs")));
1355 assert!(plan.contains(&step.target("B").name("dist-mingw")));
1356 assert!(plan.contains(&step.target("B").name("dist-rustc")));
1357 assert!(plan.contains(&step.target("B").name("dist-std")));
1358 assert!(plan.contains(&step.target("B").name("dist-src")));
1360 let all = rules.expand(&plan);
1361 println!("all rules: {:#?}", all);
1362 assert!(!all.contains(&step.name("rustc")));
1363 assert!(!all.contains(&step.name("build-crate-std_shim").stage(1)));
1365 // all stage0 compiles should be for the build target, A
1366 for step in all.iter().filter(|s| s.stage == 0) {
1367 if !step.name.contains("build-crate") {
1370 println!("step: {:?}", step);
1371 assert!(step.host != "B");
1372 assert!(step.target != "B");
1373 assert!(step.host != "C");
1374 assert!(step.target != "C");
1379 fn build_default() {
1380 let build = build(&["build"], &["B"], &["C"]);
1381 let rules = super::build_rules(&build);
1382 let plan = rules.plan();
1383 println!("rules: {:#?}", plan);
1384 assert!(plan.iter().all(|s| s.stage == 2));
1386 let step = super::Step {
1389 host: &build.config.build,
1390 target: &build.config.build,
1393 // rustc built for all for of (A, B) x (A, B)
1394 assert!(plan.contains(&step.name("librustc")));
1395 assert!(plan.contains(&step.target("B").name("librustc")));
1396 assert!(plan.contains(&step.host("B").target("A").name("librustc")));
1397 assert!(plan.contains(&step.host("B").target("B").name("librustc")));
1399 // rustc never built for C
1400 assert!(!plan.iter().any(|s| {
1401 s.name.contains("rustc") && (s.host == "C" || s.target == "C")
1404 // test built for everything
1405 assert!(plan.contains(&step.name("libtest")));
1406 assert!(plan.contains(&step.target("B").name("libtest")));
1407 assert!(plan.contains(&step.host("B").target("A").name("libtest")));
1408 assert!(plan.contains(&step.host("B").target("B").name("libtest")));
1409 assert!(plan.contains(&step.host("A").target("C").name("libtest")));
1410 assert!(plan.contains(&step.host("B").target("C").name("libtest")));
1412 let all = rules.expand(&plan);
1413 println!("all rules: {:#?}", all);
1414 assert!(all.contains(&step.name("rustc")));
1415 assert!(all.contains(&step.name("libstd")));
1419 fn build_filtered() {
1420 let build = build(&["build", "--target=C"], &["B"], &["C"]);
1421 let rules = super::build_rules(&build);
1422 let plan = rules.plan();
1423 println!("rules: {:#?}", plan);
1424 assert!(plan.iter().all(|s| s.stage == 2));
1426 assert!(!plan.iter().any(|s| s.name.contains("rustc")));
1427 assert!(plan.iter().all(|s| {
1428 !s.name.contains("test_shim") || s.target == "C"
1434 let build = build(&["test"], &[], &[]);
1435 let rules = super::build_rules(&build);
1436 let plan = rules.plan();
1437 println!("rules: {:#?}", plan);
1438 assert!(plan.iter().all(|s| s.stage == 2));
1439 assert!(plan.iter().all(|s| s.host == "A"));
1440 assert!(plan.iter().all(|s| s.target == "A"));
1442 assert!(plan.iter().any(|s| s.name.contains("-ui")));
1443 assert!(plan.iter().any(|s| s.name.contains("cfail")));
1444 assert!(plan.iter().any(|s| s.name.contains("cfail-full")));
1445 assert!(plan.iter().any(|s| s.name.contains("codegen-units")));
1446 assert!(plan.iter().any(|s| s.name.contains("debuginfo")));
1447 assert!(plan.iter().any(|s| s.name.contains("docs")));
1448 assert!(plan.iter().any(|s| s.name.contains("error-index")));
1449 assert!(plan.iter().any(|s| s.name.contains("incremental")));
1450 assert!(plan.iter().any(|s| s.name.contains("linkchecker")));
1451 assert!(plan.iter().any(|s| s.name.contains("mir-opt")));
1452 assert!(plan.iter().any(|s| s.name.contains("pfail")));
1453 assert!(plan.iter().any(|s| s.name.contains("rfail")));
1454 assert!(plan.iter().any(|s| s.name.contains("rfail-full")));
1455 assert!(plan.iter().any(|s| s.name.contains("rmake")));
1456 assert!(plan.iter().any(|s| s.name.contains("rpass")));
1457 assert!(plan.iter().any(|s| s.name.contains("rpass-full")));
1458 assert!(plan.iter().any(|s| s.name.contains("rustc-all")));
1459 assert!(plan.iter().any(|s| s.name.contains("rustdoc")));
1460 assert!(plan.iter().any(|s| s.name.contains("std-all")));
1461 assert!(plan.iter().any(|s| s.name.contains("test-all")));
1462 assert!(plan.iter().any(|s| s.name.contains("tidy")));
1463 assert!(plan.iter().any(|s| s.name.contains("valgrind")));
1467 fn test_with_a_target() {
1468 let build = build(&["test", "--target=C"], &[], &["C"]);
1469 let rules = super::build_rules(&build);
1470 let plan = rules.plan();
1471 println!("rules: {:#?}", plan);
1472 assert!(plan.iter().all(|s| s.stage == 2));
1473 assert!(plan.iter().all(|s| s.host == "A"));
1474 assert!(plan.iter().all(|s| s.target == "C"));
1476 assert!(!plan.iter().any(|s| s.name.contains("-ui")));
1477 assert!(plan.iter().any(|s| s.name.contains("cfail")));
1478 assert!(!plan.iter().any(|s| s.name.contains("cfail-full")));
1479 assert!(plan.iter().any(|s| s.name.contains("codegen-units")));
1480 assert!(plan.iter().any(|s| s.name.contains("debuginfo")));
1481 assert!(!plan.iter().any(|s| s.name.contains("docs")));
1482 assert!(!plan.iter().any(|s| s.name.contains("error-index")));
1483 assert!(plan.iter().any(|s| s.name.contains("incremental")));
1484 assert!(!plan.iter().any(|s| s.name.contains("linkchecker")));
1485 assert!(plan.iter().any(|s| s.name.contains("mir-opt")));
1486 assert!(plan.iter().any(|s| s.name.contains("pfail")));
1487 assert!(plan.iter().any(|s| s.name.contains("rfail")));
1488 assert!(!plan.iter().any(|s| s.name.contains("rfail-full")));
1489 assert!(!plan.iter().any(|s| s.name.contains("rmake")));
1490 assert!(plan.iter().any(|s| s.name.contains("rpass")));
1491 assert!(!plan.iter().any(|s| s.name.contains("rpass-full")));
1492 assert!(!plan.iter().any(|s| s.name.contains("rustc-all")));
1493 assert!(!plan.iter().any(|s| s.name.contains("rustdoc")));
1494 assert!(plan.iter().any(|s| s.name.contains("std-all")));
1495 assert!(plan.iter().any(|s| s.name.contains("test-all")));
1496 assert!(!plan.iter().any(|s| s.name.contains("tidy")));
1497 assert!(plan.iter().any(|s| s.name.contains("valgrind")));