From e645ed59ceedf7472939036381b31abe2eb6ef07 Mon Sep 17 00:00:00 2001
From: Chang Liu <cliu712@aucklanduni.ac.nz>
Date: Mon, 13 Jul 2015 12:55:56 +0000
Subject: [PATCH 01/22] Add Cargo-based build system

This commit adds a Cargo-based build system, in parallel to the old
Makefile-based build system. The new Cargo-based build system is supposed
to replace the old system, and the old system will be marked for deletion
once the new system has been tested thoroughly.

On a high-level, this commit (and the commits to follow in this pull request):

 1. Add the necessary `Cargo.toml` files to convert the crates into Cargo
    packages.
 2. Add a `build.rs` script when building native runtime libraries is
    required.
 3. Add a Python script `etc/build_llvm.py` to invoke the LLVM build system.
 4. Add a driver script `etc/build_rust.py` to parse the command line
    arguments, build LLVM, and invoke Cargo to bootstrap the compiler,
    build the docs, and build and run the compiler and library tests.
---
 build.sh                                |   3 +
 src/build_helper/Cargo.toml             |   8 +
 src/build_helper/cc.rs                  | 496 ++++++++++++++++++++++++
 src/build_helper/config.rs              |  95 +++++
 src/build_helper/lib.rs                 |  14 +
 src/build_helper/llvm.rs                |  65 ++++
 src/build_helper/run.rs                 |  77 ++++
 src/compiletest/Cargo.toml              |  12 +
 src/compiletest/build.rs                |  18 +
 src/driver/Cargo.toml                   |  24 ++
 src/driver/rustc.rs                     |  15 +
 src/driver/rustdoc.rs                   |  15 +
 src/etc/build_llvm.py                   | 136 +++++++
 src/etc/build_rust.py                   | 391 +++++++++++++++++++
 src/liballoc/Cargo.toml                 |  26 ++
 src/liballoc/build.rs                   |  83 ++++
 src/libarena/Cargo.toml                 |  16 +
 src/libcollections/Cargo.toml           |  17 +
 src/libcollectionstest/Cargo.toml       |  15 +
 src/libcore/Cargo.toml                  |   8 +
 src/libcoretest/Cargo.toml              |  16 +
 src/libflate/Cargo.toml                 |  21 +
 src/libflate/build.rs                   |   8 +
 src/libfmt_macros/Cargo.toml            |  15 +
 src/libgetopts/Cargo.toml               |  16 +
 src/libgraphviz/Cargo.toml              |  15 +
 src/liblibc/Cargo.toml                  |  15 +
 src/liblog/Cargo.toml                   |  15 +
 src/librand/Cargo.toml                  |  16 +
 src/librbml/Cargo.toml                  |  17 +
 src/librustc/Cargo.toml                 |  30 ++
 src/librustc_back/Cargo.toml            |  21 +
 src/librustc_bitflags/Cargo.toml        |  12 +
 src/librustc_borrowck/Cargo.toml        |  16 +
 src/librustc_data_structures/Cargo.toml |  17 +
 src/librustc_driver/Cargo.toml          |  32 ++
 src/librustc_lint/Cargo.toml            |  15 +
 src/librustc_llvm/Cargo.toml            |  23 ++
 src/librustc_llvm/build.rs              |  41 ++
 src/librustc_privacy/Cargo.toml         |  15 +
 src/librustc_resolve/Cargo.toml         |  16 +
 src/librustc_trans/Cargo.toml           |  23 ++
 src/librustc_typeck/Cargo.toml          |  17 +
 src/librustc_unicode/Cargo.toml         |  11 +
 src/librustdoc/Cargo.toml               |  30 ++
 src/librustdoc/build.rs                 |  11 +
 src/libserialize/Cargo.toml             |  18 +
 src/libstd/Cargo.toml                   |  27 ++
 src/libstd/build.rs                     | 131 +++++++
 src/libsyntax/Cargo.toml                |  22 ++
 src/libterm/Cargo.toml                  |  17 +
 src/libtest/Cargo.toml                  |  16 +
 src/rustbook/Cargo.toml                 |   8 +
 53 files changed, 2257 insertions(+)
 create mode 100644 build.sh
 create mode 100644 src/build_helper/Cargo.toml
 create mode 100644 src/build_helper/cc.rs
 create mode 100644 src/build_helper/config.rs
 create mode 100644 src/build_helper/lib.rs
 create mode 100644 src/build_helper/llvm.rs
 create mode 100644 src/build_helper/run.rs
 create mode 100644 src/compiletest/Cargo.toml
 create mode 100644 src/compiletest/build.rs
 create mode 100644 src/driver/Cargo.toml
 create mode 100644 src/driver/rustc.rs
 create mode 100644 src/driver/rustdoc.rs
 create mode 100644 src/etc/build_llvm.py
 create mode 100644 src/etc/build_rust.py
 create mode 100644 src/liballoc/Cargo.toml
 create mode 100644 src/liballoc/build.rs
 create mode 100644 src/libarena/Cargo.toml
 create mode 100644 src/libcollections/Cargo.toml
 create mode 100644 src/libcollectionstest/Cargo.toml
 create mode 100644 src/libcore/Cargo.toml
 create mode 100644 src/libcoretest/Cargo.toml
 create mode 100644 src/libflate/Cargo.toml
 create mode 100644 src/libflate/build.rs
 create mode 100644 src/libfmt_macros/Cargo.toml
 create mode 100644 src/libgetopts/Cargo.toml
 create mode 100644 src/libgraphviz/Cargo.toml
 create mode 100644 src/liblibc/Cargo.toml
 create mode 100644 src/liblog/Cargo.toml
 create mode 100644 src/librand/Cargo.toml
 create mode 100644 src/librbml/Cargo.toml
 create mode 100644 src/librustc/Cargo.toml
 create mode 100644 src/librustc_back/Cargo.toml
 create mode 100644 src/librustc_bitflags/Cargo.toml
 create mode 100644 src/librustc_borrowck/Cargo.toml
 create mode 100644 src/librustc_data_structures/Cargo.toml
 create mode 100644 src/librustc_driver/Cargo.toml
 create mode 100644 src/librustc_lint/Cargo.toml
 create mode 100644 src/librustc_llvm/Cargo.toml
 create mode 100644 src/librustc_llvm/build.rs
 create mode 100644 src/librustc_privacy/Cargo.toml
 create mode 100644 src/librustc_resolve/Cargo.toml
 create mode 100644 src/librustc_trans/Cargo.toml
 create mode 100644 src/librustc_typeck/Cargo.toml
 create mode 100644 src/librustc_unicode/Cargo.toml
 create mode 100644 src/librustdoc/Cargo.toml
 create mode 100644 src/librustdoc/build.rs
 create mode 100644 src/libserialize/Cargo.toml
 create mode 100644 src/libstd/Cargo.toml
 create mode 100644 src/libstd/build.rs
 create mode 100644 src/libsyntax/Cargo.toml
 create mode 100644 src/libterm/Cargo.toml
 create mode 100644 src/libtest/Cargo.toml
 create mode 100644 src/rustbook/Cargo.toml

