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 use std::collections::HashSet;
13 use build::{Build, Compiler};
15 #[derive(Hash, Eq, PartialEq, Clone, Debug)]
21 macro_rules! targets {
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 }),
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> }),
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>,
40 (libtest_link, LibtestLink {
41 compiler: Compiler<'a>,
44 (librustc_link, LibrustcLink {
45 compiler: Compiler<'a>,
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 }),
56 // Steps for long-running native builds. Ideally these wouldn't
57 // actually exist and would be part of build scripts, but for now
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: () }),
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
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 }),
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 }),
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> }),
95 macro_rules! item { ($a:item) => ($a) }
97 macro_rules! define_source {
98 ($(($short:ident, $name:ident { $($args:tt)* }),)*) => {
100 #[derive(Hash, Eq, PartialEq, Clone, Debug)]
101 pub enum Source<'a> {
102 $($name { $($args)* }),*
108 targets!(define_source);
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);
118 fn fill<'a>(build: &'a Build,
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);
126 ret.push(target.clone());
131 fn top_level(build: &Build) -> Vec<Step> {
132 let mut targets = Vec::new();
133 let stage = build.flags.stage.unwrap_or(2);
136 src: Source::Llvm { _dummy: () },
137 target: build.flags.host.iter().next()
138 .unwrap_or(&build.config.build),
141 src: Source::Llvm { _dummy: () },
142 target: build.flags.target.iter().next().map(|x| &x[..])
143 .unwrap_or(host.target)
146 add_steps(build, stage, &host, &target, &mut targets);
148 if targets.len() == 0 {
150 src: Source::Llvm { _dummy: () },
151 target: &build.config.build,
153 if build.config.docs {
154 targets.push(t.doc(stage));
156 for host in build.config.host.iter() {
157 if !build.flags.host.contains(host) {
160 let host = t.target(host);
161 if host.target == build.config.build {
162 targets.push(host.librustc(host.compiler(stage)));
164 targets.push(host.librustc_link(t.compiler(stage), host.target));
166 for target in build.config.target.iter() {
167 if !build.flags.target.contains(target) {
171 if host.target == build.config.build {
172 targets.push(host.target(target)
173 .libtest(host.compiler(stage)));
175 targets.push(host.target(target)
176 .libtest_link(t.compiler(stage), host.target));
186 fn add_steps<'a>(build: &'a Build,
190 targets: &mut Vec<Step<'a>>) {
193 compiler: Compiler<'a>,
197 for step in build.flags.step.iter() {
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
204 compiler: host.target(&build.config.build).compiler(stage),
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),*));
221 panic!("unknown step: {}", step);
225 macro_rules! constructors {
226 ($(($short:ident, $name:ident { $($arg:ident: $t:ty),* }),)*) => {$(
227 fn $short(&self, $($arg: $t),*) -> Step<'a> {
229 src: Source::$name { $($arg: $arg),* },
237 fn compiler(&self, stage: u32) -> Compiler<'a> {
238 Compiler::new(stage, self.target)
241 fn target(&self, target: &'a str) -> Step<'a> {
242 Step { target: target, src: self.src.clone() }
245 targets!(constructors);
247 pub fn deps(&self, build: &'a Build) -> Vec<Step<'a>> {
249 Source::Rustc { stage: 0 } => {
252 Source::Rustc { stage } => {
253 let compiler = Compiler::new(stage - 1, &build.config.build);
254 vec![self.librustc(compiler)]
256 Source::Librustc { compiler } => {
257 vec![self.libtest(compiler), self.llvm(())]
259 Source::Libtest { compiler } => {
260 vec![self.libstd(compiler)]
262 Source::Libstd { compiler } => {
263 vec![self.compiler_rt(()),
264 self.rustc(compiler.stage).target(compiler.host)]
266 Source::LibrustcLink { compiler, host } => {
267 vec![self.librustc(compiler),
268 self.libtest_link(compiler, host)]
270 Source::LibtestLink { compiler, host } => {
271 vec![self.libtest(compiler), self.libstd_link(compiler, host)]
273 Source::LibstdLink { compiler, host } => {
274 vec![self.libstd(compiler),
275 self.target(host).rustc(compiler.stage)]
277 Source::CompilerRt { _dummy } => {
278 vec![self.llvm(()).target(&build.config.build)]
280 Source::Llvm { _dummy } => Vec::new(),
282 // Note that all doc targets depend on artifacts from the build
283 // architecture, not the target (which is where we're generating
285 Source::DocStd { stage } => {
286 let compiler = self.target(&build.config.build).compiler(stage);
287 vec![self.libstd(compiler)]
289 Source::DocTest { stage } => {
290 let compiler = self.target(&build.config.build).compiler(stage);
291 vec![self.libtest(compiler)]
293 Source::DocBook { stage } |
294 Source::DocNomicon { stage } |
295 Source::DocStyle { stage } => {
296 vec![self.target(&build.config.build).tool_rustbook(stage)]
298 Source::DocErrorIndex { stage } => {
299 vec![self.target(&build.config.build).tool_error_index(stage)]
301 Source::DocStandalone { stage } => {
302 vec![self.target(&build.config.build).rustc(stage)]
304 Source::DocRustc { stage } => {
305 vec![self.doc_test(stage)]
307 Source::Doc { stage } => {
308 vec![self.doc_book(stage), self.doc_nomicon(stage),
309 self.doc_style(stage), self.doc_standalone(stage),
311 self.doc_error_index(stage)]
313 Source::Check { stage, compiler: _ } => {
314 vec![self.check_linkcheck(stage),
317 Source::CheckLinkcheck { stage } => {
318 vec![self.tool_linkchecker(stage), self.doc(stage)]
320 Source::CheckCargoTest { stage } => {
321 vec![self.tool_cargotest(stage)]
323 Source::CheckTidy { stage } => {
324 vec![self.tool_tidy(stage)]
327 Source::ToolLinkchecker { stage } |
328 Source::ToolTidy { stage } => {
329 vec![self.libstd(self.compiler(stage))]
331 Source::ToolErrorIndex { stage } |
332 Source::ToolRustbook { stage } => {
333 vec![self.librustc(self.compiler(stage))]
335 Source::ToolCargoTest { stage } => {
336 vec![self.librustc(self.compiler(stage))]
339 Source::DistDocs { stage } => vec![self.doc(stage)],
340 Source::DistMingw { _dummy: _ } => Vec::new(),
341 Source::DistRustc { stage } => {
342 vec![self.rustc(stage)]
344 Source::DistStd { compiler } => {
345 vec![self.libtest(compiler)]
348 Source::Dist { stage } => {
349 let mut base = Vec::new();
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(()));
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));
364 base.push(target.dist_std(compiler));