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