diff --git a/build.sh b/build.sh
new file mode 100644
index 0000000000000..ae11fed761d17
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+python src/etc/build_rust.py $@
diff --git a/src/build_helper/Cargo.toml b/src/build_helper/Cargo.toml
new file mode 100644
index 0000000000000..43f6e61e6c0fd
--- /dev/null
+++ b/src/build_helper/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "build_helper"
+version = "0.1.0"
+authors = ["Chang Liu <cliu712@aucklanduni.ac.nz>"]
+
+[lib]
+name = "build_helper"
+path = "lib.rs"
diff --git a/src/build_helper/cc.rs b/src/build_helper/cc.rs
new file mode 100644
index 0000000000000..923bd6dc8a881
--- /dev/null
+++ b/src/build_helper/cc.rs
@@ -0,0 +1,496 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Invoke the appropriate toolchain to build and assemble a static
+//! library. Different flavours of the toolchain (gnu vs. msvc) are
+//! abstracted behind the trait `Toolchain`, and the build system
+//! will select the appropriate one based on the build configuration
+//! and the platform.
+
+use std::fmt;
+use std::ffi::{OsStr, OsString};
+use std::path::{PathBuf, Path};
+use std::process::Command;
+use llvm::LLVMTools;
+use config::Config;
+use run::Run;
+
+/// Specify a target triple, in the format `arch-vendor-os-abi`.
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct Triple {
+    triple : String
+}
+
+impl Triple {
+    pub fn new(triple : &str) -> Result<Triple, String> {
+        let v : Vec<&str>= triple.split('-').map(|s| s).collect();
+        if v.len() < 3 {
+            Err(format!("Invalid target triple {}.", triple))
+        } else {
+            Ok(Triple { triple : triple.into() })
+        }
+    }
+
+    pub fn arch(&self) -> &str {
+        self.triple.split('-').nth(0).unwrap()
+    }
+
+    pub fn os(&self) -> &str {
+        self.triple.split('-').nth(2).unwrap()
+    }
+
+    pub fn abi(&self) -> Option<&str> {
+        self.triple.split('-').nth(3)
+    }
+
+    pub fn is_i686(&self) -> bool {
+        self.arch() == "i686"
+    }
+
+    pub fn is_x86_64(&self) -> bool {
+        self.arch() == "x86_64"
+    }
+
+    pub fn is_aarch64(&self) -> bool {
+        self.arch() == "aarch64"
+    }
+
+    pub fn is_windows(&self) -> bool {
+        self.os() == "windows"
+    }
+
+    pub fn is_mingw(&self) -> bool {
+        self.is_windows() && self.abi() == Some("gnu")
+    }
+
+    pub fn is_msvc(&self) -> bool {
+        self.abi() == Some("msvc")
+    }
+
+    pub fn is_linux(&self) -> bool {
+        self.os() == "linux"
+    }
+
+    pub fn is_ios(&self) -> bool {
+        self.os() == "ios"
+    }
+
+    pub fn is_android(&self) -> bool {
+        self.os() == "android"
+    }
+
+    pub fn is_darwin(&self) -> bool {
+        self.os() == "darwin"
+    }
+
+    /// Append the extension for the executables in this platform
+    pub fn with_exe_ext(&self, name : &str) -> String {
+        if self.is_windows() {
+            format!("{}.exe", name)
+        } else {
+            format!("{}", name)
+        }
+    }
+
+    /// Append the extension for the static libraries in this platform
+    pub fn with_lib_ext(&self, name : &str) -> String {
+        if self.is_msvc() {
+            format!("{}.lib", name)
+        } else {
+            format!("lib{}.a", name)
+        }
+    }
+
+    /// Get the file extension for the dynamic libraries in this platform.
+    pub fn dylib_ext(&self) -> &'static str {
+        if self.is_windows() {
+            "dll"
+        } else if self.is_darwin() {
+            "dylib"
+        } else {
+            "so"
+        }
+    }
+}
+
+impl fmt::Display for Triple {
+    fn fmt(&self, f : &mut fmt::Formatter) -> fmt::Result {
+        f.write_str(&self.triple)
+    }
+}
+
+impl AsRef<OsStr> for Triple {
+    fn as_ref(&self) -> &OsStr {
+        &OsStr::new(&self.triple)
+    }
+}
+
+impl AsRef<Path> for Triple {
+    fn as_ref(&self) -> &Path {
+        &Path::new(&self.triple)
+    }
+}
+
+impl<'a> From<&'a Triple> for &'a str {
+    fn from(t : &'a Triple) -> &'a str {
+        &t.triple
+    }
+}
+
+impl<'a> From<&'a Triple> for String {
+    fn from(t : &'a Triple) -> String {
+        t.triple.clone()
+    }
+}
+
+/// Compile and assemble a static library. This will invoke the
+/// appropriate toolchain command (or LLVM tool) to compile the
+/// given list of files into object files and then invoke ar (or
+/// equivalent) to assemble them into a static library.
+///
+/// If a directory is given instead of a file, all supported files
+/// under that directory will be compiled.
+///
+/// Supported file types are:
+///
+/// `*.ll` --- LLVM byte code, will invoke `llc`
+///
+/// `*.S`, `*.c`, `*.cc`, `*.cpp` --- will invoke toolchain command
+/// defined by trait `Toolchain`.
+pub struct StaticLib {
+    toolchain : Box<Toolchain>,
+    llvm_tools : LLVMTools,
+    include_directories: Vec<PathBuf>,
+    files: Vec<PathBuf>,
+    src_dir : PathBuf,
+    build_dir : PathBuf,
+    with_llvm : bool
+}
+
+impl StaticLib {
+    /// This builder is finished with the `compile` function.
+    fn new(toolchain : Box<Toolchain>, llvm_tools : LLVMTools)
+           -> StaticLib {
+        StaticLib {
+            toolchain : toolchain,
+            llvm_tools : llvm_tools,
+            include_directories: Vec::new(),
+            files: Vec::new(),
+            src_dir : PathBuf::new(),
+            build_dir : PathBuf::new(),
+            with_llvm : false
+        }
+    }
+
+    /// Set the source directory
+    pub fn set_src_dir<P : AsRef<Path>>(&mut self, dir : P)
+                                        -> &mut StaticLib {
+        self.src_dir = dir.as_ref().into();
+        self
+    }
+
+    /// Set the destination directory where the final artifact is written
+    pub fn set_build_dir<P : AsRef<Path>>(&mut self, dir : P)
+                                          -> &mut StaticLib {
+        self.build_dir = dir.as_ref().into();
+        self
+    }
+
+    /// Add a directory to the `-I` or include path for headers
+    pub fn include_dirs<P: AsRef<Path>>(&mut self, dir: &[P])
+                                        -> &mut StaticLib {
+        let _ : Vec<()> = dir.iter().map(|p| p.as_ref().into())
+            .map(|p| self.include_directories.push(p))
+            .collect();
+        self
+    }
+
+    /// Add a group of files which will be compiled
+    pub fn files<P : AsRef<Path>>(&mut self, files : &[P])
+                                  -> &mut StaticLib {
+        let _ : Vec<()> = files.iter().map(|p| p.as_ref().into())
+            .map(|p| self.files.push(p))
+            .collect();
+        self
+    }
+
+    /// If set, will invoke llvm-config to add the appropriate compiler flags
+    pub fn with_llvm(&mut self) -> &mut StaticLib {
+        self.with_llvm = true;
+        self
+    }
+
+    /// Run the compiler, generating the file `output`
+    pub fn compile(&self, out_lib: &str) {
+        use std::fs::{read_dir, create_dir_all};
+        let mut src_files : Vec<PathBuf> = vec![];
+        for path in &self.files {
+            if let Ok(dir) = read_dir(self.src_dir.join(path)) {
+                let _ : Vec<_> = dir.map(|ent| ent.map(|f| {
+                    if let Some(ext) = f.path().extension() {
+                        if ext == "ll" || ext == "cc" || ext == "cpp"
+                            || ext == "c" || ext == "S" {
+                                let file = path.join(
+                                    f.path().file_name().unwrap());
+                                src_files.push(file);
+                            }
+                    }
+                })).collect();
+            } else {
+                src_files.push(path.into());
+            }
+        }
+
+        let mut objects = Vec::new();
+        for file in &src_files {
+            let src = self.src_dir.join(file);
+            let obj = self.build_dir.join(file).with_extension("o");
+            let _ = create_dir_all(&obj.parent().unwrap()); // ignore errors
+            let mut cmd = self.compiler_cmd(&src, &obj);
+            if self.with_llvm {
+               let cxxflags = self.llvm_tools.get_llvm_cxxflags();
+               cmd.args(&cxxflags);
+            }
+            cmd.run();
+            objects.push(obj);
+        }
+
+        let output = self.build_dir
+            .join(self.toolchain.target_triple().with_lib_ext(out_lib));
+        self.toolchain.ar_cmd(&objects, &output).run();
+        println!("cargo:rustc-link-search=native={}", self.build_dir.display());
+        if self.with_llvm {
+            println!("cargo:rustc-link-search=native={}",
+                     self.llvm_tools.path_to_llvm_libs().display());
+        }
+    }
+
+    fn compiler_cmd(&self, src : &Path, obj : &Path) -> Command {
+        let mut inc_dirs : Vec<PathBuf> = self.include_directories.iter()
+            .map(|d| self.src_dir.join(d)).collect();
+        if self.with_llvm {
+            inc_dirs.push(self.llvm_tools.llvm_src_dir().join("include"));
+        }
+        let ext = src.extension().expect(
+            &format!("Source {:?} file has no extension.", src));
+        if ext == "ll" {
+            self.llvm_tools.llc_cmd(
+                self.toolchain.target_triple(), src, obj)
+        } else if ext == "cc" || ext == "cpp" {
+            self.toolchain.cxx_cmd(src, obj, &inc_dirs)
+        } else {
+            self.toolchain.cc_cmd(src, obj, &inc_dirs)
+        }
+    }
+}
+
+/// Define the abstract interface that a toolchain implemenation
+/// should support.
+pub trait Toolchain {
+    fn target_triple(&self) -> &Triple;
+    fn cc_cmd(&self, src_file : &Path, obj_file : &Path,
+              inc_dirs : &[PathBuf]) -> Command;
+    fn cxx_cmd(&self, src_file : &Path, obj_file : &Path,
+               inc_dirs : &[PathBuf]) -> Command;
+    fn ar_cmd(&self, obj_files : &[PathBuf], output : &Path) -> Command;
+}
+
+/// Gnu-flavoured toolchain. Support both gcc and clang.
+pub struct GccishToolchain {
+    target_triple : Triple,
+    pub cc_cmd : String,
+    cxx_cmd : String,
+    pub ar_cmd : String
+}
+
+impl GccishToolchain {
+    pub fn new(target : &Triple) -> GccishToolchain {
+        if target.is_darwin() {
+            GccishToolchain::clang(target)
+        } else if target.is_mingw() {
+            GccishToolchain::native_gcc(target)
+        } else {
+            GccishToolchain::cross_gcc(target)
+        }
+    }
+
+    fn cross_gcc(triple : &Triple) -> GccishToolchain {
+        GccishToolchain {
+            target_triple : triple.clone(),
+            cc_cmd : format!("{}-gcc", triple),
+            cxx_cmd : format!("{}-g++", triple),
+            ar_cmd : "ar".into()
+        }
+    }
+
+    fn native_gcc(triple : &Triple) -> GccishToolchain {
+        GccishToolchain {
+            target_triple : triple.clone(),
+            cc_cmd : "gcc".into(),
+            cxx_cmd : "g++".into(),
+            ar_cmd : "ar".into()
+        }
+    }
+
+    fn clang(triple : &Triple) -> GccishToolchain {
+        GccishToolchain {
+            target_triple : triple.clone(),
+            cc_cmd : "clang".into(),
+            cxx_cmd : "clang++".into(),
+            ar_cmd : "ar".into()
+        }
+    }
+
+    pub fn cflags(&self) -> Vec<&'static str> {
+        let target = self.target_triple();
+        let mut cflags = vec!["-ffunction-sections", "-fdata-sections"];
+
+        if target.is_aarch64() {
+            cflags.push("-D__aarch64__");
+        }
+
+        if target.is_android() {
+            cflags.push("-DANDROID");
+            cflags.push("-D__ANDROID__");
+        }
+
+        if target.is_windows() {
+            cflags.push("-mwin32");
+        }
+
+        if target.is_i686() {
+            cflags.push("-m32");
+        } else if target.is_x86_64() {
+            cflags.push("-m64");
+        }
+
+        if !target.is_i686() {
+            cflags.push("-fPIC");
+        }
+
+        cflags
+    }
+
+    fn add_args(&self, cmd : &mut Command, src : &Path, obj : &Path,
+                inc_dirs : &[PathBuf]) {
+        cmd.arg("-c").args(&self.cflags());
+
+        let target = self.target_triple();
+
+        if target.is_darwin() {
+            // for some reason clang on darwin doesn't seem to define this
+            cmd.arg("-DCHAR_BIT=8");
+        }
+
+        for directory in inc_dirs {
+            println!("{:?}", directory);
+            cmd.arg("-I").arg(directory);
+        }
+
+        cmd.arg("-o").arg(obj).arg(src);
+    }
+}
+
+impl Toolchain for GccishToolchain {
+    fn target_triple(&self) -> &Triple {
+        &self.target_triple
+    }
+
+    fn cc_cmd(&self, src_file : &Path, obj_file : &Path,
+              inc_dirs : &[PathBuf]) -> Command {
+        let mut cmd = Command::new(&self.cc_cmd);
+        self.add_args(&mut cmd, src_file, obj_file, inc_dirs);
+        return cmd;
+    }
+
+    fn cxx_cmd(&self, src_file : &Path, obj_file : &Path,
+               inc_dirs : &[PathBuf]) -> Command {
+        let mut cmd = Command::new(&self.cxx_cmd);
+        self.add_args(&mut cmd, src_file, obj_file, inc_dirs);
+        cmd.arg("-fno-rtti");
+        return cmd;
+    }
+
+    fn ar_cmd(&self, obj_files : &[PathBuf], output : &Path) -> Command {
+        let mut cmd = Command::new(&self.ar_cmd);
+        cmd.arg("crus");
+        cmd.arg(&output);
+        cmd.args(obj_files);
+        cmd
+    }
+}
+
+/// MSVC toolchain
+struct MsvcToolchain {
+    target_triple : Triple
+}
+
+impl MsvcToolchain {
+    fn new(triple : &Triple) -> MsvcToolchain {
+        MsvcToolchain {
+            target_triple : triple.clone()
+        }
+    }
+}
+
+impl Toolchain for MsvcToolchain {
+    fn target_triple(&self) -> &Triple {
+        &self.target_triple
+    }
+
+    fn cc_cmd(&self, src_file : &Path, obj_file : &Path,
+              inc_dirs : &[PathBuf]) -> Command {
+        let mut cmd = Command::new("cl");
+
+        cmd.arg("-nologo").arg("-c").arg(src_file);
+        let _ : Vec<_> = inc_dirs.iter().map(|p| {
+            let mut s = OsString::new();
+            s.push("-I");
+            s.push(&p);
+            cmd.arg(&s);
+        }).collect();
+
+        let mut out = OsString::new();
+        out.push("-Fo");
+        out.push(obj_file);
+        cmd.arg(&out);
+
+        cmd
+    }
+
+    fn cxx_cmd(&self, src_file : &Path, obj_file : &Path,
+               inc_dirs : &[PathBuf]) -> Command {
+        self.cc_cmd(src_file, obj_file, inc_dirs)
+    }
+
+    fn ar_cmd(&self, obj_files : &[PathBuf], output : &Path) -> Command {
+        let mut cmd = Command::new("lib");
+        cmd.arg("-nologo");
+        let mut s = OsString::new();
+        s.push("-OUT:");
+        s.push(&output);
+        cmd.arg(&s);
+        cmd.args(obj_files);
+        cmd
+    }
+}
+
+pub fn build_static_lib(cfg : &Config) -> StaticLib {
+    let target = cfg.target();
+    let toolchain : Box<Toolchain> = if target.is_msvc() {
+        Box::new(MsvcToolchain::new(target))
+    } else {
+        Box::new(GccishToolchain::new(target))
+    };
+    let mut slib = StaticLib::new(toolchain, LLVMTools::new(cfg));
+    slib.set_src_dir(&cfg.src_dir());
+    slib.set_build_dir(cfg.out_dir());
+    slib
+}
diff --git a/src/build_helper/config.rs b/src/build_helper/config.rs
new file mode 100644
index 0000000000000..c75f2f0865656
--- /dev/null
+++ b/src/build_helper/config.rs
@@ -0,0 +1,95 @@
+use std::env;
+use std::path::{Path, PathBuf};
+use std::fs::PathExt;
+use cc::Triple;
+
+/// Collect the environment variables passed to the build script.
+/// Note: To determine the root directory of the rust source repo we simply
+/// concat "../.." to the manifest directory of the Cargo package being built.
+/// This will only work if all Cargo packages are placed under `src/`.
+pub struct Config {
+    manifest_dir : PathBuf,
+    out_dir : PathBuf,
+    llvm_root : PathBuf,
+    target : Triple,
+    host : Triple,
+    njobs : u8,
+    profile : String
+}
+
+impl Config {
+    pub fn new() -> Config {
+        let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR")
+                                         .expect("CARGO_MANIFEST_DIR"));
+        let out_dir = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR"));
+        let llvm_root = PathBuf::from(env::var("CFG_LLVM_ROOT")
+                                      .expect("CFG_LLVM_ROOT"));
+        let target = Triple::new(&env::var("TARGET").expect("TARGET"))
+            .expect("target triple");
+        let host = Triple::new(&env::var("HOST").expect("HOST"))
+            .expect("host triple");
+        let njobs : u8 = env::var("NUM_JOBS").expect("NUM_JOBS")
+            .parse().expect("parse NUM_JOBS");
+        let profile = env::var("PROFILE").expect("PROFILE");
+        Config {
+            manifest_dir : manifest_dir,
+            out_dir : out_dir,
+            llvm_root : llvm_root,
+            target : target,
+            host : host,
+            njobs : njobs,
+            profile : profile
+        }
+    }
+
+    /// Root directory of the Rust project
+    pub fn root_dir(&self) -> PathBuf {
+        self.manifest_dir.join("..").join("..")
+    }
+
+    /// Parent directory of all Cargo packages
+    pub fn src_dir(&self) -> PathBuf {
+        self.manifest_dir.join("..")
+    }
+
+    /// Output directory of the Cargo package
+    pub fn out_dir(&self) -> &Path {
+        &self.out_dir
+    }
+
+    /// Build artifacts directory for LLVM
+    pub fn llvm_build_artifacts_dir(&self) -> PathBuf {
+        let dirs = vec![".", "Release", "Release+Asserts",
+                        "Debug", "Debug+Asserts"];
+        for d in &dirs {
+            let artifacts_dir = self.llvm_root.join(d);
+            if artifacts_dir.join("bin").join("llc").is_file() {
+                return artifacts_dir;
+            } else if artifacts_dir.join("bin").join("llc.exe").is_file() {
+                return artifacts_dir;
+            }
+        }
+        panic!("Directory supplied to CFG_LLVM_ROOT does not \
+                contain valid LLVM build.");
+    }
+
+    /// Target triple being compiled for
+    pub fn target(&self) -> &Triple {
+        &self.target
+    }
+
+    /// Host triple of the rustc compiler
+    pub fn host(&self) -> &Triple {
+        &self.host
+    }
+
+    /// Number of parallel jobs to run
+    pub fn njobs(&self) -> u8 {
+        self.njobs
+    }
+
+    /// Profile being built
+    pub fn profile(&self) -> &str {
+        &self.profile
+    }
+}
diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs
new file mode 100644
index 0000000000000..a0af397b46d04
--- /dev/null
+++ b/src/build_helper/lib.rs
@@ -0,0 +1,14 @@
+#![feature(result_expect, path_ext)]
+
+mod run;
+mod llvm;
+
+pub mod config;
+pub mod cc;
+
+pub use run::Run;
+pub use config::Config;
+pub use cc::Triple;
+pub use cc::GccishToolchain;
+pub use cc::build_static_lib;
+pub use llvm::LLVMTools;
diff --git a/src/build_helper/llvm.rs b/src/build_helper/llvm.rs
new file mode 100644
index 0000000000000..de8e1831b4c36
--- /dev/null
+++ b/src/build_helper/llvm.rs
@@ -0,0 +1,65 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Configure and compile LLVM. Also provide paths to the LLVM tools
+//! for other parts of the build system.
+
+use std::process::Command;
+use std::path::{Path, PathBuf};
+use cc::Triple;
+use config::Config;
+
+/// Provides paths to the LLVM tools and libraries
+pub struct LLVMTools {
+    llvm_build_artifacts_dir : PathBuf,
+    llvm_src_dir : PathBuf
+}
+
+impl LLVMTools {
+    pub fn new(cfg : &Config) -> LLVMTools {
+        LLVMTools {
+            llvm_build_artifacts_dir : cfg.llvm_build_artifacts_dir(),
+            llvm_src_dir : cfg.src_dir().join("llvm")
+        }
+    }
+
+    pub fn path_to_llvm_config(&self) -> PathBuf {
+        self.llvm_build_artifacts_dir.join("bin").join("llvm-config")
+    }
+
+    fn path_to_llc(&self) -> PathBuf {
+        self.llvm_build_artifacts_dir.join("bin").join("llc")
+    }
+
+    pub fn path_to_llvm_libs(&self) -> PathBuf {
+        self.llvm_build_artifacts_dir.join("lib")
+    }
+
+    pub fn llc_cmd(&self, target : &Triple, src : &Path, obj : &Path)
+                   -> Command {
+        let mut cmd = Command::new(&self.path_to_llc());
+        cmd.arg("-filetype=obj")
+            .arg(&format!("-mtriple={}", target))
+            .arg("-relocation-model=pic")
+            .arg("-o").arg(obj).arg(src);
+        cmd
+    }
+
+    pub fn get_llvm_cxxflags(&self) -> Vec<String> {
+        let output = Command::new(&self.path_to_llvm_config())
+            .arg("--cxxflags").output().expect("llvm-config --cxxflags");
+        let cxxflags = String::from_utf8(output.stdout).unwrap();
+        cxxflags.split_whitespace().map(|s| s.into()).collect()
+    }
+
+    pub fn llvm_src_dir(&self) -> &Path {
+        &self.llvm_src_dir
+    }
+}
diff --git a/src/build_helper/run.rs b/src/build_helper/run.rs
new file mode 100644
index 0000000000000..6b9ba601f815b
--- /dev/null
+++ b/src/build_helper/run.rs
@@ -0,0 +1,77 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Run the command in a background thread. Redirect the output (and error
+//! output) to the screen.
+
+use std::process::{Stdio, Command};
+use std::sync::mpsc::{channel, Receiver};
+use std::thread;
+use std::io::{self, Read, BufRead, BufReader, Write};
+
+/// Run the command in another thread. Print output to screen.
+/// Panics if command failed to run.
+pub trait Run {
+    fn run(&mut self);
+}
+
+#[derive(Clone, Copy)]
+enum OutputType { Stdout, Stderr }
+
+impl Run for Command {
+    fn run(&mut self) {
+        match run(self) {
+            Ok(_) => {},
+            Err(msg) => panic!(msg)
+        }
+    }
+}
+
+fn run(cmd : &mut Command) -> Result<(), String> {
+    println!("Running {:?}", cmd);
+    let mut child = try!(cmd.stdin(Stdio::piped())
+                         .stdout(Stdio::piped())
+                         .stderr(Stdio::piped())
+                         .spawn()
+                         .map_err(|e| format!("Failed: {:?}: {}", cmd, e)));
+    let stdout = child.stdout.take().expect("log.rs: child.stdout");
+    let stderr = child.stderr.take().expect("log.rs: child.stderr");
+    let stdout_ch = read_async(stdout, OutputType::Stdout);
+    let stderr_ch = read_async(stderr, OutputType::Stderr);
+    let status = child.wait().expect("log.rs: child.wait");
+    let _ = stdout_ch.recv();
+    let _ = stderr_ch.recv();
+    if status.success() {
+        Ok(())
+    } else {
+        Err(format!("Command {:?} did not return a success status.", cmd))
+    }
+}
+
+fn read_async<R : Read + Send + 'static>(reader : R, ty : OutputType)
+                                         -> Receiver<()> {
+    let (tx, rx) = channel();
+    thread::spawn(move || {
+        tx.send(log(reader, ty)).expect("log.rs: run_async()");
+    });
+    rx
+}
+
+fn log<R : Read + Send + 'static>(reader : R, ty : OutputType) {
+    let mut buf_reader = BufReader::new(reader);
+    let mut line : Vec<u8> = Vec::new();
+    while buf_reader.read_until(0xA, &mut line).expect("log.rs: log()") > 0 {
+        let _ = match ty {
+            OutputType::Stdout => io::stdout().write_all(&line),
+            OutputType::Stderr => io::stderr().write_all(&line)
+        };
+        line.clear();
+    }
+}
diff --git a/src/compiletest/Cargo.toml b/src/compiletest/Cargo.toml
new file mode 100644
index 0000000000000..7e0a48028ce9e
--- /dev/null
+++ b/src/compiletest/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "compiletest"
+version = "0.0.0"
+build = "build.rs"
+
+[[bin]]
+name = "compiletest"
+path = "compiletest.rs"
+
+[build-dependencies]
+build_helper = { path = "../build_helper" }
\ No newline at end of file
diff --git a/src/compiletest/build.rs b/src/compiletest/build.rs
new file mode 100644
index 0000000000000..504f8004a77b0
--- /dev/null
+++ b/src/compiletest/build.rs
@@ -0,0 +1,18 @@
+extern crate build_helper;
+
+use build_helper::{Config, build_static_lib};
+
+fn main() {
+    build_rust_test_helpers();
+}
+
+fn build_rust_test_helpers() {
+    let cfg = Config::new();
+    let src_dir = cfg.src_dir().join("rt");
+    let src_files = vec!["rust_test_helpers.c"];
+    build_static_lib(&cfg)
+        .set_src_dir(&src_dir)
+        .set_build_dir(&cfg.out_dir())
+        .files(&src_files)
+        .compile("rust_test_helpers");
+}
diff --git a/src/driver/Cargo.toml b/src/driver/Cargo.toml
new file mode 100644
index 0000000000000..a6393e74a9e09
--- /dev/null
+++ b/src/driver/Cargo.toml
@@ -0,0 +1,24 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "driver"
+version = "0.0.0"
+
+[[bin]]
+name = "rustc"
+path = "rustc.rs"
+
+[[bin]]
+name = "rustdoc"
+path = "rustdoc.rs"
+
+[dependencies]
+rustc_driver = { path = "../librustc_driver" }
+std = { path = "../libstd" }
+rustdoc = { path = "../librustdoc" }
+
+[profile.release]
+opt-level = 3
+lto = true
+
+[profile.dev]
+opt-level = 1
diff --git a/src/driver/rustc.rs b/src/driver/rustc.rs
new file mode 100644
index 0000000000000..4bbd3461b911c
--- /dev/null
+++ b/src/driver/rustc.rs
@@ -0,0 +1,15 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_private)]
+
+extern crate rustc_driver;
+
+fn main() { rustc_driver::main() }
diff --git a/src/driver/rustdoc.rs b/src/driver/rustdoc.rs
new file mode 100644
index 0000000000000..472a79b783ae1
--- /dev/null
+++ b/src/driver/rustdoc.rs
@@ -0,0 +1,15 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustdoc)]
+
+extern crate rustdoc;
+
+fn main() { rustdoc::main() }
diff --git a/src/etc/build_llvm.py b/src/etc/build_llvm.py
new file mode 100644
index 0000000000000..290f6837ee446
--- /dev/null
+++ b/src/etc/build_llvm.py
@@ -0,0 +1,136 @@
+# Copyright 2011-2015 The Rust Project Developers. See the COPYRIGHT
+# file at the top-level directory of this distribution and at
+# http://rust-lang.org/COPYRIGHT.
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+import os
+import subprocess
+import multiprocessing
+
+def build_llvm_cmake(src_dir, build_dir, target, ncpu,
+                     is_release, is_assert):
+    if "msvc" in target:
+        cmake_target = "Visual Studio 12"
+    elif "windows-gnu" in target:
+        cmake_target = "MinGW Makefiles"
+    else:
+        cmake_target = "Unix Makefiles"
+    if is_release:
+        cmake_build_type = "-DCMAKE_BUILD_TYPE=Release"
+    else:
+        cmake_build_type = "-DCMAKE_BUILD_TYPE=Debug"
+    if is_assert:
+        cmake_assert = "-DLLVM_ENABLE_ASSERTIONS=ON"
+    else:
+        cmake_assert = "-DLLVM_ENABLE_ASSERTIONS=OFF"
+    ret = subprocess.call(["cmake", "-G", cmake_target,
+                           cmake_build_type, cmake_assert,
+                           "-DLLVM_ENABLE_TERMINFO=OFF",
+                           "-DLLVM_ENABLE_ZLIB=OFF",
+                           "-DLLVM_ENABLE_FFI=OFF",
+                           "-DLLVM_BUILD_DOCS=OFF",
+                           src_dir], cwd = build_dir)
+    if ret != 0:
+        return ret
+    if "msvc" in target:
+        build_cmd = ["cmake", "--build", "."]
+    else:
+        build_cmd = ["cmake", "--build", ".", "--", "-j"+str(ncpu)]
+    return subprocess.call(build_cmd, cwd = build_dir)
+
+def build_llvm_autotools(src_dir, build_dir, target, ncpu,
+                         is_release, is_assert):
+    if is_release:
+        optimized = "--enable-optimized"
+    else:
+        optimized = "--disable-optimized"
+    if is_assert:
+        assertions = "--enable-assertions"
+    else:
+        assertions = "--disable-assertions"
+    ret = subprocess.call([os.path.join(src_dir, "configure"),
+                           "--enable-targets=x86,x86_64,arm,aarch64,mips,powerpc",
+                           optimized, assertions,
+                           "--disable-docs", "--enable-bindings=none",
+                           "--disable-terminfo", "--disable-zlib",
+                           "--disable-libffi",
+                           "--host=" + target, "--target=" + target,
+                           "--with-python=/usr/bin/python2.7"],
+                          cwd = build_dir)
+    if ret != 0:
+        return ret
+    return subprocess.call(["make", "-j"+str(ncpu)], cwd = build_dir)
+
+def llvm_build_dir(rust_root, target):
+    return os.path.join(rust_root, "target", "llvm", target)
+
+def llvm_build_artifacts_dir(rust_root, target, is_release, is_assert):
+    build_dir = llvm_build_dir(rust_root, target)
+    if "windows" in target:     # cmake puts everything under build_dir
+        return build_dir
+    else:
+        if is_release:
+            subdir = "Release"
+        else:
+            subdir = "Debug"
+        if is_assert:
+            subdir += "+Asserts"
+        return os.path.join(build_dir, subdir)
+
+def build_llvm(rust_root, target, force_rebuild, is_release, is_assert):
+    if is_release:
+        profile = "Release"
+    else:
+        profile = "Debug"
+    if is_assert:
+        profile += "+Asserts"
+    print "Building LLVM for target " + target + " profile " + profile + ":"
+    src_dir = os.path.join(rust_root, "src", "llvm")
+    build_dir = llvm_build_dir(rust_root, target)
+    # create build dir
+    try:
+        os.makedirs(build_dir)
+    except OSError:
+        if not os.path.isdir(build_dir):
+            raise
+    # use a stamp file to avoid rebuilding llvm
+    build_artifacts_dir = llvm_build_artifacts_dir(rust_root, target,
+                                                   is_release, is_assert)
+    stamp_file = os.path.join(build_artifacts_dir, "llvm.built.for.rust")
+    if os.path.isfile(stamp_file) and not force_rebuild:
+        print "Skipped. Use --rebuild-llvm to override."
+        return                  # no need to build llvm here.
+    ncpu = multiprocessing.cpu_count()
+    # build llvm
+    if "windows" in target:
+        ret = build_llvm_cmake(src_dir, build_dir, target, ncpu,
+                               is_release, is_assert)
+    else:
+        ret = build_llvm_autotools(src_dir, build_dir, target,
+                                   ncpu, is_release, is_assert)
+    if ret != 0:
+        print "Build failed."
+        exit(ret)
+    # make a note so that we don't rebuild llvm
+    with open(stamp_file, "w") as f:
+        f.write("built")
+
+def get_llvm_bin_dir(rust_root, target, external_llvm_root):
+    if external_llvm_root:
+        llvm_root = external_llvm_root
+    else:
+        llvm_root = os.path.join(rust_root, "target", "llvm", target)
+    dirs = [".", "Release", "Release+Asserts", "Debug", "Debug+Asserts"]
+    for d in dirs:
+        bin_dir = os.path.join(llvm_root, d, "bin")
+        f = os.path.join(bin_dir, "llc")
+        fwin = os.path.join(bin_dir, "llc.exe")
+        if os.path.isfile(f) or os.path.isfile(fwin):
+            return bin_dir
+    print "Path " + llvm_root + " does not contain valid LLVM build."
+    exit(1)
diff --git a/src/etc/build_rust.py b/src/etc/build_rust.py
new file mode 100644
index 0000000000000..a5970b02b5426
--- /dev/null
+++ b/src/etc/build_rust.py
@@ -0,0 +1,391 @@
+#!/usr/bin/python
+
+import sys
+import os
+import shutil
+import glob
+import subprocess
+import argparse
+import build_llvm
+
+def scrub(b):
+    if sys.version_info >= (3,) and type(b) == bytes:
+        return b.decode("ascii")
+    else:
+        return b
+
+def cmd_out(cmdline):
+    p = subprocess.Popen(cmdline, stdout=subprocess.PIPE)
+    return scrub(p.communicate()[0].strip())
+
+def scrape_rustc_host_triple():
+    output = cmd_out(["rustc", "-Vv"]).split()
+    return output[output.index("host:")+1]
+
+def git_commit_hash():
+    return cmd_out(["git", "rev-parse", "HEAD"])
+
+def git_short_hash():
+    return cmd_out(["git", "rev-parse", "--short", "HEAD"])
+
+def git_short_date():
+    return cmd_out(["git", "show", "-s", "--format=%cd", "--date=short"])
+
+def set_release_channel(channel):
+    RELEASE = "1.3.0-" + channel
+    VERSION = RELEASE + " (" + git_short_hash() + " " + git_short_date() + ")"
+    os.environ["CFG_VERSION"] = VERSION
+    os.environ["CFG_VER_HASH"] = git_commit_hash()
+    os.environ["CFG_VER_DATE"] = git_short_date()
+    os.environ["CFG_RELEASE"] = RELEASE
+    if channel in ["beta", "stable"]:
+        os.environ["CFG_DISABLE_UNSTABLE_FEATURES"] = "1"
+        # set the bootstrap key to subvert the feature gating during build
+        os.environ["CFG_BOOTSTRAP_KEY"] = "5196bb7834f331542c9875f3059"
+        os.environ["RUSTC_BOOTSTRAP_KEY"] = "5196bb7834f331542c9875f3059"
+    os.environ["CFG_RELEASE_CHANNEL"] = channel
+
+def set_env_vars(rust_root, target, external_llvm_root):
+    if external_llvm_root:
+        llvm_root = external_llvm_root
+    else:
+        llvm_root = build_llvm.llvm_build_dir(rust_root, target)
+    if "windows" in target:
+        os.environ["CFG_LIBDIR_RELATIVE"] = "bin"
+    else:
+        os.environ["CFG_LIBDIR_RELATIVE"] = "lib"
+    os.environ["CFG_PREFIX"] = "/"
+    os.environ["CFG_COMPILER_HOST_TRIPLE"] = target
+    os.environ["CARGO_TARGET_DIR"] = os.path.join(rust_root, "target")
+    os.environ["CFG_LLVM_ROOT"] = llvm_root
+
+# build the src/driver crate, which is the root package for the compiler
+# (including rustdoc)
+def build_driver_crate(rust_root, target, is_release, verbose):
+    args = ["cargo", "build", "--manifest-path",
+            os.path.join(rust_root, "src", "driver", "Cargo.toml")]
+    args.extend(["--target", target])
+    if is_release:
+        args.append("--release")
+    if verbose:
+        args.append("--verbose")
+    ret = subprocess.call(args)
+    if ret == 0:
+        print "Build succeeded."
+    else:
+        print "Build failed."
+        exit(ret)
+
+# build_dir refers to the <rust-root>/target directory
+def copy_rust_dist(build_dir, dest_dir, host, targets, is_release):
+    if is_release:
+        profile = "release"
+    else:
+        profile = "debug"
+    bin_dir = os.path.join(dest_dir, "bin")
+    if "windows" in host:
+        lib_dir = bin_dir
+        rustc = "rustc.exe"
+        rustdoc = "rustdoc.exe"
+    else:
+        lib_dir = os.path.join(dest_dir, "lib")
+        rustc = "rustc"
+        rustdoc = "rustdoc"
+    shutil.rmtree(dest_dir, ignore_errors = True)
+    os.makedirs(bin_dir)
+    host_build_dir = os.path.join(build_dir, host, profile)
+    shutil.copy2(os.path.join(host_build_dir, rustc), bin_dir)
+    shutil.copy2(os.path.join(host_build_dir, rustdoc), bin_dir)
+    for target in targets:
+        target_build_dir = os.path.join(build_dir, target, profile)
+        target_lib_dir = os.path.join(lib_dir, "rustlib", target, "lib")
+        rt_lib_dir = os.path.join(target_build_dir, "build", "std*", "out")
+        os.makedirs(target_lib_dir)
+        copy_list = glob.glob(os.path.join(target_build_dir, "deps", "*.*"))
+        copy_list.extend(glob.glob(os.path.join(rt_lib_dir, "*compiler-rt*.*")))
+        if not "windows" in target:
+            copy_list.extend(glob.glob(os.path.join(rt_lib_dir,
+                                                    "*morestack*.*")))
+        for f in copy_list:
+            shutil.copy2(f, target_lib_dir)
+
+# for now we only build libstd (and all dependencies) docs
+# docs are built by the stage1 compiler
+def build_rust_docs(rust_root, target, verbose):
+    print "Building docs:"
+    args = ["cargo", "doc", "--target", target, "--manifest-path",
+            os.path.join(rust_root, "src", "libstd", "Cargo.toml")]
+    if verbose:
+        args.append("--verbose")
+    ret = subprocess.call(args)
+    if ret == 0:
+        print "Cargo doc succeeded."
+    else:
+        print "Cargo doc failed."
+        exit(ret)
+    build_rustbook(rust_root, verbose)
+
+# the rustbook crate is built by the stage1 compiler, as a native exe.
+def build_rustbook(rust_root, verbose):
+    print "Building The Rust Programming Language book:"
+    args = ["cargo", "build", "--manifest-path",
+            os.path.join(rust_root, "src", "rustbook", "Cargo.toml")]
+    if verbose:
+        args.append("--verbose")
+    ret = subprocess.call(args)
+    if ret != 0:
+        print "Building rustbook failed."
+        exit(ret)
+    rustbook_exe = os.path.join(rust_root, "target", "debug", "rustbook")
+    doc_dest = os.path.join(rust_root, "target", "doc")
+    shutil.rmtree(doc_dest, ignore_errors = True)
+    os.makedirs(doc_dest)
+    book_src = os.path.join(rust_root, "src", "doc", "trpl")
+    book_dest = os.path.join(doc_dest, "book")
+    ret1 = subprocess.call([rustbook_exe, "build", book_src, book_dest])
+    style_src = os.path.join(rust_root, "src", "doc", "style")
+    style_dest = os.path.join(doc_dest, "style")
+    ret2 = subprocess.call([rustbook_exe, "build", style_src, style_dest])
+    if ret1 == 0 and ret2 == 0:
+        print "Done."
+    else:
+        print "Rustbook failed."
+        exit(1)
+
+def run_test_for_crate(rust_root, crate, target, verbose):
+    print "Running " + crate + " tests:"
+    args = ["cargo", "test", "--target", target, "--manifest-path",
+            os.path.join(rust_root, "src", crate, "Cargo.toml")]
+    if verbose:
+        args.append("--verbose")
+    return subprocess.call(args)
+
+def run_crate_tests(rust_root, target, verbose):
+    crates_to_test = ["libcoretest", "liballoc", "libarena", "libcollections",
+                      "libcollectionstest", "libflate", "libfmt_macros",
+                      "libgetopts", "libgraphviz", "liblog", "librand",
+                      "librbml", "libstd", "libterm", "libserialize",
+                      "libsyntax", "librustc", "librustc_back",
+                      "librustc_bitflags", "librustc_data_structures",
+                      "librustc_driver", "librustdoc", "libtest"]
+    clean_build_dirs(rust_root, target, "debug")
+    for crate in crates_to_test:
+        if run_test_for_crate(rust_root, crate, target, verbose) != 0:
+            print "Tests in crate " + crate + " failed."
+
+# the compiletest crate is built by the stage1 compiler, as a native exe
+def run_compiletests(rust_root, target, llvm_bin_dir, verbose):
+    print "Building compiletest:"
+    args = ["cargo", "build", "--manifest-path",
+            os.path.join(rust_root, "src", "compiletest", "Cargo.toml")]
+    if verbose:
+        args.append("--verbose")
+    ret = subprocess.call(args)
+    if ret == 0:
+        print "Done."
+    else:
+        print "Building compiletest failed."
+        exit(ret)
+    target_dir = os.path.join(rust_root, "target")
+    ctest_exe = os.path.join(target_dir, "debug", "compiletest")
+    bin_dir = os.path.join(target_dir, "stage2", "bin")
+    if "windows" in target:
+        lib_dir = bin_dir
+    else:
+        lib_dir = os.path.join(target_dir, "stage2", "lib")
+    rustlib_dir = os.path.join(lib_dir, "rustlib", target, "lib")
+    rustc_path = os.path.join(bin_dir, "rustc")
+    rustdoc_path = os.path.join(bin_dir, "rustdoc")
+    aux_base = os.path.join(rust_root, "src", "test", "auxiliary")
+    stage_id = "stage2-" + target
+    test_helpers_lib_dir = glob.glob(
+        os.path.join(target_dir, "debug", "build", "compiletest*", "out"))
+    rust_flags = "--cfg rtopt -O -L " + test_helpers_lib_dir[0]
+    tests_to_run = [("run-pass", "run-pass"),
+                    ("run-pass", "run-pass-fulldeps"),
+                    ("run-pass-valgrind", "run-pass-valgrind"),
+                    ("run-fail", "run-fail"),
+                    ("run-fail", "run-fail-fulldeps"),
+                    ("compile-fail", "compile-fail"),
+                    ("compile-fail", "compile-fail-fulldeps"),
+                    ("parse-fail", "parse-fail"),
+                    ("pretty", "pretty"),
+                    ("debuginfo-gdb", "debuginfo")] # TODO: detect gdb/lldb
+    args = [ctest_exe, "--compile-lib-path", lib_dir,
+            "--run-lib-path", rustlib_dir, "--rustc-path", rustc_path,
+            "--rustdoc-path", rustdoc_path, "--llvm-bin-path", llvm_bin_dir,
+            "--aux-base", aux_base, "--stage-id", stage_id,
+            "--target", target, "--host", host, "--python", sys.executable,
+            "--gdb-version", "", "--lldb-version=", "",
+            "--android-cross-path", "", "--adb-path", "", "--adb-test-dir", "",
+            "--host-rustcflags", rust_flags, "--target-rustcflags", rust_flags,
+            "--lldb-python-dir", ""]
+    if verbose:
+        args.append("--verbose")
+    test_logs = os.path.join(rust_root, "target", "test-report")
+    shutil.rmtree(test_logs, ignore_errors = True)
+    os.makedirs(test_logs)
+    for test in tests_to_run:
+        src_base = os.path.join(rust_root, "src", "test", test[1])
+        build_base = os.path.join(rust_root, "target", "test", test[1])
+        shutil.rmtree(build_base, ignore_errors = True)
+        os.makedirs(build_base)
+        log_file = os.path.join(test_logs, test[1])
+        final_args = args + ["--src-base", src_base,
+                             "--build-base", build_base,
+                             "--mode", test[0], "--logfile", log_file]
+        ret = subprocess.call(final_args)
+        if ret != 0:
+            print "Compiler test " + test[1] + " failed."
+
+def build_stage1_rust(rust_root, build,
+                      external_llvm_root, is_release, verbose):
+    print "Building stage1 compiler:"
+    set_env_vars(rust_root, build, external_llvm_root)
+    build_driver_crate(rust_root, build, is_release, verbose)
+    print "Copying stage1 compiler to target/stage1:"
+    build_dir = os.path.join(rust_root, "target")
+    dest_dir = os.path.join(build_dir, "stage1")
+    copy_rust_dist(build_dir, dest_dir, build, [build], is_release)
+    print "Done."
+
+def clean_build_dirs(rust_root, build, profile):
+    dir1 = os.path.join(rust_root, "target", profile)
+    dir2 = os.path.join(rust_root, "target", build, profile)
+    shutil.rmtree(dir1, ignore_errors = True)
+    shutil.rmtree(dir2, ignore_errors = True)
+
+# switch to the rustc in the specified sysroot
+def switch_rustc(sysroot, host):
+    bin_dir = os.path.join(sysroot, "bin")
+    if "windows" in host:
+        lib_dir = bin_dir
+        rustc = "rustc.exe"
+        rustdoc = "rustdoc.exe"
+    else:
+        lib_dir = os.path.join(sysroot, "lib")
+        rustc = "rustc"
+        rustdoc = "rustdoc"
+    os.environ["RUSTC"] = os.path.join(bin_dir, rustc)
+    os.environ["RUSTDOC"] = os.path.join(bin_dir, rustdoc)
+    rustlib_dir = os.path.join(lib_dir, "rustlib", host, "lib")
+    if "windows" in host:
+        os.environ["PATH"] += os.pathsep + rustlib_dir
+    elif "darwin" in host:
+        os.environ["DYLD_LIBRARY_PATH"] = rustlib_dir
+    else:
+        os.environ["LD_LIBRARY_PATH"] = rustlib_dir
+
+def build_stage2_rust(rust_root, build, host, targets,
+                      external_llvm_root, is_release, verbose):
+    build_dir = os.path.join(rust_root, "target")
+    stage1_dir = os.path.join(build_dir, "stage1")
+    switch_rustc(stage1_dir, build)
+    for target in targets:
+        print "Building stage2 compiler for target " + target + ":"
+        set_env_vars(rust_root, target, external_llvm_root)
+        build_driver_crate(rust_root, target, is_release, verbose)
+    set_env_vars(rust_root, host, llvm_root)
+    build_rust_docs(rust_root, host, verbose = verbose)
+    print "Copying stage2 compiler to target/stage2:"
+    dest_dir = os.path.join(build_dir, "stage2")
+    copy_rust_dist(build_dir, dest_dir, host, targets, is_release)
+    print "Done."
+
+
+# main function
+
+# parse command line arguments
+parser = argparse.ArgumentParser(description="Build the Rust compiler.")
+parser.add_argument("--verbose", action="store_true", default=False,
+                    help="Pass --verbose to Cargo when building Rust.")
+parser.add_argument("--host", action="store",
+                    help="GNUs ./configure syntax LLVM host triple")
+parser.add_argument("--target", action="append",
+                    help="GNUs ./configure syntax LLVM target triples")
+parser.add_argument("--release-channel", action="store", default="dev",
+                    help="The name of the release channel to build.")
+parser.add_argument("--enable-debug", action="store_true", default=False,
+                    help="Build with debug profile. The default is a\
+                    release build. Note this only applies to the\
+                    compiler, not LLVM.")
+parser.add_argument("--enable-llvm-debug",
+                    action="store_true", default=False,
+                    help="Build LLVM with debug profile. The default is a\
+                    release build with no assertions.")
+parser.add_argument("--enable-llvm-assertions",
+                    action="store_true", default=False,
+                    help="Build LLVM with assertions. Off by default for\
+                    non-nightly builds.")
+parser.add_argument("--no-bootstrap", action="store_true", default=False,
+                    help="Do not bootstrap. Build stage2 compiler only.")
+parser.add_argument("--rebuild-llvm", action="store_true", default=False,
+                    help="Force rebuilding LLVM.")
+parser.add_argument("--llvm-root", action="store",
+                    help="Specify external LLVM root.")
+parser.add_argument("--run-tests-only", action="store_true", default=False,
+                    help="Run library tests only. Don't build the compiler.")
+args = parser.parse_args()
+
+# collect some essential infomation from the build environment
+rust_root = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..")
+build = scrape_rustc_host_triple()
+if args.host:
+    host = args.host
+else:
+    host = build
+targets = [host]
+if args.target:
+    targets.append([x for x in args.target and x not in targets])
+
+is_release = not args.enable_debug
+llvm_release = not args.enable_llvm_debug
+verbose = args.verbose
+llvm_root = args.llvm_root
+is_assert = args.enable_llvm_assertions
+release_channel = args.release_channel
+
+if release_channel not in ["dev", "nightly", "beta", "stable"]:
+    print "Release channel must be one of 'dev', 'nightly', 'beta', 'stable'"
+    exit(1)
+elif release_channel == "nightly":
+    print "Nightly builds always have LLVM assertions on."
+    is_assert = True
+print "Building Rust for release channel " + release_channel + ":"
+set_release_channel(release_channel)
+
+# build LLVM
+if llvm_root and ((build != host) or targets.len() > 1):
+    print "--llvm-root is only allowed for native builds."
+    exit(1)
+if not llvm_root:
+    force_rebuild = args.rebuild_llvm
+    llvm_targets = targets
+    if build not in targets:
+        llvm_targets.insert(0, build)
+    for target in llvm_targets:
+        build_llvm.build_llvm(rust_root, target, force_rebuild = force_rebuild,
+                              is_release = llvm_release, is_assert = is_assert)
+
+# build rustc and docs
+if is_release:
+    profile = "release"
+else:
+    profile = "debug"
+if not args.run_tests_only:
+    print "Building Rust with " + profile + " profile:"
+    if not args.no_bootstrap:
+        build_stage1_rust(rust_root, build, llvm_root,
+                          is_release = is_release, verbose = verbose)
+        clean_build_dirs(rust_root, build, profile)
+    build_stage2_rust(rust_root, build, host, targets, llvm_root,
+                      is_release = is_release, verbose = verbose)
+
+# we only run tests for native builds
+if host == build:
+    set_env_vars(rust_root, host, llvm_root)
+    stage2_dir = os.path.join(rust_root, "target", "stage2")
+    switch_rustc(stage2_dir, host)
+    llvm_bin_dir = build_llvm.get_llvm_bin_dir(rust_root, target, llvm_root)
+    run_compiletests(rust_root, host, llvm_bin_dir, verbose = verbose)
+    run_crate_tests(rust_root, host, verbose = verbose)
diff --git a/src/liballoc/Cargo.toml b/src/liballoc/Cargo.toml
new file mode 100644
index 0000000000000..f6941174ca4bb
--- /dev/null
+++ b/src/liballoc/Cargo.toml
@@ -0,0 +1,26 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "alloc"
+version = "0.0.0"
+build = "build.rs"
+
+[lib]
+name = "alloc"
+path = "lib.rs"
+
+[dependencies]
+core = { path = "../libcore" }
+libc = { path = "../liblibc" }
+
+[build-dependencies]
+build_helper = { path = "../build_helper" }
+
+[dev-dependencies]
+std = { path = "../libstd" }
+log = { path = "../liblog" }
+test = { path = "../libtest" }
+
+[features]
+jemalloc = []
+debug-jemalloc = ["jemalloc"]
+default = []	# by default, we enable jemalloc for non-windows targets
diff --git a/src/liballoc/build.rs b/src/liballoc/build.rs
new file mode 100644
index 0000000000000..bf602974ce8fc
--- /dev/null
+++ b/src/liballoc/build.rs
@@ -0,0 +1,83 @@
+extern crate build_helper;
+
+use std::process::Command;
+use std::fs::copy;
+use build_helper::{Config, Run, GccishToolchain};
+
+fn main() {
+    build_jemalloc();
+    // FIXME: It seems that when building tests, Cargo missed one of the
+    // link search libraries from the transitive dependencies. In this
+    // case, both libcollections and libstd depend on liballoc, the latter
+    // of which also depends on libcollections.
+    //
+    // Because liballoc is placed into <target>/<profile> when building tests,
+    // which is not passed to rustc as a dependency search directory, rustc
+    // complains about 'possible newer version of crate' because it is
+    // looking at the liballoc from the sysroot.
+    //
+    // We workaround this by manually passing this directory to rustc.
+    let root_dir = Config::new().out_dir()
+        .join("..").join("..").join("..");
+    println!("cargo:rustc-link-search=dependency={}", root_dir.display());
+}
+
+fn build_jemalloc() {
+    let cfg = Config::new();
+
+    // We ignore jemalloc on windows for the time-being, as `bash` is not
+    // universally available on Windows.
+    let build_jemalloc =
+        cfg!(feature = "jemalloc") || !cfg.target().is_windows();
+    if !build_jemalloc {
+        return
+    }
+
+    println!("cargo:rustc-cfg=jemalloc");
+
+    let src_dir = cfg.src_dir().join("jemalloc");
+    let build_dir = cfg.out_dir();
+    let target = cfg.target();
+
+    let mut cmd = Command::new("sh");
+    cmd.arg(&src_dir.join("configure"));
+    cmd.current_dir(&build_dir);
+    if target.is_mingw() {
+        // This isn't necessarily a desired option, but it's harmless and
+        // works around what appears to be a mingw-w64 bug.
+        //
+        // https://sourceforge.net/p/mingw-w64/bugs/395/
+        cmd.arg("--enable-lazy-lock");
+    } else if target.is_ios() || target.is_android() {
+        cmd.arg("--disable-tls");
+    }
+
+    if cfg!(feature = "debug-jemalloc") {
+        cmd.arg("--enable-debug");
+    }
+
+    // Turn off broken quarantine (see jemalloc/jemalloc#161)
+    cmd.arg("--disable-fill");
+
+    match &cfg.profile()[..] {
+        "bench" | "release" => {}
+        _ => { cmd.arg("--enable-debug"); }
+    }
+
+    cmd.arg("--with-jemalloc-prefix=je_");
+    cmd.arg(format!("--host={}", target));
+
+    let gcc = GccishToolchain::new(target);
+    let cflags = gcc.cflags().connect(" ");
+    cmd.arg(format!("CC={}", gcc.cc_cmd));
+    cmd.arg(format!("AR={}", gcc.ar_cmd));
+    cmd.arg(format!("RANLIB={} s", gcc.ar_cmd));
+    cmd.arg(format!("EXTRA_CFLAGS=-g1 {}", cflags));
+    cmd.run();
+
+    Command::new("make").current_dir(&build_dir).arg("build_lib_static").run();
+
+    let _ = copy(build_dir.join("lib").join("libjemalloc_pic.a"),
+                 build_dir.join("libjemalloc.a")).unwrap();
+    println!("cargo:rustc-link-search=native={}", build_dir.display());
+}
diff --git a/src/libarena/Cargo.toml b/src/libarena/Cargo.toml
new file mode 100644
index 0000000000000..11d2ddabbdec1
--- /dev/null
+++ b/src/libarena/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "arena"
+version = "0.0.0"
+
+[lib]
+name = "arena"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+alloc = { path = "../liballoc" }
+std = { path = "../libstd" }
+
+[dev-dependencies]
+test = { path = "../libtest" }
diff --git a/src/libcollections/Cargo.toml b/src/libcollections/Cargo.toml
new file mode 100644
index 0000000000000..8d395af85d978
--- /dev/null
+++ b/src/libcollections/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "collections"
+version = "0.0.0"
+
+[lib]
+name = "collections"
+path = "lib.rs"
+
+[dependencies]
+alloc = { path = "../liballoc" }
+core = { path = "../libcore" }
+rustc_unicode = { path = "../librustc_unicode" }
+
+[dev-dependencies]
+std = { path = "../libstd" }
+test = { path = "../libtest" }
diff --git a/src/libcollectionstest/Cargo.toml b/src/libcollectionstest/Cargo.toml
new file mode 100644
index 0000000000000..89cbb9a8549ce
--- /dev/null
+++ b/src/libcollectionstest/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "collectionstest"
+version = "0.0.0"
+
+[lib]
+name = "collectionstest"
+path = "lib.rs"
+
+[dev-dependencies]
+std = { path = "../libstd" }
+log = { path = "../liblog" }
+test = { path = "../libtest" }
+collections = { path = "../libcollections" }
+rustc_unicode = { path = "../librustc_unicode" }
diff --git a/src/libcore/Cargo.toml b/src/libcore/Cargo.toml
new file mode 100644
index 0000000000000..3aa82819f7003
--- /dev/null
+++ b/src/libcore/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "core"
+version = "0.0.0"
+
+[lib]
+name = "core"
+path = "lib.rs"
diff --git a/src/libcoretest/Cargo.toml b/src/libcoretest/Cargo.toml
new file mode 100644
index 0000000000000..a0c702ff9af3f
--- /dev/null
+++ b/src/libcoretest/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "coretest"
+version = "0.0.0"
+
+[lib]
+name = "coretest"
+path = "lib.rs"
+
+[dev-dependencies]
+core = { path = "../libcore" }
+test = { path = "../libtest" }
+libc = { path = "../liblibc" }
+rustc_unicode = { path = "../librustc_unicode" }
+rand = { path = "../librand" }
+std = { path = "../libstd" }
\ No newline at end of file
diff --git a/src/libflate/Cargo.toml b/src/libflate/Cargo.toml
new file mode 100644
index 0000000000000..4c378f72c60a9
--- /dev/null
+++ b/src/libflate/Cargo.toml
@@ -0,0 +1,21 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "flate"
+version = "0.0.0"
+build = "build.rs"
+
+[lib]
+name = "flate"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+std = { path = "../libstd" }
+libc = { path = "../liblibc" }
+
+[build-dependencies]
+build_helper = { path = "../build_helper" }
+
+[dev-dependencies]
+test = { path = "../libtest" }
+log = { path = "../liblog" }
diff --git a/src/libflate/build.rs b/src/libflate/build.rs
new file mode 100644
index 0000000000000..5af1ccf3a3aa5
--- /dev/null
+++ b/src/libflate/build.rs
@@ -0,0 +1,8 @@
+extern crate build_helper;
+
+use build_helper::{Config, build_static_lib};
+
+fn main() {
+    let cfg = Config::new();
+    build_static_lib(&cfg).files(&["rt/miniz.c"]).compile("miniz");
+}
diff --git a/src/libfmt_macros/Cargo.toml b/src/libfmt_macros/Cargo.toml
new file mode 100644
index 0000000000000..5882840fd2316
--- /dev/null
+++ b/src/libfmt_macros/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "fmt_macros"
+version = "0.0.0"
+
+[lib]
+name = "fmt_macros"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+std = { path = "../libstd" }
+
+[dev-dependencies]
+test = { path = "../libtest" }
diff --git a/src/libgetopts/Cargo.toml b/src/libgetopts/Cargo.toml
new file mode 100644
index 0000000000000..d27045d4e4fa3
--- /dev/null
+++ b/src/libgetopts/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "getopts"
+version = "0.0.0"
+
+[lib]
+name = "getopts"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+std = { path = "../libstd" }
+
+[dev-dependencies]
+log = { path = "../liblog" }
+test = { path = "../libtest" }
diff --git a/src/libgraphviz/Cargo.toml b/src/libgraphviz/Cargo.toml
new file mode 100644
index 0000000000000..b7e59114c76a4
--- /dev/null
+++ b/src/libgraphviz/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "graphviz"
+version = "0.0.0"
+
+[lib]
+name = "graphviz"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+std = { path = "../libstd" }
+
+[dev-dependencies]
+test = { path = "../libtest" }
diff --git a/src/liblibc/Cargo.toml b/src/liblibc/Cargo.toml
new file mode 100644
index 0000000000000..a702d611d38a9
--- /dev/null
+++ b/src/liblibc/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "libc"
+version = "0.0.0"
+
+[lib]
+name = "libc"
+path = "lib.rs"
+
+[dependencies]
+core = { path = "../libcore" }
+
+[dev-dependencies]
+std = { path = "../libstd" }
+test = { path = "../libtest" }
diff --git a/src/liblog/Cargo.toml b/src/liblog/Cargo.toml
new file mode 100644
index 0000000000000..7c55df5715c6f
--- /dev/null
+++ b/src/liblog/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "log"
+version = "0.0.0"
+
+[lib]
+name = "log"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+std = { path = "../libstd" }
+
+[dev-dependencies]
+test = { path = "../libtest" }
diff --git a/src/librand/Cargo.toml b/src/librand/Cargo.toml
new file mode 100644
index 0000000000000..8cadd9a0663e4
--- /dev/null
+++ b/src/librand/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rand"
+version = "0.0.0"
+
+[lib]
+name = "rand"
+path = "lib.rs"
+
+[dependencies]
+core = { path = "../libcore" }
+
+[dev-dependencies]
+std = { path = "../libstd" }
+log = { path = "../liblog" }
+test = { path = "../libtest" }
diff --git a/src/librbml/Cargo.toml b/src/librbml/Cargo.toml
new file mode 100644
index 0000000000000..804fde2d10050
--- /dev/null
+++ b/src/librbml/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rbml"
+version = "0.0.0"
+
+[lib]
+name = "rbml"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+log = { path = "../liblog" }
+serialize = { path = "../libserialize" }
+std = { path = "../libstd" }
+
+[dev-dependencies]
+test = { path = "../libtest" }
diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml
new file mode 100644
index 0000000000000..d2c3df0e6736b
--- /dev/null
+++ b/src/librustc/Cargo.toml
@@ -0,0 +1,30 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc"
+version = "0.0.0"
+
+[lib]
+name = "rustc"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+arena = { path = "../libarena" }
+collections = { path = "../libcollections" }
+flate = { path = "../libflate" }
+fmt_macros = { path = "../libfmt_macros" }
+getopts = { path = "../libgetopts" }
+graphviz = { path = "../libgraphviz" }
+libc = { path = "../liblibc" }
+log = { path = "../liblog" }
+rbml = { path = "../librbml" }
+rustc_back = { path = "../librustc_back" }
+rustc_bitflags = { path = "../librustc_bitflags" }
+rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_llvm = { path = "../librustc_llvm" }
+serialize = { path = "../libserialize" }
+syntax = { path = "../libsyntax" }
+std = { path = "../libstd" }
+
+[dev-dependencies]
+test = { path = "../libtest" }
diff --git a/src/librustc_back/Cargo.toml b/src/librustc_back/Cargo.toml
new file mode 100644
index 0000000000000..1c1726617ebaa
--- /dev/null
+++ b/src/librustc_back/Cargo.toml
@@ -0,0 +1,21 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_back"
+version = "0.0.0"
+
+[lib]
+name = "rustc_back"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+syntax = { path = "../libsyntax" }
+libc = { path = "../liblibc" }
+serialize = { path = "../libserialize" }
+rustc_llvm = { path = "../librustc_llvm" }
+log = { path = "../liblog" }
+std = { path = "../libstd" }
+rand = { path = "../librand" }
+
+[dev-dependencies]
+test = { path = "../libtest" }
diff --git a/src/librustc_bitflags/Cargo.toml b/src/librustc_bitflags/Cargo.toml
new file mode 100644
index 0000000000000..c6568423605d2
--- /dev/null
+++ b/src/librustc_bitflags/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_bitflags"
+version = "0.0.0"
+
+[lib]
+name = "rustc_bitflags"
+path = "lib.rs"
+
+[dev-dependencies]
+std = { path = "../libstd" }
+test = { path = "../libtest" }
diff --git a/src/librustc_borrowck/Cargo.toml b/src/librustc_borrowck/Cargo.toml
new file mode 100644
index 0000000000000..19915816f0226
--- /dev/null
+++ b/src/librustc_borrowck/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_borrowck"
+version = "0.0.0"
+
+[lib]
+name = "rustc_borrowck"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+log = { path = "../liblog" }
+syntax = { path = "../libsyntax" }
+graphviz = { path = "../libgraphviz" }
+rustc = { path = "../librustc" }
+std = { path = "../libstd" }
diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml
new file mode 100644
index 0000000000000..8e75fe06487d5
--- /dev/null
+++ b/src/librustc_data_structures/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_data_structures"
+version = "0.0.0"
+
+[lib]
+name = "rustc_data_structures"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+log = { path = "../liblog" }
+serialize = { path = "../libserialize" }
+std = { path = "../libstd" }
+
+[dev-dependencies]
+test = { path = "../libtest" }
diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml
new file mode 100644
index 0000000000000..d44d1455facbc
--- /dev/null
+++ b/src/librustc_driver/Cargo.toml
@@ -0,0 +1,32 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_driver"
+version = "0.0.0"
+
+[lib]
+name = "rustc_driver"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+arena = { path = "../libarena" }
+flate = { path = "../libflate" }
+getopts = { path = "../libgetopts" }
+graphviz = { path = "../libgraphviz" }
+libc = { path = "../liblibc" }
+log = { path = "../liblog" }
+rustc = { path = "../librustc" }
+rustc_back = { path = "../librustc_back" }
+rustc_borrowck = { path = "../librustc_borrowck" }
+rustc_lint = { path = "../librustc_lint" }
+rustc_llvm = { path = "../librustc_llvm" }
+rustc_privacy = { path = "../librustc_privacy" }
+rustc_resolve = { path = "../librustc_resolve" }
+rustc_trans = { path = "../librustc_trans" }
+rustc_typeck = { path = "../librustc_typeck" }
+serialize = { path = "../libserialize" }
+std = { path = "../libstd" }
+syntax = { path = "../libsyntax" }
+
+[dev-dependencies]
+test = { path = "../libtest" }
diff --git a/src/librustc_lint/Cargo.toml b/src/librustc_lint/Cargo.toml
new file mode 100644
index 0000000000000..bae75e4bc49c6
--- /dev/null
+++ b/src/librustc_lint/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_lint"
+version = "0.0.0"
+
+[lib]
+name = "rustc_lint"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+log = { path = "../liblog" }
+rustc = { path = "../librustc" }
+syntax = { path = "../libsyntax" }
+std = { path = "../libstd" }
diff --git a/src/librustc_llvm/Cargo.toml b/src/librustc_llvm/Cargo.toml
new file mode 100644
index 0000000000000..b4667655db068
--- /dev/null
+++ b/src/librustc_llvm/Cargo.toml
@@ -0,0 +1,23 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_llvm"
+version = "0.0.0"
+build = "build.rs"
+
+[lib]
+name = "rustc_llvm"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+libc = { path = "../liblibc" }
+rustc_bitflags = { path = "../librustc_bitflags" }
+std = { path = "../libstd" }
+
+[features]
+static-libstdcpp = []
+cargo = []
+default = ["cargo"]
+
+[build-dependencies]
+build_helper = { path = "../build_helper" }
diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs
new file mode 100644
index 0000000000000..b3638001b0995
--- /dev/null
+++ b/src/librustc_llvm/build.rs
@@ -0,0 +1,41 @@
+extern crate build_helper;
+
+use std::process::Command;
+use build_helper::{Config, build_static_lib, Run, LLVMTools};
+
+fn main() {
+    build_rustllvm();
+    generate_llvmdeps();
+}
+
+fn build_rustllvm() {
+    let cfg = Config::new();
+    let src_dir = cfg.src_dir().join("rustllvm");
+    let src_files = vec!["ExecutionEngineWrapper.cpp",
+                         "PassWrapper.cpp", "RustWrapper.cpp"];
+    build_static_lib(&cfg)
+        .set_src_dir(&src_dir)
+        .set_build_dir(&cfg.out_dir())
+        .files(&src_files)
+        .with_llvm()
+        .compile("rustllvm");
+}
+
+fn generate_llvmdeps() {
+    let cfg = Config::new();
+    let script = cfg.src_dir().join("etc").join("mklldeps.py");
+    let dest = cfg.out_dir().join("llvmdeps.rs");
+    let llvm_tools = LLVMTools::new(&cfg);
+    let llvm_components = "x86 arm aarch64 mips powerpc ipo bitreader \
+                           bitwriter linker asmparser mcjit interpreter \
+                           instrumentation";
+    Command::new("python")
+        .arg(&script)
+        .arg(&dest)
+        .arg(llvm_components)
+        .arg(if cfg!(feature = "static-libstdcpp") { "1" } else { "" })
+        .arg(&llvm_tools.path_to_llvm_config())
+        .run();
+    println!("cargo:rustc-link-search={}/lib",
+             llvm_tools.path_to_llvm_libs().display());
+}
diff --git a/src/librustc_privacy/Cargo.toml b/src/librustc_privacy/Cargo.toml
new file mode 100644
index 0000000000000..5ed9f19cb53bd
--- /dev/null
+++ b/src/librustc_privacy/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_privacy"
+version = "0.0.0"
+
+[lib]
+name = "rustc_privacy"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+log = { path = "../liblog" }
+rustc = { path = "../librustc" }
+syntax = { path = "../libsyntax" }
+std = { path = "../libstd" }
diff --git a/src/librustc_resolve/Cargo.toml b/src/librustc_resolve/Cargo.toml
new file mode 100644
index 0000000000000..d8a9b43a34c3c
--- /dev/null
+++ b/src/librustc_resolve/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_resolve"
+version = "0.0.0"
+
+[lib]
+name = "rustc_resolve"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+log = { path = "../liblog" }
+syntax = { path = "../libsyntax" }
+rustc_bitflags = { path = "../librustc_bitflags" }
+rustc = { path = "../librustc" }
+std = { path = "../libstd" }
diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml
new file mode 100644
index 0000000000000..b787928939645
--- /dev/null
+++ b/src/librustc_trans/Cargo.toml
@@ -0,0 +1,23 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_trans"
+version = "0.0.0"
+
+[lib]
+name = "rustc_trans"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+arena = { path = "../libarena" }
+flate = { path = "../libflate" }
+getopts = { path = "../libgetopts" }
+graphviz = { path = "../libgraphviz" }
+libc = { path = "../liblibc" }
+log = { path = "../liblog" }
+rustc = { path = "../librustc" }
+rustc_back = { path = "../librustc_back" }
+rustc_llvm = { path = "../librustc_llvm" }
+serialize = { path = "../libserialize" }
+syntax = { path = "../libsyntax" }
+std = { path = "../libstd" }
diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml
new file mode 100644
index 0000000000000..128df83fc444e
--- /dev/null
+++ b/src/librustc_typeck/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_typeck"
+version = "0.0.0"
+
+[lib]
+name = "rustc_typeck"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+log = { path = "../liblog" }
+syntax = { path = "../libsyntax" }
+arena = { path = "../libarena" }
+fmt_macros = { path = "../libfmt_macros" }
+rustc = { path = "../librustc" }
+std = { path = "../libstd" }
diff --git a/src/librustc_unicode/Cargo.toml b/src/librustc_unicode/Cargo.toml
new file mode 100644
index 0000000000000..7f4971ea3ef90
--- /dev/null
+++ b/src/librustc_unicode/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_unicode"
+version = "0.0.0"
+
+[lib]
+name = "rustc_unicode"
+path = "lib.rs"
+
+[dependencies]
+core = { path = "../libcore" }
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
new file mode 100644
index 0000000000000..b13f314cadd5b
--- /dev/null
+++ b/src/librustdoc/Cargo.toml
@@ -0,0 +1,30 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustdoc"
+version = "0.0.0"
+build = "build.rs"
+
+[lib]
+name = "rustdoc"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+arena = { path = "../libarena" }
+getopts = { path = "../libgetopts" }
+libc = { path = "../liblibc" }
+rustc = { path = "../librustc" }
+rustc_driver = { path = "../librustc_driver" }
+rustc_trans = { path = "../librustc_trans" }
+rustc_resolve = { path = "../librustc_resolve" }
+rustc_lint = { path = "../librustc_lint" }
+rustc_back = { path = "../librustc_back" }
+serialize = { path = "../libserialize" }
+syntax = { path = "../libsyntax" }
+test = { path = "../libtest" }
+rustc_unicode = { path = "../librustc_unicode" }
+log = { path = "../liblog" }
+std = { path = "../libstd" }
+
+[build-dependencies]
+build_helper = { path = "../build_helper" }
diff --git a/src/librustdoc/build.rs b/src/librustdoc/build.rs
new file mode 100644
index 0000000000000..f96ae283b8677
--- /dev/null
+++ b/src/librustdoc/build.rs
@@ -0,0 +1,11 @@
+extern crate build_helper;
+
+use build_helper::{Config, build_static_lib};
+
+fn main() {
+    let cfg = Config::new();
+    build_static_lib(&cfg)
+        .files(&["rt/hoedown/src"])
+        .include_dirs(&["rt/hoedown/src"])
+        .compile("hoedown");
+}
diff --git a/src/libserialize/Cargo.toml b/src/libserialize/Cargo.toml
new file mode 100644
index 0000000000000..f93d827a7316a
--- /dev/null
+++ b/src/libserialize/Cargo.toml
@@ -0,0 +1,18 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "serialize"
+version = "0.0.0"
+
+[lib]
+name = "serialize"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+log = { path = "../liblog" }
+rustc_unicode = { path = "../librustc_unicode" }
+collections = { path = "../libcollections" }
+std = { path = "../libstd" }
+
+[dev-dependencies]
+test = { path = "../libtest" }
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
new file mode 100644
index 0000000000000..fb7bdafd7d938
--- /dev/null
+++ b/src/libstd/Cargo.toml
@@ -0,0 +1,27 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "std"
+version = "0.0.0"
+build = "build.rs"
+
+[lib]
+name = "std"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+alloc = { path = "../liballoc" }
+collections = { path = "../libcollections" }
+core = { path = "../libcore" }
+libc = { path = "../liblibc" }
+rand = { path = "../librand" }
+rustc_bitflags = { path = "../librustc_bitflags" }
+rustc_unicode = { path = "../librustc_unicode" }
+
+[build-dependencies]
+build_helper = { path = "../build_helper" }
+
+[dev-dependencies]
+log = { path = "../liblog" }
+test = { path = "../libtest" }
+std = { path = "." }
diff --git a/src/libstd/build.rs b/src/libstd/build.rs
new file mode 100644
index 0000000000000..47d7b0b2852c2
--- /dev/null
+++ b/src/libstd/build.rs
@@ -0,0 +1,131 @@
+extern crate build_helper;
+
+use std::path::PathBuf;
+use std::process::Command;
+use build_helper::{Config, Run, Triple, build_static_lib};
+
+fn main() {
+    build_rt_libraries();
+    build_backtrace();
+
+    let cfg = Config::new();
+    match &cfg.profile()[..] {
+        "bench" | "release" => { println!("cargo:rustc-cfg=rtopt"); }
+        _ => {}
+    }
+}
+
+struct RtLib {
+    name : &'static str,
+    needed : bool,
+    src_files : Vec<&'static str>,
+    inc_dirs : Vec<&'static str>
+}
+
+fn runtime_libraries(target : &Triple) -> Vec<RtLib> {
+    vec![
+        RtLib {
+            name : "rust_builtin",
+            needed : true,
+            src_files : vec!["rt/rust_builtin.c", "rt/rust_android_dummy.c"],
+            inc_dirs : vec![]
+        },
+        RtLib {
+            name : "rustrt_native",
+            needed : true,
+            src_files : {
+                let mut v = vec!["rt/rust_try.ll"];
+                if target.is_linux() {
+                    v.push("rt/arch/{arch}/record_sp.S");
+                }
+                v
+            },
+            inc_dirs : vec![]
+        },
+        RtLib {
+            name : "morestack",
+            needed : !target.is_windows(),
+            src_files : vec!["rt/arch/{arch}/morestack.S"],
+            inc_dirs : vec![],
+        },
+        RtLib {
+            name : "compiler-rt",
+            needed : !target.is_msvc(), // FIXME: Fix MSVC build for compiler-rt
+            src_files : vec!["compiler-rt/lib/builtins",
+                             "compiler-rt/lib/builtins/{arch}"],
+            inc_dirs : vec!["compiler-rt/lib/builtins",
+                            "compiler-rt/SDKS/{os}/usr/include"],
+        }
+        ]
+}
+
+fn parse_dir(s : &str, tgt : &Triple) -> PathBuf {
+    let arch = if tgt.is_i686() {
+        "i386"
+    } else {
+        tgt.arch()
+    };
+    let os = if tgt.is_windows() {
+        "win"
+    } else {
+        tgt.os()
+    };
+    PathBuf::from(s).iter().map(|d| {
+        if d == "{arch}" {
+            PathBuf::from(arch)
+        } else if d == "{os}" {
+            PathBuf::from(os)
+        } else {
+            PathBuf::from(d)
+        }
+    }).collect()
+}
+
+fn build_rt_lib(cfg : &Config, rtlib : &RtLib) {
+    let target = cfg.target();
+    let src_files : Vec<PathBuf> = rtlib.src_files.iter()
+        .map(|d| parse_dir(d, target)).collect();
+    let inc_dirs : Vec<PathBuf> = rtlib.inc_dirs.iter()
+        .map(|d| parse_dir(d, target)).collect();
+    build_static_lib(cfg)
+        .include_dirs(&inc_dirs)
+        .files(&src_files)
+        .compile(rtlib.name);
+}
+
+fn build_rt_libraries() {
+    let cfg = Config::new();
+    let libs = runtime_libraries(cfg.target());
+    for lib in &libs {
+        if lib.needed {
+            build_rt_lib(&cfg, lib);
+        }
+    }
+}
+
+fn build_backtrace() {
+    let cfg = Config::new();
+    if !cfg.target().is_linux() {
+        return
+    }
+
+    let src_dir = cfg.src_dir().join("libbacktrace");
+    let build_dir = cfg.out_dir().join("libbacktrace");
+    let _ = std::fs::create_dir_all(&build_dir);
+    Command::new(src_dir.join("configure"))
+        .current_dir(&build_dir)
+        .arg("--with-pic")
+        .arg("--disable-multilib")
+        .arg("--disable-shared")
+        .arg("--disable-host-shared")
+        .arg(format!("--build={}", cfg.host()))
+        .arg(format!("--host={}", cfg.target()))
+        .run();
+    Command::new("make")
+        .current_dir(&build_dir)
+        .arg(format!("-j{}", cfg.njobs()))
+        .arg(format!("INCDIR={}", src_dir.display()))
+        .run();
+
+    println!("cargo:rustc-link-search=native={}/.libs", build_dir.display());
+}
diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml
new file mode 100644
index 0000000000000..21d317a15bd2e
--- /dev/null
+++ b/src/libsyntax/Cargo.toml
@@ -0,0 +1,22 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "syntax"
+version = "0.0.0"
+
+[lib]
+name = "syntax"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+arena = { path = "../libarena" }
+fmt_macros = { path = "../libfmt_macros" }
+serialize = { path = "../libserialize" }
+term = { path = "../libterm" }
+libc = { path = "../liblibc" }
+log = { path = "../liblog" }
+rustc_bitflags = { path = "../librustc_bitflags" }
+std = { path = "../libstd" }
+
+[dev-dependencies]
+test = { path = "../libtest" }
diff --git a/src/libterm/Cargo.toml b/src/libterm/Cargo.toml
new file mode 100644
index 0000000000000..c1f55bdf68901
--- /dev/null
+++ b/src/libterm/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "term"
+version = "0.0.0"
+
+[lib]
+name = "term"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+log = { path = "../liblog" }
+libc = { path = "../liblibc" }
+std = { path = "../libstd" }
+
+[dev-dependencies]
+test = { path = "../libtest" }
diff --git a/src/libtest/Cargo.toml b/src/libtest/Cargo.toml
new file mode 100644
index 0000000000000..f82175feb2e5e
--- /dev/null
+++ b/src/libtest/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "test"
+version = "0.0.0"
+
+[lib]
+name = "test"
+path = "lib.rs"
+crate-type = ["dylib", "rlib"]
+
+[dependencies]
+std = { path = "../libstd" }
+getopts = { path = "../libgetopts" }
+serialize  = { path = "../libserialize" }
+term = { path = "../libterm" }
+libc = { path = "../liblibc" }
diff --git a/src/rustbook/Cargo.toml b/src/rustbook/Cargo.toml
new file mode 100644
index 0000000000000..956392ca540cd
--- /dev/null
+++ b/src/rustbook/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustbook"
+version = "0.0.0"
+
+[[bin]]
+name = "rustbook"
+path = "main.rs"

