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 //! Major workhorse of rustbuild, definition and dependencies between stages of
14 //! The primary purpose of this module is to define the various `Step`s of
15 //! execution of the build. Each `Step` has a corresponding `Source` indicating
16 //! what it's actually doing along with a number of dependencies which must be
19 //! This module will take the CLI as input and calculate the steps required for
20 //! the build requested, ensuring that all intermediate pieces are in place.
21 //! Essentially this module is a `make`-replacement, but not as good.
23 use std
::collections
::HashSet
;
25 use {Build, Compiler}
;
27 #[derive(Hash, Eq, PartialEq, Clone, Debug)]
33 /// Macro used to iterate over all targets that are recognized by the build
36 /// Whenever a new step is added it will involve adding an entry here, updating
37 /// the dependencies section below, and then adding an implementation of the
38 /// step in `build/mod.rs`.
40 /// This macro takes another macro as an argument and then calls that macro with
41 /// all steps that the build system knows about.
42 macro_rules
! targets
{
45 // Step representing building the stageN compiler. This is just the
46 // compiler executable itself, not any of the support libraries
47 (rustc
, Rustc { stage: u32 }
),
49 // Steps for the two main cargo builds. These are parameterized over
50 // the compiler which is producing the artifact.
51 (libstd
, Libstd { compiler: Compiler<'a> }
),
52 (libtest
, Libtest { compiler: Compiler<'a> }
),
53 (librustc
, Librustc { compiler: Compiler<'a> }
),
55 // Links the target produced by the compiler provided into the
56 // host's directory also provided.
57 (libstd_link
, LibstdLink
{
58 compiler
: Compiler
<'a
>,
61 (libtest_link
, LibtestLink
{
62 compiler
: Compiler
<'a
>,
65 (librustc_link
, LibrustcLink
{
66 compiler
: Compiler
<'a
>,
70 // Various tools that we can build as part of the build.
71 (tool_linkchecker
, ToolLinkchecker { stage: u32 }
),
72 (tool_rustbook
, ToolRustbook { stage: u32 }
),
73 (tool_error_index
, ToolErrorIndex { stage: u32 }
),
74 (tool_cargotest
, ToolCargoTest { stage: u32 }
),
75 (tool_tidy
, ToolTidy { stage: u32 }
),
76 (tool_compiletest
, ToolCompiletest { stage: u32 }
),
78 // Steps for long-running native builds. Ideally these wouldn't
79 // actually exist and would be part of build scripts, but for now
82 // There aren't really any parameters to this, but empty structs
83 // with braces are unstable so we just pick something that works.
84 (llvm
, Llvm { _dummy: () }
),
85 (test_helpers
, TestHelpers { _dummy: () }
),
86 (debugger_scripts
, DebuggerScripts { stage: u32 }
),
88 // Steps for various pieces of documentation that we can generate,
89 // the 'doc' step is just a pseudo target to depend on a bunch of
91 (doc
, Doc { stage: u32 }
),
92 (doc_book
, DocBook { stage: u32 }
),
93 (doc_nomicon
, DocNomicon { stage: u32 }
),
94 (doc_standalone
, DocStandalone { stage: u32 }
),
95 (doc_std
, DocStd { stage: u32 }
),
96 (doc_test
, DocTest { stage: u32 }
),
97 (doc_rustc
, DocRustc { stage: u32 }
),
98 (doc_error_index
, DocErrorIndex { stage: u32 }
),
100 // Steps for running tests. The 'check' target is just a pseudo
101 // target to depend on a bunch of others.
102 (check
, Check { stage: u32, compiler: Compiler<'a> }
),
103 (check_target
, CheckTarget { stage: u32, compiler: Compiler<'a> }
),
104 (check_linkcheck
, CheckLinkcheck { stage: u32 }
),
105 (check_cargotest
, CheckCargoTest { stage: u32 }
),
106 (check_tidy
, CheckTidy { stage: u32 }
),
107 (check_rpass
, CheckRPass { compiler: Compiler<'a> }
),
108 (check_rpass_full
, CheckRPassFull { compiler: Compiler<'a> }
),
109 (check_rpass_valgrind
, CheckRPassValgrind { compiler: Compiler<'a> }
),
110 (check_rfail
, CheckRFail { compiler: Compiler<'a> }
),
111 (check_rfail_full
, CheckRFailFull { compiler: Compiler<'a> }
),
112 (check_cfail
, CheckCFail { compiler: Compiler<'a> }
),
113 (check_cfail_full
, CheckCFailFull { compiler: Compiler<'a> }
),
114 (check_pfail
, CheckPFail { compiler: Compiler<'a> }
),
115 (check_pretty
, CheckPretty { compiler: Compiler<'a> }
),
116 (check_pretty_rpass
, CheckPrettyRPass { compiler: Compiler<'a> }
),
117 (check_pretty_rpass_full
, CheckPrettyRPassFull { compiler: Compiler<'a> }
),
118 (check_pretty_rfail
, CheckPrettyRFail { compiler: Compiler<'a> }
),
119 (check_pretty_rfail_full
, CheckPrettyRFailFull { compiler: Compiler<'a> }
),
120 (check_pretty_rpass_valgrind
, CheckPrettyRPassValgrind { compiler: Compiler<'a> }
),
121 (check_codegen
, CheckCodegen { compiler: Compiler<'a> }
),
122 (check_codegen_units
, CheckCodegenUnits { compiler: Compiler<'a> }
),
123 (check_incremental
, CheckIncremental { compiler: Compiler<'a> }
),
124 (check_ui
, CheckUi { compiler: Compiler<'a> }
),
125 (check_mir_opt
, CheckMirOpt { compiler: Compiler<'a> }
),
126 (check_debuginfo
, CheckDebuginfo { compiler: Compiler<'a> }
),
127 (check_rustdoc
, CheckRustdoc { compiler: Compiler<'a> }
),
128 (check_docs
, CheckDocs { compiler: Compiler<'a> }
),
129 (check_error_index
, CheckErrorIndex { compiler: Compiler<'a> }
),
130 (check_rmake
, CheckRMake { compiler: Compiler<'a> }
),
131 (check_crate_std
, CheckCrateStd { compiler: Compiler<'a> }
),
132 (check_crate_test
, CheckCrateTest { compiler: Compiler<'a> }
),
133 (check_crate_rustc
, CheckCrateRustc { compiler: Compiler<'a> }
),
135 // Distribution targets, creating tarballs
136 (dist
, Dist { stage: u32 }
),
137 (dist_docs
, DistDocs { stage: u32 }
),
138 (dist_mingw
, DistMingw { _dummy: () }
),
139 (dist_rustc
, DistRustc { stage: u32 }
),
140 (dist_std
, DistStd { compiler: Compiler<'a> }
),
141 (dist_src
, DistSrc { _dummy: () }
),
144 (android_copy_libs
, AndroidCopyLibs { compiler: Compiler<'a> }
),
149 // Define the `Source` enum by iterating over all the steps and peeling out just
150 // the types that we want to define.
152 macro_rules
! item { ($a:item) => ($a) }
154 macro_rules
! define_source
{
155 ($
(($short
:ident
, $name
:ident { $($args:tt)* }
),)*) => {
157 #[derive(Hash, Eq, PartialEq, Clone, Debug)]
158 pub enum Source
<'a
> {
159 $
($name { $($args)* }
),*
165 targets
!(define_source
);
167 /// Calculate a list of all steps described by `build`.
169 /// This will inspect the flags passed in on the command line and use that to
170 /// build up a list of steps to execute. These steps will then be transformed
171 /// into a topologically sorted list which when executed left-to-right will
172 /// correctly sequence the entire build.
173 pub fn all(build
: &Build
) -> Vec
<Step
> {
174 build
.verbose("inferred build steps:");
176 let mut ret
= Vec
::new();
177 let mut all
= HashSet
::new();
178 for target
in top_level(build
) {
179 fill(build
, &target
, &mut ret
, &mut all
);
183 fn fill
<'a
>(build
: &'a Build
,
185 ret
: &mut Vec
<Step
<'a
>>,
186 set
: &mut HashSet
<Step
<'a
>>) {
187 if set
.insert(target
.clone()) {
188 for dep
in target
.deps(build
) {
189 build
.verbose(&format
!("{:?}\n -> {:?}", target
, dep
));
190 fill(build
, &dep
, ret
, set
);
192 ret
.push(target
.clone());
197 /// Determines what top-level targets are requested as part of this build,
198 /// returning them as a list.
199 fn top_level(build
: &Build
) -> Vec
<Step
> {
200 let mut targets
= Vec
::new();
201 let stage
= build
.flags
.stage
.unwrap_or(2);
204 src
: Source
::Llvm { _dummy: () }
,
205 target
: build
.flags
.host
.iter().next()
206 .unwrap_or(&build
.config
.build
),
209 src
: Source
::Llvm { _dummy: () }
,
210 target
: build
.flags
.target
.iter().next().map(|x
| &x
[..])
211 .unwrap_or(host
.target
)
214 // First, try to find steps on the command line.
215 add_steps(build
, stage
, &host
, &target
, &mut targets
);
217 // If none are specified, then build everything.
218 if targets
.len() == 0 {
220 src
: Source
::Llvm { _dummy: () }
,
221 target
: &build
.config
.build
,
223 if build
.config
.docs
{
224 targets
.push(t
.doc(stage
));
226 for host
in build
.config
.host
.iter() {
227 if !build
.flags
.host
.contains(host
) {
230 let host
= t
.target(host
);
231 if host
.target
== build
.config
.build
{
232 targets
.push(host
.librustc(host
.compiler(stage
)));
234 targets
.push(host
.librustc_link(t
.compiler(stage
), host
.target
));
236 for target
in build
.config
.target
.iter() {
237 if !build
.flags
.target
.contains(target
) {
241 if host
.target
== build
.config
.build
{
242 targets
.push(host
.target(target
)
243 .libtest(host
.compiler(stage
)));
245 targets
.push(host
.target(target
)
246 .libtest_link(t
.compiler(stage
), host
.target
));
256 fn add_steps
<'a
>(build
: &'a Build
,
260 targets
: &mut Vec
<Step
<'a
>>) {
263 compiler
: Compiler
<'a
>,
267 for step
in build
.flags
.step
.iter() {
269 // The macro below insists on hygienic access to all local variables, so
270 // we shove them all in a struct and subvert hygiene by accessing struct
274 compiler
: host
.target(&build
.config
.build
).compiler(stage
),
278 macro_rules
! add_step
{
279 ($
(($short
:ident
, $name
:ident { $($arg:ident: $t:ty),* }
),)*) => ({$
(
280 let name
= stringify
!($short
).replace("_", "-");
281 if &step
[..] == &name
[..] {
282 targets
.push(target
.$
short($
(cx
.$arg
),*));
291 panic
!("unknown step: {}", step
);
295 macro_rules
! constructors
{
296 ($
(($short
:ident
, $name
:ident { $($arg:ident: $t:ty),* }
),)*) => {$
(
297 fn $
short(&self, $
($arg
: $t
),*) -> Step
<'a
> {
299 src
: Source
::$name { $($arg: $arg),* }
,
307 fn compiler(&self, stage
: u32) -> Compiler
<'a
> {
308 Compiler
::new(stage
, self.target
)
311 fn target(&self, target
: &'a
str) -> Step
<'a
> {
312 Step { target: target, src: self.src.clone() }
315 // Define ergonomic constructors for each step defined above so they can be
316 // easily constructed.
317 targets
!(constructors
);
319 /// Mapping of all dependencies for rustbuild.
321 /// This function receives a step, the build that we're building for, and
322 /// then returns a list of all the dependencies of that step.
323 pub fn deps(&self, build
: &'a Build
) -> Vec
<Step
<'a
>> {
325 Source
::Rustc { stage: 0 }
=> {
328 Source
::Rustc { stage }
=> {
329 let compiler
= Compiler
::new(stage
- 1, &build
.config
.build
);
330 vec
![self.librustc(compiler
)]
332 Source
::Librustc { compiler }
=> {
333 vec
![self.libtest(compiler
), self.llvm(())]
335 Source
::Libtest { compiler }
=> {
336 vec
![self.libstd(compiler
)]
338 Source
::Libstd { compiler }
=> {
339 vec
![self.rustc(compiler
.stage
).target(compiler
.host
)]
341 Source
::LibrustcLink { compiler, host }
=> {
342 vec
![self.librustc(compiler
),
343 self.libtest_link(compiler
, host
)]
345 Source
::LibtestLink { compiler, host }
=> {
346 vec
![self.libtest(compiler
), self.libstd_link(compiler
, host
)]
348 Source
::LibstdLink { compiler, host }
=> {
349 vec
![self.libstd(compiler
),
350 self.target(host
).rustc(compiler
.stage
)]
352 Source
::Llvm { _dummy }
=> Vec
::new(),
353 Source
::TestHelpers { _dummy }
=> Vec
::new(),
354 Source
::DebuggerScripts { stage: _ }
=> Vec
::new(),
356 // Note that all doc targets depend on artifacts from the build
357 // architecture, not the target (which is where we're generating
359 Source
::DocStd { stage }
=> {
360 let compiler
= self.target(&build
.config
.build
).compiler(stage
);
361 vec
![self.libstd(compiler
)]
363 Source
::DocTest { stage }
=> {
364 let compiler
= self.target(&build
.config
.build
).compiler(stage
);
365 vec
![self.libtest(compiler
)]
367 Source
::DocBook { stage }
|
368 Source
::DocNomicon { stage }
=> {
369 vec
![self.target(&build
.config
.build
).tool_rustbook(stage
)]
371 Source
::DocErrorIndex { stage }
=> {
372 vec
![self.target(&build
.config
.build
).tool_error_index(stage
)]
374 Source
::DocStandalone { stage }
=> {
375 vec
![self.target(&build
.config
.build
).rustc(stage
)]
377 Source
::DocRustc { stage }
=> {
378 vec
![self.doc_test(stage
)]
380 Source
::Doc { stage }
=> {
382 self.doc_book(stage
), self.doc_nomicon(stage
),
383 self.doc_standalone(stage
), self.doc_std(stage
),
384 self.doc_error_index(stage
),
387 if build
.config
.compiler_docs
{
388 deps
.push(self.doc_rustc(stage
));
393 Source
::Check { stage, compiler }
=> {
394 // Check is just a pseudo step which means check all targets,
395 // so just depend on checking all targets.
396 build
.config
.target
.iter().map(|t
| {
397 self.target(t
).check_target(stage
, compiler
)
400 Source
::CheckTarget { stage, compiler }
=> {
401 // CheckTarget here means run all possible test suites for this
402 // target. Most of the time, however, we can't actually run
403 // anything if we're not the build triple as we could be cross
406 // As a result, the base set of targets here is quite stripped
407 // down from the standard set of targets. These suites have
408 // their own internal logic to run in cross-compiled situations
409 // if they'll run at all. For example compiletest knows that
410 // when testing Android targets we ship artifacts to the
413 // When in doubt the rule of thumb for adding to this list is
414 // "should this test suite run on the android bot?"
416 self.check_rpass(compiler
),
417 self.check_rfail(compiler
),
418 self.check_crate_std(compiler
),
419 self.check_crate_test(compiler
),
420 self.check_debuginfo(compiler
),
424 // If we're testing the build triple, then we know we can
425 // actually run binaries and such, so we run all possible tests
426 // that we know about.
427 if self.target
== build
.config
.build
{
430 self.check_docs(compiler
),
431 self.check_error_index(compiler
),
432 self.check_rustdoc(compiler
),
435 self.check_cfail(compiler
),
436 self.check_pfail(compiler
),
437 self.check_ui(compiler
),
440 self.check_incremental(compiler
),
441 self.check_codegen(compiler
),
442 self.check_codegen_units(compiler
),
444 // misc compiletest-test suites
445 self.check_rpass_full(compiler
),
446 self.check_rfail_full(compiler
),
447 self.check_cfail_full(compiler
),
448 self.check_pretty_rpass_full(compiler
),
449 self.check_pretty_rfail_full(compiler
),
450 self.check_rpass_valgrind(compiler
),
451 self.check_rmake(compiler
),
452 self.check_mir_opt(compiler
),
455 self.check_crate_rustc(compiler
),
458 self.check_pretty(compiler
),
459 self.check_pretty_rpass(compiler
),
460 self.check_pretty_rfail(compiler
),
461 self.check_pretty_rpass_valgrind(compiler
),
464 self.check_linkcheck(stage
),
465 self.check_tidy(stage
),
470 Source
::CheckLinkcheck { stage }
=> {
471 vec
![self.tool_linkchecker(stage
), self.doc(stage
)]
473 Source
::CheckCargoTest { stage }
=> {
474 vec
![self.tool_cargotest(stage
),
475 self.librustc(self.compiler(stage
))]
477 Source
::CheckTidy { stage }
=> {
478 vec
![self.tool_tidy(stage
)]
480 Source
::CheckMirOpt { compiler}
|
481 Source
::CheckPrettyRPass { compiler }
|
482 Source
::CheckPrettyRFail { compiler }
|
483 Source
::CheckRFail { compiler }
|
484 Source
::CheckPFail { compiler }
|
485 Source
::CheckCodegen { compiler }
|
486 Source
::CheckCodegenUnits { compiler }
|
487 Source
::CheckIncremental { compiler }
|
488 Source
::CheckUi { compiler }
|
489 Source
::CheckRustdoc { compiler }
|
490 Source
::CheckPretty { compiler }
|
491 Source
::CheckCFail { compiler }
|
492 Source
::CheckRPassValgrind { compiler }
|
493 Source
::CheckRPass { compiler }
=> {
495 self.libtest(compiler
),
496 self.target(compiler
.host
).tool_compiletest(compiler
.stage
),
497 self.test_helpers(()),
499 if self.target
.contains("android") {
500 base
.push(self.android_copy_libs(compiler
));
504 Source
::CheckDebuginfo { compiler }
=> {
506 self.libtest(compiler
),
507 self.target(compiler
.host
).tool_compiletest(compiler
.stage
),
508 self.test_helpers(()),
509 self.debugger_scripts(compiler
.stage
),
512 Source
::CheckRPassFull { compiler }
|
513 Source
::CheckRFailFull { compiler }
|
514 Source
::CheckCFailFull { compiler }
|
515 Source
::CheckPrettyRPassFull { compiler }
|
516 Source
::CheckPrettyRFailFull { compiler }
|
517 Source
::CheckPrettyRPassValgrind { compiler }
|
518 Source
::CheckRMake { compiler }
=> {
519 vec
![self.librustc(compiler
),
520 self.target(compiler
.host
).tool_compiletest(compiler
.stage
)]
522 Source
::CheckDocs { compiler }
=> {
523 vec
![self.libstd(compiler
)]
525 Source
::CheckErrorIndex { compiler }
=> {
526 vec
![self.libstd(compiler
),
527 self.target(compiler
.host
).tool_error_index(compiler
.stage
)]
529 Source
::CheckCrateStd { compiler }
=> {
530 vec
![self.libtest(compiler
)]
532 Source
::CheckCrateTest { compiler }
=> {
533 vec
![self.libtest(compiler
)]
535 Source
::CheckCrateRustc { compiler }
=> {
536 vec
![self.libtest(compiler
)]
539 Source
::ToolLinkchecker { stage }
|
540 Source
::ToolTidy { stage }
=> {
541 vec
![self.libstd(self.compiler(stage
))]
543 Source
::ToolErrorIndex { stage }
|
544 Source
::ToolRustbook { stage }
=> {
545 vec
![self.librustc(self.compiler(stage
))]
547 Source
::ToolCargoTest { stage }
=> {
548 vec
![self.libstd(self.compiler(stage
))]
550 Source
::ToolCompiletest { stage }
=> {
551 vec
![self.libtest(self.compiler(stage
))]
554 Source
::DistDocs { stage }
=> vec
![self.doc(stage
)],
555 Source
::DistMingw { _dummy: _ }
=> Vec
::new(),
556 Source
::DistRustc { stage }
=> {
557 vec
![self.rustc(stage
)]
559 Source
::DistStd { compiler }
=> {
560 // We want to package up as many target libraries as possible
561 // for the `rust-std` package, so if this is a host target we
562 // depend on librustc and otherwise we just depend on libtest.
563 if build
.config
.host
.iter().any(|t
| t
== self.target
) {
564 vec
![self.librustc(compiler
)]
566 vec
![self.libtest(compiler
)]
569 Source
::DistSrc { _dummy: _ }
=> Vec
::new(),
571 Source
::Dist { stage }
=> {
572 let mut base
= Vec
::new();
574 for host
in build
.config
.host
.iter() {
575 let host
= self.target(host
);
576 base
.push(host
.dist_src(()));
577 base
.push(host
.dist_rustc(stage
));
578 if host
.target
.contains("windows-gnu") {
579 base
.push(host
.dist_mingw(()));
582 let compiler
= self.compiler(stage
);
583 for target
in build
.config
.target
.iter() {
584 let target
= self.target(target
);
585 if build
.config
.docs
{
586 base
.push(target
.dist_docs(stage
));
588 base
.push(target
.dist_std(compiler
));
594 Source
::AndroidCopyLibs { compiler }
=> {
595 vec
![self.libtest(compiler
)]