]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/tool.rs
Change code to work with the new system
[rust.git] / src / bootstrap / tool.rs
1 // Copyright 2017 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::env;
12 use std::path::{Path, PathBuf};
13 use std::process::Command;
14
15 use Mode;
16 use builder::{Step, Builder};
17 use util::{exe, add_lib_path};
18 use compile::{self, libtest_stamp, libstd_stamp, librustc_stamp, Rustc};
19 use native;
20 use channel::GitInfo;
21
22 //// ========================================================================
23 //// Build tools
24 ////
25 //// Tools used during the build system but not shipped
26 //// "pseudo rule" which represents completely cleaning out the tools dir in
27 //// one stage. This needs to happen whenever a dependency changes (e.g.
28 //// libstd, libtest, librustc) and all of the tool compilations above will
29 //// be sequenced after this rule.
30 //rules.build("maybe-clean-tools", "path/to/nowhere")
31 //     .after("librustc-tool")
32 //     .after("libtest-tool")
33 //     .after("libstd-tool");
34 //
35 //rules.build("librustc-tool", "path/to/nowhere")
36 //     .dep(|s| s.name("librustc"))
37 //     .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Librustc));
38 //rules.build("libtest-tool", "path/to/nowhere")
39 //     .dep(|s| s.name("libtest"))
40 //     .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Libtest));
41 //rules.build("libstd-tool", "path/to/nowhere")
42 //     .dep(|s| s.name("libstd"))
43 //     .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Libstd));
44 //
45
46 #[derive(Serialize)]
47 pub struct CleanTools<'a> {
48     pub stage: u32,
49     pub target: &'a str,
50     pub mode: Mode,
51 }
52
53 impl<'a> Step<'a> for CleanTools<'a> {
54     type Output = ();
55
56     /// Build a tool in `src/tools`
57     ///
58     /// This will build the specified tool with the specified `host` compiler in
59     /// `stage` into the normal cargo output directory.
60     fn run(self, builder: &Builder) {
61         let build = builder.build;
62         let stage = self.stage;
63         let target = self.target;
64         let mode = self.mode;
65
66         let compiler = builder.compiler(stage, &build.build);
67
68         let stamp = match mode {
69             Mode::Libstd => libstd_stamp(build, &compiler, target),
70             Mode::Libtest => libtest_stamp(build, &compiler, target),
71             Mode::Librustc => librustc_stamp(build, &compiler, target),
72             _ => panic!(),
73         };
74         let out_dir = build.cargo_out(&compiler, Mode::Tool, target);
75         build.clear_if_dirty(&out_dir, &stamp);
76     }
77 }
78
79 #[derive(Serialize)]
80 pub struct ToolBuild<'a> {
81     pub stage: u32,
82     pub target: &'a str,
83     pub tool: &'a str,
84     pub mode: Mode,
85 }
86
87 impl<'a> Step<'a> for ToolBuild<'a> {
88     type Output = PathBuf;
89
90     /// Build a tool in `src/tools`
91     ///
92     /// This will build the specified tool with the specified `host` compiler in
93     /// `stage` into the normal cargo output directory.
94     fn run(self, builder: &Builder) -> PathBuf {
95         let build = builder.build;
96         let stage = self.stage;
97         let target = self.target;
98         let tool = self.tool;
99
100         let compiler = builder.compiler(stage, &build.build);
101         builder.ensure(CleanTools { stage, target, mode: self.mode });
102         match self.mode {
103             Mode::Libstd => builder.ensure(compile::Std { compiler, target }),
104             Mode::Libtest => builder.ensure(compile::Test { compiler, target }),
105             Mode::Librustc => builder.ensure(compile::Rustc { compiler, target }),
106             Mode::Tool => panic!("unexpected Mode::Tool for tool build")
107         }
108
109         let _folder = build.fold_output(|| format!("stage{}-{}", stage, tool));
110         println!("Building stage{} tool {} ({})", stage, tool, target);
111
112         let mut cargo = build.cargo(&compiler, Mode::Tool, target, "build");
113         let dir = build.src.join("src/tools").join(tool);
114         cargo.arg("--manifest-path").arg(dir.join("Cargo.toml"));
115
116         // We don't want to build tools dynamically as they'll be running across
117         // stages and such and it's just easier if they're not dynamically linked.
118         cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
119
120         if let Some(dir) = build.openssl_install_dir(target) {
121             cargo.env("OPENSSL_STATIC", "1");
122             cargo.env("OPENSSL_DIR", dir);
123             cargo.env("LIBZ_SYS_STATIC", "1");
124         }
125
126         cargo.env("CFG_RELEASE_CHANNEL", &build.config.channel);
127
128         let info = GitInfo::new(&dir);
129         if let Some(sha) = info.sha() {
130             cargo.env("CFG_COMMIT_HASH", sha);
131         }
132         if let Some(sha_short) = info.sha_short() {
133             cargo.env("CFG_SHORT_COMMIT_HASH", sha_short);
134         }
135         if let Some(date) = info.commit_date() {
136             cargo.env("CFG_COMMIT_DATE", date);
137         }
138
139         build.run(&mut cargo);
140         build.cargo_out(compiler, Mode::Tool, target).join(exe(tool, compiler.host))
141     }
142 }
143
144 macro_rules! tool {
145     ($($name:ident, $path:expr, $tool_name:expr, $mode:expr;)+) => {
146         #[derive(Copy, Clone)]
147         pub enum Tool {
148             $(
149                 $name,
150             )+
151         }
152
153         impl<'a> Builder<'a> {
154             pub fn tool_exe(&self, tool: Tool) -> PathBuf {
155                 match tool {
156                     $(Tool::$name =>
157                         self.ensure($name {
158                             stage: 0,
159                             target: &self.build.build,
160                         }),
161                     )+
162                 }
163             }
164         }
165
166         $(
167         #[derive(Serialize)]
168         pub struct $name<'a> {
169             pub stage: u32,
170             pub target: &'a str,
171         }
172
173         impl<'a> Step<'a> for $name<'a> {
174             type Output = PathBuf;
175             const NAME: &'static str = concat!(stringify!($name), " tool");
176
177             fn should_run(_builder: &Builder, path: &Path) -> bool {
178                 path.ends_with($path)
179             }
180
181             fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) {
182                 builder.ensure($name {
183                     stage: builder.top_stage,
184                     target,
185                 });
186             }
187
188             fn run(self, builder: &Builder) -> PathBuf {
189                 builder.ensure(ToolBuild {
190                     stage: self.stage,
191                     target: self.target,
192                     tool: $tool_name,
193                     mode: $mode,
194                 })
195             }
196         }
197         )+
198     }
199 }
200
201 tool!(
202     // rules.build("tool-rustbook", "src/tools/rustbook")
203     //      .dep(|s| s.name("maybe-clean-tools"))
204     //      .dep(|s| s.name("librustc-tool"))
205     //      .run(move |s| compile::tool(build, s.stage, s.target, "rustbook"));
206     Rustbook, "src/tools/rustbook", "rustbook", Mode::Librustc;
207     // rules.build("tool-error-index", "src/tools/error_index_generator")
208     //      .dep(|s| s.name("maybe-clean-tools"))
209     //      .dep(|s| s.name("librustc-tool"))
210     //      .run(move |s| compile::tool(build, s.stage, s.target, "error_index_generator"));
211     ErrorIndex, "src/tools/error_index_generator", "error_index_generator", Mode::Librustc;
212     // rules.build("tool-unstable-book-gen", "src/tools/unstable-book-gen")
213     //      .dep(|s| s.name("maybe-clean-tools"))
214     //      .dep(|s| s.name("libstd-tool"))
215     //      .run(move |s| compile::tool(build, s.stage, s.target, "unstable-book-gen"));
216     UnstableBook, "src/tools/unstable-book-gen", "unstable-book-gen", Mode::Libstd;
217     // rules.build("tool-tidy", "src/tools/tidy")
218     //      .dep(|s| s.name("maybe-clean-tools"))
219     //      .dep(|s| s.name("libstd-tool"))
220     //      .run(move |s| compile::tool(build, s.stage, s.target, "tidy"));
221     Tidy, "src/tools/tidy", "tidy", Mode::Libstd;
222     // rules.build("tool-linkchecker", "src/tools/linkchecker")
223     //      .dep(|s| s.name("maybe-clean-tools"))
224     //      .dep(|s| s.name("libstd-tool"))
225     //      .run(move |s| compile::tool(build, s.stage, s.target, "linkchecker"));
226     Linkchecker, "src/tools/linkchecker", "linkchecker", Mode::Libstd;
227     // rules.build("tool-cargotest", "src/tools/cargotest")
228     //      .dep(|s| s.name("maybe-clean-tools"))
229     //      .dep(|s| s.name("libstd-tool"))
230     //      .run(move |s| compile::tool(build, s.stage, s.target, "cargotest"));
231     CargoTest, "src/tools/cargotest", "cargotest", Mode::Libstd;
232     // rules.build("tool-compiletest", "src/tools/compiletest")
233     //      .dep(|s| s.name("maybe-clean-tools"))
234     //      .dep(|s| s.name("libtest-tool"))
235     //      .run(move |s| compile::tool(build, s.stage, s.target, "compiletest"));
236     Compiletest, "src/tools/compiletest", "compiletest", Mode::Libtest;
237     // rules.build("tool-build-manifest", "src/tools/build-manifest")
238     //      .dep(|s| s.name("maybe-clean-tools"))
239     //      .dep(|s| s.name("libstd-tool"))
240     //      .run(move |s| compile::tool(build, s.stage, s.target, "build-manifest"));
241     BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::Libstd;
242     // rules.build("tool-remote-test-server", "src/tools/remote-test-server")
243     //      .dep(|s| s.name("maybe-clean-tools"))
244     //      .dep(|s| s.name("libstd-tool"))
245     //      .run(move |s| compile::tool(build, s.stage, s.target, "remote-test-server"));
246     RemoteTestServer, "src/tools/remote-test-server", "remote-test-server", Mode::Libstd;
247     // rules.build("tool-remote-test-client", "src/tools/remote-test-client")
248     //      .dep(|s| s.name("maybe-clean-tools"))
249     //      .dep(|s| s.name("libstd-tool"))
250     //      .run(move |s| compile::tool(build, s.stage, s.target, "remote-test-client"));
251     RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::Libstd;
252     // rules.build("tool-rust-installer", "src/tools/rust-installer")
253     //      .dep(|s| s.name("maybe-clean-tools"))
254     //      .dep(|s| s.name("libstd-tool"))
255     //      .run(move |s| compile::tool(build, s.stage, s.target, "rust-installer"));
256     RustInstaller, "src/tools/rust-installer", "rust-installer", Mode::Libstd;
257 );
258
259 // rules.build("tool-cargo", "src/tools/cargo")
260 //      .host(true)
261 //      .default(build.config.extended)
262 //      .dep(|s| s.name("maybe-clean-tools"))
263 //      .dep(|s| s.name("libstd-tool"))
264 //      .dep(|s| s.stage(0).host(s.target).name("openssl"))
265 //      .dep(move |s| {
266 //          // Cargo depends on procedural macros, which requires a full host
267 //          // compiler to be available, so we need to depend on that.
268 //          s.name("librustc-link")
269 //           .target(&build.build)
270 //           .host(&build.build)
271 //      })
272 //      .run(move |s| compile::tool(build, s.stage, s.target, "cargo"));
273 #[derive(Serialize)]
274 pub struct Cargo<'a> {
275     pub stage: u32,
276     pub target: &'a str,
277 }
278
279 impl<'a> Step<'a> for Cargo<'a> {
280     type Output = PathBuf;
281     const NAME: &'static str = "cargo tool";
282     const DEFAULT: bool = true;
283     const ONLY_HOSTS: bool = true;
284
285     fn should_run(_builder: &Builder, path: &Path) -> bool {
286         path.ends_with("src/tools/cargo")
287     }
288
289     fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) {
290         if path.is_none() && !builder.build.config.extended {
291             return;
292         }
293         builder.ensure(Cargo {
294             stage: builder.top_stage,
295             target,
296         });
297     }
298
299     fn run(self, builder: &Builder) -> PathBuf {
300         builder.ensure(native::Openssl {
301             target: self.target,
302         });
303         // Cargo depends on procedural macros, which requires a full host
304         // compiler to be available, so we need to depend on that.
305         builder.ensure(Rustc {
306             compiler: builder.compiler(builder.top_stage, &builder.build.build),
307             target: &builder.build.build,
308         });
309         builder.ensure(ToolBuild {
310             stage: self.stage,
311             target: self.target,
312             tool: "cargo",
313             mode: Mode::Libstd,
314         })
315     }
316 }
317
318 // rules.build("tool-rls", "src/tools/rls")
319 //      .host(true)
320 //      .default(build.config.extended)
321 //      .dep(|s| s.name("librustc-tool"))
322 //      .dep(|s| s.stage(0).host(s.target).name("openssl"))
323 //      .dep(move |s| {
324 //          // rls, like cargo, uses procedural macros
325 //          s.name("librustc-link")
326 //           .target(&build.build)
327 //           .host(&build.build)
328 //      })
329 //      .run(move |s| compile::tool(build, s.stage, s.target, "rls"));
330 //
331 #[derive(Serialize)]
332 pub struct Rls<'a> {
333     pub stage: u32,
334     pub target: &'a str,
335 }
336
337 impl<'a> Step<'a> for Rls<'a> {
338     type Output = PathBuf;
339     const NAME: &'static str = "RLS tool";
340     const DEFAULT: bool = true;
341     const ONLY_HOSTS: bool = true;
342
343     fn should_run(_builder: &Builder, path: &Path) -> bool {
344         path.ends_with("src/tools/rls")
345     }
346
347     fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) {
348         if path.is_none() && !builder.build.config.extended {
349             return;
350         }
351         builder.ensure(Cargo {
352             stage: builder.top_stage,
353             target,
354         });
355     }
356
357     fn run(self, builder: &Builder) -> PathBuf {
358         builder.ensure(native::Openssl {
359             target: self.target,
360         });
361         // RLS depends on procedural macros, which requires a full host
362         // compiler to be available, so we need to depend on that.
363         builder.ensure(Rustc {
364             compiler: builder.compiler(builder.top_stage, &builder.build.build),
365             target: &builder.build.build,
366         });
367         builder.ensure(ToolBuild {
368             stage: self.stage,
369             target: self.target,
370             tool: "rls",
371             mode: Mode::Librustc,
372         })
373     }
374 }