]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/tool.rs
Fix more incorrectly transitioned code
[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 Compiler;
17 use builder::{Step, Builder};
18 use util::{exe, add_lib_path};
19 use compile::{self, libtest_stamp, libstd_stamp, librustc_stamp, Rustc};
20 use native;
21 use channel::GitInfo;
22
23 //// ========================================================================
24 //// Build tools
25 ////
26 //// Tools used during the build system but not shipped
27 //// "pseudo rule" which represents completely cleaning out the tools dir in
28 //// one stage. This needs to happen whenever a dependency changes (e.g.
29 //// libstd, libtest, librustc) and all of the tool compilations above will
30 //// be sequenced after this rule.
31 //rules.build("maybe-clean-tools", "path/to/nowhere")
32 //     .after("librustc-tool")
33 //     .after("libtest-tool")
34 //     .after("libstd-tool");
35 //
36 //rules.build("librustc-tool", "path/to/nowhere")
37 //     .dep(|s| s.name("librustc"))
38 //     .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Librustc));
39 //rules.build("libtest-tool", "path/to/nowhere")
40 //     .dep(|s| s.name("libtest"))
41 //     .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Libtest));
42 //rules.build("libstd-tool", "path/to/nowhere")
43 //     .dep(|s| s.name("libstd"))
44 //     .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Libstd));
45 //
46
47 #[derive(Serialize)]
48 pub struct CleanTools<'a> {
49     pub stage: u32,
50     pub target: &'a str,
51     pub mode: Mode,
52 }
53
54 impl<'a> Step<'a> for CleanTools<'a> {
55     type Output = ();
56
57     /// Build a tool in `src/tools`
58     ///
59     /// This will build the specified tool with the specified `host` compiler in
60     /// `stage` into the normal cargo output directory.
61     fn run(self, builder: &Builder) {
62         let build = builder.build;
63         let stage = self.stage;
64         let target = self.target;
65         let mode = self.mode;
66
67         let compiler = builder.compiler(stage, &build.build);
68
69         let stamp = match mode {
70             Mode::Libstd => libstd_stamp(build, compiler, target),
71             Mode::Libtest => libtest_stamp(build, compiler, target),
72             Mode::Librustc => librustc_stamp(build, compiler, target),
73             _ => panic!(),
74         };
75         let out_dir = build.cargo_out(compiler, Mode::Tool, target);
76         build.clear_if_dirty(&out_dir, &stamp);
77     }
78 }
79
80 #[derive(Serialize)]
81 pub struct ToolBuild<'a> {
82     pub stage: u32,
83     pub target: &'a str,
84     pub tool: &'a str,
85     pub mode: Mode,
86 }
87
88 impl<'a> Step<'a> for ToolBuild<'a> {
89     type Output = PathBuf;
90
91     /// Build a tool in `src/tools`
92     ///
93     /// This will build the specified tool with the specified `host` compiler in
94     /// `stage` into the normal cargo output directory.
95     fn run(self, builder: &Builder) -> PathBuf {
96         let build = builder.build;
97         let stage = self.stage;
98         let target = self.target;
99         let tool = self.tool;
100
101         let compiler = builder.compiler(stage, &build.build);
102         builder.ensure(CleanTools { stage, target, mode: self.mode });
103         match self.mode {
104             Mode::Libstd => builder.ensure(compile::Std { compiler, target }),
105             Mode::Libtest => builder.ensure(compile::Test { compiler, target }),
106             Mode::Librustc => builder.ensure(compile::Rustc { compiler, target }),
107             Mode::Tool => panic!("unexpected Mode::Tool for tool build")
108         }
109
110         let _folder = build.fold_output(|| format!("stage{}-{}", stage, tool));
111         println!("Building stage{} tool {} ({})", stage, tool, target);
112
113         let mut cargo = builder.cargo(compiler, Mode::Tool, target, "build");
114         let dir = build.src.join("src/tools").join(tool);
115         cargo.arg("--manifest-path").arg(dir.join("Cargo.toml"));
116
117         // We don't want to build tools dynamically as they'll be running across
118         // stages and such and it's just easier if they're not dynamically linked.
119         cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
120
121         if let Some(dir) = build.openssl_install_dir(target) {
122             cargo.env("OPENSSL_STATIC", "1");
123             cargo.env("OPENSSL_DIR", dir);
124             cargo.env("LIBZ_SYS_STATIC", "1");
125         }
126
127         cargo.env("CFG_RELEASE_CHANNEL", &build.config.channel);
128
129         let info = GitInfo::new(&dir);
130         if let Some(sha) = info.sha() {
131             cargo.env("CFG_COMMIT_HASH", sha);
132         }
133         if let Some(sha_short) = info.sha_short() {
134             cargo.env("CFG_SHORT_COMMIT_HASH", sha_short);
135         }
136         if let Some(date) = info.commit_date() {
137             cargo.env("CFG_COMMIT_DATE", date);
138         }
139
140         build.run(&mut cargo);
141         build.cargo_out(compiler, Mode::Tool, target).join(exe(tool, compiler.host))
142     }
143 }
144
145 macro_rules! tool {
146     ($($name:ident, $path:expr, $tool_name:expr, $mode:expr;)+) => {
147         #[derive(Copy, Clone)]
148         pub enum Tool {
149             $(
150                 $name,
151             )+
152         }
153
154         impl<'a> Builder<'a> {
155             pub fn tool_exe(&self, tool: Tool) -> PathBuf {
156                 match tool {
157                     $(Tool::$name =>
158                         self.ensure($name {
159                             stage: 0,
160                             target: &self.build.build,
161                         }),
162                     )+
163                 }
164             }
165         }
166
167         $(
168         #[derive(Serialize)]
169         pub struct $name<'a> {
170             pub stage: u32,
171             pub target: &'a str,
172         }
173
174         impl<'a> Step<'a> for $name<'a> {
175             type Output = PathBuf;
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     UnstableBookGen, "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::Librustc;
242     // rules.build("tool-remote-test-client", "src/tools/remote-test-client")
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-client"));
246     RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::Libstd;
247     // rules.build("tool-rust-installer", "src/tools/rust-installer")
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, "rust-installer"));
251     RustInstaller, "src/tools/rust-installer", "rust-installer", Mode::Libstd;
252 );
253
254 #[derive(Serialize)]
255 pub struct RemoteTestServer<'a> {
256     pub compiler: Compiler<'a>,
257     pub target: &'a str,
258 }
259
260 impl<'a> Step<'a> for RemoteTestServer<'a> {
261     type Output = PathBuf;
262
263     fn should_run(_builder: &Builder, path: &Path) -> bool {
264         path.ends_with("src/tools/remote-test-server")
265     }
266
267     fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) {
268         builder.ensure(RemoteTestServer {
269             compiler: builder.compiler(builder.top_stage, host),
270             target,
271         });
272     }
273
274     fn run(self, builder: &Builder) -> PathBuf {
275         builder.ensure(ToolBuild {
276             stage: self.stage,
277             target: self.target,
278             tool: "remote-test-server",
279             mode: Mode::Libstd,
280         })
281     }
282 }
283
284 // rules.build("tool-cargo", "src/tools/cargo")
285 //      .host(true)
286 //      .default(build.config.extended)
287 //      .dep(|s| s.name("maybe-clean-tools"))
288 //      .dep(|s| s.name("libstd-tool"))
289 //      .dep(|s| s.stage(0).host(s.target).name("openssl"))
290 //      .dep(move |s| {
291 //          // Cargo depends on procedural macros, which requires a full host
292 //          // compiler to be available, so we need to depend on that.
293 //          s.name("librustc-link")
294 //           .target(&build.build)
295 //           .host(&build.build)
296 //      })
297 //      .run(move |s| compile::tool(build, s.stage, s.target, "cargo"));
298 #[derive(Serialize)]
299 pub struct Cargo<'a> {
300     pub stage: u32,
301     pub target: &'a str,
302 }
303
304 impl<'a> Step<'a> for Cargo<'a> {
305     type Output = PathBuf;
306     const DEFAULT: bool = true;
307     const ONLY_HOSTS: bool = true;
308
309     fn should_run(_builder: &Builder, path: &Path) -> bool {
310         path.ends_with("src/tools/cargo")
311     }
312
313     fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) {
314         if path.is_none() && !builder.build.config.extended {
315             return;
316         }
317         builder.ensure(Cargo {
318             stage: builder.top_stage,
319             target,
320         });
321     }
322
323     fn run(self, builder: &Builder) -> PathBuf {
324         builder.ensure(native::Openssl {
325             target: self.target,
326         });
327         // Cargo depends on procedural macros, which requires a full host
328         // compiler to be available, so we need to depend on that.
329         builder.ensure(Rustc {
330             compiler: builder.compiler(builder.top_stage, &builder.build.build),
331             target: &builder.build.build,
332         });
333         builder.ensure(ToolBuild {
334             stage: self.stage,
335             target: self.target,
336             tool: "cargo",
337             mode: Mode::Libstd,
338         })
339     }
340 }
341
342 // rules.build("tool-rls", "src/tools/rls")
343 //      .host(true)
344 //      .default(build.config.extended)
345 //      .dep(|s| s.name("librustc-tool"))
346 //      .dep(|s| s.stage(0).host(s.target).name("openssl"))
347 //      .dep(move |s| {
348 //          // rls, like cargo, uses procedural macros
349 //          s.name("librustc-link")
350 //           .target(&build.build)
351 //           .host(&build.build)
352 //      })
353 //      .run(move |s| compile::tool(build, s.stage, s.target, "rls"));
354 //
355 #[derive(Serialize)]
356 pub struct Rls<'a> {
357     pub stage: u32,
358     pub target: &'a str,
359 }
360
361 impl<'a> Step<'a> for Rls<'a> {
362     type Output = PathBuf;
363     const DEFAULT: bool = true;
364     const ONLY_HOSTS: bool = true;
365
366     fn should_run(_builder: &Builder, path: &Path) -> bool {
367         path.ends_with("src/tools/rls")
368     }
369
370     fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) {
371         if path.is_none() && !builder.build.config.extended {
372             return;
373         }
374         builder.ensure(Cargo {
375             stage: builder.top_stage,
376             target,
377         });
378     }
379
380     fn run(self, builder: &Builder) -> PathBuf {
381         builder.ensure(native::Openssl {
382             target: self.target,
383         });
384         // RLS depends on procedural macros, which requires a full host
385         // compiler to be available, so we need to depend on that.
386         builder.ensure(Rustc {
387             compiler: builder.compiler(builder.top_stage, &builder.build.build),
388             target: &builder.build.build,
389         });
390         builder.ensure(ToolBuild {
391             stage: self.stage,
392             target: self.target,
393             tool: "rls",
394             mode: Mode::Librustc,
395         })
396     }
397 }
398
399 impl<'a> Builder<'a> {
400     /// Get a `Command` which is ready to run `tool` in `stage` built for
401     /// `host`.
402     pub fn tool_cmd(&self, tool: Tool) -> Command {
403         let mut cmd = Command::new(self.tool_exe(tool));
404         let compiler = self.compiler(0, &self.build.build);
405         self.prepare_tool_cmd(compiler, &mut cmd);
406         cmd
407     }
408
409     /// Prepares the `cmd` provided to be able to run the `compiler` provided.
410     ///
411     /// Notably this munges the dynamic library lookup path to point to the
412     /// right location to run `compiler`.
413     fn prepare_tool_cmd(&self, compiler: Compiler, cmd: &mut Command) {
414         let host = compiler.host;
415         let mut paths = vec![
416             self.sysroot_libdir(compiler, compiler.host),
417             self.cargo_out(compiler, Mode::Tool, host).join("deps"),
418         ];
419
420         // On MSVC a tool may invoke a C compiler (e.g. compiletest in run-make
421         // mode) and that C compiler may need some extra PATH modification. Do
422         // so here.
423         if compiler.host.contains("msvc") {
424             let curpaths = env::var_os("PATH").unwrap_or_default();
425             let curpaths = env::split_paths(&curpaths).collect::<Vec<_>>();
426             for &(ref k, ref v) in self.cc[compiler.host].0.env() {
427                 if k != "PATH" {
428                     continue
429                 }
430                 for path in env::split_paths(v) {
431                     if !curpaths.contains(&path) {
432                         paths.push(path);
433                     }
434                 }
435             }
436         }
437         add_lib_path(paths, cmd);
438     }
439 }