From 37755fe695adbc15d629b25d5ed96f56181397ab Mon Sep 17 00:00:00 2001
From: Chang Liu <cliu712@aucklanduni.ac.nz>
Date: Mon, 13 Jul 2015 13:58:48 +0000
Subject: [PATCH 02/22] Fix compiletest run-pass fds-are-cloexec

With the new Cargo-based build system we no longer have Makefile, which is
used by the fds-are-cloexec test.

This commit makes said test use README.md instead.
---
 src/test/run-pass/fds-are-cloexec.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/test/run-pass/fds-are-cloexec.rs b/src/test/run-pass/fds-are-cloexec.rs
index 3be47e8430d59..4eb25f397ef1c 100644
--- a/src/test/run-pass/fds-are-cloexec.rs
+++ b/src/test/run-pass/fds-are-cloexec.rs
@@ -33,7 +33,7 @@ fn main() {
 }
 
 fn parent() {
-    let file = File::open("Makefile").unwrap();
+    let file = File::open("README.md").unwrap();
     let tcp1 = TcpListener::bind("127.0.0.1:0").unwrap();
     let tcp2 = tcp1.try_clone().unwrap();
     let addr = tcp1.local_addr().unwrap();

From 6af9387eeb46bdad90efaa368c387c159ea40a10 Mon Sep 17 00:00:00 2001
From: Chang Liu <cliu712@aucklanduni.ac.nz>
Date: Mon, 13 Jul 2015 14:01:16 +0000
Subject: [PATCH 03/22] Add lang_items to librustc_bitflags

This is necessary for librustc_bitflags to compile under Mac OS X in a
Cargo-based build.
---
 src/librustc_bitflags/lib.rs | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/librustc_bitflags/lib.rs b/src/librustc_bitflags/lib.rs
index b59c24cf12bdb..945bfe4630088 100644
--- a/src/librustc_bitflags/lib.rs
+++ b/src/librustc_bitflags/lib.rs
@@ -20,11 +20,18 @@
 #![no_std]
 #![unstable(feature = "rustc_private")]
 #![cfg_attr(test, feature(hash_default))]
+#![cfg_attr(target_os = "macos", feature(lang_items))]
 
 //! A typesafe bitmask flag generator.
 
 #[cfg(test)] #[macro_use] extern crate std;
 
+// Fix Mac complaining about missing _rust_stack_exhausted
+#[cfg(target_os = "macos")]
+#[lang = "sized"] trait Sized {}
+#[cfg(target_os = "macos")]
+#[lang = "stack_exhausted"] fn stack_exhausted() {}
+
 /// The `bitflags!` macro generates a `struct` that holds a set of C-style
 /// bitmask flags. It is useful for creating typesafe wrappers for C APIs.
 ///
@@ -62,6 +69,7 @@
 /// The generated `struct`s can also be extended with type and trait implementations:
 ///
 /// ```{.rust}
+/// # #![feature(associated_consts)]
 /// # #![feature(rustc_private)]
 /// #[macro_use] extern crate rustc_bitflags;
 ///

From 969c974ed7e7dd3d0150e97d38de70419bc65bda Mon Sep 17 00:00:00 2001
From: Chang Liu <cliu712@aucklanduni.ac.nz>
Date: Mon, 13 Jul 2015 14:05:28 +0000
Subject: [PATCH 04/22] Slience warnings when running cargo test on crates

This commit adds `#[allow]` attributes to liballoc, libcollections,
libcollectionstest, libcoretest, librand, and libstd to silence
unnecessary warnings when they are compiled under `cargo test`.
---
 src/liballoc/lib.rs           | 2 +-
 src/libcollections/lib.rs     | 2 +-
 src/libcollectionstest/lib.rs | 4 ++--
 src/libcoretest/lib.rs        | 4 ++--
 src/librand/lib.rs            | 1 +
 src/libstd/lib.rs             | 5 ++++-
 6 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 905012bbb64d8..680cfb7a353f1 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -90,6 +90,7 @@
 #![feature(unsize)]
 
 #![cfg_attr(test, feature(test, alloc, rustc_private, box_raw))]
+#![cfg_attr(test, allow(deprecated, unused_features, unused_imports))]
 #![cfg_attr(all(not(feature = "external_funcs"), not(feature = "external_crate")),
             feature(libc))]
 
