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.
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.
13 use std
::path
::PathBuf
;
14 use std
::process
::Command
;
18 use builder
::{Step, RunConfig, ShouldRun, Builder}
;
19 use util
::{copy, exe, add_lib_path}
;
20 use compile
::{self, libtest_stamp, libstd_stamp, librustc_stamp}
;
25 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
26 pub struct CleanTools
{
27 pub compiler
: Compiler
,
28 pub target
: Interned
<String
>,
32 impl Step
for CleanTools
{
35 fn should_run(run
: ShouldRun
) -> ShouldRun
{
39 /// Build a tool in `src/tools`
41 /// This will build the specified tool with the specified `host` compiler in
42 /// `stage` into the normal cargo output directory.
43 fn run(self, builder
: &Builder
) {
44 let build
= builder
.build
;
45 let compiler
= self.compiler
;
46 let target
= self.target
;
49 let stamp
= match mode
{
50 Mode
::Libstd
=> libstd_stamp(build
, compiler
, target
),
51 Mode
::Libtest
=> libtest_stamp(build
, compiler
, target
),
52 Mode
::Librustc
=> librustc_stamp(build
, compiler
, target
),
55 let out_dir
= build
.cargo_out(compiler
, Mode
::Tool
, target
);
56 build
.clear_if_dirty(&out_dir
, &stamp
);
60 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
63 target
: Interned
<String
>,
68 impl Step
for ToolBuild
{
69 type Output
= PathBuf
;
71 fn should_run(run
: ShouldRun
) -> ShouldRun
{
75 /// Build a tool in `src/tools`
77 /// This will build the specified tool with the specified `host` compiler in
78 /// `stage` into the normal cargo output directory.
79 fn run(self, builder
: &Builder
) -> PathBuf
{
80 let build
= builder
.build
;
81 let compiler
= self.compiler
;
82 let target
= self.target
;
86 Mode
::Libstd
=> builder
.ensure(compile
::Std { compiler, target }
),
87 Mode
::Libtest
=> builder
.ensure(compile
::Test { compiler, target }
),
88 Mode
::Librustc
=> builder
.ensure(compile
::Rustc { compiler, target }
),
89 Mode
::Tool
=> panic
!("unexpected Mode::Tool for tool build")
92 let _folder
= build
.fold_output(|| format
!("stage{}-{}", compiler
.stage
, tool
));
93 println
!("Building stage{} tool {} ({})", compiler
.stage
, tool
, target
);
95 let mut cargo
= prepare_tool_cargo(builder
, compiler
, target
, tool
);
96 build
.run(&mut cargo
);
97 build
.cargo_out(compiler
, Mode
::Tool
, target
).join(exe(tool
, &compiler
.host
))
101 fn prepare_tool_cargo(
104 target
: Interned
<String
>,
107 let build
= builder
.build
;
108 let mut cargo
= builder
.cargo(compiler
, Mode
::Tool
, target
, "build");
109 let dir
= build
.src
.join("src/tools").join(tool
);
110 cargo
.arg("--manifest-path").arg(dir
.join("Cargo.toml"));
112 // We don't want to build tools dynamically as they'll be running across
113 // stages and such and it's just easier if they're not dynamically linked.
114 cargo
.env("RUSTC_NO_PREFER_DYNAMIC", "1");
116 if let Some(dir
) = build
.openssl_install_dir(target
) {
117 cargo
.env("OPENSSL_STATIC", "1");
118 cargo
.env("OPENSSL_DIR", dir
);
119 cargo
.env("LIBZ_SYS_STATIC", "1");
122 cargo
.env("CFG_RELEASE_CHANNEL", &build
.config
.channel
);
124 let info
= GitInfo
::new(&build
.config
, &dir
);
125 if let Some(sha
) = info
.sha() {
126 cargo
.env("CFG_COMMIT_HASH", sha
);
128 if let Some(sha_short
) = info
.sha_short() {
129 cargo
.env("CFG_SHORT_COMMIT_HASH", sha_short
);
131 if let Some(date
) = info
.commit_date() {
132 cargo
.env("CFG_COMMIT_DATE", date
);
138 ($
($name
:ident
, $path
:expr
, $tool_name
:expr
, $mode
:expr
;)+) => {
139 #[derive(Copy, Clone)]
146 impl<'a
> Builder
<'a
> {
147 pub fn tool_exe(&self, tool
: Tool
) -> PathBuf
{
151 compiler
: self.compiler(0, self.build
.build
),
152 target
: self.build
.build
,
160 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
162 pub compiler
: Compiler
,
163 pub target
: Interned
<String
>,
166 impl Step
for $name
{
167 type Output
= PathBuf
;
169 fn should_run(run
: ShouldRun
) -> ShouldRun
{
173 fn make_run(run
: RunConfig
) {
174 run
.builder
.ensure($name
{
175 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.builder
.build
.build
),
180 fn run(self, builder
: &Builder
) -> PathBuf
{
181 builder
.ensure(ToolBuild
{
182 compiler
: self.compiler
,
194 Rustbook
, "src/tools/rustbook", "rustbook", Mode
::Librustc
;
195 ErrorIndex
, "src/tools/error_index_generator", "error_index_generator", Mode
::Librustc
;
196 UnstableBookGen
, "src/tools/unstable-book-gen", "unstable-book-gen", Mode
::Libstd
;
197 Tidy
, "src/tools/tidy", "tidy", Mode
::Libstd
;
198 Linkchecker
, "src/tools/linkchecker", "linkchecker", Mode
::Libstd
;
199 CargoTest
, "src/tools/cargotest", "cargotest", Mode
::Libstd
;
200 Compiletest
, "src/tools/compiletest", "compiletest", Mode
::Libtest
;
201 BuildManifest
, "src/tools/build-manifest", "build-manifest", Mode
::Libstd
;
202 RemoteTestClient
, "src/tools/remote-test-client", "remote-test-client", Mode
::Libstd
;
203 RustInstaller
, "src/tools/rust-installer", "rust-installer", Mode
::Libstd
;
206 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
207 pub struct RemoteTestServer
{
208 pub compiler
: Compiler
,
209 pub target
: Interned
<String
>,
212 impl Step
for RemoteTestServer
{
213 type Output
= PathBuf
;
215 fn should_run(run
: ShouldRun
) -> ShouldRun
{
216 run
.path("src/tools/remote-test-server")
219 fn make_run(run
: RunConfig
) {
220 run
.builder
.ensure(RemoteTestServer
{
221 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.builder
.build
.build
),
226 fn run(self, builder
: &Builder
) -> PathBuf
{
227 builder
.ensure(ToolBuild
{
228 compiler
: self.compiler
,
230 tool
: "remote-test-server",
236 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
238 pub host
: Interned
<String
>,
241 impl Step
for Rustdoc
{
242 type Output
= PathBuf
;
243 const DEFAULT
: bool
= true;
244 const ONLY_HOSTS
: bool
= true;
246 fn should_run(run
: ShouldRun
) -> ShouldRun
{
247 run
.path("src/tools/rustdoc")
250 fn make_run(run
: RunConfig
) {
251 run
.builder
.ensure(Rustdoc
{
256 fn run(self, builder
: &Builder
) -> PathBuf
{
257 let build
= builder
.build
;
258 let target_compiler
= builder
.compiler(builder
.top_stage
, self.host
);
259 let target
= target_compiler
.host
;
260 let build_compiler
= if target_compiler
.stage
== 0 {
261 builder
.compiler(0, builder
.build
.build
)
262 } else if target_compiler
.stage
>= 2 {
263 // Past stage 2, we consider the compiler to be ABI-compatible and hence capable of
264 // building rustdoc itself.
265 builder
.compiler(target_compiler
.stage
, builder
.build
.build
)
267 // Similar to `compile::Assemble`, build with the previous stage's compiler. Otherwise
268 // we'd have stageN/bin/rustc and stageN/bin/rustdoc be effectively different stage
269 // compilers, which isn't what we want.
270 builder
.compiler(target_compiler
.stage
- 1, builder
.build
.build
)
273 builder
.ensure(compile
::Rustc { compiler: build_compiler, target }
);
275 let _folder
= build
.fold_output(|| format
!("stage{}-rustdoc", target_compiler
.stage
));
276 println
!("Building rustdoc for stage{} ({})", target_compiler
.stage
, target_compiler
.host
);
278 let mut cargo
= prepare_tool_cargo(builder
, build_compiler
, target
, "rustdoc");
279 build
.run(&mut cargo
);
280 // Cargo adds a number of paths to the dylib search path on windows, which results in
281 // the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool"
282 // rustdoc a different name.
283 let tool_rustdoc
= build
.cargo_out(build_compiler
, Mode
::Tool
, target
)
284 .join(exe("rustdoc-tool-binary", &target_compiler
.host
));
286 // don't create a stage0-sysroot/bin directory.
287 if target_compiler
.stage
> 0 {
288 let sysroot
= builder
.sysroot(target_compiler
);
289 let bindir
= sysroot
.join("bin");
290 t
!(fs
::create_dir_all(&bindir
));
291 let bin_rustdoc
= bindir
.join(exe("rustdoc", &*target_compiler
.host
));
292 let _
= fs
::remove_file(&bin_rustdoc
);
293 copy(&tool_rustdoc
, &bin_rustdoc
);
301 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
303 pub compiler
: Compiler
,
304 pub target
: Interned
<String
>,
307 impl Step
for Cargo
{
308 type Output
= PathBuf
;
309 const DEFAULT
: bool
= true;
310 const ONLY_HOSTS
: bool
= true;
312 fn should_run(run
: ShouldRun
) -> ShouldRun
{
313 let builder
= run
.builder
;
314 run
.path("src/tools/cargo").default_condition(builder
.build
.config
.extended
)
317 fn make_run(run
: RunConfig
) {
318 run
.builder
.ensure(Cargo
{
319 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.builder
.build
.build
),
324 fn run(self, builder
: &Builder
) -> PathBuf
{
325 builder
.ensure(native
::Openssl
{
328 // Cargo depends on procedural macros, which requires a full host
329 // compiler to be available, so we need to depend on that.
330 builder
.ensure(compile
::Rustc
{
331 compiler
: self.compiler
,
332 target
: builder
.build
.build
,
334 builder
.ensure(ToolBuild
{
335 compiler
: self.compiler
,
338 mode
: Mode
::Librustc
,
343 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
345 pub compiler
: Compiler
,
346 pub target
: Interned
<String
>,
350 type Output
= PathBuf
;
351 const DEFAULT
: bool
= true;
352 const ONLY_HOSTS
: bool
= true;
354 fn should_run(run
: ShouldRun
) -> ShouldRun
{
355 let builder
= run
.builder
;
356 run
.path("src/tools/rls").default_condition(builder
.build
.config
.extended
)
359 fn make_run(run
: RunConfig
) {
360 run
.builder
.ensure(Rls
{
361 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.builder
.build
.build
),
366 fn run(self, builder
: &Builder
) -> PathBuf
{
367 builder
.ensure(native
::Openssl
{
370 // RLS depends on procedural macros, which requires a full host
371 // compiler to be available, so we need to depend on that.
372 builder
.ensure(compile
::Rustc
{
373 compiler
: self.compiler
,
374 target
: builder
.build
.build
,
376 builder
.ensure(ToolBuild
{
377 compiler
: self.compiler
,
380 mode
: Mode
::Librustc
,
385 impl<'a
> Builder
<'a
> {
386 /// Get a `Command` which is ready to run `tool` in `stage` built for
388 pub fn tool_cmd(&self, tool
: Tool
) -> Command
{
389 let mut cmd
= Command
::new(self.tool_exe(tool
));
390 let compiler
= self.compiler(0, self.build
.build
);
391 self.prepare_tool_cmd(compiler
, &mut cmd
);
395 /// Prepares the `cmd` provided to be able to run the `compiler` provided.
397 /// Notably this munges the dynamic library lookup path to point to the
398 /// right location to run `compiler`.
399 fn prepare_tool_cmd(&self, compiler
: Compiler
, cmd
: &mut Command
) {
400 let host
= &compiler
.host
;
401 let mut paths
: Vec
<PathBuf
> = vec
![
402 PathBuf
::from(&self.sysroot_libdir(compiler
, compiler
.host
)),
403 self.cargo_out(compiler
, Mode
::Tool
, *host
).join("deps"),
406 // On MSVC a tool may invoke a C compiler (e.g. compiletest in run-make
407 // mode) and that C compiler may need some extra PATH modification. Do
409 if compiler
.host
.contains("msvc") {
410 let curpaths
= env
::var_os("PATH").unwrap_or_default();
411 let curpaths
= env
::split_paths(&curpaths
).collect
::<Vec
<_
>>();
412 for &(ref k
, ref v
) in self.cc
[&compiler
.host
].0.env() {
416 for path
in env
::split_paths(v
) {
417 if !curpaths
.contains(&path
) {
423 add_lib_path(paths
, cmd
);