]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/build/step.rs
Auto merge of #32718 - timonvo:bootstrap-skip-docs, r=alexcrichton
[rust.git] / src / bootstrap / build / 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::HashSet;
12
13 use build::{Build, Compiler};
14
15 #[derive(Hash, Eq, PartialEq, Clone, Debug)]
16 pub struct Step<'a> {
17     pub src: Source<'a>,
18     pub target: &'a str,
19 }
20
21 macro_rules! targets {
22     ($m:ident) => {
23         $m! {
24             // Step representing building the stageN compiler. This is just the
25             // compiler executable itself, not any of the support libraries
26             (rustc, Rustc { stage: u32 }),
27
28             // Steps for the two main cargo builds. These are parameterized over
29             // the compiler which is producing the artifact.
30             (libstd, Libstd { compiler: Compiler<'a> }),
31             (libtest, Libtest { compiler: Compiler<'a> }),
32             (librustc, Librustc { compiler: Compiler<'a> }),
33
34             // Links the target produced by the compiler provided into the
35             // host's directory also provided.
36             (libstd_link, LibstdLink {
37                 compiler: Compiler<'a>,
38                 host: &'a str
39             }),
40             (libtest_link, LibtestLink {
41                 compiler: Compiler<'a>,
42                 host: &'a str
43             }),
44             (librustc_link, LibrustcLink {
45                 compiler: Compiler<'a>,
46                 host: &'a str
47             }),
48
49             // Various tools that we can build as part of the build.
50             (tool_linkchecker, ToolLinkchecker { stage: u32 }),
51             (tool_rustbook, ToolRustbook { stage: u32 }),
52             (tool_error_index, ToolErrorIndex { stage: u32 }),
53             (tool_cargotest, ToolCargoTest { stage: u32 }),
54             (tool_tidy, ToolTidy { stage: u32 }),
55
56             // Steps for long-running native builds. Ideally these wouldn't
57             // actually exist and would be part of build scripts, but for now
58             // these are here.
59             //
60             // There aren't really any parameters to this, but empty structs
61             // with braces are unstable so we just pick something that works.
62             (llvm, Llvm { _dummy: () }),
63             (compiler_rt, CompilerRt { _dummy: () }),
64
65             // Steps for various pieces of documentation that we can generate,
66             // the 'doc' step is just a pseudo target to depend on a bunch of
67             // others.
68             (doc, Doc { stage: u32 }),
69             (doc_book, DocBook { stage: u32 }),
70             (doc_nomicon, DocNomicon { stage: u32 }),
71             (doc_style, DocStyle { stage: u32 }),
72             (doc_standalone, DocStandalone { stage: u32 }),
73             (doc_std, DocStd { stage: u32 }),
74             (doc_test, DocTest { stage: u32 }),
75             (doc_rustc, DocRustc { stage: u32 }),
76             (doc_error_index, DocErrorIndex { stage: u32 }),
77
78             // Steps for running tests. The 'check' target is just a pseudo
79             // target to depend on a bunch of others.
80             (check, Check { stage: u32, compiler: Compiler<'a> }),
81             (check_linkcheck, CheckLinkcheck { stage: u32 }),
82             (check_cargotest, CheckCargoTest { stage: u32 }),
83             (check_tidy, CheckTidy { stage: u32 }),
84
85             // Distribution targets, creating tarballs
86             (dist, Dist { stage: u32 }),
87             (dist_docs, DistDocs { stage: u32 }),
88             (dist_mingw, DistMingw { _dummy: () }),
89             (dist_rustc, DistRustc { stage: u32 }),
90             (dist_std, DistStd { compiler: Compiler<'a> }),
91         }
92     }
93 }
94
95 macro_rules! item { ($a:item) => ($a) }
96
97 macro_rules! define_source {
98     ($(($short:ident, $name:ident { $($args:tt)* }),)*) => {
99         item! {
100             #[derive(Hash, Eq, PartialEq, Clone, Debug)]
101             pub enum Source<'a> {
102                 $($name { $($args)* }),*
103             }
104         }
105     }
106 }
107
108 targets!(define_source);
109
110 pub fn all(build: &Build) -> Vec<Step> {
111     let mut ret = Vec::new();
112     let mut all = HashSet::new();
113     for target in top_level(build) {
114         fill(build, &target, &mut ret, &mut all);
115     }
116     return ret;
117
118     fn fill<'a>(build: &'a Build,
119                 target: &Step<'a>,
120                 ret: &mut Vec<Step<'a>>,
121                 set: &mut HashSet<Step<'a>>) {
122         if set.insert(target.clone()) {
123             for dep in target.deps(build) {
124                 fill(build, &dep, ret, set);
125             }
126             ret.push(target.clone());
127         }
128     }
129 }
130
131 fn top_level(build: &Build) -> Vec<Step> {
132     let mut targets = Vec::new();
133     let stage = build.flags.stage.unwrap_or(2);
134
135     let host = Step {
136         src: Source::Llvm { _dummy: () },
137         target: build.flags.host.iter().next()
138                      .unwrap_or(&build.config.build),
139     };
140     let target = Step {
141         src: Source::Llvm { _dummy: () },
142         target: build.flags.target.iter().next().map(|x| &x[..])
143                      .unwrap_or(host.target)
144     };
145
146     add_steps(build, stage, &host, &target, &mut targets);
147
148     if targets.len() == 0 {
149         let t = Step {
150             src: Source::Llvm { _dummy: () },
151             target: &build.config.build,
152         };
153         if build.config.docs {
154           targets.push(t.doc(stage));
155         }
156         for host in build.config.host.iter() {
157             if !build.flags.host.contains(host) {
158                 continue
159             }
160             let host = t.target(host);
161             if host.target == build.config.build {
162                 targets.push(host.librustc(host.compiler(stage)));
163             } else {
164                 targets.push(host.librustc_link(t.compiler(stage), host.target));
165             }
166             for target in build.config.target.iter() {
167                 if !build.flags.target.contains(target) {
168                     continue
169                 }
170
171                 if host.target == build.config.build {
172                     targets.push(host.target(target)
173                                      .libtest(host.compiler(stage)));
174                 } else {
175                     targets.push(host.target(target)
176                                      .libtest_link(t.compiler(stage), host.target));
177                 }
178             }
179         }
180     }
181
182     return targets
183
184 }
185
186 fn add_steps<'a>(build: &'a Build,
187                  stage: u32,
188                  host: &Step<'a>,
189                  target: &Step<'a>,
190                  targets: &mut Vec<Step<'a>>) {
191     struct Context<'a> {
192         stage: u32,
193         compiler: Compiler<'a>,
194         _dummy: (),
195         host: &'a str,
196     }
197     for step in build.flags.step.iter() {
198
199         // The macro below insists on hygienic access to all local variables, so
200         // we shove them all in a struct and subvert hygiene by accessing struct
201         // fields instead,
202         let cx = Context {
203             stage: stage,
204             compiler: host.target(&build.config.build).compiler(stage),
205             _dummy: (),
206             host: host.target,
207         };
208         macro_rules! add_step {
209             ($(($short:ident, $name:ident { $($arg:ident: $t:ty),* }),)*) => ({$(
210                 let name = stringify!($short).replace("_", "-");
211                 if &step[..] == &name[..] {
212                     targets.push(target.$short($(cx.$arg),*));
213                     continue
214                 }
215                 drop(name);
216             )*})
217         }
218
219         targets!(add_step);
220
221         panic!("unknown step: {}", step);
222     }
223 }
224
225 macro_rules! constructors {
226     ($(($short:ident, $name:ident { $($arg:ident: $t:ty),* }),)*) => {$(
227         fn $short(&self, $($arg: $t),*) -> Step<'a> {
228             Step {
229                 src: Source::$name { $($arg: $arg),* },
230                 target: self.target,
231             }
232         }
233     )*}
234 }
235
236 impl<'a> Step<'a> {
237     fn compiler(&self, stage: u32) -> Compiler<'a> {
238         Compiler::new(stage, self.target)
239     }
240
241     fn target(&self, target: &'a str) -> Step<'a> {
242         Step { target: target, src: self.src.clone() }
243     }
244
245     targets!(constructors);
246
247     pub fn deps(&self, build: &'a Build) -> Vec<Step<'a>> {
248         match self.src {
249             Source::Rustc { stage: 0 } => {
250                 Vec::new()
251             }
252             Source::Rustc { stage } => {
253                 let compiler = Compiler::new(stage - 1, &build.config.build);
254                 vec![self.librustc(compiler)]
255             }
256             Source::Librustc { compiler } => {
257                 vec![self.libtest(compiler), self.llvm(())]
258             }
259             Source::Libtest { compiler } => {
260                 vec![self.libstd(compiler)]
261             }
262             Source::Libstd { compiler } => {
263                 vec![self.compiler_rt(()),
264                      self.rustc(compiler.stage).target(compiler.host)]
265             }
266             Source::LibrustcLink { compiler, host } => {
267                 vec![self.librustc(compiler),
268                      self.libtest_link(compiler, host)]
269             }
270             Source::LibtestLink { compiler, host } => {
271                 vec![self.libtest(compiler), self.libstd_link(compiler, host)]
272             }
273             Source::LibstdLink { compiler, host } => {
274                 vec![self.libstd(compiler),
275                      self.target(host).rustc(compiler.stage)]
276             }
277             Source::CompilerRt { _dummy } => {
278                 vec![self.llvm(()).target(&build.config.build)]
279             }
280             Source::Llvm { _dummy } => Vec::new(),
281
282             // Note that all doc targets depend on artifacts from the build
283             // architecture, not the target (which is where we're generating
284             // docs into).
285             Source::DocStd { stage } => {
286                 let compiler = self.target(&build.config.build).compiler(stage);
287                 vec![self.libstd(compiler)]
288             }
289             Source::DocTest { stage } => {
290                 let compiler = self.target(&build.config.build).compiler(stage);
291                 vec![self.libtest(compiler)]
292             }
293             Source::DocBook { stage } |
294             Source::DocNomicon { stage } |
295             Source::DocStyle { stage } => {
296                 vec![self.target(&build.config.build).tool_rustbook(stage)]
297             }
298             Source::DocErrorIndex { stage } => {
299                 vec![self.target(&build.config.build).tool_error_index(stage)]
300             }
301             Source::DocStandalone { stage } => {
302                 vec![self.target(&build.config.build).rustc(stage)]
303             }
304             Source::DocRustc { stage } => {
305                 vec![self.doc_test(stage)]
306             }
307             Source::Doc { stage } => {
308                 vec![self.doc_book(stage), self.doc_nomicon(stage),
309                      self.doc_style(stage), self.doc_standalone(stage),
310                      self.doc_std(stage),
311                      self.doc_error_index(stage)]
312             }
313             Source::Check { stage, compiler: _ } => {
314                 vec![self.check_linkcheck(stage),
315                      self.dist(stage)]
316             }
317             Source::CheckLinkcheck { stage } => {
318                 vec![self.tool_linkchecker(stage), self.doc(stage)]
319             }
320             Source::CheckCargoTest { stage } => {
321                 vec![self.tool_cargotest(stage)]
322             }
323             Source::CheckTidy { stage } => {
324                 vec![self.tool_tidy(stage)]
325             }
326
327             Source::ToolLinkchecker { stage } |
328             Source::ToolTidy { stage } => {
329                 vec![self.libstd(self.compiler(stage))]
330             }
331             Source::ToolErrorIndex { stage } |
332             Source::ToolRustbook { stage } => {
333                 vec![self.librustc(self.compiler(stage))]
334             }
335             Source::ToolCargoTest { stage } => {
336                 vec![self.librustc(self.compiler(stage))]
337             }
338
339             Source::DistDocs { stage } => vec![self.doc(stage)],
340             Source::DistMingw { _dummy: _ } => Vec::new(),
341             Source::DistRustc { stage } => {
342                 vec![self.rustc(stage)]
343             }
344             Source::DistStd { compiler } => {
345                 vec![self.libtest(compiler)]
346             }
347
348             Source::Dist { stage } => {
349                 let mut base = Vec::new();
350
351                 for host in build.config.host.iter() {
352                     let host = self.target(host);
353                     base.push(host.dist_rustc(stage));
354                     if host.target.contains("windows-gnu") {
355                         base.push(host.dist_mingw(()));
356                     }
357
358                     let compiler = self.compiler(stage);
359                     for target in build.config.target.iter() {
360                         let target = self.target(target);
361                         if build.config.docs {
362                             base.push(target.dist_docs(stage));
363                         }
364                         base.push(target.dist_std(compiler));
365                     }
366                 }
367                 return base
368             }
369         }
370     }
371 }