]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/tool.rs
Auto merge of #43382 - mmatyas:aarch64_ignore-stack-probes, r=alexcrichton
[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::PathBuf;
13 use std::process::Command;
14
15 use Mode;
16 use Compiler;
17 use builder::{Step, RunConfig, ShouldRun, Builder};
18 use util::{exe, add_lib_path};
19 use compile::{self, libtest_stamp, libstd_stamp, librustc_stamp};
20 use native;
21 use channel::GitInfo;
22 use cache::Interned;
23
24 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
25 pub struct CleanTools {
26     pub stage: u32,
27     pub target: Interned<String>,
28     pub mode: Mode,
29 }
30
31 impl Step for CleanTools {
32     type Output = ();
33
34     fn should_run(run: ShouldRun) -> ShouldRun {
35         run.never()
36     }
37
38     /// Build a tool in `src/tools`
39     ///
40     /// This will build the specified tool with the specified `host` compiler in
41     /// `stage` into the normal cargo output directory.
42     fn run(self, builder: &Builder) {
43         let build = builder.build;
44         let stage = self.stage;
45         let target = self.target;
46         let mode = self.mode;
47
48         let compiler = builder.compiler(stage, build.build);
49
50         let stamp = match mode {
51             Mode::Libstd => libstd_stamp(build, compiler, target),
52             Mode::Libtest => libtest_stamp(build, compiler, target),
53             Mode::Librustc => librustc_stamp(build, compiler, target),
54             _ => panic!(),
55         };
56         let out_dir = build.cargo_out(compiler, Mode::Tool, target);
57         build.clear_if_dirty(&out_dir, &stamp);
58     }
59 }
60
61 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
62 pub struct ToolBuild {
63     pub stage: u32,
64     pub target: Interned<String>,
65     pub tool: &'static str,
66     pub mode: Mode,
67 }
68
69 impl Step for ToolBuild {
70     type Output = PathBuf;
71
72     fn should_run(run: ShouldRun) -> ShouldRun {
73         run.never()
74     }
75
76     /// Build a tool in `src/tools`
77     ///
78     /// This will build the specified tool with the specified `host` compiler in
79     /// `stage` into the normal cargo output directory.
80     fn run(self, builder: &Builder) -> PathBuf {
81         let build = builder.build;
82         let stage = self.stage;
83         let target = self.target;
84         let tool = self.tool;
85
86         let compiler = builder.compiler(stage, build.build);
87         builder.ensure(CleanTools { stage, target, mode: self.mode });
88         match self.mode {
89             Mode::Libstd => builder.ensure(compile::Std { compiler, target }),
90             Mode::Libtest => builder.ensure(compile::Test { compiler, target }),
91             Mode::Librustc => builder.ensure(compile::Rustc { compiler, target }),
92             Mode::Tool => panic!("unexpected Mode::Tool for tool build")
93         }
94
95         let _folder = build.fold_output(|| format!("stage{}-{}", stage, tool));
96         println!("Building stage{} tool {} ({})", stage, tool, target);
97
98         let mut cargo = builder.cargo(compiler, Mode::Tool, target, "build");
99         let dir = build.src.join("src/tools").join(tool);
100         cargo.arg("--manifest-path").arg(dir.join("Cargo.toml"));
101
102         // We don't want to build tools dynamically as they'll be running across
103         // stages and such and it's just easier if they're not dynamically linked.
104         cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
105
106         if let Some(dir) = build.openssl_install_dir(target) {
107             cargo.env("OPENSSL_STATIC", "1");
108             cargo.env("OPENSSL_DIR", dir);
109             cargo.env("LIBZ_SYS_STATIC", "1");
110         }
111
112         cargo.env("CFG_RELEASE_CHANNEL", &build.config.channel);
113
114         let info = GitInfo::new(&dir);
115         if let Some(sha) = info.sha() {
116             cargo.env("CFG_COMMIT_HASH", sha);
117         }
118         if let Some(sha_short) = info.sha_short() {
119             cargo.env("CFG_SHORT_COMMIT_HASH", sha_short);
120         }
121         if let Some(date) = info.commit_date() {
122             cargo.env("CFG_COMMIT_DATE", date);
123         }
124
125         build.run(&mut cargo);
126         build.cargo_out(compiler, Mode::Tool, target).join(exe(tool, &compiler.host))
127     }
128 }
129
130 macro_rules! tool {
131     ($($name:ident, $path:expr, $tool_name:expr, $mode:expr;)+) => {
132         #[derive(Copy, Clone)]
133         pub enum Tool {
134             $(
135                 $name,
136             )+
137         }
138
139         impl<'a> Builder<'a> {
140             pub fn tool_exe(&self, tool: Tool) -> PathBuf {
141                 match tool {
142                     $(Tool::$name =>
143                         self.ensure($name {
144                             stage: 0,
145                             target: self.build.build,
146                         }),
147                     )+
148                 }
149             }
150         }
151
152         $(
153             #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
154         pub struct $name {
155             pub stage: u32,
156             pub target: Interned<String>,
157         }
158
159         impl Step for $name {
160             type Output = PathBuf;
161
162             fn should_run(run: ShouldRun) -> ShouldRun {
163                 run.path($path)
164             }
165
166             fn make_run(run: RunConfig) {
167                 run.builder.ensure($name {
168                     stage: run.builder.top_stage,
169                     target: run.target,
170                 });
171             }
172
173             fn run(self, builder: &Builder) -> PathBuf {
174                 builder.ensure(ToolBuild {
175                     stage: self.stage,
176                     target: self.target,
177                     tool: $tool_name,
178                     mode: $mode,
179                 })
180             }
181         }
182         )+
183     }
184 }
185
186 tool!(
187     Rustbook, "src/tools/rustbook", "rustbook", Mode::Librustc;
188     ErrorIndex, "src/tools/error_index_generator", "error_index_generator", Mode::Librustc;
189     UnstableBookGen, "src/tools/unstable-book-gen", "unstable-book-gen", Mode::Libstd;
190     Tidy, "src/tools/tidy", "tidy", Mode::Libstd;
191     Linkchecker, "src/tools/linkchecker", "linkchecker", Mode::Libstd;
192     CargoTest, "src/tools/cargotest", "cargotest", Mode::Libstd;
193     Compiletest, "src/tools/compiletest", "compiletest", Mode::Libtest;
194     BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::Librustc;
195     RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::Libstd;
196     RustInstaller, "src/tools/rust-installer", "rust-installer", Mode::Libstd;
197 );
198
199 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
200 pub struct RemoteTestServer {
201     pub stage: u32,
202     pub target: Interned<String>,
203 }
204
205 impl Step for RemoteTestServer {
206     type Output = PathBuf;
207
208     fn should_run(run: ShouldRun) -> ShouldRun {
209         run.path("src/tools/remote-test-server")
210     }
211
212     fn make_run(run: RunConfig) {
213         run.builder.ensure(RemoteTestServer {
214             stage: run.builder.top_stage,
215             target: run.target,
216         });
217     }
218
219     fn run(self, builder: &Builder) -> PathBuf {
220         builder.ensure(ToolBuild {
221             stage: self.stage,
222             target: self.target,
223             tool: "remote-test-server",
224             mode: Mode::Libstd,
225         })
226     }
227 }
228
229 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
230 pub struct Cargo {
231     pub stage: u32,
232     pub target: Interned<String>,
233 }
234
235 impl Step for Cargo {
236     type Output = PathBuf;
237     const DEFAULT: bool = true;
238     const ONLY_HOSTS: bool = true;
239
240     fn should_run(run: ShouldRun) -> ShouldRun {
241         let builder = run.builder;
242         run.path("src/tools/cargo").default_condition(builder.build.config.extended)
243     }
244
245     fn make_run(run: RunConfig) {
246         run.builder.ensure(Cargo {
247             stage: run.builder.top_stage,
248             target: run.target,
249         });
250     }
251
252     fn run(self, builder: &Builder) -> PathBuf {
253         builder.ensure(native::Openssl {
254             target: self.target,
255         });
256         // Cargo depends on procedural macros, which requires a full host
257         // compiler to be available, so we need to depend on that.
258         builder.ensure(compile::Rustc {
259             compiler: builder.compiler(self.stage, builder.build.build),
260             target: builder.build.build,
261         });
262         builder.ensure(ToolBuild {
263             stage: self.stage,
264             target: self.target,
265             tool: "cargo",
266             mode: Mode::Libstd,
267         })
268     }
269 }
270
271 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
272 pub struct Rls {
273     pub stage: u32,
274     pub target: Interned<String>,
275 }
276
277 impl Step for Rls {
278     type Output = PathBuf;
279     const DEFAULT: bool = true;
280     const ONLY_HOSTS: bool = true;
281
282     fn should_run(run: ShouldRun) -> ShouldRun {
283         let builder = run.builder;
284         run.path("src/tools/rls").default_condition(builder.build.config.extended)
285     }
286
287     fn make_run(run: RunConfig) {
288         run.builder.ensure(Rls {
289             stage: run.builder.top_stage,
290             target: run.target,
291         });
292     }
293
294     fn run(self, builder: &Builder) -> PathBuf {
295         builder.ensure(native::Openssl {
296             target: self.target,
297         });
298         // RLS depends on procedural macros, which requires a full host
299         // compiler to be available, so we need to depend on that.
300         builder.ensure(compile::Rustc {
301             compiler: builder.compiler(self.stage, builder.build.build),
302             target: builder.build.build,
303         });
304         builder.ensure(ToolBuild {
305             stage: self.stage,
306             target: self.target,
307             tool: "rls",
308             mode: Mode::Librustc,
309         })
310     }
311 }
312
313 impl<'a> Builder<'a> {
314     /// Get a `Command` which is ready to run `tool` in `stage` built for
315     /// `host`.
316     pub fn tool_cmd(&self, tool: Tool) -> Command {
317         let mut cmd = Command::new(self.tool_exe(tool));
318         let compiler = self.compiler(0, self.build.build);
319         self.prepare_tool_cmd(compiler, &mut cmd);
320         cmd
321     }
322
323     /// Prepares the `cmd` provided to be able to run the `compiler` provided.
324     ///
325     /// Notably this munges the dynamic library lookup path to point to the
326     /// right location to run `compiler`.
327     fn prepare_tool_cmd(&self, compiler: Compiler, cmd: &mut Command) {
328         let host = &compiler.host;
329         let mut paths: Vec<PathBuf> = vec![
330             PathBuf::from(&self.sysroot_libdir(compiler, compiler.host)),
331             self.cargo_out(compiler, Mode::Tool, *host).join("deps"),
332         ];
333
334         // On MSVC a tool may invoke a C compiler (e.g. compiletest in run-make
335         // mode) and that C compiler may need some extra PATH modification. Do
336         // so here.
337         if compiler.host.contains("msvc") {
338             let curpaths = env::var_os("PATH").unwrap_or_default();
339             let curpaths = env::split_paths(&curpaths).collect::<Vec<_>>();
340             for &(ref k, ref v) in self.cc[&compiler.host].0.env() {
341                 if k != "PATH" {
342                     continue
343                 }
344                 for path in env::split_paths(v) {
345                     if !curpaths.contains(&path) {
346                         paths.push(path);
347                     }
348                 }
349             }
350         }
351         add_lib_path(paths, cmd);
352     }
353 }