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("⊆".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 }