@@ -100,7 +101,6 @@ extern crate core;
 extern crate libc;
 
 // Allow testing this library
-
 #[cfg(test)] #[macro_use] extern crate std;
 #[cfg(test)] #[macro_use] extern crate log;
 
diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs
index 3c90a2c54e128..7271ed0297881 100644
--- a/src/libcollections/lib.rs
+++ b/src/libcollections/lib.rs
@@ -28,7 +28,7 @@
        test(no_crate_inject))]
 
 #![allow(trivial_casts)]
-#![cfg_attr(test, allow(deprecated))] // rand
+#![cfg_attr(test, allow(deprecated, unused_features, dead_code))] // rand
 
 #![feature(alloc)]
 #![feature(box_patterns)]
diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs
index 6bf7380fdeb50..8416ea4cf446d 100644
--- a/src/libcollectionstest/lib.rs
+++ b/src/libcollectionstest/lib.rs
@@ -54,7 +54,7 @@
 #![feature(vec_push_all)]
 #![feature(vecmap)]
 
-#![allow(deprecated)]
+#![allow(unused_features, unused_imports, dead_code, deprecated)]
 
 #[macro_use] extern crate log;
 
@@ -62,7 +62,7 @@ extern crate collections;
 extern crate test;
 extern crate rustc_unicode;
 
