]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/compile.rs
Change code to work with the new system
[rust.git] / src / bootstrap / compile.rs
1 // Copyright 2015 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 //! Implementation of compiling various phases of the compiler and standard
12 //! library.
13 //!
14 //! This module contains some of the real meat in the rustbuild build system
15 //! which is where Cargo is used to compiler the standard library, libtest, and
16 //! compiler. This module is also responsible for assembling the sysroot as it
17 //! goes along from the output of the previous stage.
18
19 use std::env;
20 use std::fs::{self, File};
21 use std::io::BufReader;
22 use std::io::prelude::*;
23 use std::path::{Path, PathBuf};
24 use std::process::{Command, Stdio};
25 use std::str;
26
27 use build_helper::{output, mtime, up_to_date};
28 use filetime::FileTime;
29 use rustc_serialize::json;
30
31 use channel::GitInfo;
32 use util::{exe, libdir, is_dylib, copy};
33 use {Build, Compiler, Mode};
34
35 //
36 //    // Crates which have build scripts need to rely on this rule to ensure that
37 //    // the necessary prerequisites for a build script are linked and located in
38 //    // place.
39 //    rules.build("may-run-build-script", "path/to/nowhere")
40 //         .dep(move |s| {
41 //             s.name("libstd-link")
42 //              .host(&build.build)
43 //              .target(&build.build)
44 //         });
45
46 //    // ========================================================================
47 //    // Crate compilations
48 //    //
49 //    // Tools used during the build system but not shipped
50 //    // These rules are "pseudo rules" that don't actually do any work
51 //    // themselves, but represent a complete sysroot with the relevant compiler
52 //    // linked into place.
53 //    //
54 //    // That is, depending on "libstd" means that when the rule is completed then
55 //    // the `stage` sysroot for the compiler `host` will be available with a
56 //    // standard library built for `target` linked in place. Not all rules need
57 //    // the compiler itself to be available, just the standard library, so
58 //    // there's a distinction between the two.
59 //    rules.build("libstd", "src/libstd")
60 //         .dep(|s| s.name("rustc").target(s.host))
61 //         .dep(|s| s.name("libstd-link"));
62 //    rules.build("libtest", "src/libtest")
63 //         .dep(|s| s.name("libstd"))
64 //         .dep(|s| s.name("libtest-link"))
65 //         .default(true);
66 //    rules.build("librustc", "src/librustc")
67 //         .dep(|s| s.name("libtest"))
68 //         .dep(|s| s.name("librustc-link"))
69 //         .host(true)
70 //         .default(true);
71
72 // Helper method to define the rules to link a crate into its place in the
73 // sysroot.
74 //
75 // The logic here is a little subtle as there's a few cases to consider.
76 // Not all combinations of (stage, host, target) actually require something
77 // to be compiled, but rather libraries could get propagated from a
78 // different location. For example:
79 //
80 // * Any crate with a `host` that's not the build triple will not actually
81 //   compile something. A different `host` means that the build triple will
82 //   actually compile the libraries, and then we'll copy them over from the
83 //   build triple to the `host` directory.
84 //
85 // * Some crates aren't even compiled by the build triple, but may be copied
86 //   from previous stages. For example if we're not doing a full bootstrap
87 //   then we may just depend on the stage1 versions of libraries to be
88 //   available to get linked forward.
89 //
90 // * Finally, there are some cases, however, which do indeed comiple crates
91 //   and link them into place afterwards.
92 //
93 // The rule definition below mirrors these three cases. The `dep` method
94 // calculates the correct dependency which either comes from stage1, a
95 // different compiler, or from actually building the crate itself (the `dep`
96 // rule). The `run` rule then mirrors these three cases and links the cases
97 // forward into the compiler sysroot specified from the correct location.
98 fn crate_rule<'a, 'b>(build: &'a Build,
99                         rules: &'b mut Rules<'a>,
100                         krate: &'a str,
101                         dep: &'a str,
102                         link: fn(&Build, &Compiler, &Compiler, &str))
103                         -> RuleBuilder<'a, 'b> {
104     let mut rule = rules.build(&krate, "path/to/nowhere");
105     rule.dep(move |s| {
106             if build.force_use_stage1(&s.compiler(), s.target) {
107                 s.host(&build.build).stage(1)
108             } else if s.host == build.build {
109                 s.name(dep)
110             } else {
111                 s.host(&build.build)
112             }
113         })
114         .run(move |s| {
115             if build.force_use_stage1(&s.compiler(), s.target) {
116                 link(build,
117                         &s.stage(1).host(&build.build).compiler(),
118                         &s.compiler(),
119                         s.target)
120             } else if s.host == build.build {
121                 link(build, &s.compiler(), &s.compiler(), s.target)
122             } else {
123                 link(build,
124                         &s.host(&build.build).compiler(),
125                         &s.compiler(),
126                         s.target)
127             }
128         });
129         rule
130 }
131
132 //        rules.build("libstd", "src/libstd")
133 //             .dep(|s| s.name("rustc").target(s.host))
134 //             .dep(|s| s.name("libstd-link"));
135 //    for (krate, path, _default) in krates("std") {
136 //        rules.build(&krate.build_step, path)
137 //             .dep(|s| s.name("startup-objects"))
138 //             .dep(move |s| s.name("rustc").host(&build.build).target(s.host))
139 //             .run(move |s| compile::std(build, s.target, &s.compiler()));
140 //    }
141 #[derive(Serialize)]
142 pub struct Std<'a> {
143     pub target: &'a str,
144     pub compiler: &'a Compiler<'a>,
145 }
146
147 impl<'a> Step<'a> for Std<'a> {
148     type Output = ();
149     const DEFAULT: bool = true;
150
151     fn should_run(builder: &Builder, path: &Path) -> bool {
152         path.ends_with("src/libstd") ||
153         builder.crates("std").into_iter().any(|(_, krate_path)| {
154             path.ends_with(krate_path)
155         })
156     }
157
158     fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) {
159         builder.ensure(Std {
160             compiler: builder.compiler(builder.top_stage, host),
161             target,
162         })
163     }
164
165     /// Build the standard library.
166     ///
167     /// This will build the standard library for a particular stage of the build
168     /// using the `compiler` targeting the `target` architecture. The artifacts
169     /// created will also be linked into the sysroot directory.
170     fn run(self, builder: &Builder) {
171         let build = builder.build;
172         let target = self.target;
173         let compiler = self.compiler;
174
175         builder.ensure(StartupObjects { compiler, target });
176
177         if build.force_use_stage1(compiler, target) {
178             let from = builder.compiler(1, &build.build);
179             builder.ensure(Std {
180                 compiler: from,
181                 target: target,
182             });
183             println!("Uplifting stage1 std ({} -> {})", from.host, target);
184             builder.ensure(StdLink {
185                 compiler: from,
186                 target_compiler: compiler,
187                 target: target,
188             });
189             return;
190         }
191
192         let _folder = build.fold_output(|| format!("stage{}-std", compiler.stage));
193         println!("Building stage{} std artifacts ({} -> {})", compiler.stage,
194                 compiler.host, target);
195
196         let out_dir = build.cargo_out(compiler, Mode::Libstd, target);
197         build.clear_if_dirty(&out_dir, &build.compiler_path(compiler));
198         let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "build");
199         let mut features = build.std_features();
200
201         if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
202             cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
203         }
204
205         // When doing a local rebuild we tell cargo that we're stage1 rather than
206         // stage0. This works fine if the local rust and being-built rust have the
207         // same view of what the default allocator is, but fails otherwise. Since
208         // we don't have a way to express an allocator preference yet, work
209         // around the issue in the case of a local rebuild with jemalloc disabled.
210         if compiler.stage == 0 && build.local_rebuild && !build.config.use_jemalloc {
211             features.push_str(" force_alloc_system");
212         }
213
214         if compiler.stage != 0 && build.config.sanitizers {
215             // This variable is used by the sanitizer runtime crates, e.g.
216             // rustc_lsan, to build the sanitizer runtime from C code
217             // When this variable is missing, those crates won't compile the C code,
218             // so we don't set this variable during stage0 where llvm-config is
219             // missing
220             // We also only build the runtimes when --enable-sanitizers (or its
221             // config.toml equivalent) is used
222             cargo.env("LLVM_CONFIG", build.llvm_config(target));
223         }
224
225         cargo.arg("--features").arg(features)
226             .arg("--manifest-path")
227             .arg(build.src.join("src/libstd/Cargo.toml"));
228
229         if let Some(target) = build.config.target_config.get(target) {
230             if let Some(ref jemalloc) = target.jemalloc {
231                 cargo.env("JEMALLOC_OVERRIDE", jemalloc);
232             }
233         }
234         if target.contains("musl") {
235             if let Some(p) = build.musl_root(target) {
236                 cargo.env("MUSL_ROOT", p);
237             }
238         }
239
240         run_cargo(build,
241                 &mut cargo,
242                 &libstd_stamp(build, &compiler, target));
243
244         builder.ensure(StdLink {
245             compiler: builder.compiler(compiler.stage, &build.build),
246             target_compiler: compiler,
247             target: target,
248         });
249     }
250 }
251
252
253 // crate_rule(build,
254 //            &mut rules,
255 //            "libstd-link",
256 //            "build-crate-std",
257 //            compile::std_link)
258 //     .dep(|s| s.name("startup-objects"))
259 //     .dep(|s| s.name("create-sysroot").target(s.host));
260
261 #[derive(Serialize)]
262 struct StdLink<'a> {
263     pub compiler: Compiler<'a>,
264     pub target_compiler: Compiler<'a>,
265     pub target: &'a str,
266 }
267
268 impl<'a> Step<'a> for StdLink<'a> {
269     type Output = ();
270
271     /// Link all libstd rlibs/dylibs into the sysroot location.
272     ///
273     /// Links those artifacts generated by `compiler` to a the `stage` compiler's
274     /// sysroot for the specified `host` and `target`.
275     ///
276     /// Note that this assumes that `compiler` has already generated the libstd
277     /// libraries for `target`, and this method will find them in the relevant
278     /// output directory.
279     fn run(self, builder: &Builder) {
280         let build = builder.build;
281         let compiler = self.compiler;
282         let target_compiler = self.target_compiler;
283         let target = self.target;
284         println!("Copying stage{} std from stage{} ({} -> {} / {})",
285                 target_compiler.stage,
286                 compiler.stage,
287                 compiler.host,
288                 target_compiler.host,
289                 target);
290         let libdir = build.sysroot_libdir(target_compiler, target);
291         add_to_sysroot(&libdir, &libstd_stamp(build, compiler, target));
292
293         if target.contains("musl") && !target.contains("mips") {
294             copy_musl_third_party_objects(build, target, &libdir);
295         }
296
297         if build.config.sanitizers && compiler.stage != 0 && target == "x86_64-apple-darwin" {
298             // The sanitizers are only built in stage1 or above, so the dylibs will
299             // be missing in stage0 and causes panic. See the `std()` function above
300             // for reason why the sanitizers are not built in stage0.
301             copy_apple_sanitizer_dylibs(&build.native_dir(target), "osx", &libdir);
302         }
303     }
304 }
305
306 /// Copies the crt(1,i,n).o startup objects
307 ///
308 /// Only required for musl targets that statically link to libc
309 fn copy_musl_third_party_objects(build: &Build, target: &str, into: &Path) {
310     for &obj in &["crt1.o", "crti.o", "crtn.o"] {
311         copy(&build.musl_root(target).unwrap().join("lib").join(obj), &into.join(obj));
312     }
313 }
314
315 fn copy_apple_sanitizer_dylibs(native_dir: &Path, platform: &str, into: &Path) {
316     for &sanitizer in &["asan", "tsan"] {
317         let filename = format!("libclang_rt.{}_{}_dynamic.dylib", sanitizer, platform);
318         let mut src_path = native_dir.join(sanitizer);
319         src_path.push("build");
320         src_path.push("lib");
321         src_path.push("darwin");
322         src_path.push(&filename);
323         copy(&src_path, &into.join(filename));
324     }
325 }
326
327 // rules.build("startup-objects", "src/rtstartup")
328 //      .dep(|s| s.name("create-sysroot").target(s.host))
329 //      .run(move |s| compile::build_startup_objects(build, &s.compiler(), s.target));
330
331 #[derive(Serialize)]
332 pub struct StartupObjects<'a> {
333     pub for_compiler: Compiler<'a>,
334     pub target: &'a str,
335 }
336
337 impl<'a> Step<'a> for StartupObjects<'a> {
338     type Output = ();
339
340     fn should_run(_builder: &Builder, path: &Path) -> bool {
341         path.ends_with("src/rtstartup")
342     }
343
344     fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) {
345         builder.ensure(StartupObjects {
346             compiler: builder.compiler(builder.top_stage, host),
347             target,
348         })
349     }
350
351     /// Build and prepare startup objects like rsbegin.o and rsend.o
352     ///
353     /// These are primarily used on Windows right now for linking executables/dlls.
354     /// They don't require any library support as they're just plain old object
355     /// files, so we just use the nightly snapshot compiler to always build them (as
356     /// no other compilers are guaranteed to be available).
357     fn run(self, builder: &Builder) {
358         let build = builder.build;
359         let for_compiler = self.for_compiler;
360         let target = self.target;
361         if !target.contains("pc-windows-gnu") {
362             return
363         }
364
365         let compiler = Compiler::new(0, &build.build);
366         let compiler_path = build.compiler_path(&compiler);
367         let src_dir = &build.src.join("src/rtstartup");
368         let dst_dir = &build.native_dir(target).join("rtstartup");
369         let sysroot_dir = &build.sysroot_libdir(for_compiler, target);
370         t!(fs::create_dir_all(dst_dir));
371         t!(fs::create_dir_all(sysroot_dir));
372
373         for file in &["rsbegin", "rsend"] {
374             let src_file = &src_dir.join(file.to_string() + ".rs");
375             let dst_file = &dst_dir.join(file.to_string() + ".o");
376             if !up_to_date(src_file, dst_file) {
377                 let mut cmd = Command::new(&compiler_path);
378                 build.run(cmd.env("RUSTC_BOOTSTRAP", "1")
379                             .arg("--cfg").arg(format!("stage{}", compiler.stage))
380                             .arg("--target").arg(target)
381                             .arg("--emit=obj")
382                             .arg("--out-dir").arg(dst_dir)
383                             .arg(src_file));
384             }
385
386             copy(dst_file, &sysroot_dir.join(file.to_string() + ".o"));
387         }
388
389         for obj in ["crt2.o", "dllcrt2.o"].iter() {
390             copy(&compiler_file(build.cc(target), obj), &sysroot_dir.join(obj));
391         }
392     }
393 }
394
395 //    for (krate, path, _default) in krates("test") {
396 //        rules.build(&krate.build_step, path)
397 //             .dep(|s| s.name("libstd-link"))
398 //             .run(move |s| compile::test(build, s.target, &s.compiler()));
399 //    }
400 #[derive(Serialize)]
401 pub struct Test<'a> {
402     pub compiler: Compiler<'a>,
403     pub target: &'a str,
404 }
405
406 impl<'a> Step<'a> for Test<'a> {
407     type Output = ();
408     const DEFAULT: bool = true;
409
410     fn should_run(builder: &Builder, path: &Path) -> bool {
411         path.ends_with("src/libtest") ||
412         builder.crates("test").into_iter().any(|(_, krate_path)| {
413             path.ends_with(krate_path)
414         })
415     }
416
417     fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) {
418         builder.ensure(Test {
419             compiler: builder.compiler(builder.top_stage, host),
420             target,
421         })
422     }
423
424     /// Build libtest.
425     ///
426     /// This will build libtest and supporting libraries for a particular stage of
427     /// the build using the `compiler` targeting the `target` architecture. The
428     /// artifacts created will also be linked into the sysroot directory.
429     fn run(self, builder: &Builder) {
430         let build = builder.build;
431         let target = self.target;
432         let compiler = self.compiler;
433
434         builder.ensure(Std { compiler, target });
435
436         if build.force_use_stage1(compiler, target) {
437             builder.ensure(Test {
438                 compiler: builder.compiler(1, &build.build),
439                 target: target,
440             });
441             println!("Uplifting stage1 test ({} -> {})", &build.build, target);
442             builder.ensure(TestLink {
443                 compiler: builder.compiler(1, &build.build),
444                 target_compiler: compiler,
445                 target: target,
446             });
447             return;
448         }
449
450         let _folder = build.fold_output(|| format!("stage{}-test", compiler.stage));
451         println!("Building stage{} test artifacts ({} -> {})", compiler.stage,
452                 compiler.host, target);
453         let out_dir = build.cargo_out(compiler, Mode::Libtest, target);
454         build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target));
455         let mut cargo = build.cargo(compiler, Mode::Libtest, target, "build");
456         if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
457             cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
458         }
459         cargo.arg("--manifest-path")
460             .arg(build.src.join("src/libtest/Cargo.toml"));
461         run_cargo(build,
462                 &mut cargo,
463                 &libtest_stamp(build, compiler, target));
464
465         builder.ensure(TestLink {
466             compiler: builder.compiler(1, &build.build),
467             target_compiler: compiler,
468             target: target,
469         });
470     }
471 }
472
473
474 // crate_rule(build,
475 //            &mut rules,
476 //            "libtest-link",
477 //            "build-crate-test",
478 //            compile::test_link)
479 //     .dep(|s| s.name("libstd-link"));
480
481 #[derive(Serialize)]
482 pub struct TestLink<'a> {
483     pub compiler: Compiler<'a>,
484     pub target_compiler: Compiler<'a>,
485     pub target: &'a str,
486 }
487
488 impl<'a> Step<'a> for Step<'a> {
489     type Output = ();
490
491     /// Same as `std_link`, only for libtest
492     fn run(self, builder: &Builder) {
493         let build = builder.build;
494         let compiler = self.compiler;
495         let target_compiler = self.target_compiler;
496         let target = self.target;
497         println!("Copying stage{} test from stage{} ({} -> {} / {})",
498                 target_compiler.stage,
499                 compiler.stage,
500                 compiler.host,
501                 target_compiler.host,
502                 target);
503         add_to_sysroot(&build.sysroot_libdir(target_compiler, target),
504                     &libtest_stamp(build, compiler, target));
505     }
506 }
507
508 //    for (krate, path, _default) in krates("rustc-main") {
509 //        rules.build(&krate.build_step, path)
510 //             .dep(|s| s.name("libtest-link"))
511 //             .dep(move |s| s.name("llvm").host(&build.build).stage(0))
512 //             .dep(|s| s.name("may-run-build-script"))
513 //             .run(move |s| compile::rustc(build, s.target, &s.compiler()));
514 //    }
515
516 #[derive(Serialize)]
517 pub struct Rustc<'a> {
518     pub compiler: Compiler<'a>,
519     pub target: &'a str,
520 }
521
522 impl<'a> Step<'a> for Rustc<'a> {
523     type Output = ();
524     const ONLY_HOSTS: bool = true;
525     const DEFAULT: bool = true;
526
527     fn should_run(builder: &Builder, path: &Path) -> bool {
528         path.ends_with("src/librustc") ||
529         builder.crates("rustc-main").into_iter().any(|(_, krate_path)| {
530             path.ends_with(krate_path)
531         })
532     }
533
534     fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) {
535         builder.ensure(Rustc {
536             compiler: builder.compiler(builder.top_stage, host),
537             target,
538         })
539     }
540
541     /// Build the compiler.
542     ///
543     /// This will build the compiler for a particular stage of the build using
544     /// the `compiler` targeting the `target` architecture. The artifacts
545     /// created will also be linked into the sysroot directory.
546     fn run(self, builder: &Builder) {
547         let build = builder.build;
548         let compiler = self.compiler;
549         let target = self.target;
550
551         builder.ensure(Test { compiler, target });
552
553         // Build LLVM for our target. This will implicitly build the host LLVM
554         // if necessary.
555         builder.ensure(native::Llvm { target });
556
557         if build.force_use_stage1(compiler, target) {
558             builder.ensure(Rustc {
559                 compiler: builder.compiler(1, &build.build),
560                 target: target,
561             });
562             println!("Uplifting stage1 rustc ({} -> {})", &build.build, target);
563             builder.ensure(RustcLink {
564                 compiler: builder.compiler(1, &build.build),
565                 target_compiler: compiler,
566                 target,
567             });
568             return;
569         }
570
571         // Ensure that build scripts have a std to link against.
572         builder.ensure(Std {
573             compiler: builder.compiler(self.compiler.stage, &build.build),
574             target: &build.build,
575         });
576
577         let _folder = build.fold_output(|| format!("stage{}-rustc", compiler.stage));
578         println!("Building stage{} compiler artifacts ({} -> {})",
579                  compiler.stage, compiler.host, target);
580
581         let out_dir = build.cargo_out(compiler, Mode::Librustc, target);
582         build.clear_if_dirty(&out_dir, &libtest_stamp(build, compiler, target));
583
584         let mut cargo = build.cargo(compiler, Mode::Librustc, target, "build");
585         cargo.arg("--features").arg(build.rustc_features())
586              .arg("--manifest-path")
587              .arg(build.src.join("src/rustc/Cargo.toml"));
588
589         // Set some configuration variables picked up by build scripts and
590         // the compiler alike
591         cargo.env("CFG_RELEASE", build.rust_release())
592              .env("CFG_RELEASE_CHANNEL", &build.config.channel)
593              .env("CFG_VERSION", build.rust_version())
594              .env("CFG_PREFIX", build.config.prefix.clone().unwrap_or_default());
595
596         if compiler.stage == 0 {
597             cargo.env("CFG_LIBDIR_RELATIVE", "lib");
598         } else {
599             let libdir_relative = build.config.libdir_relative.clone().unwrap_or(PathBuf::from("lib"));
600             cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
601         }
602
603         // If we're not building a compiler with debugging information then remove
604         // these two env vars which would be set otherwise.
605         if build.config.rust_debuginfo_only_std {
606             cargo.env_remove("RUSTC_DEBUGINFO");
607             cargo.env_remove("RUSTC_DEBUGINFO_LINES");
608         }
609
610         if let Some(ref ver_date) = build.rust_info.commit_date() {
611             cargo.env("CFG_VER_DATE", ver_date);
612         }
613         if let Some(ref ver_hash) = build.rust_info.sha() {
614             cargo.env("CFG_VER_HASH", ver_hash);
615         }
616         if !build.unstable_features() {
617             cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
618         }
619         // Flag that rust llvm is in use
620         if build.is_rust_llvm(target) {
621             cargo.env("LLVM_RUSTLLVM", "1");
622         }
623         cargo.env("LLVM_CONFIG", build.llvm_config(target));
624         let target_config = build.config.target_config.get(target);
625         if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
626             cargo.env("CFG_LLVM_ROOT", s);
627         }
628         // Building with a static libstdc++ is only supported on linux right now,
629         // not for MSVC or macOS
630         if build.config.llvm_static_stdcpp &&
631            !target.contains("windows") &&
632            !target.contains("apple") {
633             cargo.env("LLVM_STATIC_STDCPP",
634                       compiler_file(build.cxx(target).unwrap(), "libstdc++.a"));
635         }
636         if build.config.llvm_link_shared {
637             cargo.env("LLVM_LINK_SHARED", "1");
638         }
639         if let Some(ref s) = build.config.rustc_default_linker {
640             cargo.env("CFG_DEFAULT_LINKER", s);
641         }
642         if let Some(ref s) = build.config.rustc_default_ar {
643             cargo.env("CFG_DEFAULT_AR", s);
644         }
645         run_cargo(build,
646                   &mut cargo,
647                   &librustc_stamp(build, compiler, target));
648
649         builder.ensure(RustcLink {
650             compiler: builder.compiler(compiler.stage, &build.build),
651             target_compiler: compiler,
652             target,
653         });
654     }
655 }
656
657 // crate_rule(build,
658 //            &mut rules,
659 //            "librustc-link",
660 //            "build-crate-rustc-main",
661 //            compile::rustc_link)
662 //     .dep(|s| s.name("libtest-link"));
663 #[derive(Serialize)]
664 struct RustcLink<'a> {
665     pub compiler: Compiler<'a>,
666     pub target_compiler: Compiler<'a>,
667     pub target: &'a str,
668 }
669
670 impl<'a> Step<'a> for RustcLink<'a> {
671     type Output = ();
672
673     /// Same as `std_link`, only for librustc
674     fn run(self, builder: &Builder) {
675         let build = builder.build;
676         let compiler = self.compiler;
677         let target_compiler = self.target_compiler;
678         let target = self.target;
679         println!("Copying stage{} rustc from stage{} ({} -> {} / {})",
680                  target_compiler.stage,
681                  compiler.stage,
682                  compiler.host,
683                  target_compiler.host,
684                  target);
685         add_to_sysroot(&build.sysroot_libdir(target_compiler, target),
686                        &librustc_stamp(build, compiler, target));
687     }
688 }
689
690 /// Cargo's output path for the standard library in a given stage, compiled
691 /// by a particular compiler for the specified target.
692 pub fn libstd_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf {
693     build.cargo_out(compiler, Mode::Libstd, target).join(".libstd.stamp")
694 }
695
696 /// Cargo's output path for libtest in a given stage, compiled by a particular
697 /// compiler for the specified target.
698 pub fn libtest_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf {
699     build.cargo_out(compiler, Mode::Libtest, target).join(".libtest.stamp")
700 }
701
702 /// Cargo's output path for librustc in a given stage, compiled by a particular
703 /// compiler for the specified target.
704 pub fn librustc_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf {
705     build.cargo_out(compiler, Mode::Librustc, target).join(".librustc.stamp")
706 }
707
708 fn compiler_file(compiler: &Path, file: &str) -> PathBuf {
709     let out = output(Command::new(compiler)
710                             .arg(format!("-print-file-name={}", file)));
711     PathBuf::from(out.trim())
712 }
713
714 // rules.build("create-sysroot", "path/to/nowhere")
715 //      .run(move |s| compile::create_sysroot(build, &s.compiler()));
716
717 #[derive(Serialize)]
718 pub struct Sysroot<'a> {
719     pub compiler: Compiler<'a>,
720 }
721
722 impl<'a> Step<'a> for Sysroot<'a> {
723     type Output = PathBuf;
724
725     /// Returns the sysroot for the `compiler` specified that *this build system
726     /// generates*.
727     ///
728     /// That is, the sysroot for the stage0 compiler is not what the compiler
729     /// thinks it is by default, but it's the same as the default for stages
730     /// 1-3.
731     fn run(self, builder: &Builder) -> PathBuf {
732         let build = builder.build;
733         let compiler = self.compiler;
734         let sysroot = if compiler.stage == 0 {
735             build.out.join(compiler.host).join("stage0-sysroot")
736         } else {
737             build.out.join(compiler.host).join(format!("stage{}", compiler.stage))
738         };
739         let _ = fs::remove_dir_all(&sysroot);
740         t!(fs::create_dir_all(&sysroot));
741         sysroot
742     }
743 }
744
745 // the compiler with no target libraries ready to go
746 // rules.build("rustc", "src/rustc")
747 //      .dep(|s| s.name("create-sysroot").target(s.host))
748 //      .dep(move |s| {
749 //          if s.stage == 0 {
750 //              Step::noop()
751 //          } else {
752 //              s.name("librustc")
753 //               .host(&build.build)
754 //               .stage(s.stage - 1)
755 //          }
756 //      })
757 //      .run(move |s| compile::assemble_rustc(build, s.stage, s.target));
758
759 #[derive(Serialize)]
760 pub struct Assemble<'a> {
761     /// The compiler which we will produce in this step. Assemble itself will
762     /// take care of ensuring that the necessary prerequisites to do so exist,
763     /// that is, this target can be a stage2 compiler and Assemble will build
764     /// previous stages for you.
765     pub target_compiler: Compiler<'a>,
766 }
767
768 impl<'a> Step<'a> for Assemble<'a> {
769     type Output = ();
770
771     /// Prepare a new compiler from the artifacts in `stage`
772     ///
773     /// This will assemble a compiler in `build/$host/stage$stage`. The compiler
774     /// must have been previously produced by the `stage - 1` build.build
775     /// compiler.
776     fn run(self, builder: &Builder) {
777         let build = builder.build;
778         let target_compiler = self.target_compiler;
779
780         if target_compiler.stage == 0 {
781             assert_eq!(build.build, target_compiler.host,
782                 "Cannot obtain compiler for non-native build triple at stage 0");
783             // The stage 0 compiler for the build triple is always pre-built.
784             return target_compiler;
785         }
786
787         // Get the compiler that we'll use to bootstrap ourselves.
788         let build_compiler = if target_compiler.host != build.build {
789             // Build a compiler for the host platform. We cannot use the stage0
790             // compiler for the host platform for this because it doesn't have
791             // the libraries we need.  FIXME: Perhaps we should download those
792             // libraries? It would make builds faster...
793             builder.ensure(Assemble {
794                 target_compiler: Compiler {
795                     // FIXME: It may be faster if we build just a stage 1
796                     // compiler and then use that to bootstrap this compiler
797                     // forward.
798                     stage: target_compiler.stage - 1,
799                     host: &build.build
800                 },
801             })
802         } else {
803             // Build the compiler we'll use to build the stage requested. This
804             // may build more than one compiler (going down to stage 0).
805             builder.ensure(Assemble {
806                 target_compiler: target_compiler.with_stage(target_compiler.stage - 1),
807             })
808         };
809
810         // Build the libraries for this compiler to link to (i.e., the libraries
811         // it uses at runtime). NOTE: Crates the target compiler compiles don't
812         // link to these. (FIXME: Is that correct? It seems to be correct most
813         // of the time but I think we do link to these for stage2/bin compilers
814         // when not performing a full bootstrap).
815         builder.ensure(Rustc { compiler: build_compiler, target: target_compiler.host });
816
817         let stage = target_compiler.stage;
818         let host = target_compiler.host;
819         println!("Assembling stage{} compiler ({})", stage, host);
820
821         // Link in all dylibs to the libdir
822         let sysroot = build.sysroot(&target_compiler);
823         let sysroot_libdir = sysroot.join(libdir(host));
824         t!(fs::create_dir_all(&sysroot_libdir));
825         let src_libdir = build.sysroot_libdir(&build_compiler, host);
826         for f in t!(fs::read_dir(&src_libdir)).map(|f| t!(f)) {
827             let filename = f.file_name().into_string().unwrap();
828             if is_dylib(&filename) {
829                 copy(&f.path(), &sysroot_libdir.join(&filename));
830             }
831         }
832
833         let out_dir = build.cargo_out(&build_compiler, Mode::Librustc, host);
834
835         // Link the compiler binary itself into place
836         let rustc = out_dir.join(exe("rustc", host));
837         let bindir = sysroot.join("bin");
838         t!(fs::create_dir_all(&bindir));
839         let compiler = build.compiler_path(&target_compiler);
840         let _ = fs::remove_file(&compiler);
841         copy(&rustc, &compiler);
842
843         // See if rustdoc exists to link it into place
844         let rustdoc = exe("rustdoc", host);
845         let rustdoc_src = out_dir.join(&rustdoc);
846         let rustdoc_dst = bindir.join(&rustdoc);
847         if fs::metadata(&rustdoc_src).is_ok() {
848             let _ = fs::remove_file(&rustdoc_dst);
849             copy(&rustdoc_src, &rustdoc_dst);
850         }
851     }
852 }
853
854 /// Link some files into a rustc sysroot.
855 ///
856 /// For a particular stage this will link the file listed in `stamp` into the
857 /// `sysroot_dst` provided.
858 fn add_to_sysroot(sysroot_dst: &Path, stamp: &Path) {
859     t!(fs::create_dir_all(&sysroot_dst));
860     let mut contents = Vec::new();
861     t!(t!(File::open(stamp)).read_to_end(&mut contents));
862     // This is the method we use for extracting paths from the stamp file passed to us. See
863     // run_cargo for more information (in this file).
864     for part in contents.split(|b| *b == 0) {
865         if part.is_empty() {
866             continue
867         }
868         let path = Path::new(t!(str::from_utf8(part)));
869         copy(&path, &sysroot_dst.join(path.file_name().unwrap()));
870     }
871 }
872
873 // Avoiding a dependency on winapi to keep compile times down
874 #[cfg(unix)]
875 fn stderr_isatty() -> bool {
876     use libc;
877     unsafe { libc::isatty(libc::STDERR_FILENO) != 0 }
878 }
879 #[cfg(windows)]
880 fn stderr_isatty() -> bool {
881     type DWORD = u32;
882     type BOOL = i32;
883     type HANDLE = *mut u8;
884     const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD;
885     extern "system" {
886         fn GetStdHandle(which: DWORD) -> HANDLE;
887         fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: *mut DWORD) -> BOOL;
888     }
889     unsafe {
890         let handle = GetStdHandle(STD_ERROR_HANDLE);
891         let mut out = 0;
892         GetConsoleMode(handle, &mut out) != 0
893     }
894 }
895
896 fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path) {
897     // Instruct Cargo to give us json messages on stdout, critically leaving
898     // stderr as piped so we can get those pretty colors.
899     cargo.arg("--message-format").arg("json")
900          .stdout(Stdio::piped());
901
902     if stderr_isatty() {
903         // since we pass message-format=json to cargo, we need to tell the rustc
904         // wrapper to give us colored output if necessary. This is because we
905         // only want Cargo's JSON output, not rustcs.
906         cargo.env("RUSTC_COLOR", "1");
907     }
908
909     build.verbose(&format!("running: {:?}", cargo));
910     let mut child = match cargo.spawn() {
911         Ok(child) => child,
912         Err(e) => panic!("failed to execute command: {:?}\nerror: {}", cargo, e),
913     };
914
915     // `target_root_dir` looks like $dir/$target/release
916     let target_root_dir = stamp.parent().unwrap();
917     // `target_deps_dir` looks like $dir/$target/release/deps
918     let target_deps_dir = target_root_dir.join("deps");
919     // `host_root_dir` looks like $dir/release
920     let host_root_dir = target_root_dir.parent().unwrap() // chop off `release`
921                                        .parent().unwrap() // chop off `$target`
922                                        .join(target_root_dir.file_name().unwrap());
923
924     // Spawn Cargo slurping up its JSON output. We'll start building up the
925     // `deps` array of all files it generated along with a `toplevel` array of
926     // files we need to probe for later.
927     let mut deps = Vec::new();
928     let mut toplevel = Vec::new();
929     let stdout = BufReader::new(child.stdout.take().unwrap());
930     for line in stdout.lines() {
931         let line = t!(line);
932         let json = if line.starts_with("{") {
933             t!(line.parse::<json::Json>())
934         } else {
935             // If this was informational, just print it out and continue
936             println!("{}", line);
937             continue
938         };
939         if json.find("reason").and_then(|j| j.as_string()) != Some("compiler-artifact") {
940             continue
941         }
942         for filename in json["filenames"].as_array().unwrap() {
943             let filename = filename.as_string().unwrap();
944             // Skip files like executables
945             if !filename.ends_with(".rlib") &&
946                !filename.ends_with(".lib") &&
947                !is_dylib(&filename) {
948                 continue
949             }
950
951             let filename = Path::new(filename);
952
953             // If this was an output file in the "host dir" we don't actually
954             // worry about it, it's not relevant for us.
955             if filename.starts_with(&host_root_dir) {
956                 continue;
957             }
958
959             // If this was output in the `deps` dir then this is a precise file
960             // name (hash included) so we start tracking it.
961             if filename.starts_with(&target_deps_dir) {
962                 deps.push(filename.to_path_buf());
963                 continue;
964             }
965
966             // Otherwise this was a "top level artifact" which right now doesn't
967             // have a hash in the name, but there's a version of this file in
968             // the `deps` folder which *does* have a hash in the name. That's
969             // the one we'll want to we'll probe for it later.
970             toplevel.push((filename.file_stem().unwrap()
971                                     .to_str().unwrap().to_string(),
972                             filename.extension().unwrap().to_owned()
973                                     .to_str().unwrap().to_string()));
974         }
975     }
976
977     // Make sure Cargo actually succeeded after we read all of its stdout.
978     let status = t!(child.wait());
979     if !status.success() {
980         panic!("command did not execute successfully: {:?}\n\
981                 expected success, got: {}",
982                cargo,
983                status);
984     }
985
986     // Ok now we need to actually find all the files listed in `toplevel`. We've
987     // got a list of prefix/extensions and we basically just need to find the
988     // most recent file in the `deps` folder corresponding to each one.
989     let contents = t!(target_deps_dir.read_dir())
990         .map(|e| t!(e))
991         .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
992         .collect::<Vec<_>>();
993     for (prefix, extension) in toplevel {
994         let candidates = contents.iter().filter(|&&(_, ref filename, _)| {
995             filename.starts_with(&prefix[..]) &&
996                 filename[prefix.len()..].starts_with("-") &&
997                 filename.ends_with(&extension[..])
998         });
999         let max = candidates.max_by_key(|&&(_, _, ref metadata)| {
1000             FileTime::from_last_modification_time(metadata)
1001         });
1002         let path_to_add = match max {
1003             Some(triple) => triple.0.to_str().unwrap(),
1004             None => panic!("no output generated for {:?} {:?}", prefix, extension),
1005         };
1006         if is_dylib(path_to_add) {
1007             let candidate = format!("{}.lib", path_to_add);
1008             let candidate = PathBuf::from(candidate);
1009             if candidate.exists() {
1010                 deps.push(candidate);
1011             }
1012         }
1013         deps.push(path_to_add.into());
1014     }
1015
1016     // Now we want to update the contents of the stamp file, if necessary. First
1017     // we read off the previous contents along with its mtime. If our new
1018     // contents (the list of files to copy) is different or if any dep's mtime
1019     // is newer then we rewrite the stamp file.
1020     deps.sort();
1021     let mut stamp_contents = Vec::new();
1022     if let Ok(mut f) = File::open(stamp) {
1023         t!(f.read_to_end(&mut stamp_contents));
1024     }
1025     let stamp_mtime = mtime(&stamp);
1026     let mut new_contents = Vec::new();
1027     let mut max = None;
1028     let mut max_path = None;
1029     for dep in deps {
1030         let mtime = mtime(&dep);
1031         if Some(mtime) > max {
1032             max = Some(mtime);
1033             max_path = Some(dep.clone());
1034         }
1035         new_contents.extend(dep.to_str().unwrap().as_bytes());
1036         new_contents.extend(b"\0");
1037     }
1038     let max = max.unwrap();
1039     let max_path = max_path.unwrap();
1040     if stamp_contents == new_contents && max <= stamp_mtime {
1041         return
1042     }
1043     if max > stamp_mtime {
1044         build.verbose(&format!("updating {:?} as {:?} changed", stamp, max_path));
1045     } else {
1046         build.verbose(&format!("updating {:?} as deps changed", stamp));
1047     }
1048     t!(t!(File::create(stamp)).write_all(&new_contents));
1049 }