]> git.proxmox.com Git - rustc.git/blob - src/bootstrap/step.rs
New upstream version 1.14.0+dfsg1
[rustc.git] / src / bootstrap / step.rs
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.
4 //
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.
10
11 use std::collections::{HashMap, HashSet};
12 use std::mem;
13
14 use check;
15 use compile;
16 use dist;
17 use doc;
18 use flags::Subcommand;
19 use install;
20 use native;
21 use {Compiler, Build, Mode};
22
23 #[derive(PartialEq, Eq, Hash, Clone, Debug)]
24 struct Step<'a> {
25 name: &'a str,
26 stage: u32,
27 host: &'a str,
28 target: &'a str,
29 }
30
31 impl<'a> Step<'a> {
32 fn name(&self, name: &'a str) -> Step<'a> {
33 Step { name: name, ..*self }
34 }
35
36 fn stage(&self, stage: u32) -> Step<'a> {
37 Step { stage: stage, ..*self }
38 }
39
40 fn host(&self, host: &'a str) -> Step<'a> {
41 Step { host: host, ..*self }
42 }
43
44 fn target(&self, target: &'a str) -> Step<'a> {
45 Step { target: target, ..*self }
46 }
47
48 fn compiler(&self) -> Compiler<'a> {
49 Compiler::new(self.stage, self.host)
50 }
51 }
52
53 pub fn run(build: &Build) {
54 let rules = build_rules(build);
55 let steps = rules.plan();
56 rules.run(&steps);
57 }
58
59 pub fn build_rules(build: &Build) -> Rules {
60 let mut rules: Rules = Rules::new(build);
61 // dummy rule to do nothing, useful when a dep maps to no deps
62 rules.build("dummy", "path/to/nowhere");
63 fn dummy<'a>(s: &Step<'a>, build: &'a Build) -> Step<'a> {
64 s.name("dummy").stage(0)
65 .target(&build.config.build)
66 .host(&build.config.build)
67 }
68
69 // Helper for loading an entire DAG of crates, rooted at `name`
70 let krates = |name: &str| {
71 let mut ret = Vec::new();
72 let mut list = vec![name];
73 let mut visited = HashSet::new();
74 while let Some(krate) = list.pop() {
75 let default = krate == name;
76 let krate = &build.crates[krate];
77 let path = krate.path.strip_prefix(&build.src).unwrap();
78 ret.push((krate, path.to_str().unwrap(), default));
79 for dep in krate.deps.iter() {
80 if visited.insert(dep) && dep != "build_helper" {
81 list.push(dep);
82 }
83 }
84 }
85 return ret
86 };
87
88 rules.build("rustc", "path/to/nowhere")
89 .dep(move |s| {
90 if s.stage == 0 {
91 dummy(s, build)
92 } else {
93 s.name("librustc")
94 .host(&build.config.build)
95 .stage(s.stage - 1)
96 }
97 })
98 .run(move |s| compile::assemble_rustc(build, s.stage, s.target));
99 rules.build("llvm", "src/llvm")
100 .host(true)
101 .run(move |s| native::llvm(build, s.target));
102
103 // ========================================================================
104 // Crate compilations
105 //
106 // Tools used during the build system but not shipped
107 rules.build("libstd", "src/libstd")
108 .dep(|s| s.name("build-crate-std_shim"));
109 rules.build("libtest", "src/libtest")
110 .dep(|s| s.name("build-crate-test_shim"));
111 rules.build("librustc", "src/librustc")
112 .dep(|s| s.name("build-crate-rustc-main"));
113 for (krate, path, _default) in krates("std_shim") {
114 rules.build(&krate.build_step, path)
115 .dep(move |s| s.name("rustc").host(&build.config.build).target(s.host))
116 .dep(move |s| {
117 if s.host == build.config.build {
118 dummy(s, build)
119 } else {
120 s.host(&build.config.build)
121 }
122 })
123 .run(move |s| {
124 if s.host == build.config.build {
125 compile::std(build, s.target, &s.compiler())
126 } else {
127 compile::std_link(build, s.target, s.stage, s.host)
128 }
129 });
130 }
131 for (krate, path, default) in krates("test_shim") {
132 rules.build(&krate.build_step, path)
133 .dep(|s| s.name("libstd"))
134 .dep(move |s| {
135 if s.host == build.config.build {
136 dummy(s, build)
137 } else {
138 s.host(&build.config.build)
139 }
140 })
141 .default(default)
142 .run(move |s| {
143 if s.host == build.config.build {
144 compile::test(build, s.target, &s.compiler())
145 } else {
146 compile::test_link(build, s.target, s.stage, s.host)
147 }
148 });
149 }
150 for (krate, path, default) in krates("rustc-main") {
151 rules.build(&krate.build_step, path)
152 .dep(|s| s.name("libtest"))
153 .dep(move |s| s.name("llvm").host(&build.config.build).stage(0))
154 .dep(move |s| {
155 if s.host == build.config.build {
156 dummy(s, build)
157 } else {
158 s.host(&build.config.build)
159 }
160 })
161 .host(true)
162 .default(default)
163 .run(move |s| {
164 if s.host == build.config.build {
165 compile::rustc(build, s.target, &s.compiler())
166 } else {
167 compile::rustc_link(build, s.target, s.stage, s.host)
168 }
169 });
170 }
171
172 // ========================================================================
173 // Test targets
174 //
175 // Various unit tests and tests suites we can run
176 {
177 let mut suite = |name, path, dir, mode| {
178 rules.test(name, path)
179 .dep(|s| s.name("libtest"))
180 .dep(|s| s.name("tool-compiletest").target(s.host))
181 .dep(|s| s.name("test-helpers"))
182 .dep(move |s| {
183 if s.target.contains("android") {
184 s.name("android-copy-libs")
185 } else {
186 dummy(s, build)
187 }
188 })
189 .default(true)
190 .run(move |s| {
191 check::compiletest(build, &s.compiler(), s.target, dir, mode)
192 });
193 };
194
195 suite("check-rpass", "src/test/run-pass", "run-pass", "run-pass");
196 suite("check-cfail", "src/test/compile-fail", "compile-fail", "compile-fail");
197 suite("check-pfail", "src/test/parse-fail", "parse-fail", "parse-fail");
198 suite("check-rfail", "src/test/run-fail", "run-fail", "run-fail");
199 suite("check-rpass-valgrind", "src/test/run-pass-valgrind",
200 "run-pass-valgrind", "run-pass-valgrind");
201 suite("check-mir-opt", "src/test/mir-opt", "mir-opt", "mir-opt");
202 if build.config.codegen_tests {
203 suite("check-codegen", "src/test/codegen", "codegen", "codegen");
204 }
205 suite("check-codegen-units", "src/test/codegen-units", "codegen-units",
206 "codegen-units");
207 suite("check-incremental", "src/test/incremental", "incremental",
208 "incremental");
209 suite("check-ui", "src/test/ui", "ui", "ui");
210 suite("check-pretty", "src/test/pretty", "pretty", "pretty");
211 suite("check-pretty-rpass", "src/test/run-pass/pretty", "pretty",
212 "run-pass");
213 suite("check-pretty-rfail", "src/test/run-pass/pretty", "pretty",
214 "run-fail");
215 suite("check-pretty-valgrind", "src/test/run-pass-valgrind", "pretty",
216 "run-pass-valgrind");
217 }
218
219 if build.config.build.contains("msvc") {
220 // nothing to do for debuginfo tests
221 } else if build.config.build.contains("apple") {
222 rules.test("check-debuginfo", "src/test/debuginfo")
223 .dep(|s| s.name("libtest"))
224 .dep(|s| s.name("tool-compiletest").host(s.host))
225 .dep(|s| s.name("test-helpers"))
226 .dep(|s| s.name("debugger-scripts"))
227 .run(move |s| check::compiletest(build, &s.compiler(), s.target,
228 "debuginfo-lldb", "debuginfo"));
229 } else {
230 rules.test("check-debuginfo", "src/test/debuginfo")
231 .dep(|s| s.name("libtest"))
232 .dep(|s| s.name("tool-compiletest").host(s.host))
233 .dep(|s| s.name("test-helpers"))
234 .dep(|s| s.name("debugger-scripts"))
235 .run(move |s| check::compiletest(build, &s.compiler(), s.target,
236 "debuginfo-gdb", "debuginfo"));
237 }
238
239 rules.test("debugger-scripts", "src/etc/lldb_batchmode.py")
240 .run(move |s| dist::debugger_scripts(build, &build.sysroot(&s.compiler()),
241 s.target));
242
243 {
244 let mut suite = |name, path, dir, mode| {
245 rules.test(name, path)
246 .dep(|s| s.name("librustc"))
247 .dep(|s| s.name("tool-compiletest").target(s.host))
248 .default(true)
249 .host(true)
250 .run(move |s| {
251 check::compiletest(build, &s.compiler(), s.target, dir, mode)
252 });
253 };
254
255 suite("check-rpass-full", "src/test/run-pass-fulldeps",
256 "run-pass", "run-pass-fulldeps");
257 suite("check-cfail-full", "src/test/compile-fail-fulldeps",
258 "compile-fail", "compile-fail-fulldeps");
259 suite("check-rmake", "src/test/run-make", "run-make", "run-make");
260 suite("check-rustdoc", "src/test/rustdoc", "rustdoc", "rustdoc");
261 suite("check-pretty-rpass-full", "src/test/run-pass-fulldeps",
262 "pretty", "run-pass-fulldeps");
263 suite("check-pretty-rfail-full", "src/test/run-fail-fulldeps",
264 "pretty", "run-fail-fulldeps");
265 }
266
267 for (krate, path, _default) in krates("std_shim") {
268 rules.test(&krate.test_step, path)
269 .dep(|s| s.name("libtest"))
270 .run(move |s| check::krate(build, &s.compiler(), s.target,
271 Mode::Libstd, Some(&krate.name)));
272 }
273 rules.test("check-std-all", "path/to/nowhere")
274 .dep(|s| s.name("libtest"))
275 .default(true)
276 .run(move |s| check::krate(build, &s.compiler(), s.target, Mode::Libstd,
277 None));
278 for (krate, path, _default) in krates("test_shim") {
279 rules.test(&krate.test_step, path)
280 .dep(|s| s.name("libtest"))
281 .run(move |s| check::krate(build, &s.compiler(), s.target,
282 Mode::Libtest, Some(&krate.name)));
283 }
284 rules.test("check-test-all", "path/to/nowhere")
285 .dep(|s| s.name("libtest"))
286 .default(true)
287 .run(move |s| check::krate(build, &s.compiler(), s.target, Mode::Libtest,
288 None));
289 for (krate, path, _default) in krates("rustc-main") {
290 rules.test(&krate.test_step, path)
291 .dep(|s| s.name("librustc"))
292 .host(true)
293 .run(move |s| check::krate(build, &s.compiler(), s.target,
294 Mode::Librustc, Some(&krate.name)));
295 }
296 rules.test("check-rustc-all", "path/to/nowhere")
297 .dep(|s| s.name("librustc"))
298 .default(true)
299 .host(true)
300 .run(move |s| check::krate(build, &s.compiler(), s.target, Mode::Librustc,
301 None));
302
303 rules.test("check-linkchecker", "src/tools/linkchecker")
304 .dep(|s| s.name("tool-linkchecker"))
305 .dep(|s| s.name("default:doc"))
306 .default(true)
307 .host(true)
308 .run(move |s| check::linkcheck(build, s.stage, s.target));
309 rules.test("check-cargotest", "src/tools/cargotest")
310 .dep(|s| s.name("tool-cargotest"))
311 .dep(|s| s.name("librustc"))
312 .host(true)
313 .run(move |s| check::cargotest(build, s.stage, s.target));
314 rules.test("check-tidy", "src/tools/tidy")
315 .dep(|s| s.name("tool-tidy"))
316 .default(true)
317 .host(true)
318 .run(move |s| check::tidy(build, s.stage, s.target));
319 rules.test("check-error-index", "src/tools/error_index_generator")
320 .dep(|s| s.name("libstd"))
321 .dep(|s| s.name("tool-error-index").host(s.host))
322 .default(true)
323 .host(true)
324 .run(move |s| check::error_index(build, &s.compiler()));
325 rules.test("check-docs", "src/doc")
326 .dep(|s| s.name("libtest"))
327 .default(true)
328 .host(true)
329 .run(move |s| check::docs(build, &s.compiler()));
330
331 rules.build("test-helpers", "src/rt/rust_test_helpers.c")
332 .run(move |s| native::test_helpers(build, s.target));
333 rules.test("android-copy-libs", "path/to/nowhere")
334 .dep(|s| s.name("libtest"))
335 .run(move |s| check::android_copy_libs(build, &s.compiler(), s.target));
336
337 // ========================================================================
338 // Build tools
339 //
340 // Tools used during the build system but not shipped
341 rules.build("tool-rustbook", "src/tools/rustbook")
342 .dep(|s| s.name("librustc"))
343 .run(move |s| compile::tool(build, s.stage, s.target, "rustbook"));
344 rules.build("tool-error-index", "src/tools/error_index_generator")
345 .dep(|s| s.name("librustc"))
346 .run(move |s| compile::tool(build, s.stage, s.target, "error_index_generator"));
347 rules.build("tool-tidy", "src/tools/tidy")
348 .dep(|s| s.name("libstd"))
349 .run(move |s| compile::tool(build, s.stage, s.target, "tidy"));
350 rules.build("tool-linkchecker", "src/tools/linkchecker")
351 .dep(|s| s.name("libstd"))
352 .run(move |s| compile::tool(build, s.stage, s.target, "linkchecker"));
353 rules.build("tool-cargotest", "src/tools/cargotest")
354 .dep(|s| s.name("libstd"))
355 .run(move |s| compile::tool(build, s.stage, s.target, "cargotest"));
356 rules.build("tool-compiletest", "src/tools/compiletest")
357 .dep(|s| s.name("libtest"))
358 .run(move |s| compile::tool(build, s.stage, s.target, "compiletest"));
359
360 // ========================================================================
361 // Documentation targets
362 rules.doc("doc-book", "src/doc/book")
363 .dep(move |s| s.name("tool-rustbook").target(&build.config.build))
364 .default(build.config.docs)
365 .run(move |s| doc::rustbook(build, s.stage, s.target, "book"));
366 rules.doc("doc-nomicon", "src/doc/nomicon")
367 .dep(move |s| s.name("tool-rustbook").target(&build.config.build))
368 .default(build.config.docs)
369 .run(move |s| doc::rustbook(build, s.stage, s.target, "nomicon"));
370 rules.doc("doc-standalone", "src/doc")
371 .dep(move |s| s.name("rustc").host(&build.config.build).target(&build.config.build))
372 .default(build.config.docs)
373 .run(move |s| doc::standalone(build, s.stage, s.target));
374 rules.doc("doc-error-index", "src/tools/error_index_generator")
375 .dep(move |s| s.name("tool-error-index").target(&build.config.build))
376 .dep(move |s| s.name("librustc"))
377 .default(build.config.docs)
378 .host(true)
379 .run(move |s| doc::error_index(build, s.stage, s.target));
380 for (krate, path, default) in krates("std_shim") {
381 rules.doc(&krate.doc_step, path)
382 .dep(|s| s.name("libstd"))
383 .default(default && build.config.docs)
384 .run(move |s| doc::std(build, s.stage, s.target));
385 }
386 for (krate, path, default) in krates("test_shim") {
387 rules.doc(&krate.doc_step, path)
388 .dep(|s| s.name("libtest"))
389 .default(default && build.config.docs)
390 .run(move |s| doc::test(build, s.stage, s.target));
391 }
392 for (krate, path, default) in krates("rustc-main") {
393 rules.doc(&krate.doc_step, path)
394 .dep(|s| s.name("librustc"))
395 .host(true)
396 .default(default && build.config.compiler_docs)
397 .run(move |s| doc::rustc(build, s.stage, s.target));
398 }
399
400 // ========================================================================
401 // Distribution targets
402 rules.dist("dist-rustc", "src/librustc")
403 .dep(move |s| s.name("rustc").host(&build.config.build))
404 .host(true)
405 .default(true)
406 .run(move |s| dist::rustc(build, s.stage, s.target));
407 rules.dist("dist-std", "src/libstd")
408 .dep(move |s| {
409 // We want to package up as many target libraries as possible
410 // for the `rust-std` package, so if this is a host target we
411 // depend on librustc and otherwise we just depend on libtest.
412 if build.config.host.iter().any(|t| t == s.target) {
413 s.name("librustc")
414 } else {
415 s.name("libtest")
416 }
417 })
418 .default(true)
419 .run(move |s| dist::std(build, &s.compiler(), s.target));
420 rules.dist("dist-mingw", "path/to/nowhere")
421 .run(move |s| dist::mingw(build, s.target));
422 rules.dist("dist-src", "src")
423 .default(true)
424 .host(true)
425 .run(move |_| dist::rust_src(build));
426 rules.dist("dist-docs", "src/doc")
427 .default(true)
428 .dep(|s| s.name("default:doc"))
429 .run(move |s| dist::docs(build, s.stage, s.target));
430 rules.dist("install", "src")
431 .dep(|s| s.name("default:dist"))
432 .run(move |s| install::install(build, s.stage, s.target));
433
434 rules.verify();
435 return rules
436 }
437
438 struct Rule<'a> {
439 name: &'a str,
440 path: &'a str,
441 kind: Kind,
442 deps: Vec<Box<Fn(&Step<'a>) -> Step<'a> + 'a>>,
443 run: Box<Fn(&Step<'a>) + 'a>,
444 default: bool,
445 host: bool,
446 }
447
448 #[derive(PartialEq)]
449 enum Kind {
450 Build,
451 Test,
452 Dist,
453 Doc,
454 }
455
456 impl<'a> Rule<'a> {
457 fn new(name: &'a str, path: &'a str, kind: Kind) -> Rule<'a> {
458 Rule {
459 name: name,
460 deps: Vec::new(),
461 run: Box::new(|_| ()),
462 path: path,
463 kind: kind,
464 default: false,
465 host: false,
466 }
467 }
468 }
469
470 struct RuleBuilder<'a: 'b, 'b> {
471 rules: &'b mut Rules<'a>,
472 rule: Rule<'a>,
473 }
474
475 impl<'a, 'b> RuleBuilder<'a, 'b> {
476 fn dep<F>(&mut self, f: F) -> &mut Self
477 where F: Fn(&Step<'a>) -> Step<'a> + 'a,
478 {
479 self.rule.deps.push(Box::new(f));
480 self
481 }
482
483 fn run<F>(&mut self, f: F) -> &mut Self
484 where F: Fn(&Step<'a>) + 'a,
485 {
486 self.rule.run = Box::new(f);
487 self
488 }
489
490 fn default(&mut self, default: bool) -> &mut Self {
491 self.rule.default = default;
492 self
493 }
494
495 fn host(&mut self, host: bool) -> &mut Self {
496 self.rule.host = host;
497 self
498 }
499 }
500
501 impl<'a, 'b> Drop for RuleBuilder<'a, 'b> {
502 fn drop(&mut self) {
503 let rule = mem::replace(&mut self.rule, Rule::new("", "", Kind::Build));
504 let prev = self.rules.rules.insert(rule.name, rule);
505 if let Some(prev) = prev {
506 panic!("duplicate rule named: {}", prev.name);
507 }
508 }
509 }
510
511 pub struct Rules<'a> {
512 build: &'a Build,
513 sbuild: Step<'a>,
514 rules: HashMap<&'a str, Rule<'a>>,
515 }
516
517 impl<'a> Rules<'a> {
518 fn new(build: &'a Build) -> Rules<'a> {
519 Rules {
520 build: build,
521 sbuild: Step {
522 stage: build.flags.stage.unwrap_or(2),
523 target: &build.config.build,
524 host: &build.config.build,
525 name: "",
526 },
527 rules: HashMap::new(),
528 }
529 }
530
531 fn build<'b>(&'b mut self, name: &'a str, path: &'a str)
532 -> RuleBuilder<'a, 'b> {
533 self.rule(name, path, Kind::Build)
534 }
535
536 fn test<'b>(&'b mut self, name: &'a str, path: &'a str)
537 -> RuleBuilder<'a, 'b> {
538 self.rule(name, path, Kind::Test)
539 }
540
541 fn doc<'b>(&'b mut self, name: &'a str, path: &'a str)
542 -> RuleBuilder<'a, 'b> {
543 self.rule(name, path, Kind::Doc)
544 }
545
546 fn dist<'b>(&'b mut self, name: &'a str, path: &'a str)
547 -> RuleBuilder<'a, 'b> {
548 self.rule(name, path, Kind::Dist)
549 }
550
551 fn rule<'b>(&'b mut self,
552 name: &'a str,
553 path: &'a str,
554 kind: Kind) -> RuleBuilder<'a, 'b> {
555 RuleBuilder {
556 rules: self,
557 rule: Rule::new(name, path, kind),
558 }
559 }
560
561 /// Verify the dependency graph defined by all our rules are correct, e.g.
562 /// everything points to a valid something else.
563 fn verify(&self) {
564 for rule in self.rules.values() {
565 for dep in rule.deps.iter() {
566 let dep = dep(&self.sbuild.name(rule.name));
567 if self.rules.contains_key(&dep.name) || dep.name.starts_with("default:") {
568 continue
569 }
570 panic!("\
571
572 invalid rule dependency graph detected, was a rule added and maybe typo'd?
573
574 `{}` depends on `{}` which does not exist
575
576 ", rule.name, dep.name);
577 }
578 }
579 }
580
581 pub fn print_help(&self, command: &str) {
582 let kind = match command {
583 "build" => Kind::Build,
584 "doc" => Kind::Doc,
585 "test" => Kind::Test,
586 "dist" => Kind::Dist,
587 _ => return,
588 };
589 let rules = self.rules.values().filter(|r| r.kind == kind);
590 let rules = rules.filter(|r| !r.path.contains("nowhere"));
591 let mut rules = rules.collect::<Vec<_>>();
592 rules.sort_by_key(|r| r.path);
593
594 println!("Available paths:\n");
595 for rule in rules {
596 print!(" ./x.py {} {}", command, rule.path);
597
598 println!("");
599 }
600 }
601
602 /// Construct the top-level build steps that we're going to be executing,
603 /// given the subcommand that our build is performing.
604 fn plan(&self) -> Vec<Step<'a>> {
605 let (kind, paths) = match self.build.flags.cmd {
606 Subcommand::Build { ref paths } => (Kind::Build, &paths[..]),
607 Subcommand::Doc { ref paths } => (Kind::Doc, &paths[..]),
608 Subcommand::Test { ref paths, test_args: _ } => (Kind::Test, &paths[..]),
609 Subcommand::Dist { install } => {
610 if install {
611 return vec![self.sbuild.name("install")]
612 } else {
613 (Kind::Dist, &[][..])
614 }
615 }
616 Subcommand::Clean => panic!(),
617 };
618
619 self.rules.values().filter(|rule| rule.kind == kind).filter(|rule| {
620 (paths.len() == 0 && rule.default) || paths.iter().any(|path| {
621 path.ends_with(rule.path)
622 })
623 }).flat_map(|rule| {
624 let hosts = if self.build.flags.host.len() > 0 {
625 &self.build.flags.host
626 } else {
627 &self.build.config.host
628 };
629 let targets = if self.build.flags.target.len() > 0 {
630 &self.build.flags.target
631 } else {
632 &self.build.config.target
633 };
634 let arr = if rule.host {hosts} else {targets};
635
636 hosts.iter().flat_map(move |host| {
637 arr.iter().map(move |target| {
638 self.sbuild.name(rule.name).target(target).host(host)
639 })
640 })
641 }).collect()
642 }
643
644 /// Execute all top-level targets indicated by `steps`.
645 ///
646 /// This will take the list returned by `plan` and then execute each step
647 /// along with all required dependencies as it goes up the chain.
648 fn run(&self, steps: &[Step<'a>]) {
649 self.build.verbose("bootstrap top targets:");
650 for step in steps.iter() {
651 self.build.verbose(&format!("\t{:?}", step));
652 }
653
654 // Using `steps` as the top-level targets, make a topological ordering
655 // of what we need to do.
656 let mut order = Vec::new();
657 let mut added = HashSet::new();
658 for step in steps.iter().cloned() {
659 self.fill(step, &mut order, &mut added);
660 }
661
662 // Print out what we're doing for debugging
663 self.build.verbose("bootstrap build plan:");
664 for step in order.iter() {
665 self.build.verbose(&format!("\t{:?}", step));
666 }
667
668 // And finally, iterate over everything and execute it.
669 for step in order.iter() {
670 self.build.verbose(&format!("executing step {:?}", step));
671 (self.rules[step.name].run)(step);
672 }
673 }
674
675 fn fill(&self,
676 step: Step<'a>,
677 order: &mut Vec<Step<'a>>,
678 added: &mut HashSet<Step<'a>>) {
679 if !added.insert(step.clone()) {
680 return
681 }
682 for dep in self.rules[step.name].deps.iter() {
683 let dep = dep(&step);
684 if dep.name.starts_with("default:") {
685 let kind = match &dep.name[8..] {
686 "doc" => Kind::Doc,
687 "dist" => Kind::Dist,
688 kind => panic!("unknown kind: `{}`", kind),
689 };
690 let host = self.build.config.host.iter().any(|h| h == dep.target);
691 let rules = self.rules.values().filter(|r| r.default);
692 for rule in rules.filter(|r| r.kind == kind && (!r.host || host)) {
693 self.fill(dep.name(rule.name), order, added);
694 }
695 } else {
696 self.fill(dep, order, added);
697 }
698 }
699 order.push(step);
700 }
701 }