-#[cfg(test)] #[macro_use] mod bench;
+#[macro_use] mod bench;
 
 mod binary_heap;
 mod bit;
diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs
index 08536e6320475..850991eb71153 100644
--- a/src/libcoretest/lib.rs
+++ b/src/libcoretest/lib.rs
@@ -25,11 +25,9 @@
 #![feature(iter_arith)]
 #![feature(iter_arith)]
 #![feature(iter_cmp)]
-#![feature(iter_empty)]
 #![feature(iter_idx)]
 #![feature(iter_iterate)]
 #![feature(iter_min_max)]
-#![feature(iter_once)]
 #![feature(iter_order)]
 #![feature(iter_unfold)]
 #![feature(libc)]
@@ -48,6 +46,8 @@
 #![feature(unicode)]
 #![feature(unique)]
 
+#![allow(dead_code, unused_imports, deprecated, unused_features)]
+
 extern crate core;
 extern crate test;
 extern crate libc;
diff --git a/src/librand/lib.rs b/src/librand/lib.rs
index 2f76aa53f83ae..a4169609b9e9d 100644
--- a/src/librand/lib.rs
+++ b/src/librand/lib.rs
@@ -38,6 +38,7 @@
 #![feature(step_by)]
 
 #![cfg_attr(test, feature(test, rand, rustc_private, iter_order))]
+#![cfg_attr(test, allow(unused_imports, unused_features))]
 
 #![allow(deprecated)]
 
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 1e82a03f28630..840cb0a82f1fb 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -150,9 +150,12 @@
 #![feature(wrapping)]
 #![feature(zero_one)]
 #![cfg_attr(windows, feature(str_utf16))]
+#![cfg_attr(target_env = "msvc", feature(link_args))]
 #![cfg_attr(test, feature(float_from_str_radix, range_inclusive, float_extras, hash_default))]
 #![cfg_attr(test, feature(test, rustc_private, float_consts))]
-#![cfg_attr(target_env = "msvc", feature(link_args))]
+#![cfg_attr(test, allow(deprecated, dead_code, unreachable_code))]
+#![cfg_attr(test, allow(unused_must_use, unused_imports, unused_features))]
+#![cfg_attr(test, allow(unused_variables, unused_mut))]
 
 // Don't link to std. We are std.
 #![no_std]

From 4f96077a0c44458afc826a5bd579c53342faadb8 Mon Sep 17 00:00:00 2001
From: Chang Liu <cliu712@aucklanduni.ac.nz>
Date: Mon, 13 Jul 2015 14:11:48 +0000
Subject: [PATCH 05/22] Update .gitignore

Update .gitignore to include files produced by Cargo-based builds.
---
 .gitignore | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/.gitignore b/.gitignore
index 572111bf96158..823b3ab5a55e9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -93,3 +93,9 @@ tmp.*.rs
 version.md
 version.ml
 version.texi
+*.racertmp
+Cargo.lock
+/src/*/target
+/src/*/tmp
+/target/
+!/src/librustc_back/target

From 6042556f286f38fd21ad6f13b7bbd45e8359ebf3 Mon Sep 17 00:00:00 2001
From: Chang Liu <cliu712@aucklanduni.ac.nz>
Date: Mon, 13 Jul 2015 14:13:44 +0000
Subject: [PATCH 06/22] Make build.sh executable

---
 build.sh | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 mode change 100644 => 100755 build.sh

diff --git a/build.sh b/build.sh
old mode 100644
new mode 100755

From 92fae85bb9bc1e14fdcb16eb8744880e51e65942 Mon Sep 17 00:00:00 2001
From: Chang Liu <cliu712@aucklanduni.ac.nz>
Date: Mon, 13 Jul 2015 14:14:25 +0000
Subject: [PATCH 07/22] Fix compilation of librustc_llvm under Cargo

Cargo puts the generated files under $OUT_DIR. We update the source to
look at $OUT_DIR when compiling under Cargo.
---
 src/librustc_llvm/lib.rs | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index 7afcb54cce436..327d9af84985d 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -2313,6 +2313,12 @@ pub unsafe fn debug_loc_to_string(c: ContextRef, tr: DebugLocRef) -> String {
 // parts of LLVM that rustllvm depends on aren't thrown away by the linker.
 // Works to the above fix for #15460 to ensure LLVM dependencies that
 // are only used by rustllvm don't get stripped by the linker.
+#[cfg(not(feature = "cargo"))]
 mod llvmdeps {
     include! { env!("CFG_LLVM_LINKAGE_FILE") }
 }
+
+#[cfg(feature = "cargo")]
+mod llvmdeps {
+    include! { concat!(env!("OUT_DIR"), "/llvmdeps.rs") }
+}

From c0fe7095276dd87af6ded3ba11a3575459cf1d8b Mon Sep 17 00:00:00 2001
From: Chang Liu <cliu712@aucklanduni.ac.nz>
Date: Mon, 13 Jul 2015 14:23:51 +0000
Subject: [PATCH 08/22] Fix doctests of libgetops, liblog, librustc, libsyntax,
 and librustdoc

The old build system does not run doctests. Cargo runs them by default.
---
 src/libgetopts/lib.rs                         | 12 ++---
 src/libgraphviz/lib.rs                        |  2 +-
 src/liblog/lib.rs                             |  1 +
 src/liblog/macros.rs                          |  8 +++-
 src/librustc/middle/def.rs                    |  2 +
 src/librustc/middle/dependency_format.rs      | 44 +++++++++----------
 .../middle/infer/higher_ranked/mod.rs         |  4 +-
 src/librustc/middle/mem_categorization.rs     |  4 ++
 src/librustc/middle/region.rs                 |  5 ++-
 src/librustc/middle/subst.rs                  |  8 +++-
 src/librustc/middle/traits/mod.rs             |  2 +-
 src/librustc/middle/traits/project.rs         | 10 +++--
 src/librustc/middle/traits/select.rs          |  4 +-
 src/librustc/middle/ty.rs                     | 10 ++++-
 src/librustc/middle/ty_fold.rs                |  2 +
 src/librustc/middle/ty_walk.rs                |  2 +-
 src/librustc/plugin/registry.rs               |  2 +-
 src/librustc/util/common.rs                   |  4 +-
 src/librustdoc/clean/simplify.rs              |  4 ++
 src/libsyntax/ast.rs                          |  2 +
 src/libsyntax/ext/deriving/generic/mod.rs     | 10 ++---
 src/libsyntax/ext/format.rs                   |  2 +
 src/libsyntax/parse/parser.rs                 |  2 +-
 src/libsyntax/print/pp.rs                     |  2 +
 24 files changed, 97 insertions(+), 51 deletions(-)

diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs
index 8ee0b10e1748e..a5247cef565d4 100644
--- a/src/libgetopts/lib.rs
+++ b/src/libgetopts/lib.rs
@@ -30,9 +30,11 @@
 //! file name following `-o`, and accepts both `-h` and `--help` as optional flags.
 //!
 //! ```{.rust}
+//! #![feature(rustc_private)]
+//! #![feature(slice_extras)]
 //! extern crate getopts;
 //! use getopts::{optopt,optflag,getopts,OptGroup,usage};
-//! use std::os;
+//! use std::env;
 //!
 //! fn do_work(inp: &str, out: Option<String>) {
 //!     println!("{}", inp);
@@ -44,13 +46,13 @@
 //!
 //! fn print_usage(program: &str, opts: &[OptGroup]) {
 //!     let brief = format!("Usage: {} [options]", program);
-//!     print!("{}", usage(brief, opts));
+//!     print!("{}", usage(&brief, opts));
 //! }
 //!
 //! fn main() {
-//!     let args: Vec<String> = os::args();
+//!     let args: Vec<String> = env::args().collect();
 //!
-//!     let program = args[0].clone();
+//!     let program = &args[0];
 //!
 //!     let opts = &[
 //!         optopt("o", "", "set output file name", "NAME"),
@@ -71,7 +73,7 @@
 //!         print_usage(program, opts);
 //!         return;
 //!     };
-//!     do_work(input, output);
+//!     do_work(&input, output);
 //! }
 //! ```
 
diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs
index cd9e677d87fae..33518a54db24c 100644
--- a/src/libgraphviz/lib.rs
+++ b/src/libgraphviz/lib.rs
@@ -172,7 +172,7 @@
 //!         dot::Id::new(format!("N{}", n)).unwrap()
 //!     }
 //!     fn node_label<'b>(&'b self, n: &Nd) -> dot::LabelText<'b> {
-//!         dot::LabelText::LabelStr(self.nodes[*n].as_slice().into_cow())
+//!         dot::LabelText::LabelStr(self.nodes[*n].into_cow())
 //!     }
 //!     fn edge_label<'b>(&'b self, _: &Ed) -> dot::LabelText<'b> {
 //!         dot::LabelText::LabelStr("&sube;".into_cow())
diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs
index 7bafd9382f059..12b341b9836f3 100644
--- a/src/liblog/lib.rs
+++ b/src/liblog/lib.rs
@@ -13,6 +13,7 @@
 //! # Examples
 //!
 //! ```
+//! #![feature(rustc_private)]
 //! #[macro_use] extern crate log;
 //!
 //! fn main() {
diff --git a/src/liblog/macros.rs b/src/liblog/macros.rs
index c9a3e39c42351..b9fdac50eeb5f 100644
--- a/src/liblog/macros.rs
+++ b/src/liblog/macros.rs
@@ -19,6 +19,7 @@
 /// # Examples
 ///
 /// ```
+/// #![feature(rustc_private)]
 /// #[macro_use] extern crate log;
 ///
 /// fn main() {
@@ -67,6 +68,7 @@ macro_rules! log {
 /// # Examples
 ///
 /// ```
+/// #![feature(rustc_private)]
 /// #[macro_use] extern crate log;
 ///
 /// fn main() {
@@ -92,6 +94,7 @@ macro_rules! error {
 /// # Examples
 ///
 /// ```
+/// #![feature(rustc_private)]
 /// #[macro_use] extern crate log;
 ///
 /// fn main() {
@@ -116,6 +119,7 @@ macro_rules! warn {
 /// # Examples
 ///
 /// ```
+/// #![feature(rustc_private)]
 /// #[macro_use] extern crate log;
 ///
 /// fn main() {
@@ -142,6 +146,7 @@ macro_rules! info {
 /// # Examples
 ///
 /// ```
+/// #![feature(rustc_private)]
 /// #[macro_use] extern crate log;
 ///
 /// fn main() {
@@ -165,9 +170,10 @@ macro_rules! debug {
 /// # Examples
 ///
 /// ```
+/// #![feature(rustc_private)]
 /// #[macro_use] extern crate log;
 ///
-/// struct Point { x: int, y: int }
+/// struct Point { x: u8, y: u8 }
 /// fn some_expensive_computation() -> Point { Point { x: 1, y: 2 } }
 ///
 /// fn main() {
diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs
index bce246fa4af86..f0bfe1cc4647e 100644
--- a/src/librustc/middle/def.rs
+++ b/src/librustc/middle/def.rs
@@ -60,6 +60,7 @@ pub enum Def {
 /// were no errors, all paths should be fully resolved, with `depth`
 /// set to `0` and `base_def` representing the final resolution.
 ///
+/// ```{.text}
 ///     module::Type::AssocX::AssocY::MethodOrAssocType
 ///     ^~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ///     base_def      depth = 3
@@ -67,6 +68,7 @@ pub enum Def {
 ///     <T as Trait>::AssocX::AssocY::MethodOrAssocType
 ///           ^~~~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~
 ///           base_def        depth = 2
+/// ```
 #[derive(Copy, Clone, Debug)]
 pub struct PathResolution {
     pub base_def: Def,
diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs
index ff5178fbefc10..ec1727dd2d9d1 100644
--- a/src/librustc/middle/dependency_format.rs
+++ b/src/librustc/middle/dependency_format.rs
@@ -21,10 +21,10 @@
 //! should be used when linking each output type requested in this session. This
 //! generally follows this set of rules:
 //!
-//!     1. Each library must appear exactly once in the output.
-//!     2. Each rlib contains only one library (it's just an object file)
-//!     3. Each dylib can contain more than one library (due to static linking),
-//!        and can also bring in many dynamic dependencies.
+//!  1. Each library must appear exactly once in the output.
+//!  2. Each rlib contains only one library (it's just an object file)
+//!  3. Each dylib can contain more than one library (due to static linking),
+//!     and can also bring in many dynamic dependencies.
 //!
 //! With these constraints in mind, it's generally a very difficult problem to
 //! find a solution that's not "all rlibs" or "all dylibs". I have suspicions
@@ -32,24 +32,24 @@
 //!
 //! The current selection algorithm below looks mostly similar to:
 //!
-//!     1. If static linking is required, then require all upstream dependencies
-//!        to be available as rlibs. If not, generate an error.
-//!     2. If static linking is requested (generating an executable), then
-//!        attempt to use all upstream dependencies as rlibs. If any are not
-//!        found, bail out and continue to step 3.
-//!     3. Static linking has failed, at least one library must be dynamically
-//!        linked. Apply a heuristic by greedily maximizing the number of
-//!        dynamically linked libraries.
-//!     4. Each upstream dependency available as a dynamic library is
-//!        registered. The dependencies all propagate, adding to a map. It is
-//!        possible for a dylib to add a static library as a dependency, but it
-//!        is illegal for two dylibs to add the same static library as a
-//!        dependency. The same dylib can be added twice. Additionally, it is
-//!        illegal to add a static dependency when it was previously found as a
-//!        dylib (and vice versa)
-//!     5. After all dynamic dependencies have been traversed, re-traverse the
-//!        remaining dependencies and add them statically (if they haven't been
-//!        added already).
+//!  1. If static linking is required, then require all upstream dependencies
+//!     to be available as rlibs. If not, generate an error.
+//!  2. If static linking is requested (generating an executable), then
+//!     attempt to use all upstream dependencies as rlibs. If any are not
+//!     found, bail out and continue to step 3.
+//!  3. Static linking has failed, at least one library must be dynamically
+//!     linked. Apply a heuristic by greedily maximizing the number of
+//!     dynamically linked libraries.
+//!  4. Each upstream dependency available as a dynamic library is
+//!     registered. The dependencies all propagate, adding to a map. It is
+//!     possible for a dylib to add a static library as a dependency, but it
+//!     is illegal for two dylibs to add the same static library as a
+//!     dependency. The same dylib can be added twice. Additionally, it is
+//!     illegal to add a static dependency when it was previously found as a
+//!     dylib (and vice versa)
+//!  5. After all dynamic dependencies have been traversed, re-traverse the
+//!     remaining dependencies and add them statically (if they haven't been
+//!     added already).
 //!
 //! While not perfect, this algorithm should help support use-cases such as leaf
 //! dependencies being static while the larger tree of inner dependencies are
diff --git a/src/librustc/middle/infer/higher_ranked/mod.rs b/src/librustc/middle/infer/higher_ranked/mod.rs
index 1919d8ffd294d..b3a185729a637 100644
--- a/src/librustc/middle/infer/higher_ranked/mod.rs
+++ b/src/librustc/middle/infer/higher_ranked/mod.rs
@@ -404,7 +404,7 @@ impl<'a,'tcx> InferCtxtExt for InferCtxt<'a,'tcx> {
          * `sub_free_bound_false_infer`.  In this test, we want to
          * know whether
          *
-         * ```rust
+         * ```rust,ignore
          * fn(_#0t) <: for<'a> fn(&'a int)
          * ```
          *
@@ -596,9 +596,11 @@ pub fn leak_check<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
 /// As a brief example, consider the obligation `for<'a> Fn(&'a int)
 /// -> &'a int`, and the impl:
 ///
+/// ```rust,ignore
 ///     impl<A,R> Fn<A,R> for SomethingOrOther
 ///         where A : Clone
 ///     { ... }
+/// ```
 ///
 /// Here we will have replaced `'a` with a skolemized region
 /// `'0`. This means that our substitution will be `{A=>&'0
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index bf47396bb9f65..256425b89ddef 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -20,10 +20,12 @@
 //! possibilities, naturally, but they are all variants of these base
 //! forms):
 //!
+//! ```{.text}
 //!     E = rvalue    // some computed rvalue
 //!       | x         // address of a local variable or argument
 //!       | *E        // deref of a ptr
 //!       | E.comp    // access to an interior component
+//! ```
 //!
 //! Imagine a routine ToAddr(Expr) that evaluates an expression and returns an
 //! address where the result is to be found.  If Expr is an lvalue, then this
@@ -50,9 +52,11 @@
 //! closure upvars into the dereference of a borrowed pointer; this more closely
 //! resembles the runtime translation. So, for example, if we had:
 //!
+//! ```rust,ignore
 //!     let mut x = 3;
 //!     let y = 5;
 //!     let inc = || x += y;
+//! ```
 //!
 //! Then when we categorize `x` (*within* the closure) we would yield a
 //! result of `*x'`, effectively, where `x'` is a `cat_upvar` reference
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 2a033d36a4777..bae7e43835ddf 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -47,10 +47,10 @@ use syntax::visit::{Visitor, FnKind};
 /// expression for the indexed statement, until the end of the block.
 ///
 /// So: the following code can be broken down into the extents beneath:
-/// ```
+/// ```rust,ignore
 /// let a = f().g( 'b: { let x = d(); let y = d(); x.h(y)  }   ) ;
 /// ```
-///
+/// ```{.text}
 ///                                                              +-+ (D12.)
 ///                                                        +-+       (D11.)
 ///                                              +---------+         (R10.)
@@ -63,6 +63,7 @@ use syntax::visit::{Visitor, FnKind};
 ///         +--------------------------------------------------+      (M3.)
 ///         +--+                                                      (M2.)
 /// +-----------------------------------------------------------+     (M1.)
+/// ```
 ///
 ///  (M1.): Misc extent of the whole `let a = ...;` statement.
 ///  (M2.): Misc extent of the `f()` expression.
diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs
index 4e98ef2753105..a88e7a6e94e7d 100644
--- a/src/librustc/middle/subst.rs
+++ b/src/librustc/middle/subst.rs
@@ -685,18 +685,20 @@ impl<'a,'tcx> SubstFolder<'a,'tcx> {
     /// when we are substituting a type with escaping regions into a context where we have passed
     /// through region binders. That's quite a mouthful. Let's see an example:
     ///
-    /// ```
+    /// ```rust,ignore
     /// type Func<A> = fn(A);
     /// type MetaFunc = for<'a> fn(Func<&'a int>)
     /// ```
     ///
     /// The type `MetaFunc`, when fully expanded, will be
     ///
+    /// ```{.text}
     ///     for<'a> fn(fn(&'a int))
     ///             ^~ ^~ ^~~
     ///             |  |  |
     ///             |  |  DebruijnIndex of 2
     ///             Binders
+    /// ```
     ///
     /// Here the `'a` lifetime is bound in the outer function, but appears as an argument of the
     /// inner one. Therefore, that appearance will have a DebruijnIndex of 2, because we must skip
@@ -707,18 +709,20 @@ impl<'a,'tcx> SubstFolder<'a,'tcx> {
     ///
     /// As a second example, consider this twist:
     ///
-    /// ```
+    /// ```rust,ignore
     /// type FuncTuple<A> = (A,fn(A));
     /// type MetaFuncTuple = for<'a> fn(FuncTuple<&'a int>)
     /// ```
     ///
     /// Here the final type will be:
     ///
+    /// ```{.text}
     ///     for<'a> fn((&'a int, fn(&'a int)))
     ///                 ^~~         ^~~
     ///                 |           |
     ///          DebruijnIndex of 1 |
     ///                      DebruijnIndex of 2
+    /// ```
     ///
     /// As indicated in the diagram, here the same type `&'a int` is substituted once, but in the
     /// first case we do not increase the Debruijn index and in the second case we do. The reason
diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs
index 148b27adf64b2..935e746e7389f 100644
--- a/src/librustc/middle/traits/mod.rs
+++ b/src/librustc/middle/traits/mod.rs
@@ -192,7 +192,7 @@ pub type SelectionResult<'tcx, T> = Result<Option<T>, SelectionError<'tcx>>;
 /// or it may be relative to some bound that is in scope (case B).
 ///
 ///
-/// ```
+/// ```rust,ignore
 /// impl<T:Clone> Clone<T> for Option<T> { ... } // Impl_1
 /// impl<T:Clone> Clone<T> for Box<T> { ... }    // Impl_2
 /// impl Clone for int { ... }             // Impl_3
diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs
index cd38e9d0d31bc..17db065b9f9a1 100644
--- a/src/librustc/middle/traits/project.rs
+++ b/src/librustc/middle/traits/project.rs
@@ -69,7 +69,9 @@ struct ProjectionTyCandidateSet<'tcx> {
 
 /// Evaluates constraints of the form:
 ///
+/// ```rust,ignore
 ///     for<...> <T as Trait>::U == V
+/// ```
 ///
 /// If successful, this may result in additional obligations.
 pub fn poly_project_and_unify_type<'cx,'tcx>(
@@ -102,7 +104,9 @@ pub fn poly_project_and_unify_type<'cx,'tcx>(
 
 /// Evaluates constraints of the form:
 ///
+/// ```rust,ignore
 ///     <T as Trait>::U == V
+/// ```
 ///
 /// If successful, this may result in additional obligations.
 fn project_and_unify_type<'cx,'tcx>(
@@ -548,7 +552,7 @@ fn assemble_candidates_from_param_env<'cx,'tcx>(
 /// In the case of a nested projection like <<A as Foo>::FooT as Bar>::BarT, we may find
 /// that the definition of `Foo` has some clues:
 ///
-/// ```
+/// ```rust,ignore
 /// trait Foo {
 ///     type FooT : Bar<BarT=i32>
 /// }
@@ -701,7 +705,7 @@ fn assemble_candidates_from_impls<'cx,'tcx>(
             // This case tell us nothing about the value of an
             // associated type. Consider:
             //
-            // ```
+            // ```rust,ignore
             // trait SomeTrait { type Foo; }
             // fn foo<T:SomeTrait>(...) { }
             // ```
@@ -713,7 +717,7 @@ fn assemble_candidates_from_impls<'cx,'tcx>(
             //
             // But wait, you say! What about an example like this:
             //
-            // ```
+            // ```rust,ignore
             // fn bar<T:SomeTrait<Foo=usize>>(...) { ... }
             // ```
             //
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index e8a2e29b590b8..aa61ad5f6c1a5 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -1813,7 +1813,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     ///
     /// Here are some (simple) examples:
     ///
-    /// ```
+    /// ```rust,ignore
     /// (i32, u32) -> [i32, u32]
     /// Foo where struct Foo { x: i32, y: u32 } -> [i32, u32]
     /// Bar<i32> where struct Bar<T> { x: T, y: u32 } -> [i32, u32]
@@ -2410,7 +2410,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// `Closure`, and `Closure` expects an int as argument. Then it
     /// is "as if" the compiler generated this impl:
     ///
+    /// ```rust,ignore
     ///     impl Fn(int) for Closure { ... }
+    /// ```
     ///
     /// Now imagine our obligation is `Fn(usize) for Closure`. So far
     /// we have matched the self-type `Closure`. At this point we'll
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 5200ed1eb5b50..aa0114df3f1bc 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -566,7 +566,7 @@ pub enum AutoAdjustment<'tcx> {
 /// sized struct to a dyncamically sized one. E.g., &[i32; 4] -> &[i32] is
 /// represented by:
 ///
-/// ```
+/// ```rust,ignore
 /// AutoDerefRef {
 ///     autoderefs: 1,          // &[i32; 4] -> [i32; 4]
 ///     autoref: Some(AutoPtr), // [i32] -> &[i32]
@@ -587,7 +587,7 @@ pub enum AutoAdjustment<'tcx> {
 /// case this is analogous to transformating a struct. E.g., Box<[i32; 4]> ->
 /// Box<[i32]> is represented by:
 ///
-/// ```
+/// ```rust,ignore
 /// AutoDerefRef {
 ///     autoderefs: 0,
 ///     autoref: None,
@@ -1462,6 +1462,7 @@ pub struct ParamTy {
 /// regions (and perhaps later types) in a higher-ranked setting. In
 /// particular, imagine a type like this:
 ///
+/// ```{.text}
 ///     for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char)
 ///     ^          ^            |        |         |
 ///     |          |            |        |         |
@@ -1470,6 +1471,7 @@ pub struct ParamTy {
 ///     +--------------------------------+ 2       |
 ///     |                                          |
 ///     +------------------------------------------+ 1
+/// ```
 ///
 /// In this type, there are two binders (the outer fn and the inner
 /// fn). We need to be able to determine, for any given region, which
@@ -1845,7 +1847,9 @@ impl<'tcx> TraitTy<'tcx> {
 /// A complete reference to a trait. These take numerous guises in syntax,
 /// but perhaps the most recognizable form is in a where clause:
 ///
+/// ```rust,ignore
 ///     T : Foo<U>
+/// ```
 ///
 /// This would be represented by a trait-reference where the def-id is the
 /// def-id for the trait `Foo` and the substs defines `T` as parameter 0 in the
@@ -2623,7 +2627,9 @@ impl<'tcx> Predicate<'tcx> {
 ///
 /// Example:
 ///
+/// ```rust,ignore
 ///     struct Foo<T,U:Bar<T>> { ... }
+/// ```
 ///
 /// Here, the `GenericPredicates` for `Foo` would contain a list of bounds like
 /// `[[], [U:Bar<T>]]`.  Now if there were some particular reference
diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs
index 3cf5e6ffa039f..809815d8a36b0 100644
--- a/src/librustc/middle/ty_fold.rs
+++ b/src/librustc/middle/ty_fold.rs
@@ -14,7 +14,9 @@
 //! instance of a "folder" (a type which implements `TypeFolder`). Then
 //! the setup is intended to be:
 //!
+//! ```{.text}
 //!     T.fold_with(F) --calls--> F.fold_T(T) --calls--> super_fold_T(F, T)
+//! ```
 //!
 //! This way, when you define a new folder F, you can override
 //! `fold_T()` to customize the behavior, and invoke `super_fold_T()`
diff --git a/src/librustc/middle/ty_walk.rs b/src/librustc/middle/ty_walk.rs
index 3e9a402f9499c..b12783fa0ee94 100644
--- a/src/librustc/middle/ty_walk.rs
+++ b/src/librustc/middle/ty_walk.rs
@@ -30,7 +30,7 @@ impl<'tcx> TypeWalker<'tcx> {
     ///
     /// Example: Imagine you are walking `Foo<Bar<int>, usize>`.
     ///
-    /// ```
+    /// ```rust,ignore
     /// let mut iter: TypeWalker = ...;
     /// iter.next(); // yields Foo
     /// iter.next(); // yields Bar<int>
diff --git a/src/librustc/plugin/registry.rs b/src/librustc/plugin/registry.rs
index 5faaa53e4d0b5..8831650040ec4 100644
--- a/src/librustc/plugin/registry.rs
+++ b/src/librustc/plugin/registry.rs
@@ -79,7 +79,7 @@ impl<'a> Registry<'a> {
     ///
     /// These are specified inside the `plugin` crate attribute as
     ///
-    /// ```no_run
+    /// ```rust,ignore
     /// #![plugin(my_plugin_name(... args ...))]
     /// ```
     pub fn args<'b>(&'b self) -> &'b Vec<P<ast::MetaItem>> {
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index 77575cd6b24c9..f4cdfaf806521 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -261,7 +261,7 @@ pub fn can_reach<T, S>(edges_map: &HashMap<T, Vec<T>, S>, source: T,
 /// a type implementing MutableMap to serve as a cache.
 ///
 /// In the future the signature of this function is expected to be:
-/// ```
+/// ```rust,ignore
 /// pub fn memoized<T: Clone, U: Clone, M: MutableMap<T, U>>(
 ///    cache: &RefCell<M>,
 ///    f: &|T| -> U
@@ -270,7 +270,7 @@ pub fn can_reach<T, S>(edges_map: &HashMap<T, Vec<T>, S>, source: T,
 /// but currently it is not possible.
 ///
 /// # Examples
-/// ```
+/// ```rust,ignore
 /// struct Context {
 ///    cache: RefCell<HashMap<usize, usize>>
 /// }
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index e65cdd8ff5de6..bd8c03157ded1 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -17,11 +17,15 @@
 //! for functions and such is simply a list of predicates. One example of this
 //! is that the AST predicate of:
 //!
+//! ```rust,ignore
 //!     where T: Trait<Foo=Bar>
+//! ```
 //!
 //! is encoded as:
 //!
+//! ```rust,ignore
 //!     where T: Trait, <T as Trait>::Foo = Bar
+//! ```
 //!
 //! This module attempts to reconstruct the original where and/or parameter
 //! bounds by special casing scenarios such as these. Fun!
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index e844b206cc0a0..bf6ee43881622 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -967,6 +967,7 @@ pub enum Expr_ {
 /// separately. `position` represents the index of the associated
 /// item qualified with this Self type.
 ///
+/// ```{.text}
 ///     <Vec<T> as a::b::Trait>::AssociatedItem
 ///      ^~~~~     ~~~~~~~~~~~~~~^
 ///      ty        position = 3
@@ -974,6 +975,7 @@ pub enum Expr_ {
 ///     <Vec<T>>::AssociatedItem
 ///      ^~~~~    ^
 ///      ty       position = 0
+/// ```
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct QSelf {
     pub ty: P<Ty>,
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index e7d242ab70364..55bacc79dab48 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -53,7 +53,7 @@
 //! an identifier in the source code. For example, the `x`s in the
 //! following snippet
 //!
-//! ```rust
+//! ```rust,ignore
 //! struct A { x : i32 }
 //!
 //! struct B(i32);
@@ -86,7 +86,7 @@
 //!
 //! The following simplified `PartialEq` is used for in-code examples:
 //!
-//! ```rust
+//! ```rust,ignore
 //! trait PartialEq {
 //!     fn eq(&self, other: &Self);
 //! }
@@ -886,7 +886,7 @@ impl<'a> MethodDef<'a> {
         })
     }
 
-    /// ```
+    /// ```rust,ignore
     /// #[derive(PartialEq)]
     /// struct A { x: i32, y: i32 }
     ///
@@ -991,7 +991,7 @@ impl<'a> MethodDef<'a> {
                                       &StaticStruct(struct_def, summary))
     }
 
-    /// ```
+    /// ```rust,ignore
     /// #[derive(PartialEq)]
     /// enum A {
     ///     A1,
@@ -1616,7 +1616,7 @@ pub fn cs_fold<F>(use_foldl: bool,
 /// Call the method that is being derived on all the fields, and then
 /// process the collected results. i.e.
 ///
-/// ```
+/// ```rust,ignore
 /// f(cx, span, vec![self_1.method(__arg_1_1, __arg_2_1),
 ///                  self_2.method(__arg_1_2, __arg_2_2)])
 /// ```
diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs
index 5b972b464c960..c49fa1132a2cc 100644
--- a/src/libsyntax/ext/format.rs
+++ b/src/libsyntax/ext/format.rs
@@ -78,8 +78,10 @@ struct Context<'a, 'b:'a> {
 ///
 /// If parsing succeeds, the return value is:
 ///
+/// ```{.text}
 ///     Some((fmtstr, unnamed arguments, ordering of named arguments,
 ///           named arguments))
+/// ```
 fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
               -> Option<(P<ast::Expr>, Vec<P<ast::Expr>>, Vec<String>,
                          HashMap<String, P<ast::Expr>>)> {
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 81ae607fea250..9b2ded89dee70 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -3922,7 +3922,7 @@ impl<'a> Parser<'a> {
 
     /// Parses an optional `where` clause and places it in `generics`.
     ///
-    /// ```
+    /// ```rust,ignore
     /// where T : Trait<U, V> + 'b, 'a : 'b
     /// ```
     pub fn parse_where_clause(&mut self) -> PResult<ast::WhereClause> {
diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs
index 7c5a46465f513..1635f46371cf3 100644
--- a/src/libsyntax/print/pp.rs
+++ b/src/libsyntax/print/pp.rs
@@ -11,8 +11,10 @@
 //! This pretty-printer is a direct reimplementation of Philip Karlton's
 //! Mesa pretty-printer, as described in appendix A of
 //!
+//! ```{.text}
 //!     STAN-CS-79-770: "Pretty Printing", by Derek C. Oppen.
 //!     Stanford Department of Computer Science, 1979.
+//! ```
 //!
 //! The algorithm's aim is to break a stream into as few lines as possible
 //! while respecting the indentation-consistency requirements of the enclosing

From 769b18c88a672f36aa8731bd8d56e6c12c2aba47 Mon Sep 17 00:00:00 2001
From: Chang Liu <cliu712@aucklanduni.ac.nz>
Date: Mon, 13 Jul 2015 14:48:25 +0000
Subject: [PATCH 09/22] Update README.md to include instructions on building
 with Cargo

---
 README.md | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 54 insertions(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 9e54704a5ebad..c5c008c8eaca5 100644
--- a/README.md
+++ b/README.md
@@ -18,6 +18,59 @@ Read ["Installing Rust"] from [The Book].
 
 ## Building from Source
 
+Starting from `e645ed59` the Rust Build System is being converted to use
+Cargo. The new build system is supposed to replace the old Makefile-based
+build system once it is mature enough. It is encouraged to use the new build
+system whenever possible as the Makefile-based system is marked for deletion
+in the future.
+
+To build the compiler,
+
+1. Make sure you have installed the dependencies:
+
+   * `g++` 4.7 or `clang++` 3.x
+   * `python` 2.7 or later (but not 3.x)
+   * `git`
+
+   On a Unix-based system (Linux/Mac) you also need:
+
+   * GNU `make` 3.81 or later
+
+2. Download the latest nightly build of Rust, and install it.
+
+   On Unix-based systems, you can use the `multirust` tool to do this.
+
+3. Clone the [source] with `git`:
+
+   ```sh
+   $ git clone https://github.com/rust-lang/rust.git
+   $ cd rust
+   ```
+
+[source]: https://github.com/rust-lang/rust
+
+4. Update the git submodules within the source repository:
+
+   ```sh
+   $ git submodule init
+   $ git submodule update
+   ```
+
+5. On a Unix-based system, run
+
+   ```sh
+   $ ./build.sh
+   ```
+
+   On Windows, open a (normal) command line window and run
+
+   ```
+   python src\etc\build_rust.py
+   ```
+
+
+## Building from Source with the Makefile-based Build System
+
 1. Make sure you have installed the dependencies:
 
    * `g++` 4.7 or `clang++` 3.x
@@ -55,7 +108,7 @@ Read ["Installing Rust"] from [The Book].
 
 [Cargo]: https://github.com/rust-lang/cargo
 
-### Building on Windows
+### Building on Windows with the Makefile-based Build System
 
 [MSYS2](http://msys2.github.io/) can be used to easily build Rust on Windows:
 

From 85c3adeec5398b148c4d03dbc449f73916850c6f Mon Sep 17 00:00:00 2001
From: Chang Liu <cliu712@aucklanduni.ac.nz>
Date: Mon, 13 Jul 2015 15:19:10 +0000
Subject: [PATCH 10/22] Update compiler-rt

This is necessary to build compiler-rt under Windows, with the standalone
mingw distribution.
---
 src/compiler-rt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/compiler-rt b/src/compiler-rt
index 58ab642c30d9f..c48c757e17336 160000
--- a/src/compiler-rt
+++ b/src/compiler-rt
@@ -1 +1 @@
-Subproject commit 58ab642c30d9f97735d5745b5d01781ee199c6ae
+Subproject commit c48c757e17336fdab7692220d3f95cee41c07c72

From f47c848ec3d74dcfbaefa6e5e164a139aaea767b Mon Sep 17 00:00:00 2001
From: Chang Liu <cliu712@aucklanduni.ac.nz>
Date: Mon, 13 Jul 2015 16:11:54 +1200
Subject: [PATCH 11/22] Add ArchiveWrapper.cpp when building rustllvm

---
 src/librustc_llvm/build.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs
index b3638001b0995..a7490c35b973e 100644
--- a/src/librustc_llvm/build.rs
+++ b/src/librustc_llvm/build.rs
@@ -11,7 +11,7 @@ fn main() {
 fn build_rustllvm() {
     let cfg = Config::new();
     let src_dir = cfg.src_dir().join("rustllvm");
-    let src_files = vec!["ExecutionEngineWrapper.cpp",
+    let src_files = vec!["ExecutionEngineWrapper.cpp", "ArchiveWrapper.cpp",
                          "PassWrapper.cpp", "RustWrapper.cpp"];
     build_static_lib(&cfg)
         .set_src_dir(&src_dir)

From cdcc1ac3653cf9b105cb7c16d4aa3dfe224512cd Mon Sep 17 00:00:00 2001
From: Chang Liu <cliu712@aucklanduni.ac.nz>
Date: Tue, 14 Jul 2015 10:31:49 +0000
Subject: [PATCH 12/22] Make build_llvm.py and build_rust.py compatible with
 Python3

---
 src/etc/build_llvm.py |  8 +++----
 src/etc/build_rust.py | 52 +++++++++++++++++++++----------------------
 2 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/src/etc/build_llvm.py b/src/etc/build_llvm.py
index 290f6837ee446..c775b0c26ad24 100644
--- a/src/etc/build_llvm.py
+++ b/src/etc/build_llvm.py
@@ -89,7 +89,7 @@ def build_llvm(rust_root, target, force_rebuild, is_release, is_assert):
         profile = "Debug"
     if is_assert:
         profile += "+Asserts"
-    print "Building LLVM for target " + target + " profile " + profile + ":"
+    print("Building LLVM for target " + target + " profile " + profile + ":")
     src_dir = os.path.join(rust_root, "src", "llvm")
     build_dir = llvm_build_dir(rust_root, target)
     # create build dir
@@ -103,7 +103,7 @@ def build_llvm(rust_root, target, force_rebuild, is_release, is_assert):
                                                    is_release, is_assert)
     stamp_file = os.path.join(build_artifacts_dir, "llvm.built.for.rust")
     if os.path.isfile(stamp_file) and not force_rebuild:
-        print "Skipped. Use --rebuild-llvm to override."
+        print("Skipped. Use --rebuild-llvm to override.")
         return                  # no need to build llvm here.
     ncpu = multiprocessing.cpu_count()
     # build llvm
@@ -114,7 +114,7 @@ def build_llvm(rust_root, target, force_rebuild, is_release, is_assert):
         ret = build_llvm_autotools(src_dir, build_dir, target,
                                    ncpu, is_release, is_assert)
     if ret != 0:
-        print "Build failed."
+        print("Build failed.")
         exit(ret)
     # make a note so that we don't rebuild llvm
     with open(stamp_file, "w") as f:
@@ -132,5 +132,5 @@ def get_llvm_bin_dir(rust_root, target, external_llvm_root):
         fwin = os.path.join(bin_dir, "llc.exe")
         if os.path.isfile(f) or os.path.isfile(fwin):
             return bin_dir
-    print "Path " + llvm_root + " does not contain valid LLVM build."
+    print("Path " + llvm_root + " does not contain valid LLVM build.")
     exit(1)
diff --git a/src/etc/build_rust.py b/src/etc/build_rust.py
index a5970b02b5426..48597d1d86c1b 100644
--- a/src/etc/build_rust.py
+++ b/src/etc/build_rust.py
@@ -71,9 +71,9 @@ def build_driver_crate(rust_root, target, is_release, verbose):
         args.append("--verbose")
     ret = subprocess.call(args)
     if ret == 0:
-        print "Build succeeded."
+        print("Build succeeded.")
     else:
-        print "Build failed."
+        print("Build failed.")
         exit(ret)
 
 # build_dir refers to the <rust-root>/target directory
@@ -112,29 +112,29 @@ def copy_rust_dist(build_dir, dest_dir, host, targets, is_release):
 # for now we only build libstd (and all dependencies) docs
 # docs are built by the stage1 compiler
 def build_rust_docs(rust_root, target, verbose):
-    print "Building docs:"
+    print("Building docs:")
     args = ["cargo", "doc", "--target", target, "--manifest-path",
             os.path.join(rust_root, "src", "libstd", "Cargo.toml")]
     if verbose:
         args.append("--verbose")
     ret = subprocess.call(args)
     if ret == 0:
-        print "Cargo doc succeeded."
+        print("Cargo doc succeeded.")
     else:
-        print "Cargo doc failed."
+        print("Cargo doc failed.")
         exit(ret)
     build_rustbook(rust_root, verbose)
 
 # the rustbook crate is built by the stage1 compiler, as a native exe.
 def build_rustbook(rust_root, verbose):
-    print "Building The Rust Programming Language book:"
+    print("Building The Rust Programming Language book:")
     args = ["cargo", "build", "--manifest-path",
             os.path.join(rust_root, "src", "rustbook", "Cargo.toml")]
     if verbose:
         args.append("--verbose")
     ret = subprocess.call(args)
     if ret != 0:
-        print "Building rustbook failed."
+        print("Building rustbook failed.")
         exit(ret)
     rustbook_exe = os.path.join(rust_root, "target", "debug", "rustbook")
     doc_dest = os.path.join(rust_root, "target", "doc")
@@ -147,13 +147,13 @@ def build_rustbook(rust_root, verbose):
     style_dest = os.path.join(doc_dest, "style")
     ret2 = subprocess.call([rustbook_exe, "build", style_src, style_dest])
     if ret1 == 0 and ret2 == 0:
-        print "Done."
+        print("Done.")
     else:
-        print "Rustbook failed."
+        print("Rustbook failed.")
         exit(1)
 
 def run_test_for_crate(rust_root, crate, target, verbose):
-    print "Running " + crate + " tests:"
+    print("Running " + crate + " tests:")
     args = ["cargo", "test", "--target", target, "--manifest-path",
             os.path.join(rust_root, "src", crate, "Cargo.toml")]
     if verbose:
@@ -171,20 +171,20 @@ def run_crate_tests(rust_root, target, verbose):
     clean_build_dirs(rust_root, target, "debug")
     for crate in crates_to_test:
         if run_test_for_crate(rust_root, crate, target, verbose) != 0:
-            print "Tests in crate " + crate + " failed."
+            print("Tests in crate " + crate + " failed.")
 
 # the compiletest crate is built by the stage1 compiler, as a native exe
 def run_compiletests(rust_root, target, llvm_bin_dir, verbose):
-    print "Building compiletest:"
+    print("Building compiletest:")
     args = ["cargo", "build", "--manifest-path",
             os.path.join(rust_root, "src", "compiletest", "Cargo.toml")]
     if verbose:
         args.append("--verbose")
     ret = subprocess.call(args)
     if ret == 0:
-        print "Done."
+        print("Done.")
     else:
-        print "Building compiletest failed."
+        print("Building compiletest failed.")
         exit(ret)
     target_dir = os.path.join(rust_root, "target")
     ctest_exe = os.path.join(target_dir, "debug", "compiletest")
@@ -236,18 +236,18 @@ def run_compiletests(rust_root, target, llvm_bin_dir, verbose):
                              "--mode", test[0], "--logfile", log_file]
         ret = subprocess.call(final_args)
         if ret != 0:
-            print "Compiler test " + test[1] + " failed."
+            print("Compiler test " + test[1] + " failed.")
 
 def build_stage1_rust(rust_root, build,
                       external_llvm_root, is_release, verbose):
-    print "Building stage1 compiler:"
+    print("Building stage1 compiler:")
     set_env_vars(rust_root, build, external_llvm_root)
     build_driver_crate(rust_root, build, is_release, verbose)
-    print "Copying stage1 compiler to target/stage1:"
+    print("Copying stage1 compiler to target/stage1:")
     build_dir = os.path.join(rust_root, "target")
     dest_dir = os.path.join(build_dir, "stage1")
     copy_rust_dist(build_dir, dest_dir, build, [build], is_release)
-    print "Done."
+    print("Done.")
 
 def clean_build_dirs(rust_root, build, profile):
     dir1 = os.path.join(rust_root, "target", profile)
@@ -282,15 +282,15 @@ def build_stage2_rust(rust_root, build, host, targets,
     stage1_dir = os.path.join(build_dir, "stage1")
     switch_rustc(stage1_dir, build)
     for target in targets:
-        print "Building stage2 compiler for target " + target + ":"
+        print("Building stage2 compiler for target " + target + ":")
         set_env_vars(rust_root, target, external_llvm_root)
         build_driver_crate(rust_root, target, is_release, verbose)
     set_env_vars(rust_root, host, llvm_root)
     build_rust_docs(rust_root, host, verbose = verbose)
-    print "Copying stage2 compiler to target/stage2:"
+    print("Copying stage2 compiler to target/stage2:")
     dest_dir = os.path.join(build_dir, "stage2")
     copy_rust_dist(build_dir, dest_dir, host, targets, is_release)
-    print "Done."
+    print("Done.")
 
 
 # main function
@@ -346,17 +346,17 @@ def build_stage2_rust(rust_root, build, host, targets,
 release_channel = args.release_channel
 
 if release_channel not in ["dev", "nightly", "beta", "stable"]:
-    print "Release channel must be one of 'dev', 'nightly', 'beta', 'stable'"
+    print("Release channel must be one of 'dev', 'nightly', 'beta', 'stable'")
     exit(1)
 elif release_channel == "nightly":
-    print "Nightly builds always have LLVM assertions on."
+    print("Nightly builds always have LLVM assertions on.")
     is_assert = True
-print "Building Rust for release channel " + release_channel + ":"
+print("Building Rust for release channel " + release_channel + ":")
 set_release_channel(release_channel)
 
 # build LLVM
 if llvm_root and ((build != host) or targets.len() > 1):
-    print "--llvm-root is only allowed for native builds."
+    print("--llvm-root is only allowed for native builds.")
     exit(1)
 if not llvm_root:
     force_rebuild = args.rebuild_llvm
@@ -373,7 +373,7 @@ def build_stage2_rust(rust_root, build, host, targets,
 else:
     profile = "debug"
 if not args.run_tests_only:
-    print "Building Rust with " + profile + " profile:"
+    print("Building Rust with " + profile + " profile:")
     if not args.no_bootstrap:
         build_stage1_rust(rust_root, build, llvm_root,
                           is_release = is_release, verbose = verbose)

From bc8d4659e49f8882354a9037c685b8b1c62f9243 Mon Sep 17 00:00:00 2001
From: Chang Liu <cliu712@aucklanduni.ac.nz>
Date: Tue, 14 Jul 2015 10:56:18 +0000
Subject: [PATCH 13/22] Fix year in copyright notice

---
 src/driver/rustc.rs   | 2 +-
 src/driver/rustdoc.rs | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/driver/rustc.rs b/src/driver/rustc.rs
index 4bbd3461b911c..2df8eb14d9cc4 100644
--- a/src/driver/rustc.rs
+++ b/src/driver/rustc.rs
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
diff --git a/src/driver/rustdoc.rs b/src/driver/rustdoc.rs
index 472a79b783ae1..2da60ed6931ec 100644
--- a/src/driver/rustdoc.rs
+++ b/src/driver/rustdoc.rs
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //

From c7bbd39d9e47201fe87b0efe8622aac908f3fbef Mon Sep 17 00:00:00 2001
From: Chang Liu <cliu712@aucklanduni.ac.nz>
Date: Tue, 14 Jul 2015 10:56:49 +0000
Subject: [PATCH 14/22] Add trailing '\n' in src/compiletest/Cargo.toml

---
 src/compiletest/Cargo.toml | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/compiletest/Cargo.toml b/src/compiletest/Cargo.toml
index 7e0a48028ce9e..59d6d3b6c388f 100644
--- a/src/compiletest/Cargo.toml
+++ b/src/compiletest/Cargo.toml
@@ -9,4 +9,5 @@ name = "compiletest"
 path = "compiletest.rs"
 
 [build-dependencies]
-build_helper = { path = "../build_helper" }
\ No newline at end of file
+build_helper = { path = "../build_helper" }
+

From 49a0466ecc6c1442a49935dbc9dec7fa6a6c012e Mon Sep 17 00:00:00 2001
From: Chang Liu <cliu712@aucklanduni.ac.nz>
Date: Tue, 14 Jul 2015 12:15:13 +0000
Subject: [PATCH 15/22] Add from __future__ import print_function

---
 src/etc/build_llvm.py | 2 ++
 src/etc/build_rust.py | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/src/etc/build_llvm.py b/src/etc/build_llvm.py
index c775b0c26ad24..909b481e46a3d 100644
--- a/src/etc/build_llvm.py
+++ b/src/etc/build_llvm.py
@@ -8,6 +8,8 @@
 # option. This file may not be copied, modified, or distributed
 # except according to those terms.
 
+from __future__ import print_function
+
 import os
 import subprocess
 import multiprocessing
diff --git a/src/etc/build_rust.py b/src/etc/build_rust.py
index 48597d1d86c1b..5473147141d14 100644
--- a/src/etc/build_rust.py
+++ b/src/etc/build_rust.py
@@ -1,5 +1,7 @@
 #!/usr/bin/python
 
+from __future__ import print_function
+
 import sys
 import os
 import shutil

From a7e0eb8ac19062a72e23be91919317028460f719 Mon Sep 17 00:00:00 2001
From: Chang Liu <cliu712@aucklanduni.ac.nz>
Date: Tue, 14 Jul 2015 12:37:34 +0000
Subject: [PATCH 16/22] Use python2 instead of python in librustc_llvm/build.rs

Because some system may have `python == python3`
---
 src/librustc_llvm/build.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs
index a7490c35b973e..1bda494ec1d7c 100644
--- a/src/librustc_llvm/build.rs
+++ b/src/librustc_llvm/build.rs
@@ -29,7 +29,7 @@ fn generate_llvmdeps() {
     let llvm_components = "x86 arm aarch64 mips powerpc ipo bitreader \
                            bitwriter linker asmparser mcjit interpreter \
                            instrumentation";
-    Command::new("python")
+    Command::new("python2")
         .arg(&script)
         .arg(&dest)
         .arg(llvm_components)

From 6cab349a12fd4007f3419050a4fd0d999464830c Mon Sep 17 00:00:00 2001
From: Chang Liu <cliu712@aucklanduni.ac.nz>
Date: Tue, 14 Jul 2015 15:00:18 +0000
Subject: [PATCH 17/22] Detect gdb version and feed into compiletest

---
 src/etc/build_rust.py | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/src/etc/build_rust.py b/src/etc/build_rust.py
index 5473147141d14..054da592dd3ac 100644
--- a/src/etc/build_rust.py
+++ b/src/etc/build_rust.py
@@ -20,6 +20,18 @@ def cmd_out(cmdline):
     p = subprocess.Popen(cmdline, stdout=subprocess.PIPE)
     return scrub(p.communicate()[0].strip())
 
+def gdb_version():
+    try:
+        return cmd_out(["gdb", "--version"]).split('\n')[0]
+    except:
+        return ""
+
+def lldb_version():
+    try:
+        return cmd_out(["lldb", "--version"]).split('\n')[0]
+    except:
+        return ""
+
 def scrape_rustc_host_triple():
     output = cmd_out(["rustc", "-Vv"]).split()
     return output[output.index("host:")+1]
@@ -211,14 +223,19 @@ def run_compiletests(rust_root, target, llvm_bin_dir, verbose):
                     ("compile-fail", "compile-fail"),
                     ("compile-fail", "compile-fail-fulldeps"),
                     ("parse-fail", "parse-fail"),
-                    ("pretty", "pretty"),
-                    ("debuginfo-gdb", "debuginfo")] # TODO: detect gdb/lldb
+                    ("pretty", "pretty")]
+    gdb_ver = gdb_version()
+    lldb_ver = lldb_version()
+    if gdb_ver:
+        tests_to_run.append(("debuginfo-gdb", "debuginfo"))
+    if lldb_ver:
+        tests_to_run.append(("debuginfo-lldb", "debuginfo"))
     args = [ctest_exe, "--compile-lib-path", lib_dir,
             "--run-lib-path", rustlib_dir, "--rustc-path", rustc_path,
             "--rustdoc-path", rustdoc_path, "--llvm-bin-path", llvm_bin_dir,
             "--aux-base", aux_base, "--stage-id", stage_id,
             "--target", target, "--host", host, "--python", sys.executable,
-            "--gdb-version", "", "--lldb-version=", "",
+            "--gdb-version", gdb_ver, "--lldb-version=", lldb_ver,
             "--android-cross-path", "", "--adb-path", "", "--adb-test-dir", "",
             "--host-rustcflags", rust_flags, "--target-rustcflags", rust_flags,
             "--lldb-python-dir", ""]

From 70858dc07e9eed91e3bfeda92f0780919337be3c Mon Sep 17 00:00:00 2001
From: Chang Liu <cliu712@aucklanduni.ac.nz>
Date: Wed, 15 Jul 2015 09:59:21 +0000
Subject: [PATCH 18/22] Fix .gitignore

---
 .gitignore | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/.gitignore b/.gitignore
index 823b3ab5a55e9..b98797f2821e8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -95,7 +95,5 @@ version.ml
 version.texi
 *.racertmp
 Cargo.lock
-/src/*/target
-/src/*/tmp
-/target/
+target
 !/src/librustc_back/target

From 2a795be63ce0d3a4615fc5354002d5bb3e8cc524 Mon Sep 17 00:00:00 2001
From: Chang Liu <cliu712@aucklanduni.ac.nz>
Date: Wed, 15 Jul 2015 09:45:19 +1200
Subject: [PATCH 19/22] Refactor build_rust_stagei into build_rust_stage

---
 src/etc/build_rust.py | 84 ++++++++++++++++++++-----------------------
 1 file changed, 39 insertions(+), 45 deletions(-)

diff --git a/src/etc/build_rust.py b/src/etc/build_rust.py
index 054da592dd3ac..7ddd55f7333c0 100644
--- a/src/etc/build_rust.py
+++ b/src/etc/build_rust.py
@@ -90,8 +90,9 @@ def build_driver_crate(rust_root, target, is_release, verbose):
         print("Build failed.")
         exit(ret)
 
-# build_dir refers to the <rust-root>/target directory
-def copy_rust_dist(build_dir, dest_dir, host, targets, is_release):
+def copy_rust_dist(rust_root, stage, host, targets, is_release):
+    build_dir = os.path.join(rust_root, "target")
+    dest_dir = os.path.join(build_dir, stage)
     if is_release:
         profile = "release"
     else:
@@ -257,27 +258,35 @@ def run_compiletests(rust_root, target, llvm_bin_dir, verbose):
         if ret != 0:
             print("Compiler test " + test[1] + " failed.")
 
-def build_stage1_rust(rust_root, build,
-                      external_llvm_root, is_release, verbose):
-    print("Building stage1 compiler:")
-    set_env_vars(rust_root, build, external_llvm_root)
-    build_driver_crate(rust_root, build, is_release, verbose)
-    print("Copying stage1 compiler to target/stage1:")
-    build_dir = os.path.join(rust_root, "target")
-    dest_dir = os.path.join(build_dir, "stage1")
-    copy_rust_dist(build_dir, dest_dir, build, [build], is_release)
+def build_rust_stage(rust_root, build, host, targets, stage,
+                     external_llvm_root, is_release, verbose):
+    if stage != "stage2":
+        compiler_host = build
+        targets_to_build = [build]
+    else:
+        compiler_host = host
+        targets_to_build = targets
+    for target in targets_to_build:
+        print("Building " + stage + " compiler for target " + target + ":")
+        set_env_vars(rust_root, target, external_llvm_root)
+        build_driver_crate(rust_root, target, is_release, verbose)
+    print("Copying " + stage + " compiler to target/" + stage + ":")
+    copy_rust_dist(rust_root, stage, compiler_host,
+                   targets_to_build, is_release)
+    switch_rustc(stage, compiler_host)
     print("Done.")
 
-def clean_build_dirs(rust_root, build, profile):
+def clean_build_dirs(rust_root, target, profile):
     dir1 = os.path.join(rust_root, "target", profile)
-    dir2 = os.path.join(rust_root, "target", build, profile)
+    dir2 = os.path.join(rust_root, "target", target, profile)
     shutil.rmtree(dir1, ignore_errors = True)
     shutil.rmtree(dir2, ignore_errors = True)
 
-# switch to the rustc in the specified sysroot
-def switch_rustc(sysroot, host):
+# switch to the stagei rustc
+def switch_rustc(stage, compiler_host):
+    sysroot = os.path.join(rust_root, "target", stage)
     bin_dir = os.path.join(sysroot, "bin")
-    if "windows" in host:
+    if "windows" in compiler_host:
         lib_dir = bin_dir
         rustc = "rustc.exe"
         rustdoc = "rustdoc.exe"
@@ -287,31 +296,14 @@ def switch_rustc(sysroot, host):
         rustdoc = "rustdoc"
     os.environ["RUSTC"] = os.path.join(bin_dir, rustc)
     os.environ["RUSTDOC"] = os.path.join(bin_dir, rustdoc)
-    rustlib_dir = os.path.join(lib_dir, "rustlib", host, "lib")
-    if "windows" in host:
+    rustlib_dir = os.path.join(lib_dir, "rustlib", compiler_host, "lib")
+    if "windows" in compiler_host:
         os.environ["PATH"] += os.pathsep + rustlib_dir
-    elif "darwin" in host:
+    elif "darwin" in compiler_host:
         os.environ["DYLD_LIBRARY_PATH"] = rustlib_dir
     else:
         os.environ["LD_LIBRARY_PATH"] = rustlib_dir
 
-def build_stage2_rust(rust_root, build, host, targets,
-                      external_llvm_root, is_release, verbose):
-    build_dir = os.path.join(rust_root, "target")
-    stage1_dir = os.path.join(build_dir, "stage1")
-    switch_rustc(stage1_dir, build)
-    for target in targets:
-        print("Building stage2 compiler for target " + target + ":")
-        set_env_vars(rust_root, target, external_llvm_root)
-        build_driver_crate(rust_root, target, is_release, verbose)
-    set_env_vars(rust_root, host, llvm_root)
-    build_rust_docs(rust_root, host, verbose = verbose)
-    print("Copying stage2 compiler to target/stage2:")
-    dest_dir = os.path.join(build_dir, "stage2")
-    copy_rust_dist(build_dir, dest_dir, host, targets, is_release)
-    print("Done.")
-
-
 # main function
 
 # parse command line arguments
@@ -394,17 +386,19 @@ def build_stage2_rust(rust_root, build, host, targets,
 if not args.run_tests_only:
     print("Building Rust with " + profile + " profile:")
     if not args.no_bootstrap:
-        build_stage1_rust(rust_root, build, llvm_root,
-                          is_release = is_release, verbose = verbose)
-        clean_build_dirs(rust_root, build, profile)
-    build_stage2_rust(rust_root, build, host, targets, llvm_root,
-                      is_release = is_release, verbose = verbose)
+        stages_to_build = ["stage0", "stage1", "stage2"]
+    else:
+        stages_to_build = ["stage2"]
+    for stage in stages_to_build:
+        build_rust_stage(rust_root, build, host, targets, stage, llvm_root,
+                         is_release = is_release, verbose = verbose)
+        if stage != "stage2":
+            clean_build_dirs(rust_root, build, profile)
+    set_env_vars(rust_root, host, llvm_root)
+    build_rust_docs(rust_root, host, verbose = verbose)
 
-# we only run tests for native builds
+# we only run stage2 tests for native builds
 if host == build:
-    set_env_vars(rust_root, host, llvm_root)
-    stage2_dir = os.path.join(rust_root, "target", "stage2")
-    switch_rustc(stage2_dir, host)
     llvm_bin_dir = build_llvm.get_llvm_bin_dir(rust_root, target, llvm_root)
     run_compiletests(rust_root, host, llvm_bin_dir, verbose = verbose)
     run_crate_tests(rust_root, host, verbose = verbose)

From 4b593417dbeb2b98696938f23dc4008cfc790361 Mon Sep 17 00:00:00 2001
From: Chang Liu <cliu712@aucklanduni.ac.nz>
Date: Wed, 15 Jul 2015 10:48:40 +0000
Subject: [PATCH 20/22] Remove LTO for release builds. Remove opt-level=1 for
 debug builds.

---
 src/driver/Cargo.toml | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/src/driver/Cargo.toml b/src/driver/Cargo.toml
index a6393e74a9e09..2fa0fce17646d 100644
--- a/src/driver/Cargo.toml
+++ b/src/driver/Cargo.toml
@@ -15,10 +15,3 @@ path = "rustdoc.rs"
 rustc_driver = { path = "../librustc_driver" }
 std = { path = "../libstd" }
 rustdoc = { path = "../librustdoc" }
-
-[profile.release]
-opt-level = 3
-lto = true
-
-[profile.dev]
-opt-level = 1

From ff8b83f4a4bf964ae54d6fc873d2fbccf7b3a8b3 Mon Sep 17 00:00:00 2001
From: Chang Liu <cliu712@aucklanduni.ac.nz>
Date: Wed, 15 Jul 2015 13:01:13 +0000
Subject: [PATCH 21/22] Link `rustc` and `rustdoc` dynamically rather than
 statically

---
 src/etc/build_rust.py | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/src/etc/build_rust.py b/src/etc/build_rust.py
index 7ddd55f7333c0..41f35f6140574 100644
--- a/src/etc/build_rust.py
+++ b/src/etc/build_rust.py
@@ -73,16 +73,15 @@ def set_env_vars(rust_root, target, external_llvm_root):
     os.environ["CARGO_TARGET_DIR"] = os.path.join(rust_root, "target")
     os.environ["CFG_LLVM_ROOT"] = llvm_root
 
-# build the src/driver crate, which is the root package for the compiler
-# (including rustdoc)
-def build_driver_crate(rust_root, target, is_release, verbose):
-    args = ["cargo", "build", "--manifest-path",
+def build_rust_exe(rust_root, target, exe_name, is_release, verbose):
+    args = ["cargo", "rustc", "--bin", exe_name, "--manifest-path",
             os.path.join(rust_root, "src", "driver", "Cargo.toml")]
     args.extend(["--target", target])
     if is_release:
         args.append("--release")
     if verbose:
         args.append("--verbose")
+    args.extend(["--", "-C", "prefer-dynamic"])
     ret = subprocess.call(args)
     if ret == 0:
         print("Build succeeded.")
@@ -110,7 +109,8 @@ def copy_rust_dist(rust_root, stage, host, targets, is_release):
     os.makedirs(bin_dir)
     host_build_dir = os.path.join(build_dir, host, profile)
     shutil.copy2(os.path.join(host_build_dir, rustc), bin_dir)
-    shutil.copy2(os.path.join(host_build_dir, rustdoc), bin_dir)
+    if stage == "stage2":
+        shutil.copy2(os.path.join(host_build_dir, rustdoc), bin_dir)
     for target in targets:
         target_build_dir = os.path.join(build_dir, target, profile)
         target_lib_dir = os.path.join(lib_dir, "rustlib", target, "lib")
@@ -263,13 +263,16 @@ def build_rust_stage(rust_root, build, host, targets, stage,
     if stage != "stage2":
         compiler_host = build
         targets_to_build = [build]
+        exes_to_build = ["rustc"]
     else:
         compiler_host = host
         targets_to_build = targets
+        exes_to_build = ["rustc", "rustdoc"]
     for target in targets_to_build:
         print("Building " + stage + " compiler for target " + target + ":")
         set_env_vars(rust_root, target, external_llvm_root)
-        build_driver_crate(rust_root, target, is_release, verbose)
+        for exe_name in exes_to_build:
+            build_rust_exe(rust_root, target, exe_name, is_release, verbose)
     print("Copying " + stage + " compiler to target/" + stage + ":")
     copy_rust_dist(rust_root, stage, compiler_host,
                    targets_to_build, is_release)

From 90f55a7022313388a11c87e6270ad8c2e3b8ac2f Mon Sep 17 00:00:00 2001
From: Chang Liu <cliu712@aucklanduni.ac.nz>
Date: Wed, 15 Jul 2015 15:47:12 +0000
Subject: [PATCH 22/22] Remove `struct Triple` in `build_helper::cc`

---
 src/build_helper/cc.rs     | 192 +++++++++----------------------------
 src/build_helper/config.rs |  15 ++-
 src/build_helper/lib.rs    |   1 -
 src/build_helper/llvm.rs   |   3 +-
 src/liballoc/build.rs      |   8 +-
 src/libstd/build.rs        |  30 +++---
 6 files changed, 76 insertions(+), 173 deletions(-)

diff --git a/src/build_helper/cc.rs b/src/build_helper/cc.rs
index 923bd6dc8a881..d399bde1d78a6 100644
--- a/src/build_helper/cc.rs
+++ b/src/build_helper/cc.rs
@@ -14,139 +14,39 @@
 //! will select the appropriate one based on the build configuration
 //! and the platform.
 
-use std::fmt;
-use std::ffi::{OsStr, OsString};
+use std::ffi::OsString;
 use std::path::{PathBuf, Path};
 use std::process::Command;
 use llvm::LLVMTools;
 use config::Config;
 use run::Run;
 
-/// Specify a target triple, in the format `arch-vendor-os-abi`.
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct Triple {
-    triple : String
-}
-
-impl Triple {
-    pub fn new(triple : &str) -> Result<Triple, String> {
-        let v : Vec<&str>= triple.split('-').map(|s| s).collect();
-        if v.len() < 3 {
-            Err(format!("Invalid target triple {}.", triple))
-        } else {
-            Ok(Triple { triple : triple.into() })
-        }
-    }
-
-    pub fn arch(&self) -> &str {
-        self.triple.split('-').nth(0).unwrap()
-    }
-
-    pub fn os(&self) -> &str {
-        self.triple.split('-').nth(2).unwrap()
-    }
-
-    pub fn abi(&self) -> Option<&str> {
-        self.triple.split('-').nth(3)
-    }
-
-    pub fn is_i686(&self) -> bool {
-        self.arch() == "i686"
-    }
-
-    pub fn is_x86_64(&self) -> bool {
-        self.arch() == "x86_64"
-    }
-
-    pub fn is_aarch64(&self) -> bool {
-        self.arch() == "aarch64"
-    }
-
-    pub fn is_windows(&self) -> bool {
-        self.os() == "windows"
-    }
-
-    pub fn is_mingw(&self) -> bool {
-        self.is_windows() && self.abi() == Some("gnu")
-    }
-
-    pub fn is_msvc(&self) -> bool {
-        self.abi() == Some("msvc")
-    }
-
-    pub fn is_linux(&self) -> bool {
-        self.os() == "linux"
-    }
-
-    pub fn is_ios(&self) -> bool {
-        self.os() == "ios"
-    }
-
-    pub fn is_android(&self) -> bool {
-        self.os() == "android"
-    }
-
-    pub fn is_darwin(&self) -> bool {
-        self.os() == "darwin"
-    }
-
-    /// Append the extension for the executables in this platform
-    pub fn with_exe_ext(&self, name : &str) -> String {
-        if self.is_windows() {
-            format!("{}.exe", name)
-        } else {
-            format!("{}", name)
-        }
-    }
-
-    /// Append the extension for the static libraries in this platform
-    pub fn with_lib_ext(&self, name : &str) -> String {
-        if self.is_msvc() {
-            format!("{}.lib", name)
-        } else {
-            format!("lib{}.a", name)
-        }
-    }
-
-    /// Get the file extension for the dynamic libraries in this platform.
-    pub fn dylib_ext(&self) -> &'static str {
-        if self.is_windows() {
-            "dll"
-        } else if self.is_darwin() {
-            "dylib"
-        } else {
-            "so"
-        }
-    }
-}
-
-impl fmt::Display for Triple {
-    fn fmt(&self, f : &mut fmt::Formatter) -> fmt::Result {
-        f.write_str(&self.triple)
-    }
-}
-
-impl AsRef<OsStr> for Triple {
-    fn as_ref(&self) -> &OsStr {
-        &OsStr::new(&self.triple)
-    }
-}
-
-impl AsRef<Path> for Triple {
-    fn as_ref(&self) -> &Path {
-        &Path::new(&self.triple)
+/// Append the extension for the executables in this platform
+pub fn with_exe_ext(triple : &str, name : &str) -> String {
+    if triple.contains("windows") {
+        format!("{}.exe", name)
+    } else {
+        format!("{}", name)
     }
 }
 
-impl<'a> From<&'a Triple> for &'a str {
-    fn from(t : &'a Triple) -> &'a str {
-        &t.triple
+/// Append the extension for the static libraries in this platform
+pub fn with_lib_ext(triple : &str, name : &str) -> String {
+    if triple.contains("msvc") {
+        format!("{}.lib", name)
+    } else {
+        format!("lib{}.a", name)
     }
 }
 
-impl<'a> From<&'a Triple> for String {
-    fn from(t : &'a Triple) -> String {
-        t.triple.clone()
+/// Get the file extension for the dynamic libraries in this platform.
+pub fn dylib_ext(triple : &str) -> &'static str {
+    if triple.contains("windows") {
+        "dll"
+    } else if triple.contains("darwin") {
+        "dylib"
+    } else {
+        "so"
     }
 }
 
@@ -263,7 +163,7 @@ impl StaticLib {
         }
 
         let output = self.build_dir
-            .join(self.toolchain.target_triple().with_lib_ext(out_lib));
+            .join(with_lib_ext(self.toolchain.target_triple(), out_lib));
         self.toolchain.ar_cmd(&objects, &output).run();
         println!("cargo:rustc-link-search=native={}", self.build_dir.display());
         if self.with_llvm {
@@ -294,7 +194,7 @@ impl StaticLib {
 /// Define the abstract interface that a toolchain implemenation
 /// should support.
 pub trait Toolchain {
-    fn target_triple(&self) -> &Triple;
+    fn target_triple(&self) -> &str;
     fn cc_cmd(&self, src_file : &Path, obj_file : &Path,
               inc_dirs : &[PathBuf]) -> Command;
     fn cxx_cmd(&self, src_file : &Path, obj_file : &Path,
@@ -304,44 +204,44 @@ pub trait Toolchain {
 
 /// Gnu-flavoured toolchain. Support both gcc and clang.
 pub struct GccishToolchain {
-    target_triple : Triple,
+    target_triple : String,
     pub cc_cmd : String,
     cxx_cmd : String,
     pub ar_cmd : String
 }
 
 impl GccishToolchain {
-    pub fn new(target : &Triple) -> GccishToolchain {
-        if target.is_darwin() {
+    pub fn new(target : &str) -> GccishToolchain {
+        if target.contains("darwin") {
             GccishToolchain::clang(target)
-        } else if target.is_mingw() {
+        } else if target.contains("windows") && target.contains("gnu") {
             GccishToolchain::native_gcc(target)
         } else {
             GccishToolchain::cross_gcc(target)
         }
     }
 
-    fn cross_gcc(triple : &Triple) -> GccishToolchain {
+    fn cross_gcc(triple : &str) -> GccishToolchain {
         GccishToolchain {
-            target_triple : triple.clone(),
+            target_triple : triple.into(),
             cc_cmd : format!("{}-gcc", triple),
             cxx_cmd : format!("{}-g++", triple),
             ar_cmd : "ar".into()
         }
     }
 
-    fn native_gcc(triple : &Triple) -> GccishToolchain {
+    fn native_gcc(triple : &str) -> GccishToolchain {
         GccishToolchain {
-            target_triple : triple.clone(),
+            target_triple : triple.into(),
             cc_cmd : "gcc".into(),
             cxx_cmd : "g++".into(),
             ar_cmd : "ar".into()
         }
     }
 
-    fn clang(triple : &Triple) -> GccishToolchain {
+    fn clang(triple : &str) -> GccishToolchain {
         GccishToolchain {
-            target_triple : triple.clone(),
+            target_triple : triple.into(),
             cc_cmd : "clang".into(),
             cxx_cmd : "clang++".into(),
             ar_cmd : "ar".into()
@@ -352,26 +252,26 @@ impl GccishToolchain {
         let target = self.target_triple();
         let mut cflags = vec!["-ffunction-sections", "-fdata-sections"];
 
-        if target.is_aarch64() {
+        if target.contains("aarch64") {
             cflags.push("-D__aarch64__");
         }
 
-        if target.is_android() {
+        if target.contains("android") {
             cflags.push("-DANDROID");
             cflags.push("-D__ANDROID__");
         }
 
-        if target.is_windows() {
+        if target.contains("windows") {
             cflags.push("-mwin32");
         }
 
-        if target.is_i686() {
+        if target.contains("i686") {
             cflags.push("-m32");
-        } else if target.is_x86_64() {
+        } else if target.contains("x86_64") {
             cflags.push("-m64");
         }
 
-        if !target.is_i686() {
+        if !target.contains("i686") {
             cflags.push("-fPIC");
         }
 
@@ -384,7 +284,7 @@ impl GccishToolchain {
 
         let target = self.target_triple();
 
-        if target.is_darwin() {
+        if target.contains("darwin") {
             // for some reason clang on darwin doesn't seem to define this
             cmd.arg("-DCHAR_BIT=8");
         }
@@ -399,7 +299,7 @@ impl GccishToolchain {
 }
 
 impl Toolchain for GccishToolchain {
-    fn target_triple(&self) -> &Triple {
+    fn target_triple(&self) -> &str {
         &self.target_triple
     }
 
@@ -429,19 +329,19 @@ impl Toolchain for GccishToolchain {
 
 /// MSVC toolchain
 struct MsvcToolchain {
-    target_triple : Triple
+    target_triple : String
 }
 
 impl MsvcToolchain {
-    fn new(triple : &Triple) -> MsvcToolchain {
+    fn new(triple : &str) -> MsvcToolchain {
         MsvcToolchain {
-            target_triple : triple.clone()
+            target_triple : triple.into()
         }
     }
 }
 
 impl Toolchain for MsvcToolchain {
-    fn target_triple(&self) -> &Triple {
+    fn target_triple(&self) -> &str {
         &self.target_triple
     }
 
@@ -484,7 +384,7 @@ impl Toolchain for MsvcToolchain {
 
 pub fn build_static_lib(cfg : &Config) -> StaticLib {
     let target = cfg.target();
-    let toolchain : Box<Toolchain> = if target.is_msvc() {
+    let toolchain : Box<Toolchain> = if target.contains("msvc") {
         Box::new(MsvcToolchain::new(target))
     } else {
         Box::new(GccishToolchain::new(target))
diff --git a/src/build_helper/config.rs b/src/build_helper/config.rs
index c75f2f0865656..e105aba25086f 100644
--- a/src/build_helper/config.rs
+++ b/src/build_helper/config.rs
@@ -1,7 +1,6 @@
 use std::env;
 use std::path::{Path, PathBuf};
 use std::fs::PathExt;
-use cc::Triple;
 
 /// Collect the environment variables passed to the build script.
 /// Note: To determine the root directory of the rust source repo we simply
@@ -11,8 +10,8 @@ pub struct Config {
     manifest_dir : PathBuf,
     out_dir : PathBuf,
     llvm_root : PathBuf,
-    target : Triple,
-    host : Triple,
+    target : String,
+    host : String,
     njobs : u8,
     profile : String
 }
@@ -24,10 +23,8 @@ impl Config {
         let out_dir = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR"));
         let llvm_root = PathBuf::from(env::var("CFG_LLVM_ROOT")
                                       .expect("CFG_LLVM_ROOT"));
-        let target = Triple::new(&env::var("TARGET").expect("TARGET"))
-            .expect("target triple");
-        let host = Triple::new(&env::var("HOST").expect("HOST"))
-            .expect("host triple");
+        let target = env::var("TARGET").expect("TARGET");
+        let host = env::var("HOST").expect("HOST");
         let njobs : u8 = env::var("NUM_JOBS").expect("NUM_JOBS")
             .parse().expect("parse NUM_JOBS");
         let profile = env::var("PROFILE").expect("PROFILE");
@@ -74,12 +71,12 @@ impl Config {
     }
 
     /// Target triple being compiled for
-    pub fn target(&self) -> &Triple {
+    pub fn target(&self) -> &str {
         &self.target
     }
 
     /// Host triple of the rustc compiler
-    pub fn host(&self) -> &Triple {
+    pub fn host(&self) -> &str {
         &self.host
     }
 
diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs
index a0af397b46d04..72af05b0f09ba 100644
--- a/src/build_helper/lib.rs
+++ b/src/build_helper/lib.rs
@@ -8,7 +8,6 @@ pub mod cc;
 
 pub use run::Run;
 pub use config::Config;
-pub use cc::Triple;
 pub use cc::GccishToolchain;
 pub use cc::build_static_lib;
 pub use llvm::LLVMTools;
diff --git a/src/build_helper/llvm.rs b/src/build_helper/llvm.rs
index de8e1831b4c36..74dd9fe02d132 100644
--- a/src/build_helper/llvm.rs
+++ b/src/build_helper/llvm.rs
@@ -13,7 +13,6 @@
 
 use std::process::Command;
 use std::path::{Path, PathBuf};
-use cc::Triple;
 use config::Config;
 
 /// Provides paths to the LLVM tools and libraries
@@ -42,7 +41,7 @@ impl LLVMTools {
         self.llvm_build_artifacts_dir.join("lib")
     }
 
-    pub fn llc_cmd(&self, target : &Triple, src : &Path, obj : &Path)
+    pub fn llc_cmd(&self, target : &str, src : &Path, obj : &Path)
                    -> Command {
         let mut cmd = Command::new(&self.path_to_llc());
         cmd.arg("-filetype=obj")
diff --git a/src/liballoc/build.rs b/src/liballoc/build.rs
index bf602974ce8fc..95648ffc5c1bc 100644
--- a/src/liballoc/build.rs
+++ b/src/liballoc/build.rs
@@ -28,7 +28,7 @@ fn build_jemalloc() {
     // We ignore jemalloc on windows for the time-being, as `bash` is not
     // universally available on Windows.
     let build_jemalloc =
-        cfg!(feature = "jemalloc") || !cfg.target().is_windows();
+        cfg!(feature = "jemalloc") || !cfg.target().contains("windows");
     if !build_jemalloc {
         return
     }
@@ -42,13 +42,13 @@ fn build_jemalloc() {
     let mut cmd = Command::new("sh");
     cmd.arg(&src_dir.join("configure"));
     cmd.current_dir(&build_dir);
-    if target.is_mingw() {
+    if target.contains("windows") && target.contains("gnu") {
         // This isn't necessarily a desired option, but it's harmless and
         // works around what appears to be a mingw-w64 bug.
         //
         // https://sourceforge.net/p/mingw-w64/bugs/395/
         cmd.arg("--enable-lazy-lock");
-    } else if target.is_ios() || target.is_android() {
+    } else if target.contains("ios") || target.contains("android") {
         cmd.arg("--disable-tls");
     }
 
@@ -68,7 +68,7 @@ fn build_jemalloc() {
     cmd.arg(format!("--host={}", target));
 
     let gcc = GccishToolchain::new(target);
-    let cflags = gcc.cflags().connect(" ");
+    let cflags = gcc.cflags().join(" ");
     cmd.arg(format!("CC={}", gcc.cc_cmd));
     cmd.arg(format!("AR={}", gcc.ar_cmd));
     cmd.arg(format!("RANLIB={} s", gcc.ar_cmd));
diff --git a/src/libstd/build.rs b/src/libstd/build.rs
index 47d7b0b2852c2..a1e4fc1b6c847 100644
--- a/src/libstd/build.rs
+++ b/src/libstd/build.rs
@@ -2,7 +2,7 @@ extern crate build_helper;
 
 use std::path::PathBuf;
 use std::process::Command;
-use build_helper::{Config, Run, Triple, build_static_lib};
+use build_helper::{Config, Run, build_static_lib};
 
 fn main() {
     build_rt_libraries();
@@ -22,7 +22,7 @@ struct RtLib {
     inc_dirs : Vec<&'static str>
 }
 
-fn runtime_libraries(target : &Triple) -> Vec<RtLib> {
+fn runtime_libraries(target : &str) -> Vec<RtLib> {
     vec![
         RtLib {
             name : "rust_builtin",
@@ -35,7 +35,7 @@ fn runtime_libraries(target : &Triple) -> Vec<RtLib> {
             needed : true,
             src_files : {
                 let mut v = vec!["rt/rust_try.ll"];
-                if target.is_linux() {
+                if target.contains("linux") {
                     v.push("rt/arch/{arch}/record_sp.S");
                 }
                 v
@@ -44,13 +44,13 @@ fn runtime_libraries(target : &Triple) -> Vec<RtLib> {
         },
         RtLib {
             name : "morestack",
-            needed : !target.is_windows(),
+            needed : !target.contains("windows"),
             src_files : vec!["rt/arch/{arch}/morestack.S"],
             inc_dirs : vec![],
         },
         RtLib {
             name : "compiler-rt",
-            needed : !target.is_msvc(), // FIXME: Fix MSVC build for compiler-rt
+            needed : !target.contains("msvc"), // FIXME: Fix MSVC build for compiler-rt
             src_files : vec!["compiler-rt/lib/builtins",
                              "compiler-rt/lib/builtins/{arch}"],
             inc_dirs : vec!["compiler-rt/lib/builtins",
@@ -59,16 +59,24 @@ fn runtime_libraries(target : &Triple) -> Vec<RtLib> {
         ]
 }
 
-fn parse_dir(s : &str, tgt : &Triple) -> PathBuf {
-    let arch = if tgt.is_i686() {
+pub fn arch(triple : &str) -> &str {
+    triple.split('-').nth(0).expect("invalid target triple")
+}
+
+pub fn os(triple : &str) -> &str {
+    triple.split('-').nth(2).expect("invalid target triple")
+}
+
+fn parse_dir(s : &str, tgt : &str) -> PathBuf {
+    let arch = if tgt.contains("i686") {
         "i386"
     } else {
-        tgt.arch()
+        arch(tgt)
     };
-    let os = if tgt.is_windows() {
+    let os = if tgt.contains("windows") {
         "win"
     } else {
-        tgt.os()
+        os(tgt)
     };
     PathBuf::from(s).iter().map(|d| {
         if d == "{arch}" {
@@ -105,7 +113,7 @@ fn build_rt_libraries() {
 
 fn build_backtrace() {
     let cfg = Config::new();
-    if !cfg.target().is_linux() {
+    if !cfg.target().contains("linux") {
         return
     }