From 046e6874c47ec55e23b7a566bca51d2920562485 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 19 Nov 2015 15:20:12 -0800 Subject: [PATCH 01/10] Add a Cargo-based build system This commit is the start of a series of commits which start to replace the makefiles with a Cargo-based build system. The aim is not to remove the makefiles entirely just yet but rather just replace the portions that invoke the compiler to do the bootstrap. This commit specifically adds enough support to perform the bootstrap (and all the cross compilation within) along with generating documentation. More commits will follow up in this series to actually wire up the makefiles to call this build system, so stay tuned! --- .gitignore | 1 + src/bootstrap/Cargo.lock | 109 ++++++++ src/bootstrap/Cargo.toml | 29 +++ src/bootstrap/README.md | 110 ++++++++ src/bootstrap/bootstrap.py | 300 ++++++++++++++++++++++ src/bootstrap/build/cc.rs | 98 +++++++ src/bootstrap/build/channel.rs | 82 ++++++ src/bootstrap/build/compile.rs | 248 ++++++++++++++++++ src/bootstrap/build/config.rs | 255 +++++++++++++++++++ src/bootstrap/build/flags.rs | 99 ++++++++ src/bootstrap/build/job.rs | 100 ++++++++ src/bootstrap/build/mod.rs | 452 +++++++++++++++++++++++++++++++++ src/bootstrap/build/native.rs | 157 ++++++++++++ src/bootstrap/build/sanity.rs | 122 +++++++++ src/bootstrap/build/step.rs | 177 +++++++++++++ src/bootstrap/build/util.rs | 97 +++++++ src/bootstrap/lib.rs | 28 ++ src/bootstrap/main.rs | 38 +++ src/bootstrap/rustc.rs | 91 +++++++ src/build_helper/Cargo.toml | 8 + src/build_helper/lib.rs | 68 +++++ src/etc/tidy.py | 2 +- src/nightlies.txt | 2 + src/rustc/Cargo.lock | 356 ++++++++++++++++++++++++++ src/rustc/Cargo.toml | 36 +++ src/rustc/libc_shim/Cargo.toml | 20 ++ src/rustc/libc_shim/build.rs | 15 ++ src/rustc/rustbook.rs | 14 + src/rustc/rustc.rs | 15 ++ src/rustc/rustdoc.rs | 15 ++ src/rustc/std_shim/Cargo.lock | 124 +++++++++ src/rustc/std_shim/Cargo.toml | 46 ++++ src/rustc/std_shim/lib.rs | 11 + 33 files changed, 3324 insertions(+), 1 deletion(-) create mode 100644 src/bootstrap/Cargo.lock create mode 100644 src/bootstrap/Cargo.toml create mode 100644 src/bootstrap/README.md create mode 100644 src/bootstrap/bootstrap.py create mode 100644 src/bootstrap/build/cc.rs create mode 100644 src/bootstrap/build/channel.rs create mode 100644 src/bootstrap/build/compile.rs create mode 100644 src/bootstrap/build/config.rs create mode 100644 src/bootstrap/build/flags.rs create mode 100644 src/bootstrap/build/job.rs create mode 100644 src/bootstrap/build/mod.rs create mode 100644 src/bootstrap/build/native.rs create mode 100644 src/bootstrap/build/sanity.rs create mode 100644 src/bootstrap/build/step.rs create mode 100644 src/bootstrap/build/util.rs create mode 100644 src/bootstrap/lib.rs create mode 100644 src/bootstrap/main.rs create mode 100644 src/bootstrap/rustc.rs create mode 100644 src/build_helper/Cargo.toml create mode 100644 src/build_helper/lib.rs create mode 100644 src/nightlies.txt create mode 100644 src/rustc/Cargo.lock create mode 100644 src/rustc/Cargo.toml create mode 100644 src/rustc/libc_shim/Cargo.toml create mode 100644 src/rustc/libc_shim/build.rs create mode 100644 src/rustc/rustbook.rs create mode 100644 src/rustc/rustc.rs create mode 100644 src/rustc/rustdoc.rs create mode 100644 src/rustc/std_shim/Cargo.lock create mode 100644 src/rustc/std_shim/Cargo.toml create mode 100644 src/rustc/std_shim/lib.rs diff --git a/.gitignore b/.gitignore index 572111bf96158..b6f5f04bff62f 100644 --- a/.gitignore +++ b/.gitignore @@ -93,3 +93,4 @@ tmp.*.rs version.md version.ml version.texi +/target diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock new file mode 100644 index 0000000000000..f9593eb1609d8 --- /dev/null +++ b/src/bootstrap/Cargo.lock @@ -0,0 +1,109 @@ +[root] +name = "bootstrap" +version = "0.0.0" +dependencies = [ + "build_helper 0.1.0", + "cmake 0.1.10 (registry+/~https://github.com/rust-lang/crates.io-index)", + "filetime 0.1.8 (registry+/~https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.19 (registry+/~https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.14 (registry+/~https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.1 (registry+/~https://github.com/rust-lang/crates.io-index)", + "libc 0.2.2 (registry+/~https://github.com/rust-lang/crates.io-index)", + "num_cpus 0.2.9 (registry+/~https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.16 (registry+/~https://github.com/rust-lang/crates.io-index)", + "toml 0.1.23 (registry+/~https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.5 (registry+/~https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "advapi32-sys" +version = "0.1.2" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.5 (registry+/~https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+/~https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "build_helper" +version = "0.1.0" + +[[package]] +name = "cmake" +version = "0.1.10" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.19 (registry+/~https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "filetime" +version = "0.1.8" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.1 (registry+/~https://github.com/rust-lang/crates.io-index)", + "libc 0.2.2 (registry+/~https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.5 (registry+/~https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gcc" +version = "0.3.19" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +dependencies = [ + "advapi32-sys 0.1.2 (registry+/~https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.5 (registry+/~https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "getopts" +version = "0.2.14" +source = "registry+/~https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "kernel32-sys" +version = "0.2.1" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.5 (registry+/~https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+/~https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libc" +version = "0.2.2" +source = "registry+/~https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "num_cpus" +version = "0.2.9" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.1 (registry+/~https://github.com/rust-lang/crates.io-index)", + "libc 0.2.2 (registry+/~https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.5 (registry+/~https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-serialize" +version = "0.3.16" +source = "registry+/~https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "toml" +version = "0.1.23" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-serialize 0.3.16 (registry+/~https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi" +version = "0.2.5" +source = "registry+/~https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+/~https://github.com/rust-lang/crates.io-index" + diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml new file mode 100644 index 0000000000000..8321f93c90f61 --- /dev/null +++ b/src/bootstrap/Cargo.toml @@ -0,0 +1,29 @@ +[package] +authors = ["The Rust Project Developers"] +name = "bootstrap" +version = "0.0.0" + +[lib] +name = "bootstrap" +path = "lib.rs" + +[[bin]] +name = "bootstrap" +path = "main.rs" + +[[bin]] +name = "rustc" +path = "rustc.rs" + +[dependencies] +build_helper = { path = "../build_helper" } +cmake = "0.1.10" +filetime = "0.1" +num_cpus = "0.2" +toml = "0.1" +getopts = "0.2" +rustc-serialize = "0.3" +winapi = "0.2" +kernel32-sys = "0.2" +gcc = "0.3.17" +libc = "0.2" diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md new file mode 100644 index 0000000000000..9e97ec4da0769 --- /dev/null +++ b/src/bootstrap/README.md @@ -0,0 +1,110 @@ +# Bootstrapping Rust + +This is an in-progress README which is targeted at helping to explain how Rust +is bootstrapped and in general some of the technical details of the build +system. + +> **Note**: This build system is currently under active development and is not +> intended to be the primarily used one just yet. The makefiles are currently +> the ones that are still "guaranteed to work" as much as possible at least. + +## Using the new build system + +When configuring Rust via `./configure`, pass the following to enable building +via this build system: + +``` +./configure --enable-rustbuild +``` + +## ... + +## Directory Layout + +This build system houses all output under the `target` directory, which looks +like this: + +``` +# Root folder of all output. Everything is scoped underneath here +build/ + + # Location where the stage0 compiler downloads are all cached. This directory + # only contains the tarballs themselves as they're extracted elsewhere. + cache/ + 2015-12-19/ + 2016-01-15/ + 2016-01-21/ + ... + + # Output directory for building this build system itself. The stage0 + # cargo/rustc are used to build the build system into this location. + bootstrap/ + debug/ + release/ + + # Each remaining directory is scoped by the "host" triple of compilation at + # hand. + x86_64-unknown-linux-gnu/ + + # The build artifacts for the `compiler-rt` library for the target this + # folder is under. The exact layout here will likely depend on the platform, + # and this is also built with CMake so the build system is also likely + # different. + compiler-rt/build/ + + # Output folder for LLVM if it is compiled for this target + llvm/ + + # build folder (e.g. the platform-specific build system). Like with + # compiler-rt this is compiled with CMake + build/ + + # Installation of LLVM. Note that we run the equivalent of 'make install' + # for LLVM to setup these folders. + bin/ + lib/ + include/ + share/ + ... + + # Location where the stage0 Cargo and Rust compiler are unpacked. This + # directory is purely an extracted and overlaid tarball of these two (done + # by the bootstrapy python script). In theory the build system does not + # modify anything under this directory afterwards. + stage0/ + + # These to build directories are the cargo output directories for builds of + # the standard library and compiler, respectively. Internally these may also + # have other target directories, which represent artifacts being compiled + # from the host to the specified target. + # + # Essentially, each of these directories is filled in by one `cargo` + # invocation. The build system instruments calling Cargo in the right order + # with the right variables to ensure these are filled in correctly. + stageN-std/ + stageN-rustc/ + + # This is a special case of the above directories, **not** filled in via + # Cargo but rather the build system itself. The stage0 compiler already has + # a set of target libraries for its own host triple (in its own sysroot) + # inside of stage0/. When we run the stage0 compiler to bootstrap more + # things, however, we don't want to use any of these libraries (as those are + # the ones that we're building). So essentially, when the stage1 compiler is + # being compiled (e.g. after libstd has been built), *this* is used as the + # sysroot for the stage0 compiler being run. + # + # Basically this directory is just a temporary artifact use to configure the + # stage0 compiler to ensure that the libstd we just built is used to + # compile the stage1 compiler. + stage0-rustc/lib/ + + # These output directories are intended to be standalone working + # implementations of the compiler (corresponding to each stage). The build + # system will link (using hard links) output from stageN-{std,rustc} into + # each of these directories. + # + # In theory there is no extra build output in these directories. + stage1/ + stage2/ + stage3/ +``` diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py new file mode 100644 index 0000000000000..435304645459d --- /dev/null +++ b/src/bootstrap/bootstrap.py @@ -0,0 +1,300 @@ +# Copyright 2015-2016 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 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +import argparse +import contextlib +import os +import shutil +import subprocess +import sys +import tarfile + +def get(url, path, verbose=False): + print("downloading " + url) + # see http://serverfault.com/questions/301128/how-to-download + if sys.platform == 'win32': + run(["PowerShell.exe", "/nologo", "-Command", + "(New-Object System.Net.WebClient).DownloadFile('" + url + + "', '" + path + "')"], verbose=verbose) + else: + run(["curl", "-o", path, url], verbose=verbose) + +def unpack(tarball, dst, verbose=False, match=None): + print("extracting " + tarball) + fname = os.path.basename(tarball).replace(".tar.gz", "") + with contextlib.closing(tarfile.open(tarball)) as tar: + for p in tar.getnames(): + if "/" not in p: + continue + name = p.replace(fname + "/", "", 1) + if match is not None and not name.startswith(match): + continue + name = name[len(match) + 1:] + + fp = os.path.join(dst, name) + if verbose: + print(" extracting " + p) + tar.extract(p, dst) + tp = os.path.join(dst, p) + if os.path.isdir(tp) and os.path.exists(fp): + continue + shutil.move(tp, fp) + shutil.rmtree(os.path.join(dst, fname)) + +def run(args, verbose=False): + if verbose: + print("running: " + ' '.join(args)) + sys.stdout.flush() + # Use Popen here instead of call() as it apparently allows powershell on + # Windows to not lock up waiting for input presumably. + ret = subprocess.Popen(args) + code = ret.wait() + if code != 0: + if not verbose: + print("failed to run: " + ' '.join(args)) + raise RuntimeError("failed to run command") + +class RustBuild: + def download_rust_nightly(self): + cache_dst = os.path.join(self.build_dir, "cache") + rustc_cache = os.path.join(cache_dst, self.snap_rustc_date()) + cargo_cache = os.path.join(cache_dst, self.snap_cargo_date()) + if not os.path.exists(rustc_cache): + os.makedirs(rustc_cache) + if not os.path.exists(cargo_cache): + os.makedirs(cargo_cache) + + if self.rustc().startswith(self.bin_root()) and \ + (not os.path.exists(self.rustc()) or self.rustc_out_of_date()): + filename = "rust-std-nightly-" + self.build + ".tar.gz" + url = "https://static.rust-lang.org/dist/" + self.snap_rustc_date() + tarball = os.path.join(rustc_cache, filename) + if not os.path.exists(tarball): + get(url + "/" + filename, tarball, verbose=self.verbose) + unpack(tarball, self.bin_root(), + match="rust-std-" + self.build, + verbose=self.verbose) + + filename = "rustc-nightly-" + self.build + ".tar.gz" + url = "https://static.rust-lang.org/dist/" + self.snap_rustc_date() + tarball = os.path.join(rustc_cache, filename) + if not os.path.exists(tarball): + get(url + "/" + filename, tarball, verbose=self.verbose) + unpack(tarball, self.bin_root(), match="rustc", verbose=self.verbose) + with open(self.rustc_stamp(), 'w') as f: + f.write(self.snap_rustc_date()) + + if self.cargo().startswith(self.bin_root()) and \ + (not os.path.exists(self.cargo()) or self.cargo_out_of_date()): + filename = "cargo-nightly-" + self.build + ".tar.gz" + url = "https://static.rust-lang.org/cargo-dist/" + self.snap_cargo_date() + tarball = os.path.join(cargo_cache, filename) + if not os.path.exists(tarball): + get(url + "/" + filename, tarball, verbose=self.verbose) + unpack(tarball, self.bin_root(), match="cargo", verbose=self.verbose) + with open(self.cargo_stamp(), 'w') as f: + f.write(self.snap_cargo_date()) + + def snap_cargo_date(self): + return self._cargo_date + + def snap_rustc_date(self): + return self._rustc_date + + def rustc_stamp(self): + return os.path.join(self.bin_root(), '.rustc-stamp') + + def cargo_stamp(self): + return os.path.join(self.bin_root(), '.cargo-stamp') + + def rustc_out_of_date(self): + if not os.path.exists(self.rustc_stamp()): + return True + with open(self.rustc_stamp(), 'r') as f: + return self.snap_rustc_date() != f.read() + + def cargo_out_of_date(self): + if not os.path.exists(self.cargo_stamp()): + return True + with open(self.cargo_stamp(), 'r') as f: + return self.snap_cargo_date() != f.read() + + def bin_root(self): + return os.path.join(self.build_dir, self.build, "stage0") + + def get_toml(self, key): + for line in self.config_toml.splitlines(): + if line.startswith(key + ' ='): + return self.get_string(line) + return None + + def cargo(self): + config = self.get_toml('cargo') + if config: + return config + return os.path.join(self.bin_root(), "bin/cargo" + self.exe_suffix()) + + def rustc(self): + config = self.get_toml('rustc') + if config: + return config + return os.path.join(self.bin_root(), "bin/rustc" + self.exe_suffix()) + + def get_string(self, line): + start = line.find('"') + end = start + 1 + line[start+1:].find('"') + return line[start+1:end] + + def exe_suffix(self): + if sys.platform == 'win32': + return '.exe' + else: + return '' + + def parse_nightly_dates(self): + nightlies = os.path.join(self.rust_root, "src/nightlies.txt") + with open(nightlies, 'r') as nightlies: + rustc, cargo = nightlies.read().split("\n")[:2] + assert rustc.startswith("rustc: ") + assert cargo.startswith("cargo: ") + self._rustc_date = rustc[len("rustc: "):] + self._cargo_date = cargo[len("cargo: "):] + + def build_bootstrap(self): + env = os.environ.copy() + env["CARGO_TARGET_DIR"] = os.path.join(self.build_dir, "bootstrap") + env["RUSTC"] = self.rustc() + env["LD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + env["DYLD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + env["PATH"] = os.path.join(self.bin_root(), "bin") + \ + os.pathsep + env["PATH"] + self.run([self.cargo(), "build", "--manifest-path", + os.path.join(self.rust_root, "src/bootstrap/Cargo.toml")], + env) + + def run(self, args, env): + proc = subprocess.Popen(args, env = env) + ret = proc.wait() + if ret != 0: + sys.exit(ret) + + def build_triple(self): + config = self.get_toml('build') + if config: + return config + try: + ostype = subprocess.check_output(['uname', '-s']).strip() + cputype = subprocess.check_output(['uname', '-m']).strip() + except FileNotFoundError: + if sys.platform == 'win32': + return 'x86_64-pc-windows-msvc' + else: + raise + + # Darwin's `uname -s` lies and always returns i386. We have to use + # sysctl instead. + if ostype == 'Darwin' and cputype == 'i686': + sysctl = subprocess.check_output(['sysctl', 'hw.optional.x86_64']) + if sysctl.contains(': 1'): + cputype = 'x86_64' + + # The goal here is to come up with the same triple as LLVM would, + # at least for the subset of platforms we're willing to target. + if ostype == 'Linux': + ostype = 'unknown-linux-gnu' + elif ostype == 'FreeBSD': + ostype = 'unknown-freebsd' + elif ostype == 'DragonFly': + ostype = 'unknown-dragonfly' + elif ostype == 'Bitrig': + ostype = 'unknown-bitrig' + elif ostype == 'OpenBSD': + ostype = 'unknown-openbsd' + elif ostype == 'NetBSD': + ostype = 'unknown-netbsd' + elif ostype == 'Darwin': + ostype = 'apple-darwin' + elif ostype.startswith('MINGW'): + # msys' `uname` does not print gcc configuration, but prints msys + # configuration. so we cannot believe `uname -m`: + # msys1 is always i686 and msys2 is always x86_64. + # instead, msys defines $MSYSTEM which is MINGW32 on i686 and + # MINGW64 on x86_64. + ostype = 'pc-windows-gnu' + cputype = 'i686' + if os.environ.get('MSYSTEM') == 'MINGW64': + cputype = 'x86_64' + elif ostype.startswith('MSYS'): + ostype = 'pc-windows-gnu' + elif ostype.startswith('CYGWIN_NT'): + cputype = 'i686' + if ostype.endswith('WOW64'): + cputype = 'x86_64' + ostype = 'pc-windows-gnu' + else: + raise ValueError("unknown OS type: " + ostype) + + if cputype in {'i386', 'i486', 'i686', 'i786', 'x86'}: + cputype = 'i686' + elif cputype in {'xscale', 'arm'}: + cputype = 'arm' + elif cputype == 'armv7l': + cputype = 'arm' + ostype += 'eabihf' + elif cputype == 'aarch64': + cputype = 'aarch64' + elif cputype in {'powerpc', 'ppc', 'ppc64'}: + cputype = 'powerpc' + elif cputype in {'amd64', 'x86_64', 'x86-64', 'x64'}: + cputype = 'x86_64' + else: + raise ValueError("unknown cpu type: " + cputype) + + return cputype + '-' + ostype + +parser = argparse.ArgumentParser(description='Build rust') +parser.add_argument('--config') +parser.add_argument('-v', '--verbose', action='store_true') + +args = [a for a in sys.argv if a != '-h'] +args, _ = parser.parse_known_args(args) + +# Configure initial bootstrap +rb = RustBuild() +rb.config_toml = '' +rb.config_mk = '' +rb.rust_root = os.path.abspath(os.path.join(__file__, '../../..')) +rb.build_dir = os.path.join(os.getcwd(), "build") +rb.verbose = args.verbose + +try: + with open(args.config or 'config.toml') as config: + rb.config_toml = config.read() +except: + pass + +# Fetch/build the bootstrap +rb.build = rb.build_triple() +rb.parse_nightly_dates() +rb.download_rust_nightly() +sys.stdout.flush() +rb.build_bootstrap() +sys.stdout.flush() + +# Run the bootstrap +args = [os.path.join(rb.build_dir, "bootstrap/debug/bootstrap")] +args.extend(sys.argv[1:]) +args.append('--src') +args.append(rb.rust_root) +args.append('--build') +args.append(rb.build) +env = os.environ.copy() +env["BOOTSTRAP_PARENT_ID"] = str(os.getpid()) +rb.run(args, env) diff --git a/src/bootstrap/build/cc.rs b/src/bootstrap/build/cc.rs new file mode 100644 index 0000000000000..9f962e9d9e61a --- /dev/null +++ b/src/bootstrap/build/cc.rs @@ -0,0 +1,98 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::process::Command; + +use build_helper::{cc2ar, output}; +use gcc; + +use build::Build; +use build::config::Target; + +pub fn find(build: &mut Build) { + // For all targets we're going to need a C compiler for building some shims + // and such as well as for being a linker for Rust code. + for target in build.config.target.iter() { + let mut cfg = gcc::Config::new(); + cfg.cargo_metadata(false).opt_level(0).debug(false) + .target(target).host(&build.config.build); + + let config = build.config.target_config.get(target); + if let Some(cc) = config.and_then(|c| c.cc.as_ref()) { + cfg.compiler(cc); + } else { + set_compiler(&mut cfg, "gcc", target, config); + } + + let compiler = cfg.get_compiler(); + let ar = cc2ar(compiler.path(), target); + build.verbose(&format!("CC_{} = {:?}", target, compiler.path())); + build.verbose(&format!("AR_{} = {:?}", target, ar)); + build.cc.insert(target.to_string(), (compiler, ar)); + } + + // For all host triples we need to find a C++ compiler as well + for host in build.config.host.iter() { + let mut cfg = gcc::Config::new(); + cfg.cargo_metadata(false).opt_level(0).debug(false).cpp(true) + .target(host).host(&build.config.build); + let config = build.config.target_config.get(host); + if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) { + cfg.compiler(cxx); + } else { + set_compiler(&mut cfg, "g++", host, config); + } + let compiler = cfg.get_compiler(); + build.verbose(&format!("CXX_{} = {:?}", host, compiler.path())); + build.cxx.insert(host.to_string(), compiler); + } +} + +fn set_compiler(cfg: &mut gcc::Config, + gnu_compiler: &str, + target: &str, + config: Option<&Target>) { + match target { + // When compiling for android we may have the NDK configured in the + // config.toml in which case we look there. Otherwise the default + // compiler already takes into account the triple in question. + t if t.contains("android") => { + if let Some(ndk) = config.and_then(|c| c.ndk.as_ref()) { + let compiler = format!("{}-{}", target, gnu_compiler); + cfg.compiler(ndk.join("bin").join(compiler)); + } + } + + // The default gcc version from OpenBSD may be too old, try using egcc, + // which is a gcc version from ports, if this is the case. + t if t.contains("openbsd") => { + let c = cfg.get_compiler(); + if !c.path().ends_with(gnu_compiler) { + return + } + + let output = output(c.to_command().arg("--version")); + let i = match output.find(" 4.") { + Some(i) => i, + None => return, + }; + match output[i + 3..].chars().next().unwrap() { + '0' ... '6' => {} + _ => return, + } + let alternative = format!("e{}", gnu_compiler); + if Command::new(&alternative).output().is_ok() { + cfg.compiler(alternative); + } + } + + _ => {} + } +} diff --git a/src/bootstrap/build/channel.rs b/src/bootstrap/build/channel.rs new file mode 100644 index 0000000000000..628b1d764320b --- /dev/null +++ b/src/bootstrap/build/channel.rs @@ -0,0 +1,82 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::fs::{self, File}; +use std::io::prelude::*; +use std::path::Path; +use std::process::Command; + +use build_helper::output; + +use build::Build; +use build::util::mtime; + +pub fn collect(build: &mut Build) { + let mut main_mk = String::new(); + t!(t!(File::open(build.src.join("mk/main.mk"))).read_to_string(&mut main_mk)); + let mut release_num = ""; + let mut prerelease_version = ""; + for line in main_mk.lines() { + if line.starts_with("CFG_RELEASE_NUM") { + release_num = line.split('=').skip(1).next().unwrap().trim(); + } + if line.starts_with("CFG_PRERELEASE_VERSION") { + prerelease_version = line.split('=').skip(1).next().unwrap().trim(); + } + } + + // FIXME: this is duplicating makefile logic + match &build.config.channel[..] { + "stable" => { + build.release = release_num.to_string(); + build.unstable_features = false; + } + "beta" => { + build.release = format!("{}-beta{}", release_num, + prerelease_version); + build.unstable_features = false; + } + "nightly" => { + build.release = format!("{}-nightly", release_num); + build.unstable_features = true; + } + _ => { + build.release = format!("{}-dev", release_num); + build.unstable_features = true; + } + } + build.version = build.release.clone(); + + if fs::metadata(build.src.join(".git")).is_ok() { + let ver_date = output(Command::new("git").current_dir(&build.src) + .arg("log").arg("-1") + .arg("--date=short") + .arg("--pretty=format:%cd")); + let ver_hash = output(Command::new("git").current_dir(&build.src) + .arg("rev-parse").arg("HEAD")); + let short_ver_hash = output(Command::new("git") + .current_dir(&build.src) + .arg("rev-parse") + .arg("--short=9") + .arg("HEAD")); + let ver_date = ver_date.trim().to_string(); + let ver_hash = ver_hash.trim().to_string(); + let short_ver_hash = short_ver_hash.trim().to_string(); + build.version.push_str(&format!(" ({} {})", short_ver_hash, + ver_date)); + build.ver_date = Some(ver_date.to_string()); + build.ver_hash = Some(ver_hash); + build.short_ver_hash = Some(short_ver_hash); + } + + build.bootstrap_key = mtime(Path::new("config.toml")).seconds() + .to_string(); +} + diff --git a/src/bootstrap/build/compile.rs b/src/bootstrap/build/compile.rs new file mode 100644 index 0000000000000..05b444633b4cc --- /dev/null +++ b/src/bootstrap/build/compile.rs @@ -0,0 +1,248 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::HashMap; +use std::fs; +use std::path::{Path, PathBuf}; +use std::process::Command; + +use build_helper::output; + +use build::util::{exe, staticlib, libdir, mtime, is_dylib}; +use build::{Build, Compiler}; + +/// Build the standard library. +/// +/// This will build the standard library for a particular stage of the build +/// using the `compiler` targeting the `target` architecture. The artifacts +/// created will also be linked into the sysroot directory. +pub fn std<'a>(build: &'a Build, stage: u32, target: &str, + compiler: &Compiler<'a>) { + let host = compiler.host; + println!("Building stage{} std artifacts ({} -> {})", stage, + host, target); + + // Move compiler-rt into place as it'll be required by the compiler when + // building the standard library to link the dylib of libstd + let libdir = build.sysroot_libdir(stage, &host, target); + let _ = fs::remove_dir_all(&libdir); + t!(fs::create_dir_all(&libdir)); + t!(fs::hard_link(&build.compiler_rt_built.borrow()[target], + libdir.join(staticlib("compiler-rt", target)))); + + build_startup_objects(build, target, &libdir); + + let out_dir = build.cargo_out(stage, &host, true, target); + build.clear_if_dirty(&out_dir, &build.compiler_path(compiler)); + let mut cargo = build.cargo(stage, compiler, true, target, "build"); + cargo.arg("--features").arg(build.std_features()) + .arg("--manifest-path") + .arg(build.src.join("src/rustc/std_shim/Cargo.toml")); + + if let Some(target) = build.config.target_config.get(target) { + if let Some(ref jemalloc) = target.jemalloc { + cargo.env("JEMALLOC_OVERRIDE", jemalloc); + } + } + if let Some(ref p) = build.config.musl_root { + if target.contains("musl") { + cargo.env("MUSL_ROOT", p); + } + } + + build.run(&mut cargo); + add_to_sysroot(&out_dir, &libdir); +} + +/// Build and prepare startup objects like rsbegin.o and rsend.o +/// +/// These are primarily used on Windows right now for linking executables/dlls. +/// They don't require any library support as they're just plain old object +/// files, so we just use the nightly snapshot compiler to always build them (as +/// no other compilers are guaranteed to be available). +fn build_startup_objects(build: &Build, target: &str, into: &Path) { + if !target.contains("pc-windows-gnu") { + return + } + let compiler = Compiler::new(0, &build.config.build); + let compiler = build.compiler_path(&compiler); + + for file in t!(fs::read_dir(build.src.join("src/rtstartup"))) { + let file = t!(file); + build.run(Command::new(&compiler) + .arg("--emit=obj") + .arg("--out-dir").arg(into) + .arg(file.path())); + } + + for obj in ["crt2.o", "dllcrt2.o"].iter() { + t!(fs::copy(compiler_file(build.cc(target), obj), into.join(obj))); + } +} + +/// Build the compiler. +/// +/// This will build the compiler for a particular stage of the build using +/// the `compiler` targeting the `target` architecture. The artifacts +/// created will also be linked into the sysroot directory. +pub fn rustc<'a>(build: &'a Build, stage: u32, target: &str, + compiler: &Compiler<'a>) { + let host = compiler.host; + println!("Building stage{} compiler artifacts ({} -> {})", stage, + host, target); + + let out_dir = build.cargo_out(stage, &host, false, target); + let rustc = out_dir.join(exe("rustc", target)); + build.clear_if_dirty(&out_dir, &libstd_shim(build, stage, &host, target)); + + let mut cargo = build.cargo(stage, compiler, false, target, "build"); + cargo.arg("--features").arg(build.rustc_features(stage)) + .arg("--manifest-path") + .arg(build.src.join("src/rustc/Cargo.toml")); + + // In stage0 we may not need to build as many executables + if stage == 0 { + cargo.arg("--bin").arg("rustc"); + } + + // Set some configuration variables picked up by build scripts and + // the compiler alike + cargo.env("CFG_RELEASE", &build.release) + .env("CFG_RELEASE_CHANNEL", &build.config.channel) + .env("CFG_VERSION", &build.version) + .env("CFG_BOOTSTRAP_KEY", &build.bootstrap_key) + .env("RUSTC_BOOTSTRAP_KEY", &build.bootstrap_key) + .env("CFG_LIBDIR_RELATIVE", "lib"); + + if let Some(ref ver_date) = build.ver_date { + cargo.env("CFG_VER_DATE", ver_date); + } + if let Some(ref ver_hash) = build.ver_hash { + cargo.env("CFG_VER_HASH", ver_hash); + } + if !build.unstable_features { + cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1"); + } + if let Some(config) = build.config.target_config.get(target) { + if let Some(ref s) = config.llvm_config { + cargo.env("LLVM_CONFIG", s); + } + } + if build.config.llvm_static_stdcpp { + cargo.env("LLVM_STATIC_STDCPP", + compiler_file(build.cxx(target), "libstdc++.a")); + } + if let Some(ref s) = build.config.rustc_default_linker { + cargo.env("CFG_DEFAULT_LINKER", s); + } + if let Some(ref s) = build.config.rustc_default_ar { + cargo.env("CFG_DEFAULT_AR", s); + } + build.run(&mut cargo); + + let sysroot_libdir = build.sysroot_libdir(stage, host, target); + add_to_sysroot(&out_dir, &sysroot_libdir); + + if host == target { + assemble_compiler(build, stage, target, &rustc); + } +} + +/// Cargo's output path for the standard library in a given stage, compiled +/// by a particular compiler for the specified target. +fn libstd_shim(build: &Build, stage: u32, host: &str, target: &str) -> PathBuf { + build.cargo_out(stage, host, true, target).join("libstd_shim.rlib") +} + +fn compiler_file(compiler: &Path, file: &str) -> String { + output(Command::new(compiler) + .arg(format!("-print-file-name={}", file))).trim().to_string() +} + +/// Prepare a new compiler from the artifacts in `stage` +/// +/// This will link the compiler built by `host` during the stage +/// specified to the sysroot location for `host` to be the official +/// `stage + 1` compiler for that host. This means that the `rustc` binary +/// itself will be linked into place along with all supporting dynamic +/// libraries. +fn assemble_compiler(build: &Build, stage: u32, host: &str, rustc: &Path) { + // Clear out old files + let sysroot = build.sysroot(stage + 1, host); + let _ = fs::remove_dir_all(&sysroot); + t!(fs::create_dir_all(&sysroot)); + + // Link in all dylibs to the libdir + let sysroot_libdir = sysroot.join(libdir(host)); + t!(fs::create_dir_all(&sysroot_libdir)); + let src_libdir = build.sysroot_libdir(stage, host, host); + for f in t!(fs::read_dir(&src_libdir)).map(|f| t!(f)) { + let filename = f.file_name().into_string().unwrap(); + if is_dylib(&filename) { + t!(fs::hard_link(&f.path(), sysroot_libdir.join(&filename))); + } + } + + // Link the compiler binary itself into place + let bindir = sysroot.join("bin"); + t!(fs::create_dir_all(&bindir)); + let compiler = build.compiler_path(&Compiler::new(stage + 1, host)); + let _ = fs::remove_file(&compiler); + t!(fs::hard_link(rustc, compiler)); + + // See if rustdoc exists to link it into place + let exe = exe("rustdoc", host); + let rustdoc_src = rustc.parent().unwrap().join(&exe); + let rustdoc_dst = bindir.join(exe); + if fs::metadata(&rustdoc_src).is_ok() { + let _ = fs::remove_file(&rustdoc_dst); + t!(fs::hard_link(&rustdoc_src, &rustdoc_dst)); + } +} + +/// Link some files into a rustc sysroot. +/// +/// For a particular stage this will link all of the contents of `out_dir` +/// into the sysroot of the `host` compiler, assuming the artifacts are +/// compiled for the specified `target`. +fn add_to_sysroot(out_dir: &Path, sysroot_dst: &Path) { + // Collect the set of all files in the dependencies directory, keyed + // off the name of the library. We assume everything is of the form + // `foo-.{rlib,so,...}`, and there could be multiple different + // `` values for the same name (of old builds). + let mut map = HashMap::new(); + for file in t!(fs::read_dir(out_dir.join("deps"))).map(|f| t!(f)) { + let filename = file.file_name().into_string().unwrap(); + + // We're only interested in linking rlibs + dylibs, other things like + // unit tests don't get linked in + if !filename.ends_with(".rlib") && + !filename.ends_with(".lib") && + !is_dylib(&filename) { + continue + } + let file = file.path(); + let dash = filename.find("-").unwrap(); + let key = (filename[..dash].to_string(), + file.extension().unwrap().to_owned()); + map.entry(key).or_insert(Vec::new()) + .push(file.clone()); + } + + // For all hash values found, pick the most recent one to move into the + // sysroot, that should be the one we just built. + for (_, paths) in map { + let (_, path) = paths.iter().map(|path| { + (mtime(&path).seconds(), path) + }).max().unwrap(); + t!(fs::hard_link(&path, + sysroot_dst.join(path.file_name().unwrap()))); + } +} diff --git a/src/bootstrap/build/config.rs b/src/bootstrap/build/config.rs new file mode 100644 index 0000000000000..862ee15cb080c --- /dev/null +++ b/src/bootstrap/build/config.rs @@ -0,0 +1,255 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::HashMap; +use std::env; +use std::fs::File; +use std::io::prelude::*; +use std::path::PathBuf; +use std::process; + +use num_cpus; +use rustc_serialize::Decodable; +use toml::{Parser, Decoder, Value}; + +/// Global configuration for the entire build and/or bootstrap. +/// +/// This structure is derived from a combination of both `config.toml` and +/// `config.mk`. As of the time of this writing it's unlikely that `config.toml` +/// is used all that much, so this is primarily filled out by `config.mk` which +/// is generated from `./configure`. +/// +/// Note that this structure is not decoded directly into, but rather it is +/// filled out from the decoded forms of the structs below. +#[derive(Default)] +pub struct Config { + pub ccache: bool, + pub verbose: bool, + pub submodules: bool, + pub compiler_docs: bool, + pub docs: bool, + pub target_config: HashMap, + + // llvm codegen options + pub llvm_assertions: bool, + pub llvm_optimize: bool, + pub llvm_version_check: bool, + pub llvm_static_stdcpp: bool, + + // rust codegen options + pub rust_optimize: bool, + pub rust_codegen_units: u32, + pub rust_debug_assertions: bool, + pub rust_debuginfo: bool, + pub rust_rpath: bool, + pub rustc_default_linker: Option, + pub rustc_default_ar: Option, + + pub build: String, + pub host: Vec, + pub target: Vec, + pub rustc: Option, + pub cargo: Option, + + // libstd features + pub debug_jemalloc: bool, + pub use_jemalloc: bool, + + // misc + pub channel: String, + pub musl_root: Option, +} + +/// Per-target configuration stored in the global configuration structure. +#[derive(Default)] +pub struct Target { + pub llvm_config: Option, + pub jemalloc: Option, + pub cc: Option, + pub cxx: Option, + pub ndk: Option, +} + +/// Structure of the `config.toml` file that configuration is read from. +/// +/// This structure uses `Decodable` to automatically decode a TOML configuration +/// file into this format, and then this is traversed and written into the above +/// `Config` structure. +#[derive(RustcDecodable, Default)] +struct TomlConfig { + build: Option, + llvm: Option, + rust: Option, + target: Option>, +} + +/// TOML representation of various global build decisions. +#[derive(RustcDecodable, Default, Clone)] +struct Build { + build: Option, + host: Vec, + target: Vec, + cargo: Option, + rustc: Option, + compiler_docs: Option, + docs: Option, +} + +/// TOML representation of how the LLVM build is configured. +#[derive(RustcDecodable, Default)] +struct Llvm { + ccache: Option, + assertions: Option, + optimize: Option, + version_check: Option, + static_libstdcpp: Option, +} + +/// TOML representation of how the Rust build is configured. +#[derive(RustcDecodable, Default)] +struct Rust { + optimize: Option, + codegen_units: Option, + debug_assertions: Option, + debuginfo: Option, + debug_jemalloc: Option, + use_jemalloc: Option, + default_linker: Option, + default_ar: Option, + channel: Option, + musl_root: Option, + rpath: Option, +} + +/// TOML representation of how each build target is configured. +#[derive(RustcDecodable, Default)] +struct TomlTarget { + llvm_config: Option, + jemalloc: Option, + cc: Option, + cxx: Option, + android_ndk: Option, +} + +impl Config { + pub fn parse(build: &str, file: Option) -> Config { + let mut config = Config::default(); + config.llvm_optimize = true; + config.use_jemalloc = true; + config.rust_optimize = true; + config.submodules = true; + config.docs = true; + config.rust_rpath = true; + config.rust_codegen_units = 1; + config.build = build.to_string(); + config.channel = "dev".to_string(); + + let toml = file.map(|file| { + let mut f = t!(File::open(&file)); + let mut toml = String::new(); + t!(f.read_to_string(&mut toml)); + let mut p = Parser::new(&toml); + let table = match p.parse() { + Some(table) => table, + None => { + println!("failed to parse TOML configuration:"); + for err in p.errors.iter() { + let (loline, locol) = p.to_linecol(err.lo); + let (hiline, hicol) = p.to_linecol(err.hi); + println!("{}:{}-{}:{}: {}", loline, locol, hiline, + hicol, err.desc); + } + process::exit(2); + } + }; + let mut d = Decoder::new(Value::Table(table)); + match Decodable::decode(&mut d) { + Ok(cfg) => cfg, + Err(e) => { + println!("failed to decode TOML: {}", e); + process::exit(2); + } + } + }).unwrap_or_else(|| TomlConfig::default()); + + let build = toml.build.clone().unwrap_or(Build::default()); + set(&mut config.build, build.build.clone()); + config.host.push(config.build.clone()); + for host in build.host.iter() { + if !config.host.contains(host) { + config.host.push(host.clone()); + } + } + for target in config.host.iter().chain(&build.target) { + if !config.target.contains(target) { + config.target.push(target.clone()); + } + } + config.rustc = build.rustc; + config.cargo = build.cargo; + set(&mut config.compiler_docs, build.compiler_docs); + set(&mut config.docs, build.docs); + + if let Some(ref llvm) = toml.llvm { + set(&mut config.ccache, llvm.ccache); + set(&mut config.llvm_assertions, llvm.assertions); + set(&mut config.llvm_optimize, llvm.optimize); + set(&mut config.llvm_optimize, llvm.optimize); + set(&mut config.llvm_version_check, llvm.version_check); + set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp); + } + if let Some(ref rust) = toml.rust { + set(&mut config.rust_debug_assertions, rust.debug_assertions); + set(&mut config.rust_debuginfo, rust.debuginfo); + set(&mut config.rust_optimize, rust.optimize); + set(&mut config.rust_rpath, rust.rpath); + set(&mut config.debug_jemalloc, rust.debug_jemalloc); + set(&mut config.use_jemalloc, rust.use_jemalloc); + set(&mut config.channel, rust.channel.clone()); + config.rustc_default_linker = rust.default_linker.clone(); + config.rustc_default_ar = rust.default_ar.clone(); + config.musl_root = rust.musl_root.clone().map(PathBuf::from); + + match rust.codegen_units { + Some(0) => config.rust_codegen_units = num_cpus::get() as u32, + Some(n) => config.rust_codegen_units = n, + None => {} + } + } + + if let Some(ref t) = toml.target { + for (triple, cfg) in t { + let mut target = Target::default(); + + if let Some(ref s) = cfg.llvm_config { + target.llvm_config = Some(env::current_dir().unwrap().join(s)); + } + if let Some(ref s) = cfg.jemalloc { + target.jemalloc = Some(env::current_dir().unwrap().join(s)); + } + if let Some(ref s) = cfg.android_ndk { + target.ndk = Some(env::current_dir().unwrap().join(s)); + } + target.cxx = cfg.cxx.clone().map(PathBuf::from); + target.cc = cfg.cc.clone().map(PathBuf::from); + + config.target_config.insert(triple.clone(), target); + } + } + + return config + } +} + +fn set(field: &mut T, val: Option) { + if let Some(v) = val { + *field = v; + } +} diff --git a/src/bootstrap/build/flags.rs b/src/bootstrap/build/flags.rs new file mode 100644 index 0000000000000..cd538bb0a905a --- /dev/null +++ b/src/bootstrap/build/flags.rs @@ -0,0 +1,99 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::fs; +use std::path::PathBuf; +use std::process; +use std::slice; + +use getopts::Options; + +pub struct Flags { + pub verbose: bool, + pub stage: Option, + pub build: String, + pub host: Filter, + pub target: Filter, + pub step: Vec, + pub config: Option, + pub src: Option, + pub jobs: Option, + pub args: Vec, +} + +pub struct Filter { + values: Vec, +} + +impl Flags { + pub fn parse(args: &[String]) -> Flags { + let mut opts = Options::new(); + opts.optflag("v", "verbose", "use verbose output"); + opts.optopt("", "config", "TOML configuration file for build", "FILE"); + opts.optmulti("", "host", "host targets to build", "HOST"); + opts.reqopt("", "build", "build target of the stage0 compiler", "BUILD"); + opts.optmulti("", "target", "targets to build", "TARGET"); + opts.optmulti("s", "step", "build step to execute", "STEP"); + opts.optopt("", "stage", "stage to build", "N"); + opts.optopt("", "src", "path to repo root", "DIR"); + opts.optopt("j", "jobs", "number of jobs to run in parallel", "JOBS"); + opts.optflag("h", "help", "print this help message"); + + let usage = |n| -> ! { + let brief = format!("Usage: rust.py [options]"); + print!("{}", opts.usage(&brief)); + process::exit(n); + }; + + let m = opts.parse(args).unwrap_or_else(|e| { + println!("failed to parse options: {}", e); + usage(1); + }); + if m.opt_present("h") { + usage(0); + } + + if m.free.len() > 0 { + println!("free arguments are not currently accepted"); + usage(1); + } + + let cfg_file = m.opt_str("config").map(PathBuf::from).or_else(|| { + if fs::metadata("config.toml").is_ok() { + Some(PathBuf::from("config.toml")) + } else { + None + } + }); + + Flags { + verbose: m.opt_present("v"), + stage: m.opt_str("stage").map(|j| j.parse().unwrap()), + build: m.opt_str("build").unwrap(), + host: Filter { values: m.opt_strs("host") }, + target: Filter { values: m.opt_strs("target") }, + step: m.opt_strs("step"), + config: cfg_file, + src: m.opt_str("src").map(PathBuf::from), + jobs: m.opt_str("jobs").map(|j| j.parse().unwrap()), + args: m.free.clone(), + } + } +} + +impl Filter { + pub fn contains(&self, name: &str) -> bool { + self.values.len() == 0 || self.values.iter().any(|s| s == name) + } + + pub fn iter(&self) -> slice::Iter { + self.values.iter() + } +} diff --git a/src/bootstrap/build/job.rs b/src/bootstrap/build/job.rs new file mode 100644 index 0000000000000..49e027ffda596 --- /dev/null +++ b/src/bootstrap/build/job.rs @@ -0,0 +1,100 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Job management on Windows for bootstrapping +//! +//! Most of the time when you're running a build system (e.g. make) you expect +//! Ctrl-C or abnormal termination to actually terminate the entire tree of +//! process in play, not just the one at the top. This currently works "by +//! default" on Unix platforms because Ctrl-C actually sends a signal to the +//! *process group* rather than the parent process, so everything will get torn +//! down. On Windows, however, this does not happen and Ctrl-C just kills the +//! parent process. +//! +//! To achieve the same semantics on Windows we use Job Objects to ensure that +//! all processes die at the same time. Job objects have a mode of operation +//! where when all handles to the object are closed it causes all child +//! processes associated with the object to be terminated immediately. +//! Conveniently whenever a process in the job object spawns a new process the +//! child will be associated with the job object as well. This means if we add +//! ourselves to the job object we create then everything will get torn down! +//! +//! Unfortunately most of the time the build system is actually called from a +//! python wrapper (which manages things like building the build system) so this +//! all doesn't quite cut it so far. To go the last mile we duplicate the job +//! object handle into our parent process (a python process probably) and then +//! close our own handle. This means that the only handle to the job object +//! resides in the parent python process, so when python dies the whole build +//! system dies (as one would probably expect!). +//! +//! Note that this module has a #[cfg(windows)] above it as none of this logic +//! is required on Unix. + +extern crate kernel32; +extern crate winapi; + +use std::env; +use std::io; +use std::mem; + +use self::winapi::*; +use self::kernel32::*; + +pub unsafe fn setup() { + // Create a new job object for us to use + let job = CreateJobObjectW(0 as *mut _, 0 as *const _); + assert!(job != 0 as *mut _, "{}", io::Error::last_os_error()); + + // Indicate that when all handles to the job object are gone that all + // process in the object should be killed. Note that this includes our + // entire process tree by default because we've added ourselves and and our + // children will reside in the job by default. + let mut info = mem::zeroed::(); + info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; + let r = SetInformationJobObject(job, + JobObjectExtendedLimitInformation, + &mut info as *mut _ as LPVOID, + mem::size_of_val(&info) as DWORD); + assert!(r != 0, "{}", io::Error::last_os_error()); + + // Assign our process to this job object + let r = AssignProcessToJobObject(job, GetCurrentProcess()); + assert!(r != 0, "{}", io::Error::last_os_error()); + + // If we've got a parent process (e.g. the python script that called us) + // then move ownership of this job object up to them. That way if the python + // script is killed (e.g. via ctrl-c) then we'll all be torn down. + // + // If we don't have a parent (e.g. this was run directly) then we + // intentionally leak the job object handle. When our process exits + // (normally or abnormally) it will close the handle implicitly, causing all + // processes in the job to be cleaned up. + let pid = match env::var("BOOTSTRAP_PARENT_ID") { + Ok(s) => s, + Err(..) => return, + }; + + let parent = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid.parse().unwrap()); + assert!(parent != 0 as *mut _, "{}", io::Error::last_os_error()); + let mut parent_handle = 0 as *mut _; + let r = DuplicateHandle(GetCurrentProcess(), job, + parent, &mut parent_handle, + 0, FALSE, DUPLICATE_SAME_ACCESS); + + // If this failed, well at least we tried! An example of DuplicateHandle + // failing in the past has been when the wrong python2 package spawed this + // build system (e.g. the `python2` package in MSYS instead of + // `mingw-w64-x86_64-python2`. Not sure why it failed, but the "failure + // mode" here is that we only clean everything up when the build system + // dies, not when the python parent does, so not too bad. + if r != 0 { + CloseHandle(job); + } +} diff --git a/src/bootstrap/build/mod.rs b/src/bootstrap/build/mod.rs new file mode 100644 index 0000000000000..6f962aae92334 --- /dev/null +++ b/src/bootstrap/build/mod.rs @@ -0,0 +1,452 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::cell::RefCell; +use std::collections::HashMap; +use std::env; +use std::fs::{self, File}; +use std::path::{PathBuf, Path}; +use std::process::Command; + +use build_helper::{run_silent, output}; +use gcc; +use num_cpus; + +use build::util::{exe, mtime, libdir, add_lib_path}; + +macro_rules! t { + ($e:expr) => (match $e { + Ok(e) => e, + Err(e) => panic!("{} failed with {}", stringify!($e), e), + }) +} + +mod cc; +mod channel; +mod compile; +mod config; +mod flags; +mod native; +mod sanity; +mod step; +mod util; + +pub use build::config::Config; +pub use build::flags::Flags; + +#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] +pub struct Compiler<'a> { + stage: u32, + host: &'a str, +} + +pub struct Build { + // User-specified configuration via config.toml + config: Config, + + // User-specified configuration via CLI flags + flags: Flags, + + // Derived properties from the above two configurations + cargo: PathBuf, + rustc: PathBuf, + src: PathBuf, + out: PathBuf, + release: String, + unstable_features: bool, + ver_hash: Option, + short_ver_hash: Option, + ver_date: Option, + version: String, + bootstrap_key: String, + + // Runtime state filled in later on + cc: HashMap, + cxx: HashMap, + compiler_rt_built: RefCell>, +} + +impl Build { + pub fn new(flags: Flags, config: Config) -> Build { + let cwd = t!(env::current_dir()); + let src = flags.src.clone().unwrap_or(cwd.clone()); + let out = cwd.join("build"); + + let stage0_root = out.join(&config.build).join("stage0/bin"); + let rustc = match config.rustc { + Some(ref s) => PathBuf::from(s), + None => stage0_root.join(exe("rustc", &config.build)), + }; + let cargo = match config.cargo { + Some(ref s) => PathBuf::from(s), + None => stage0_root.join(exe("cargo", &config.build)), + }; + + Build { + flags: flags, + config: config, + cargo: cargo, + rustc: rustc, + src: src, + out: out, + + release: String::new(), + unstable_features: false, + ver_hash: None, + short_ver_hash: None, + ver_date: None, + version: String::new(), + bootstrap_key: String::new(), + cc: HashMap::new(), + cxx: HashMap::new(), + compiler_rt_built: RefCell::new(HashMap::new()), + } + } + + pub fn build(&mut self) { + use build::step::Source::*; + + // see comments in job.rs for what's going on here + #[cfg(windows)] + fn setup_job() { + mod job; + unsafe { job::setup() } + } + #[cfg(not(windows))] fn setup_job() {} + setup_job(); + + cc::find(self); + sanity::check(self); + channel::collect(self); + self.update_submodules(); + + for target in step::all(self) { + match target.src { + Llvm { _dummy } => { + native::llvm(self, target.target); + } + CompilerRt { _dummy } => { + native::compiler_rt(self, target.target); + } + Libstd { stage, compiler } => { + compile::std(self, stage, target.target, &compiler); + } + Librustc { stage, compiler } => { + compile::rustc(self, stage, target.target, &compiler); + } + Rustc { stage } => { + println!("ok, rustc stage{} in {}", stage, target.target); + } + } + } + } + + fn update_submodules(&self) { + if !self.config.submodules { + return + } + if fs::metadata(self.src.join(".git")).is_err() { + return + } + let out = output(Command::new("git").arg("submodule").arg("status")); + if !out.lines().any(|l| l.starts_with("+") || l.starts_with("-")) { + return + } + + self.run(Command::new("git").arg("submodule").arg("sync")); + self.run(Command::new("git").arg("submodule").arg("init")); + self.run(Command::new("git").arg("submodule").arg("update")); + self.run(Command::new("git").arg("submodule").arg("update") + .arg("--recursive")); + self.run(Command::new("git").arg("submodule").arg("status") + .arg("--recursive")); + self.run(Command::new("git").arg("submodule").arg("foreach") + .arg("--recursive") + .arg("git").arg("clean").arg("-fdx")); + self.run(Command::new("git").arg("submodule").arg("foreach") + .arg("--recursive") + .arg("git").arg("checkout").arg(".")); + } + + /// Clear out `dir` if our build has been flagged as dirty, and also set + /// ourselves as dirty if `file` changes when `f` is executed. + fn clear_if_dirty(&self, dir: &Path, input: &Path) { + let stamp = dir.join(".stamp"); + if mtime(&stamp) < mtime(input) { + self.verbose(&format!("Dirty - {}", dir.display())); + let _ = fs::remove_dir_all(dir); + } + t!(fs::create_dir_all(dir)); + t!(File::create(stamp)); + } + + /// Prepares an invocation of `cargo` to be run. + /// + /// This will create a `Command` that represents a pending execution of + /// Cargo for the specified stage, whether or not the standard library is + /// being built, and using the specified compiler targeting `target`. + // FIXME: aren't stage/compiler duplicated? + fn cargo(&self, stage: u32, compiler: &Compiler, is_std: bool, + target: &str, cmd: &str) -> Command { + let mut cargo = Command::new(&self.cargo); + let host = compiler.host; + let out_dir = self.stage_out(stage, host, is_std); + cargo.env("CARGO_TARGET_DIR", out_dir) + .arg(cmd) + .arg("--target").arg(target) + .arg("-j").arg(self.jobs().to_string()); + + // Customize the compiler we're running. Specify the compiler to cargo + // as our shim and then pass it some various options used to configure + // how the actual compiler itself is called. + cargo.env("RUSTC", self.out.join("bootstrap/debug/rustc")) + .env("RUSTC_REAL", self.compiler_path(compiler)) + .env("RUSTC_STAGE", self.stage_arg(stage, compiler).to_string()) + .env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string()) + .env("RUSTC_CODEGEN_UNITS", + self.config.rust_codegen_units.to_string()) + .env("RUSTC_DEBUG_ASSERTIONS", + self.config.rust_debug_assertions.to_string()) + .env("RUSTC_SNAPSHOT", &self.rustc) + .env("RUSTC_SYSROOT", self.sysroot(stage, host)) + .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir()) + .env("RUSTC_FLAGS", self.rustc_flags(target).join(" ")) + .env("RUSTC_RPATH", self.config.rust_rpath.to_string()) + .env("RUSTDOC", self.tool(compiler, "rustdoc")); + + // Specify some variuos options for build scripts used throughout the + // build. + // + // FIXME: the guard against msvc shouldn't need to be here + if !target.contains("msvc") { + cargo.env(format!("CC_{}", target), self.cc(target)) + .env(format!("AR_{}", target), self.ar(target)) + .env(format!("CFLAGS_{}", target), self.cflags(target)); + } + + // Environment variables *required* needed throughout the build + // + // FIXME: should update code to not require this env vars + cargo.env("CFG_COMPILER_HOST_TRIPLE", target); + + if self.config.verbose || self.flags.verbose { + cargo.arg("-v"); + } + if self.config.rust_optimize { + cargo.arg("--release"); + } + self.add_rustc_lib_path(compiler, &mut cargo); + return cargo + } + + /// Get a path to the compiler specified. + fn compiler_path(&self, compiler: &Compiler) -> PathBuf { + if compiler.is_snapshot(self) { + self.rustc.clone() + } else { + self.sysroot(compiler.stage, compiler.host).join("bin") + .join(exe("rustc", compiler.host)) + } + } + + /// Get the specified tool next to the specified compiler + fn tool(&self, compiler: &Compiler, tool: &str) -> PathBuf { + if compiler.is_snapshot(self) { + assert!(tool == "rustdoc", "no tools other than rustdoc in stage0"); + let mut rustdoc = self.rustc.clone(); + rustdoc.pop(); + rustdoc.push(exe("rustdoc", &self.config.build)); + return rustdoc + } + let (stage, host) = (compiler.stage, compiler.host); + self.cargo_out(stage - 1, host, false, host).join(exe(tool, host)) + } + + /// Get a `Command` which is ready to run `tool` in `stage` built for + /// `host`. + #[allow(dead_code)] // this will be used soon + fn tool_cmd(&self, compiler: &Compiler, tool: &str) -> Command { + let mut cmd = Command::new(self.tool(&compiler, tool)); + let host = compiler.host; + let stage = compiler.stage; + let paths = vec![ + self.cargo_out(stage - 1, host, true, host).join("deps"), + self.cargo_out(stage - 1, host, false, host).join("deps"), + ]; + add_lib_path(paths, &mut cmd); + return cmd + } + + fn stage_arg(&self, stage: u32, compiler: &Compiler) -> u32 { + if stage == 0 && compiler.host != self.config.build {1} else {stage} + } + + /// Get the space-separated set of activated features for the standard + /// library. + fn std_features(&self) -> String { + let mut features = String::new(); + if self.config.debug_jemalloc { + features.push_str(" debug-jemalloc"); + } + if self.config.use_jemalloc { + features.push_str(" jemalloc"); + } + return features + } + + /// Get the space-separated set of activated features for the compiler. + fn rustc_features(&self, stage: u32) -> String { + let mut features = String::new(); + if self.config.use_jemalloc { + features.push_str(" jemalloc"); + } + if stage > 0 { + features.push_str(" rustdoc"); + features.push_str(" rustbook"); + } + return features + } + + /// Component directory that Cargo will produce output into (e.g. + /// release/debug) + fn cargo_dir(&self) -> &'static str { + if self.config.rust_optimize {"release"} else {"debug"} + } + + fn sysroot(&self, stage: u32, host: &str) -> PathBuf { + if stage == 0 { + self.stage_out(stage, host, false) + } else { + self.out.join(host).join(format!("stage{}", stage)) + } + } + + fn sysroot_libdir(&self, stage: u32, host: &str, target: &str) -> PathBuf { + self.sysroot(stage, host).join("lib").join("rustlib") + .join(target).join("lib") + } + + /// Returns the root directory for all output generated in a particular + /// stage when running with a particular host compiler. + /// + /// The `is_std` flag indicates whether the root directory is for the + /// bootstrap of the standard library or for the compiler. + fn stage_out(&self, stage: u32, host: &str, is_std: bool) -> PathBuf { + self.out.join(host) + .join(format!("stage{}{}", stage, if is_std {"-std"} else {"-rustc"})) + } + + /// Returns the root output directory for all Cargo output in a given stage, + /// running a particular comipler, wehther or not we're building the + /// standard library, and targeting the specified architecture. + fn cargo_out(&self, stage: u32, host: &str, is_std: bool, + target: &str) -> PathBuf { + self.stage_out(stage, host, is_std).join(target).join(self.cargo_dir()) + } + + /// Root output directory for LLVM compiled for `target` + fn llvm_out(&self, target: &str) -> PathBuf { + self.out.join(target).join("llvm") + } + + /// Root output directory for compiler-rt compiled for `target` + fn compiler_rt_out(&self, target: &str) -> PathBuf { + self.out.join(target).join("compiler-rt") + } + + fn add_rustc_lib_path(&self, compiler: &Compiler, cmd: &mut Command) { + // Windows doesn't need dylib path munging because the dlls for the + // compiler live next to the compiler and the system will find them + // automatically. + if cfg!(windows) { return } + + add_lib_path(vec![self.rustc_libdir(compiler)], cmd); + } + + fn rustc_libdir(&self, compiler: &Compiler) -> PathBuf { + if compiler.is_snapshot(self) { + self.rustc_snapshot_libdir() + } else { + self.sysroot(compiler.stage, compiler.host) + .join(libdir(compiler.host)) + } + } + + fn rustc_snapshot_libdir(&self) -> PathBuf { + self.rustc.parent().unwrap().parent().unwrap() + .join(libdir(&self.config.build)) + } + + fn run(&self, cmd: &mut Command) { + self.verbose(&format!("running: {:?}", cmd)); + run_silent(cmd) + } + + fn verbose(&self, msg: &str) { + if self.flags.verbose || self.config.verbose { + println!("{}", msg); + } + } + + fn jobs(&self) -> u32 { + self.flags.jobs.unwrap_or(num_cpus::get() as u32) + } + + fn cc(&self, target: &str) -> &Path { + self.cc[target].0.path() + } + + fn cflags(&self, target: &str) -> String { + self.cc[target].0.args().iter() + .map(|s| s.to_string_lossy()) + .collect::>() + .join(" ") + } + + fn ar(&self, target: &str) -> &Path { + &self.cc[target].1 + } + + fn cxx(&self, target: &str) -> &Path { + self.cxx[target].path() + } + + fn rustc_flags(&self, target: &str) -> Vec { + let mut base = match target { + "arm-unknown-linux-gnueabihf" => { + vec!["-Ctarget-feature=+v6,+vfp2".to_string()] + } + "mips-unknown-linux-gnu" => { + vec!["-Ctarget-cpu=mips32r2".to_string(), + "-Ctarget-feature=+mips32r2".to_string(), + "-Csoft-float".to_string()] + } + "mipsel-unknown-linux-gnu" => { + vec!["-Ctarget-cpu=mips32".to_string(), + "-Ctarget-feature=+mips32".to_string()] + } + _ => Vec::new(), + }; + if target != self.config.build && !target.contains("msvc") { + base.push(format!("-Clinker={}", self.cc(target).display())); + } + return base + } +} + +impl<'a> Compiler<'a> { + fn new(stage: u32, host: &'a str) -> Compiler<'a> { + Compiler { stage: stage, host: host } + } + + fn is_snapshot(&self, build: &Build) -> bool { + self.stage == 0 && self.host == build.config.build + } +} diff --git a/src/bootstrap/build/native.rs b/src/bootstrap/build/native.rs new file mode 100644 index 0000000000000..6ad5f40412394 --- /dev/null +++ b/src/bootstrap/build/native.rs @@ -0,0 +1,157 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::path::Path; +use std::process::Command; +use std::fs; + +use build_helper::output; +use cmake; + +use build::Build; +use build::util::{exe, staticlib}; + +pub fn llvm(build: &Build, target: &str) { + // If we're using a custom LLVM bail out here, but we can only use a + // custom LLVM for the build triple. + if let Some(config) = build.config.target_config.get(target) { + if let Some(ref s) = config.llvm_config { + return check_llvm_version(build, s); + } + } + + // If the cleaning trigger is newer than our built artifacts (or if the + // artifacts are missing) then we keep going, otherwise we bail out. + let dst = build.llvm_out(target); + let stamp = build.src.join("src/rustllvm/llvm-auto-clean-trigger"); + let llvm_config = dst.join("bin").join(exe("llvm-config", target)); + build.clear_if_dirty(&dst, &stamp); + if fs::metadata(llvm_config).is_ok() { + return + } + + let _ = fs::remove_dir_all(&dst.join("build")); + t!(fs::create_dir_all(&dst.join("build"))); + let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"}; + + // http://llvm.org/docs/CMake.html + let mut cfg = cmake::Config::new(build.src.join("src/llvm")); + cfg.target(target) + .host(&build.config.build) + .out_dir(&dst) + .profile(if build.config.llvm_optimize {"Release"} else {"Debug"}) + .define("LLVM_ENABLE_ASSERTIONS", assertions) + .define("LLVM_TARGETS_TO_BUILD", "X86;ARM;AArch64;Mips;PowerPC") + .define("LLVM_INCLUDE_EXAMPLES", "OFF") + .define("LLVM_INCLUDE_TESTS", "OFF") + .define("LLVM_INCLUDE_DOCS", "OFF") + .define("LLVM_ENABLE_ZLIB", "OFF") + .define("WITH_POLLY", "OFF") + .define("LLVM_ENABLE_TERMINFO", "OFF") + .define("LLVM_ENABLE_LIBEDIT", "OFF") + .define("LLVM_PARALLEL_COMPILE_JOBS", build.jobs().to_string()); + + if target.starts_with("i686") { + cfg.define("LLVM_BUILD_32_BITS", "ON"); + } + + // http://llvm.org/docs/HowToCrossCompileLLVM.html + if target != build.config.build { + // FIXME: if the llvm root for the build triple is overridden then we + // should use llvm-tblgen from there, also should verify that it + // actually exists most of the time in normal installs of LLVM. + let host = build.llvm_out(&build.config.build).join("bin/llvm-tblgen"); + cfg.define("CMAKE_CROSSCOMPILING", "True") + .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap()) + .define("LLVM_TABLEGEN", &host) + .define("LLVM_DEFAULT_TARGET_TRIPLE", target); + } + + // MSVC handles compiler business itself + if !target.contains("msvc") { + if build.config.ccache { + cfg.define("CMAKE_C_COMPILER", "ccache") + .define("CMAKE_C_COMPILER_ARG1", build.cc(target)) + .define("CMAKE_CXX_COMPILER", "ccache") + .define("CMAKE_CXX_COMPILER_ARG1", build.cxx(target)); + } else { + cfg.define("CMAKE_C_COMPILER", build.cc(target)) + .define("CMAKE_CXX_COMPILER", build.cxx(target)); + } + cfg.build_arg("-j").build_arg(build.jobs().to_string()); + } + + // FIXME: we don't actually need to build all LLVM tools and all LLVM + // libraries here, e.g. we just want a few components and a few + // tools. Figure out how to filter them down and only build the right + // tools and libs on all platforms. + cfg.build(); +} + +fn check_llvm_version(build: &Build, llvm_config: &Path) { + if !build.config.llvm_version_check { + return + } + + let mut cmd = Command::new(llvm_config); + let version = output(cmd.arg("--version")); + if version.starts_with("3.5") || version.starts_with("3.6") || + version.starts_with("3.7") { + return + } + panic!("\n\nbad LLVM version: {}, need >=3.5\n\n", version) +} + +pub fn compiler_rt(build: &Build, target: &str) { + let dst = build.compiler_rt_out(target); + let arch = target.split('-').next().unwrap(); + let mode = if build.config.rust_optimize {"Release"} else {"Debug"}; + let (dir, build_target, libname) = if target.contains("linux") { + let os = if target.contains("android") {"-android"} else {""}; + let target = format!("clang_rt.builtins-{}{}", arch, os); + ("linux".to_string(), target.clone(), target) + } else if target.contains("darwin") { + let target = format!("clang_rt.builtins_{}_osx", arch); + ("builtins".to_string(), target.clone(), target) + } else if target.contains("windows-gnu") { + let target = format!("clang_rt.builtins-{}", arch); + ("windows".to_string(), target.clone(), target) + } else if target.contains("windows-msvc") { + (format!("windows/{}", mode), + "lib/builtins/builtins".to_string(), + format!("clang_rt.builtins-{}", arch.replace("i686", "i386"))) + } else { + panic!("can't get os from target: {}", target) + }; + let output = dst.join("build/lib").join(dir) + .join(staticlib(&libname, target)); + build.compiler_rt_built.borrow_mut().insert(target.to_string(), + output.clone()); + if fs::metadata(&output).is_ok() { + return + } + let _ = fs::remove_dir_all(&dst); + t!(fs::create_dir_all(&dst)); + let build_llvm_config = build.llvm_out(&build.config.build) + .join("bin") + .join(exe("llvm-config", &build.config.build)); + let mut cfg = cmake::Config::new(build.src.join("src/compiler-rt")); + cfg.target(target) + .host(&build.config.build) + .out_dir(&dst) + .profile(mode) + .define("LLVM_CONFIG_PATH", build_llvm_config) + .define("COMPILER_RT_DEFAULT_TARGET_TRIPLE", target) + .define("COMPILER_RT_BUILD_SANITIZERS", "OFF") + .define("COMPILER_RT_BUILD_EMUTLS", "OFF") + .define("CMAKE_C_COMPILER", build.cc(target)) + .build_target(&build_target); + cfg.build(); +} diff --git a/src/bootstrap/build/sanity.rs b/src/bootstrap/build/sanity.rs new file mode 100644 index 0000000000000..40f4c7076092d --- /dev/null +++ b/src/bootstrap/build/sanity.rs @@ -0,0 +1,122 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::HashSet; +use std::env; +use std::ffi::{OsStr, OsString}; +use std::fs; +use std::process::Command; + +use build_helper::output; + +use build::Build; + +pub fn check(build: &mut Build) { + let mut checked = HashSet::new(); + let path = env::var_os("PATH").unwrap_or(OsString::new()); + let mut need_cmd = |cmd: &OsStr| { + if !checked.insert(cmd.to_owned()) { + return + } + for path in env::split_paths(&path).map(|p| p.join(cmd)) { + if fs::metadata(&path).is_ok() || + fs::metadata(path.with_extension("exe")).is_ok() { + return + } + } + panic!("\n\ncouldn't find required command: {:?}\n\n", cmd); + }; + + // If we've got a git directory we're gona need git to update + // submodules and learn about various other aspects. + if fs::metadata(build.src.join(".git")).is_ok() { + need_cmd("git".as_ref()); + } + + // We need cmake, but only if we're actually building LLVM + for host in build.config.host.iter() { + if let Some(config) = build.config.target_config.get(host) { + if config.llvm_config.is_some() { + continue + } + } + need_cmd("cmake".as_ref()); + break + } + + need_cmd("python".as_ref()); + + // We're gonna build some custom C code here and there, host triples + // also build some C++ shims for LLVM so we need a C++ compiler. + for target in build.config.target.iter() { + need_cmd(build.cc(target).as_ref()); + need_cmd(build.ar(target).as_ref()); + } + for host in build.config.host.iter() { + need_cmd(build.cxx(host).as_ref()); + } + + for target in build.config.target.iter() { + // Either can't build or don't want to run jemalloc on these targets + if target.contains("rumprun") || + target.contains("bitrig") || + target.contains("openbsd") || + target.contains("msvc") { + build.config.use_jemalloc = false; + } + + // Can't compile for iOS unless we're on OSX + if target.contains("apple-ios") && + !build.config.build.contains("apple-darwin") { + panic!("the iOS target is only supported on OSX"); + } + + // Make sure musl-root is valid if specified + if target.contains("musl") { + match build.config.musl_root { + Some(ref root) => { + if fs::metadata(root.join("lib/libc.a")).is_err() { + panic!("couldn't find libc.a in musl dir: {}", + root.join("lib").display()); + } + if fs::metadata(root.join("lib/libunwind.a")).is_err() { + panic!("couldn't find libunwind.a in musl dir: {}", + root.join("lib").display()); + } + } + None => { + panic!("when targeting MUSL the build.musl-root option \ + must be specified in config.toml") + } + } + } + + if target.contains("msvc") { + // There are three builds of cmake on windows: MSVC, MinGW, and + // Cygwin. The Cygwin build does not have generators for Visual + // Studio, so detect that here and error. + let out = output(Command::new("cmake").arg("--help")); + if !out.contains("Visual Studio") { + panic!(" +cmake does not support Visual Studio generators. + +This is likely due to it being an msys/cygwin build of cmake, +rather than the required windows version, built using MinGW +or Visual Studio. + +If you are building under msys2 try installing the mingw-w64-x86_64-cmake +package instead of cmake: + +$ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake +"); + } + } + } +} diff --git a/src/bootstrap/build/step.rs b/src/bootstrap/build/step.rs new file mode 100644 index 0000000000000..2fbf1a6ad1db2 --- /dev/null +++ b/src/bootstrap/build/step.rs @@ -0,0 +1,177 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::HashSet; + +use build::{Build, Compiler}; + +#[derive(Hash, Eq, PartialEq, Clone, Debug)] +pub struct Step<'a> { + pub src: Source<'a>, + pub target: &'a str, +} + +macro_rules! targets { + ($m:ident) => { + $m! { + (rustc, Rustc { stage: u32 }), + (libstd, Libstd { stage: u32, compiler: Compiler<'a> }), + (librustc, Librustc { stage: u32, compiler: Compiler<'a> }), + (llvm, Llvm { _dummy: () }), + (compiler_rt, CompilerRt { _dummy: () }), + } + } +} + +macro_rules! item { ($a:item) => ($a) } + +macro_rules! define_source { + ($(($short:ident, $name:ident { $($args:tt)* }),)*) => { + item! { + #[derive(Hash, Eq, PartialEq, Clone, Debug)] + pub enum Source<'a> { + $($name { $($args)* }),* + } + } + } +} + +targets!(define_source); + +pub fn all(build: &Build) -> Vec { + let mut ret = Vec::new(); + let mut all = HashSet::new(); + for target in top_level(build) { + fill(build, &target, &mut ret, &mut all); + } + return ret; + + fn fill<'a>(build: &'a Build, + target: &Step<'a>, + ret: &mut Vec>, + set: &mut HashSet>) { + if set.insert(target.clone()) { + for dep in target.deps(build) { + fill(build, &dep, ret, set); + } + ret.push(target.clone()); + } + } +} + +fn top_level(build: &Build) -> Vec { + let mut targets = Vec::new(); + let stage = build.flags.stage.unwrap_or(2); + + let host = Step { + src: Source::Llvm { _dummy: () }, + target: build.flags.host.iter().next() + .unwrap_or(&build.config.build), + }; + let target = Step { + src: Source::Llvm { _dummy: () }, + target: build.flags.target.iter().next().map(|x| &x[..]) + .unwrap_or(host.target) + }; + + add_steps(build, stage, &host, &target, &mut targets); + + if targets.len() == 0 { + let t = Step { + src: Source::Llvm { _dummy: () }, + target: &build.config.build, + }; + for host in build.config.host.iter() { + if !build.flags.host.contains(host) { + continue + } + let host = t.target(host); + targets.push(host.librustc(stage, host.compiler(stage))); + for target in build.config.target.iter() { + if !build.flags.target.contains(target) { + continue + } + targets.push(host.target(target) + .libstd(stage, host.compiler(stage))); + } + } + } + + return targets + +} + +fn add_steps<'a>(build: &'a Build, + stage: u32, + host: &Step<'a>, + target: &Step<'a>, + targets: &mut Vec>) { + for step in build.flags.step.iter() { + let compiler = host.compiler(stage); + match &step[..] { + "libstd" => targets.push(target.libstd(stage, compiler)), + "librustc" => targets.push(target.libstd(stage, compiler)), + "rustc" => targets.push(host.rustc(stage)), + "llvm" => targets.push(target.llvm(())), + "compiler-rt" => targets.push(target.compiler_rt(())), + _ => panic!("unknown build target: `{}`", step), + } + } +} + +macro_rules! constructors { + ($(($short:ident, $name:ident { $($arg:ident: $t:ty),* }),)*) => {$( + fn $short(&self, $($arg: $t),*) -> Step<'a> { + Step { + src: Source::$name { $($arg: $arg),* }, + target: self.target, + } + } + )*} +} + +impl<'a> Step<'a> { + fn compiler(&self, stage: u32) -> Compiler<'a> { + Compiler::new(stage, self.target) + } + + fn target(&self, target: &'a str) -> Step<'a> { + Step { target: target, src: self.src.clone() } + } + + targets!(constructors); + + pub fn deps(&self, build: &'a Build) -> Vec> { + match self.src { + Source::Rustc { stage: 0 } => { + if self.target == build.config.build { + Vec::new() + } else { + let compiler = Compiler::new(0, &build.config.build); + vec![self.librustc(0, compiler)] + } + } + Source::Rustc { stage } => { + vec![self.librustc(stage - 1, self.compiler(stage - 1))] + } + Source::Librustc { stage, compiler } => { + vec![self.libstd(stage, compiler), self.llvm(())] + } + Source::Libstd { stage: _, compiler } => { + vec![self.compiler_rt(()), + self.rustc(compiler.stage).target(compiler.host)] + } + Source::CompilerRt { _dummy } => { + vec![self.llvm(()).target(&build.config.build)] + } + Source::Llvm { _dummy } => Vec::new(), + } + } +} diff --git a/src/bootstrap/build/util.rs b/src/bootstrap/build/util.rs new file mode 100644 index 0000000000000..6c700671f1111 --- /dev/null +++ b/src/bootstrap/build/util.rs @@ -0,0 +1,97 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::env; +use std::path::{Path, PathBuf}; +use std::fs; +use std::process::Command; + +use bootstrap::{dylib_path, dylib_path_var}; +use filetime::FileTime; + +pub fn staticlib(name: &str, target: &str) -> String { + if target.contains("windows-msvc") { + format!("{}.lib", name) + } else { + format!("lib{}.a", name) + } +} + +pub fn mtime(path: &Path) -> FileTime { + fs::metadata(path).map(|f| { + FileTime::from_last_modification_time(&f) + }).unwrap_or(FileTime::zero()) +} + +#[allow(dead_code)] // this will be used soon +pub fn cp_r(src: &Path, dst: &Path) { + for f in t!(fs::read_dir(src)) { + let f = t!(f); + let path = f.path(); + let name = path.file_name().unwrap(); + let dst = dst.join(name); + if t!(f.file_type()).is_dir() { + let _ = fs::remove_dir_all(&dst); + t!(fs::create_dir(&dst)); + cp_r(&path, &dst); + } else { + let _ = fs::remove_file(&dst); + t!(fs::hard_link(&path, dst)); + } + } +} + +/// Given an executable called `name`, return the filename for the +/// executable for a particular target. +pub fn exe(name: &str, target: &str) -> String { + if target.contains("windows") { + format!("{}.exe", name) + } else { + name.to_string() + } +} + +pub fn is_dylib(name: &str) -> bool { + name.ends_with(".dylib") || name.ends_with(".so") || name.ends_with(".dll") +} + +pub fn libdir(target: &str) -> &'static str { + if target.contains("windows") {"bin"} else {"lib"} +} + +pub fn add_lib_path(path: Vec, cmd: &mut Command) { + let mut list = dylib_path(); + for path in path { + list.insert(0, path); + } + cmd.env(dylib_path_var(), t!(env::join_paths(list))); +} + +#[allow(dead_code)] // this will be used soon +pub fn up_to_date(src: &Path, dst: &Path) -> bool { + let threshold = mtime(dst); + let meta = t!(fs::metadata(src)); + if meta.is_dir() { + dir_up_to_date(src, &threshold) + } else { + FileTime::from_last_modification_time(&meta) <= threshold + } +} + +fn dir_up_to_date(src: &Path, threshold: &FileTime) -> bool { + t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| { + let meta = t!(e.metadata()); + if meta.is_dir() { + dir_up_to_date(&e.path(), threshold) + } else { + FileTime::from_last_modification_time(&meta) < *threshold + } + }) +} diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs new file mode 100644 index 0000000000000..3158a3ab05860 --- /dev/null +++ b/src/bootstrap/lib.rs @@ -0,0 +1,28 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::env; +use std::ffi::OsString; +use std::path::PathBuf; + +pub fn dylib_path_var() -> &'static str { + if cfg!(target_os = "windows") { + "PATH" + } else if cfg!(target_os = "macos") { + "DYLD_LIBRARY_PATH" + } else { + "LD_LIBRARY_PATH" + } +} + +pub fn dylib_path() -> Vec { + env::split_paths(&env::var_os(dylib_path_var()).unwrap_or(OsString::new())) + .collect() +} diff --git a/src/bootstrap/main.rs b/src/bootstrap/main.rs new file mode 100644 index 0000000000000..32432132c1730 --- /dev/null +++ b/src/bootstrap/main.rs @@ -0,0 +1,38 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![deny(warnings)] + +extern crate bootstrap; +extern crate build_helper; +extern crate cmake; +extern crate filetime; +extern crate gcc; +extern crate getopts; +extern crate libc; +extern crate num_cpus; +extern crate rustc_serialize; +extern crate toml; + +use std::env; + +use build::{Flags, Config, Build}; + +mod build; + +fn main() { + let args = env::args().skip(1).collect::>(); + let flags = Flags::parse(&args); + let mut config = Config::parse(&flags.build, flags.config.clone()); + if std::fs::metadata("config.mk").is_ok() { + config.update_with_config_mk(); + } + Build::new(flags, config).build(); +} diff --git a/src/bootstrap/rustc.rs b/src/bootstrap/rustc.rs new file mode 100644 index 0000000000000..0c30360ba79f0 --- /dev/null +++ b/src/bootstrap/rustc.rs @@ -0,0 +1,91 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate bootstrap; + +use std::env; +use std::ffi::OsString; +use std::path::PathBuf; +use std::process::Command; + +fn main() { + let args = env::args_os().skip(1).collect::>(); + // Detect whether or not we're a build script depending on whether --target + // is passed (a bit janky...) + let is_build_script = args.iter() + .position(|i| i.to_str() == Some("--target")) + .is_none(); + + // Build scripts always use the snapshot compiler which is guaranteed to be + // able to produce an executable, whereas intermediate compilers may not + // have the standard library built yet and may not be able to produce an + // executable. Otherwise we just use the standard compiler we're + // bootstrapping with. + let rustc = if is_build_script { + env::var_os("RUSTC_SNAPSHOT").unwrap() + } else { + env::var_os("RUSTC_REAL").unwrap() + }; + + let mut cmd = Command::new(rustc); + cmd.args(&args) + .arg("--cfg").arg(format!("stage{}", env::var("RUSTC_STAGE").unwrap())); + + if is_build_script { + // Build scripts are always built with the snapshot compiler, so we need + // to be sure to set up the right path information for the OS dynamic + // linker to find the libraries in question. + if let Some(p) = env::var_os("RUSTC_SNAPSHOT_LIBDIR") { + let mut path = bootstrap::dylib_path(); + path.insert(0, PathBuf::from(p)); + cmd.env(bootstrap::dylib_path_var(), env::join_paths(path).unwrap()); + } + } else { + cmd.arg("--sysroot").arg(env::var_os("RUSTC_SYSROOT").unwrap()); + + // When we build Rust dylibs they're all intended for intermediate + // usage, so make sure we pass the -Cprefer-dynamic flag instead of + // linking all deps statically into the dylib. + cmd.arg("-Cprefer-dynamic"); + + if let Some(s) = env::var_os("MUSL_ROOT") { + let mut root = OsString::from("native="); + root.push(&s); + root.push("/lib"); + cmd.arg("-L").arg(&root); + } + } + + // Set various options from config.toml to configure how we're building + // code. + if env::var("RUSTC_DEBUGINFO") == Ok("true".to_string()) { + cmd.arg("-g"); + } + if env::var("RUSTC_RPATH") == Ok("true".to_string()) { + cmd.arg("-Crpath"); + } + let debug_assertions = match env::var("RUSTC_DEBUG_ASSERTIONS") { + Ok(s) => if s == "true" {"y"} else {"n"}, + Err(..) => "n", + }; + cmd.arg("-C").arg(format!("debug-assertions={}", debug_assertions)); + if let Ok(s) = env::var("RUSTC_CODEGEN_UNITS") { + cmd.arg("-C").arg(format!("codegen-units={}", s)); + } + if let Ok(s) = env::var("RUSTC_FLAGS") { + cmd.args(&s.split(" ").filter(|s| !s.is_empty()).collect::>()); + } + + // Actually run the compiler! + std::process::exit(match cmd.status() { + Ok(s) => s.code().unwrap_or(1), + Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e), + }) +} diff --git a/src/build_helper/Cargo.toml b/src/build_helper/Cargo.toml new file mode 100644 index 0000000000000..01d704f816bbc --- /dev/null +++ b/src/build_helper/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "build_helper" +version = "0.1.0" +authors = ["The Rust Project Developers"] + +[lib] +name = "build_helper" +path = "lib.rs" diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs new file mode 100644 index 0000000000000..092a1cabc746f --- /dev/null +++ b/src/build_helper/lib.rs @@ -0,0 +1,68 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![deny(warnings)] + +use std::process::{Command, Stdio}; +use std::path::{Path, PathBuf}; + +pub fn run(cmd: &mut Command) { + println!("running: {:?}", cmd); + run_silent(cmd); +} + +pub fn run_silent(cmd: &mut Command) { + let status = match cmd.status() { + Ok(status) => status, + Err(e) => fail(&format!("failed to execute command: {}", e)), + }; + if !status.success() { + fail(&format!("command did not execute successfully: {:?}\n\ + expected success, got: {}", cmd, status)); + } +} + +pub fn gnu_target(target: &str) -> String { + match target { + "i686-pc-windows-msvc" => "i686-pc-win32".to_string(), + "x86_64-pc-windows-msvc" => "x86_64-pc-win32".to_string(), + "i686-pc-windows-gnu" => "i686-w64-mingw32".to_string(), + "x86_64-pc-windows-gnu" => "x86_64-w64-mingw32".to_string(), + s => s.to_string(), + } +} + +pub fn cc2ar(cc: &Path, target: &str) -> PathBuf { + if target.contains("musl") || target.contains("msvc") { + PathBuf::from("ar") + } else { + let file = cc.file_name().unwrap().to_str().unwrap(); + cc.parent().unwrap().join(file.replace("gcc", "ar") + .replace("cc", "ar") + .replace("clang", "ar")) + } +} + +pub fn output(cmd: &mut Command) -> String { + let output = match cmd.stderr(Stdio::inherit()).output() { + Ok(status) => status, + Err(e) => fail(&format!("failed to execute command: {}", e)), + }; + if !output.status.success() { + panic!("command did not execute successfully: {:?}\n\ + expected success, got: {}", cmd, output.status); + } + String::from_utf8(output.stdout).unwrap() +} + +fn fail(s: &str) -> ! { + println!("\n\n{}\n\n", s); + std::process::exit(1); +} diff --git a/src/etc/tidy.py b/src/etc/tidy.py index 942793adc31de..fd3f4bf0b13b1 100644 --- a/src/etc/tidy.py +++ b/src/etc/tidy.py @@ -147,7 +147,7 @@ def interesting_file(f): report_err("snapshot out of date (" + date + "): " + line) else: - if "SNAP" in line: + if "SNAP " in line: report_warn("unmatched SNAP line: " + line) if cr_flag in line: diff --git a/src/nightlies.txt b/src/nightlies.txt new file mode 100644 index 0000000000000..86186222d90bb --- /dev/null +++ b/src/nightlies.txt @@ -0,0 +1,2 @@ +rustc: 2015-12-19 +cargo: 2016-01-21 diff --git a/src/rustc/Cargo.lock b/src/rustc/Cargo.lock new file mode 100644 index 0000000000000..db1a87679c271 --- /dev/null +++ b/src/rustc/Cargo.lock @@ -0,0 +1,356 @@ +[root] +name = "rustc-main" +version = "0.0.0" +dependencies = [ + "rustbook 0.0.0", + "rustc_back 0.0.0", + "rustc_driver 0.0.0", + "rustdoc 0.0.0", +] + +[[package]] +name = "advapi32-sys" +version = "0.1.2" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.2 (registry+/~https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+/~https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "arena" +version = "0.0.0" + +[[package]] +name = "build_helper" +version = "0.1.0" + +[[package]] +name = "flate" +version = "0.0.0" +dependencies = [ + "build_helper 0.1.0", + "gcc 0.3.17 (registry+/~https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fmt_macros" +version = "0.0.0" + +[[package]] +name = "gcc" +version = "0.3.17" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +dependencies = [ + "advapi32-sys 0.1.2 (registry+/~https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.2 (registry+/~https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "getopts" +version = "0.0.0" + +[[package]] +name = "graphviz" +version = "0.0.0" + +[[package]] +name = "log" +version = "0.0.0" + +[[package]] +name = "rbml" +version = "0.0.0" +dependencies = [ + "log 0.0.0", + "serialize 0.0.0", +] + +[[package]] +name = "rustbook" +version = "0.0.0" +dependencies = [ + "rustc_back 0.0.0", + "rustdoc 0.0.0", +] + +[[package]] +name = "rustc" +version = "0.0.0" +dependencies = [ + "arena 0.0.0", + "flate 0.0.0", + "fmt_macros 0.0.0", + "getopts 0.0.0", + "graphviz 0.0.0", + "log 0.0.0", + "rbml 0.0.0", + "rustc_back 0.0.0", + "rustc_data_structures 0.0.0", + "rustc_front 0.0.0", + "rustc_llvm 0.0.0", + "serialize 0.0.0", + "syntax 0.0.0", +] + +[[package]] +name = "rustc_back" +version = "0.0.0" +dependencies = [ + "log 0.0.0", + "rustc_front 0.0.0", + "rustc_llvm 0.0.0", + "serialize 0.0.0", + "syntax 0.0.0", +] + +[[package]] +name = "rustc_borrowck" +version = "0.0.0" +dependencies = [ + "graphviz 0.0.0", + "log 0.0.0", + "rustc 0.0.0", + "rustc_front 0.0.0", + "syntax 0.0.0", +] + +[[package]] +name = "rustc_data_structures" +version = "0.0.0" +dependencies = [ + "log 0.0.0", + "serialize 0.0.0", +] + +[[package]] +name = "rustc_driver" +version = "0.0.0" +dependencies = [ + "arena 0.0.0", + "flate 0.0.0", + "getopts 0.0.0", + "graphviz 0.0.0", + "log 0.0.0", + "rustc 0.0.0", + "rustc_back 0.0.0", + "rustc_borrowck 0.0.0", + "rustc_front 0.0.0", + "rustc_lint 0.0.0", + "rustc_llvm 0.0.0", + "rustc_metadata 0.0.0", + "rustc_mir 0.0.0", + "rustc_plugin 0.0.0", + "rustc_privacy 0.0.0", + "rustc_resolve 0.0.0", + "rustc_trans 0.0.0", + "rustc_typeck 0.0.0", + "serialize 0.0.0", + "syntax 0.0.0", + "syntax_ext 0.0.0", +] + +[[package]] +name = "rustc_front" +version = "0.0.0" +dependencies = [ + "log 0.0.0", + "serialize 0.0.0", + "syntax 0.0.0", +] + +[[package]] +name = "rustc_lint" +version = "0.0.0" +dependencies = [ + "log 0.0.0", + "rustc 0.0.0", + "rustc_back 0.0.0", + "rustc_front 0.0.0", + "syntax 0.0.0", +] + +[[package]] +name = "rustc_llvm" +version = "0.0.0" +dependencies = [ + "build_helper 0.1.0", + "gcc 0.3.17 (registry+/~https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc_metadata" +version = "0.0.0" +dependencies = [ + "flate 0.0.0", + "log 0.0.0", + "rbml 0.0.0", + "rustc 0.0.0", + "rustc_back 0.0.0", + "rustc_front 0.0.0", + "rustc_llvm 0.0.0", + "serialize 0.0.0", + "syntax 0.0.0", +] + +[[package]] +name = "rustc_mir" +version = "0.0.0" +dependencies = [ + "graphviz 0.0.0", + "log 0.0.0", + "rustc 0.0.0", + "rustc_back 0.0.0", + "rustc_data_structures 0.0.0", + "rustc_front 0.0.0", + "syntax 0.0.0", +] + +[[package]] +name = "rustc_platform_intrinsics" +version = "0.0.0" +dependencies = [ + "rustc 0.0.0", + "rustc_llvm 0.0.0", +] + +[[package]] +name = "rustc_plugin" +version = "0.0.0" +dependencies = [ + "log 0.0.0", + "rustc 0.0.0", + "rustc_front 0.0.0", + "rustc_metadata 0.0.0", + "syntax 0.0.0", +] + +[[package]] +name = "rustc_privacy" +version = "0.0.0" +dependencies = [ + "log 0.0.0", + "rustc 0.0.0", + "rustc_front 0.0.0", + "syntax 0.0.0", +] + +[[package]] +name = "rustc_resolve" +version = "0.0.0" +dependencies = [ + "arena 0.0.0", + "log 0.0.0", + "rustc 0.0.0", + "rustc_front 0.0.0", + "syntax 0.0.0", +] + +[[package]] +name = "rustc_trans" +version = "0.0.0" +dependencies = [ + "arena 0.0.0", + "flate 0.0.0", + "getopts 0.0.0", + "graphviz 0.0.0", + "log 0.0.0", + "rustc 0.0.0", + "rustc_back 0.0.0", + "rustc_data_structures 0.0.0", + "rustc_front 0.0.0", + "rustc_llvm 0.0.0", + "rustc_mir 0.0.0", + "rustc_platform_intrinsics 0.0.0", + "serialize 0.0.0", + "syntax 0.0.0", +] + +[[package]] +name = "rustc_typeck" +version = "0.0.0" +dependencies = [ + "arena 0.0.0", + "fmt_macros 0.0.0", + "log 0.0.0", + "rustc 0.0.0", + "rustc_back 0.0.0", + "rustc_front 0.0.0", + "rustc_platform_intrinsics 0.0.0", + "syntax 0.0.0", +] + +[[package]] +name = "rustdoc" +version = "0.0.0" +dependencies = [ + "arena 0.0.0", + "build_helper 0.1.0", + "gcc 0.3.17 (registry+/~https://github.com/rust-lang/crates.io-index)", + "getopts 0.0.0", + "log 0.0.0", + "rustc 0.0.0", + "rustc_back 0.0.0", + "rustc_driver 0.0.0", + "rustc_front 0.0.0", + "rustc_lint 0.0.0", + "rustc_metadata 0.0.0", + "rustc_resolve 0.0.0", + "rustc_trans 0.0.0", + "serialize 0.0.0", + "syntax 0.0.0", + "test 0.0.0", +] + +[[package]] +name = "serialize" +version = "0.0.0" +dependencies = [ + "log 0.0.0", +] + +[[package]] +name = "syntax" +version = "0.0.0" +dependencies = [ + "arena 0.0.0", + "fmt_macros 0.0.0", + "log 0.0.0", + "serialize 0.0.0", + "term 0.0.0", +] + +[[package]] +name = "syntax_ext" +version = "0.0.0" +dependencies = [ + "fmt_macros 0.0.0", + "syntax 0.0.0", +] + +[[package]] +name = "term" +version = "0.0.0" +dependencies = [ + "log 0.0.0", +] + +[[package]] +name = "test" +version = "0.0.0" +dependencies = [ + "getopts 0.0.0", + "serialize 0.0.0", + "term 0.0.0", +] + +[[package]] +name = "winapi" +version = "0.2.2" +source = "registry+/~https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+/~https://github.com/rust-lang/crates.io-index" + diff --git a/src/rustc/Cargo.toml b/src/rustc/Cargo.toml new file mode 100644 index 0000000000000..9fcefd9d3a4dd --- /dev/null +++ b/src/rustc/Cargo.toml @@ -0,0 +1,36 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc-main" +version = "0.0.0" + +[[bin]] +name = "rustc" +path = "rustc.rs" + +[[bin]] +name = "rustdoc" +path = "rustdoc.rs" + +[[bin]] +name = "rustbook" +path = "rustbook.rs" + +[profile.release] +opt-level = 2 + +# These options are controlled from our rustc wrapper script, so turn them off +# here and have them controlled elsewhere. +[profile.dev] +debug = false +debug-assertions = false + +# All optional dependencies so the features passed to this Cargo.toml select +# what should actually be built. +[dependencies] +rustbook = { path = "../rustbook", optional = true } +rustc_back = { path = "../librustc_back" } +rustc_driver = { path = "../librustc_driver" } +rustdoc = { path = "../librustdoc", optional = true } + +[features] +jemalloc = ["rustc_back/jemalloc"] diff --git a/src/rustc/libc_shim/Cargo.toml b/src/rustc/libc_shim/Cargo.toml new file mode 100644 index 0000000000000..a7860b50e08ff --- /dev/null +++ b/src/rustc/libc_shim/Cargo.toml @@ -0,0 +1,20 @@ +# This is a shim Cargo.toml over the "real Cargo.toml" found in the libc +# repository itself. The purpose for this is to add a build script which prints +# out `--cfg stdbuild` to mirror the makefiles' build system. +# +# Note that other than that this isn't actually needed, and we should probably +# remove this shim in favor of just working with cargo features directly with +# libc. That should make everything nicer! + +[package] +name = "libc" +version = "0.0.0" +authors = ["The Rust Project Developers"] +build = "build.rs" + +[lib] +name = "libc" +path = "../../liblibc/src/lib.rs" + +[dependencies] +core = { path = "../../libcore" } diff --git a/src/rustc/libc_shim/build.rs b/src/rustc/libc_shim/build.rs new file mode 100644 index 0000000000000..bc428d6908235 --- /dev/null +++ b/src/rustc/libc_shim/build.rs @@ -0,0 +1,15 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// See comments in Cargo.toml for why this exists + +fn main() { + println!("cargo:rustc-cfg=stdbuild"); +} diff --git a/src/rustc/rustbook.rs b/src/rustc/rustbook.rs new file mode 100644 index 0000000000000..6f78f78bc55a6 --- /dev/null +++ b/src/rustc/rustbook.rs @@ -0,0 +1,14 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate rustbook; + +fn main() { rustbook::main() } + diff --git a/src/rustc/rustc.rs b/src/rustc/rustc.rs new file mode 100644 index 0000000000000..bfd01146d2c46 --- /dev/null +++ b/src/rustc/rustc.rs @@ -0,0 +1,15 @@ +// Copyright 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 or the MIT license +// , 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/rustc/rustdoc.rs b/src/rustc/rustdoc.rs new file mode 100644 index 0000000000000..6fecd3a27a8a4 --- /dev/null +++ b/src/rustc/rustdoc.rs @@ -0,0 +1,15 @@ +// Copyright 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 or the MIT license +// , 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/rustc/std_shim/Cargo.lock b/src/rustc/std_shim/Cargo.lock new file mode 100644 index 0000000000000..d88e9c7e5aa94 --- /dev/null +++ b/src/rustc/std_shim/Cargo.lock @@ -0,0 +1,124 @@ +[root] +name = "std_shim" +version = "0.1.0" +dependencies = [ + "std 0.0.0", +] + +[[package]] +name = "advapi32-sys" +version = "0.1.2" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.2 (registry+/~https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+/~https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "alloc" +version = "0.0.0" +dependencies = [ + "alloc_system 0.0.0", + "core 0.0.0", + "libc 0.0.0", +] + +[[package]] +name = "alloc_jemalloc" +version = "0.0.0" +dependencies = [ + "build_helper 0.1.0", + "core 0.0.0", + "gcc 0.3.17 (registry+/~https://github.com/rust-lang/crates.io-index)", + "libc 0.0.0", +] + +[[package]] +name = "alloc_system" +version = "0.0.0" +dependencies = [ + "core 0.0.0", + "libc 0.0.0", +] + +[[package]] +name = "build_helper" +version = "0.1.0" + +[[package]] +name = "collections" +version = "0.0.0" +dependencies = [ + "alloc 0.0.0", + "core 0.0.0", + "rustc_unicode 0.0.0", +] + +[[package]] +name = "core" +version = "0.0.0" + +[[package]] +name = "gcc" +version = "0.3.17" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +dependencies = [ + "advapi32-sys 0.1.2 (registry+/~https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.2 (registry+/~https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libc" +version = "0.0.0" +dependencies = [ + "core 0.0.0", +] + +[[package]] +name = "rand" +version = "0.0.0" +dependencies = [ + "core 0.0.0", +] + +[[package]] +name = "rustc_bitflags" +version = "0.0.0" +dependencies = [ + "core 0.0.0", +] + +[[package]] +name = "rustc_unicode" +version = "0.0.0" +dependencies = [ + "core 0.0.0", +] + +[[package]] +name = "std" +version = "0.0.0" +dependencies = [ + "alloc 0.0.0", + "alloc_jemalloc 0.0.0", + "alloc_system 0.0.0", + "build_helper 0.1.0", + "collections 0.0.0", + "core 0.0.0", + "gcc 0.3.17 (registry+/~https://github.com/rust-lang/crates.io-index)", + "libc 0.0.0", + "rand 0.0.0", + "rustc_bitflags 0.0.0", + "rustc_unicode 0.0.0", +] + +[[package]] +name = "winapi" +version = "0.2.2" +source = "registry+/~https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+/~https://github.com/rust-lang/crates.io-index" + diff --git a/src/rustc/std_shim/Cargo.toml b/src/rustc/std_shim/Cargo.toml new file mode 100644 index 0000000000000..1ce3937157da0 --- /dev/null +++ b/src/rustc/std_shim/Cargo.toml @@ -0,0 +1,46 @@ +# This is a shim Cargo.toml which serves as a proxy for building the standard +# library. The reason for this is a little subtle, as one might reasonably +# expect that we just `cargo build` the standard library itself. +# +# One of the output artifacts for the standard library is a dynamic library, and +# on platforms like OSX the name of the output artifact is actually encoded into +# the library itself (similar to a soname on Linux). When the library is linked +# against, this encoded name is what's literally looked for at runtime when the +# dynamic loader is probing for libraries. +# +# Cargo, however, by default will not mangle the output filename of the +# top-level target. If we were to run `cargo build` on libstd itself, we would +# generate a file `libstd.so`. When installing, however, this file is called +# something like `libstd-abcdef0123.so`. On OSX at least this causes a failure +# at runtime because the encoded "soname" is `libstd.so`, not what the file is +# actually called. +# +# By using this shim library to build the standard library by proxy we sidestep +# this problem. The standard library is built with mangled hex already in its +# name so there's nothing extra we need to do. + +[package] +name = "std_shim" +version = "0.1.0" +authors = ["The Rust Project Developers"] + +[lib] +name = "std_shim" +path = "lib.rs" + +[profile.release] +opt-level = 2 + +# These options are controlled from our rustc wrapper script, so turn them off +# here and have them controlled elsewhere. +[profile.dev] +debug = false +debug-assertions = false + +[dependencies] +std = { path = "../../libstd" } + +# Reexport features from std +[features] +jemalloc = ["std/jemalloc"] +debug-jemalloc = ["std/debug-jemalloc"] diff --git a/src/rustc/std_shim/lib.rs b/src/rustc/std_shim/lib.rs new file mode 100644 index 0000000000000..3cf4cfab135fd --- /dev/null +++ b/src/rustc/std_shim/lib.rs @@ -0,0 +1,11 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// See comments in Cargo.toml for why this exists From 0a54e4dd8704b2850f083c62ca782886e5587d18 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 19 Nov 2015 16:55:21 -0800 Subject: [PATCH 02/10] bootstrap: Read configuration from config.mk During the transition period where we're still using ./configure and makefiles, read some extra configuration from `config.mk` if it's present. This means that the bootstrap build should be configured the same as the original ./configure invocation. Eventually this will all be removed in favor of only storing information in `config.toml` (e.g. the configure script will generate config.toml), but for now this should suffice. --- src/bootstrap/bootstrap.py | 16 +++++ src/bootstrap/build/compile.rs | 1 + src/bootstrap/build/config.rs | 106 +++++++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 435304645459d..744c30aa08f07 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -135,6 +135,12 @@ def get_toml(self, key): return self.get_string(line) return None + def get_mk(self, key): + for line in iter(self.config_mk.splitlines()): + if line.startswith(key): + return line[line.find(':=') + 2:].strip() + return None + def cargo(self): config = self.get_toml('cargo') if config: @@ -145,6 +151,9 @@ def rustc(self): config = self.get_toml('rustc') if config: return config + config = self.get_mk('CFG_LOCAL_RUST') + if config: + return config + '/bin/rustc' + self.exe_suffix() return os.path.join(self.bin_root(), "bin/rustc" + self.exe_suffix()) def get_string(self, line): @@ -187,6 +196,9 @@ def run(self, args, env): def build_triple(self): config = self.get_toml('build') + if config: + return config + config = self.get_mk('CFG_BUILD') if config: return config try: @@ -279,6 +291,10 @@ def build_triple(self): rb.config_toml = config.read() except: pass +try: + rb.config_mk = open('config.mk').read() +except: + pass # Fetch/build the bootstrap rb.build = rb.build_triple() diff --git a/src/bootstrap/build/compile.rs b/src/bootstrap/build/compile.rs index 05b444633b4cc..c22648b471098 100644 --- a/src/bootstrap/build/compile.rs +++ b/src/bootstrap/build/compile.rs @@ -118,6 +118,7 @@ pub fn rustc<'a>(build: &'a Build, stage: u32, target: &str, .env("CFG_RELEASE_CHANNEL", &build.config.channel) .env("CFG_VERSION", &build.version) .env("CFG_BOOTSTRAP_KEY", &build.bootstrap_key) + .env("CFG_PREFIX", build.config.prefix.clone().unwrap_or(String::new())) .env("RUSTC_BOOTSTRAP_KEY", &build.bootstrap_key) .env("CFG_LIBDIR_RELATIVE", "lib"); diff --git a/src/bootstrap/build/config.rs b/src/bootstrap/build/config.rs index 862ee15cb080c..1e67c4a9a3e8d 100644 --- a/src/bootstrap/build/config.rs +++ b/src/bootstrap/build/config.rs @@ -65,6 +65,7 @@ pub struct Config { // misc pub channel: String, pub musl_root: Option, + pub prefix: Option, } /// Per-target configuration stored in the global configuration structure. @@ -246,6 +247,111 @@ impl Config { return config } + + pub fn update_with_config_mk(&mut self) { + let mut config = String::new(); + File::open("config.mk").unwrap().read_to_string(&mut config).unwrap(); + for line in config.lines() { + let mut parts = line.splitn(2, ":=").map(|s| s.trim()); + let key = parts.next().unwrap(); + let value = match parts.next() { + Some(n) if n.starts_with('\"') => &n[1..n.len() - 1], + Some(n) => n, + None => continue + }; + + macro_rules! check { + ($(($name:expr, $val:expr),)*) => { + if value == "1" { + $( + if key == concat!("CFG_ENABLE_", $name) { + $val = true; + continue + } + if key == concat!("CFG_DISABLE_", $name) { + $val = false; + continue + } + )* + } + } + } + + check! { + ("CCACHE", self.ccache), + ("MANAGE_SUBMODULES", self.submodules), + ("COMPILER_DOCS", self.compiler_docs), + ("DOCS", self.docs), + ("LLVM_ASSERTIONS", self.llvm_assertions), + ("OPTIMIZE_LLVM", self.llvm_optimize), + ("LLVM_VERSION_CHECK", self.llvm_version_check), + ("LLVM_STATIC_STDCPP", self.llvm_static_stdcpp), + ("OPTIMIZE", self.rust_optimize), + ("DEBUG_ASSERTIONS", self.rust_debug_assertions), + ("DEBUGINFO", self.rust_debuginfo), + ("JEMALLOC", self.use_jemalloc), + ("DEBUG_JEMALLOC", self.debug_jemalloc), + ("RPATH", self.rust_rpath), + } + + match key { + "CFG_BUILD" => self.build = value.to_string(), + "CFG_HOST" => { + self.host = value.split(" ").map(|s| s.to_string()) + .collect(); + } + "CFG_TARGET" => { + self.target = value.split(" ").map(|s| s.to_string()) + .collect(); + } + "CFG_MUSL_ROOT" if value.len() > 0 => { + self.musl_root = Some(PathBuf::from(value)); + } + "CFG_DEFAULT_AR" if value.len() > 0 => { + self.rustc_default_ar = Some(value.to_string()); + } + "CFG_DEFAULT_LINKER" if value.len() > 0 => { + self.rustc_default_linker = Some(value.to_string()); + } + "CFG_RELEASE_CHANNEL" => { + self.channel = value.to_string(); + } + "CFG_PREFIX" => { + self.prefix = Some(value.to_string()); + } + "CFG_LLVM_ROOT" if value.len() > 0 => { + let target = self.target_config.entry(self.build.clone()) + .or_insert(Target::default()); + let root = PathBuf::from(value); + target.llvm_config = Some(root.join("bin/llvm-config")); + } + "CFG_JEMALLOC_ROOT" if value.len() > 0 => { + let target = self.target_config.entry(self.build.clone()) + .or_insert(Target::default()); + target.jemalloc = Some(PathBuf::from(value)); + } + "CFG_ARM_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => { + let target = "arm-linux-androideabi".to_string(); + let target = self.target_config.entry(target) + .or_insert(Target::default()); + target.ndk = Some(PathBuf::from(value)); + } + "CFG_I686_LINUX_ANDROID_NDK" if value.len() > 0 => { + let target = "i686-linux-androideabi".to_string(); + let target = self.target_config.entry(target) + .or_insert(Target::default()); + target.ndk = Some(PathBuf::from(value)); + } + "CFG_AARCH64_LINUX_ANDROID_NDK" if value.len() > 0 => { + let target = "aarch64-linux-androideabi".to_string(); + let target = self.target_config.entry(target) + .or_insert(Target::default()); + target.ndk = Some(PathBuf::from(value)); + } + _ => {} + } + } + } } fn set(field: &mut T, val: Option) { From 7cbd2457adcd2a47f6e716983bb618541ec25633 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 14 Jan 2016 16:19:41 -0800 Subject: [PATCH 03/10] configure: Remove default NDK path value This likely isn't always valid, and subverts auto-detection. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index dde17e76d8a86..631c5f49f0643 100755 --- a/configure +++ b/configure @@ -625,7 +625,7 @@ valopt llvm-root "" "set LLVM root" valopt python "" "set path to python" valopt jemalloc-root "" "set directory where libjemalloc_pic.a is located" valopt build "${DEFAULT_BUILD}" "GNUs ./configure syntax LLVM build triple" -valopt android-cross-path "/opt/ndk_standalone" "Android NDK standalone path (deprecated)" +valopt android-cross-path "" "Android NDK standalone path (deprecated)" valopt i686-linux-android-ndk "" "i686-linux-android NDK standalone path" valopt arm-linux-androideabi-ndk "" "arm-linux-androideabi NDK standalone path" valopt aarch64-linux-android-ndk "" "aarch64-linux-android NDK standalone path" From 2581b141473f8333728c8dc330a31dc2373dc0e6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 21 Jan 2016 15:19:23 -0800 Subject: [PATCH 04/10] bootstrap: Add a bunch of Cargo.toml files These describe the structure of all our crate dependencies. --- src/liballoc/Cargo.toml | 14 +++++++++ src/liballoc_jemalloc/Cargo.toml | 22 ++++++++++++++ src/liballoc_system/Cargo.toml | 13 ++++++++ src/libarena/Cargo.toml | 9 ++++++ src/libcollections/Cargo.toml | 14 +++++++++ src/libcore/Cargo.toml | 9 ++++++ src/libflate/Cargo.toml | 14 +++++++++ src/libfmt_macros/Cargo.toml | 9 ++++++ src/libgetopts/Cargo.toml | 9 ++++++ src/libgraphviz/Cargo.toml | 9 ++++++ src/liblog/Cargo.toml | 9 ++++++ src/librand/Cargo.toml | 12 ++++++++ src/librbml/Cargo.toml | 13 ++++++++ src/librustc/Cargo.toml | 24 +++++++++++++++ src/librustc_back/Cargo.toml | 19 ++++++++++++ src/librustc_bitflags/Cargo.toml | 12 ++++++++ src/librustc_borrowck/Cargo.toml | 16 ++++++++++ src/librustc_data_structures/Cargo.toml | 13 ++++++++ src/librustc_driver/Cargo.toml | 33 +++++++++++++++++++++ src/librustc_front/Cargo.toml | 14 +++++++++ src/librustc_lint/Cargo.toml | 16 ++++++++++ src/librustc_llvm/Cargo.toml | 17 +++++++++++ src/librustc_metadata/Cargo.toml | 20 +++++++++++++ src/librustc_mir/Cargo.toml | 18 +++++++++++ src/librustc_passes/Cargo.toml | 15 ++++++++++ src/librustc_platform_intrinsics/Cargo.toml | 13 ++++++++ src/librustc_plugin/Cargo.toml | 17 +++++++++++ src/librustc_privacy/Cargo.toml | 15 ++++++++++ src/librustc_resolve/Cargo.toml | 16 ++++++++++ src/librustc_trans/Cargo.toml | 25 ++++++++++++++++ src/librustc_typeck/Cargo.toml | 19 ++++++++++++ src/librustc_unicode/Cargo.toml | 12 ++++++++ src/librustdoc/Cargo.toml | 30 +++++++++++++++++++ src/libserialize/Cargo.toml | 12 ++++++++ src/libstd/Cargo.toml | 30 +++++++++++++++++++ src/libsyntax/Cargo.toml | 16 ++++++++++ src/libsyntax_ext/Cargo.toml | 13 ++++++++ src/libterm/Cargo.toml | 12 ++++++++ src/libtest/Cargo.toml | 14 +++++++++ src/rustbook/Cargo.toml | 13 ++++++++ src/rustc/Cargo.lock | 12 ++++++++ 41 files changed, 642 insertions(+) create mode 100644 src/liballoc/Cargo.toml create mode 100644 src/liballoc_jemalloc/Cargo.toml create mode 100644 src/liballoc_system/Cargo.toml create mode 100644 src/libarena/Cargo.toml create mode 100644 src/libcollections/Cargo.toml create mode 100644 src/libcore/Cargo.toml create mode 100644 src/libflate/Cargo.toml 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/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_front/Cargo.toml create mode 100644 src/librustc_lint/Cargo.toml create mode 100644 src/librustc_llvm/Cargo.toml create mode 100644 src/librustc_metadata/Cargo.toml create mode 100644 src/librustc_mir/Cargo.toml create mode 100644 src/librustc_passes/Cargo.toml create mode 100644 src/librustc_platform_intrinsics/Cargo.toml create mode 100644 src/librustc_plugin/Cargo.toml 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/libserialize/Cargo.toml create mode 100644 src/libstd/Cargo.toml create mode 100644 src/libsyntax/Cargo.toml create mode 100644 src/libsyntax_ext/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/src/liballoc/Cargo.toml b/src/liballoc/Cargo.toml new file mode 100644 index 0000000000000..5af8d9e8e27c1 --- /dev/null +++ b/src/liballoc/Cargo.toml @@ -0,0 +1,14 @@ +[package] +authors = ["The Rust Project Developers"] +name = "alloc" +version = "0.0.0" + +[lib] +name = "alloc" +path = "lib.rs" +test = false + +[dependencies] +core = { path = "../libcore" } +libc = { path = "../rustc/libc_shim" } +alloc_system = { path = "../liballoc_system" } diff --git a/src/liballoc_jemalloc/Cargo.toml b/src/liballoc_jemalloc/Cargo.toml new file mode 100644 index 0000000000000..768a0c2c0a54d --- /dev/null +++ b/src/liballoc_jemalloc/Cargo.toml @@ -0,0 +1,22 @@ +[package] +authors = ["The Rust Project Developers"] +name = "alloc_jemalloc" +version = "0.0.0" +build = "build.rs" +links = "jemalloc" + +[lib] +name = "alloc_jemalloc" +path = "lib.rs" +test = false + +[dependencies] +core = { path = "../libcore" } +libc = { path = "../rustc/libc_shim" } + +[build-dependencies] +build_helper = { path = "../build_helper" } +gcc = "0.3.17" + +[features] +debug = [] diff --git a/src/liballoc_system/Cargo.toml b/src/liballoc_system/Cargo.toml new file mode 100644 index 0000000000000..88e8e2d7adbc3 --- /dev/null +++ b/src/liballoc_system/Cargo.toml @@ -0,0 +1,13 @@ +[package] +authors = ["The Rust Project Developers"] +name = "alloc_system" +version = "0.0.0" + +[lib] +name = "alloc_system" +path = "lib.rs" +test = false + +[dependencies] +core = { path = "../libcore" } +libc = { path = "../rustc/libc_shim" } diff --git a/src/libarena/Cargo.toml b/src/libarena/Cargo.toml new file mode 100644 index 0000000000000..b53c0a2f48bf7 --- /dev/null +++ b/src/libarena/Cargo.toml @@ -0,0 +1,9 @@ +[package] +authors = ["The Rust Project Developers"] +name = "arena" +version = "0.0.0" + +[lib] +name = "arena" +path = "lib.rs" +crate-type = ["dylib"] diff --git a/src/libcollections/Cargo.toml b/src/libcollections/Cargo.toml new file mode 100644 index 0000000000000..18e322ff74f6c --- /dev/null +++ b/src/libcollections/Cargo.toml @@ -0,0 +1,14 @@ +[package] +authors = ["The Rust Project Developers"] +name = "collections" +version = "0.0.0" + +[lib] +name = "collections" +path = "lib.rs" +test = false + +[dependencies] +alloc = { path = "../liballoc" } +core = { path = "../libcore" } +rustc_unicode = { path = "../librustc_unicode" } diff --git a/src/libcore/Cargo.toml b/src/libcore/Cargo.toml new file mode 100644 index 0000000000000..24455a1d841bd --- /dev/null +++ b/src/libcore/Cargo.toml @@ -0,0 +1,9 @@ +[package] +authors = ["The Rust Project Developers"] +name = "core" +version = "0.0.0" + +[lib] +name = "core" +path = "lib.rs" +test = false diff --git a/src/libflate/Cargo.toml b/src/libflate/Cargo.toml new file mode 100644 index 0000000000000..52aa6bb86ef90 --- /dev/null +++ b/src/libflate/Cargo.toml @@ -0,0 +1,14 @@ +[package] +authors = ["The Rust Project Developers"] +name = "flate" +version = "0.0.0" +build = "build.rs" + +[lib] +name = "flate" +path = "lib.rs" +crate-type = ["dylib"] + +[build-dependencies] +build_helper = { path = "../build_helper" } +gcc = "0.3" diff --git a/src/libfmt_macros/Cargo.toml b/src/libfmt_macros/Cargo.toml new file mode 100644 index 0000000000000..b3f4d2deae2fc --- /dev/null +++ b/src/libfmt_macros/Cargo.toml @@ -0,0 +1,9 @@ +[package] +authors = ["The Rust Project Developers"] +name = "fmt_macros" +version = "0.0.0" + +[lib] +name = "fmt_macros" +path = "lib.rs" +crate-type = ["dylib"] diff --git a/src/libgetopts/Cargo.toml b/src/libgetopts/Cargo.toml new file mode 100644 index 0000000000000..99e3b89285888 --- /dev/null +++ b/src/libgetopts/Cargo.toml @@ -0,0 +1,9 @@ +[package] +authors = ["The Rust Project Developers"] +name = "getopts" +version = "0.0.0" + +[lib] +name = "getopts" +path = "lib.rs" +crate-type = ["dylib", "rlib"] diff --git a/src/libgraphviz/Cargo.toml b/src/libgraphviz/Cargo.toml new file mode 100644 index 0000000000000..76ef3a1d188ce --- /dev/null +++ b/src/libgraphviz/Cargo.toml @@ -0,0 +1,9 @@ +[package] +authors = ["The Rust Project Developers"] +name = "graphviz" +version = "0.0.0" + +[lib] +name = "graphviz" +path = "lib.rs" +crate-type = ["dylib"] diff --git a/src/liblog/Cargo.toml b/src/liblog/Cargo.toml new file mode 100644 index 0000000000000..31a862478d034 --- /dev/null +++ b/src/liblog/Cargo.toml @@ -0,0 +1,9 @@ +[package] +authors = ["The Rust Project Developers"] +name = "log" +version = "0.0.0" + +[lib] +name = "log" +path = "lib.rs" +crate-type = ["dylib", "rlib"] diff --git a/src/librand/Cargo.toml b/src/librand/Cargo.toml new file mode 100644 index 0000000000000..784654c085990 --- /dev/null +++ b/src/librand/Cargo.toml @@ -0,0 +1,12 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rand" +version = "0.0.0" + +[lib] +name = "rand" +path = "lib.rs" +test = false + +[dependencies] +core = { path = "../libcore" } diff --git a/src/librbml/Cargo.toml b/src/librbml/Cargo.toml new file mode 100644 index 0000000000000..ab89ac2b7a1eb --- /dev/null +++ b/src/librbml/Cargo.toml @@ -0,0 +1,13 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rbml" +version = "0.0.0" + +[lib] +name = "rbml" +path = "lib.rs" +crate-type = ["dylib"] + +[dependencies] +log = { path = "../liblog" } +serialize = { path = "../libserialize" } diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml new file mode 100644 index 0000000000000..2aefeb5fc2d44 --- /dev/null +++ b/src/librustc/Cargo.toml @@ -0,0 +1,24 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc" +version = "0.0.0" + +[lib] +name = "rustc" +path = "lib.rs" +crate-type = ["dylib"] + +[dependencies] +arena = { path = "../libarena" } +flate = { path = "../libflate" } +fmt_macros = { path = "../libfmt_macros" } +getopts = { path = "../libgetopts" } +graphviz = { path = "../libgraphviz" } +log = { path = "../liblog" } +rbml = { path = "../librbml" } +rustc_back = { path = "../librustc_back" } +rustc_data_structures = { path = "../librustc_data_structures" } +rustc_front = { path = "../librustc_front" } +rustc_llvm = { path = "../librustc_llvm" } +serialize = { path = "../libserialize" } +syntax = { path = "../libsyntax" } diff --git a/src/librustc_back/Cargo.toml b/src/librustc_back/Cargo.toml new file mode 100644 index 0000000000000..255ca60e2b8f4 --- /dev/null +++ b/src/librustc_back/Cargo.toml @@ -0,0 +1,19 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc_back" +version = "0.0.0" + +[lib] +name = "rustc_back" +path = "lib.rs" +crate-type = ["dylib"] + +[dependencies] +syntax = { path = "../libsyntax" } +serialize = { path = "../libserialize" } +rustc_llvm = { path = "../librustc_llvm" } +rustc_front = { path = "../librustc_front" } +log = { path = "../liblog" } + +[features] +jemalloc = [] diff --git a/src/librustc_bitflags/Cargo.toml b/src/librustc_bitflags/Cargo.toml new file mode 100644 index 0000000000000..e82c6ec05c84b --- /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" +test = false + +[dependencies] +core = { path = "../libcore" } diff --git a/src/librustc_borrowck/Cargo.toml b/src/librustc_borrowck/Cargo.toml new file mode 100644 index 0000000000000..f78f6fb86ae22 --- /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"] + +[dependencies] +log = { path = "../liblog" } +syntax = { path = "../libsyntax" } +graphviz = { path = "../libgraphviz" } +rustc = { path = "../librustc" } +rustc_front = { path = "../librustc_front" } diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml new file mode 100644 index 0000000000000..e2e16059d9871 --- /dev/null +++ b/src/librustc_data_structures/Cargo.toml @@ -0,0 +1,13 @@ +[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"] + +[dependencies] +log = { path = "../liblog" } +serialize = { path = "../libserialize" } diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml new file mode 100644 index 0000000000000..bf86e8f039ad4 --- /dev/null +++ b/src/librustc_driver/Cargo.toml @@ -0,0 +1,33 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc_driver" +version = "0.0.0" + +[lib] +name = "rustc_driver" +path = "lib.rs" +crate-type = ["dylib"] + +[dependencies] +arena = { path = "../libarena" } +flate = { path = "../libflate" } +getopts = { path = "../libgetopts" } +graphviz = { path = "../libgraphviz" } +log = { path = "../liblog" } +rustc = { path = "../librustc" } +rustc_back = { path = "../librustc_back" } +rustc_borrowck = { path = "../librustc_borrowck" } +rustc_front = { path = "../librustc_front" } +rustc_lint = { path = "../librustc_lint" } +rustc_llvm = { path = "../librustc_llvm" } +rustc_mir = { path = "../librustc_mir" } +rustc_plugin = { path = "../librustc_plugin" } +rustc_passes = { path = "../librustc_passes" } +rustc_privacy = { path = "../librustc_privacy" } +rustc_resolve = { path = "../librustc_resolve" } +rustc_trans = { path = "../librustc_trans" } +rustc_typeck = { path = "../librustc_typeck" } +rustc_metadata = { path = "../librustc_metadata" } +serialize = { path = "../libserialize" } +syntax = { path = "../libsyntax" } +syntax_ext = { path = "../libsyntax_ext" } diff --git a/src/librustc_front/Cargo.toml b/src/librustc_front/Cargo.toml new file mode 100644 index 0000000000000..eae0b0646a3dd --- /dev/null +++ b/src/librustc_front/Cargo.toml @@ -0,0 +1,14 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc_front" +version = "0.0.0" + +[lib] +name = "rustc_front" +path = "lib.rs" +crate-type = ["dylib"] + +[dependencies] +log = { path = "../liblog" } +syntax = { path = "../libsyntax" } +serialize = { path = "../libserialize" } diff --git a/src/librustc_lint/Cargo.toml b/src/librustc_lint/Cargo.toml new file mode 100644 index 0000000000000..33443957d1b3b --- /dev/null +++ b/src/librustc_lint/Cargo.toml @@ -0,0 +1,16 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc_lint" +version = "0.0.0" + +[lib] +name = "rustc_lint" +path = "lib.rs" +crate-type = ["dylib"] + +[dependencies] +log = { path = "../liblog" } +rustc = { path = "../librustc" } +rustc_back = { path = "../librustc_back" } +rustc_front = { path = "../librustc_front" } +syntax = { path = "../libsyntax" } diff --git a/src/librustc_llvm/Cargo.toml b/src/librustc_llvm/Cargo.toml new file mode 100644 index 0000000000000..62e1a71d196e2 --- /dev/null +++ b/src/librustc_llvm/Cargo.toml @@ -0,0 +1,17 @@ +[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"] + +[features] +static-libstdcpp = [] + +[build-dependencies] +build_helper = { path = "../build_helper" } +gcc = "0.3" diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml new file mode 100644 index 0000000000000..3f8249aabf948 --- /dev/null +++ b/src/librustc_metadata/Cargo.toml @@ -0,0 +1,20 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc_metadata" +version = "0.0.0" + +[lib] +name = "rustc_metadata" +path = "lib.rs" +crate-type = ["dylib"] + +[dependencies] +flate = { path = "../libflate" } +log = { path = "../liblog" } +rbml = { path = "../librbml" } +rustc = { path = "../librustc" } +rustc_back = { path = "../librustc_back" } +rustc_front = { path = "../librustc_front" } +rustc_llvm = { path = "../librustc_llvm" } +serialize = { path = "../libserialize" } +syntax = { path = "../libsyntax" } diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml new file mode 100644 index 0000000000000..93817ab0db61b --- /dev/null +++ b/src/librustc_mir/Cargo.toml @@ -0,0 +1,18 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc_mir" +version = "0.0.0" + +[lib] +name = "rustc_mir" +path = "lib.rs" +crate-type = ["dylib"] + +[dependencies] +graphviz = { path = "../libgraphviz" } +log = { path = "../liblog" } +rustc = { path = "../librustc" } +rustc_back = { path = "../librustc_back" } +rustc_data_structures = { path = "../librustc_data_structures" } +rustc_front = { path = "../librustc_front" } +syntax = { path = "../libsyntax" } diff --git a/src/librustc_passes/Cargo.toml b/src/librustc_passes/Cargo.toml new file mode 100644 index 0000000000000..7cc6510fa1fd1 --- /dev/null +++ b/src/librustc_passes/Cargo.toml @@ -0,0 +1,15 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc_passes" +version = "0.0.0" + +[lib] +name = "rustc_passes" +path = "lib.rs" +crate-type = ["dylib"] + +[dependencies] +log = { path = "../liblog" } +rustc = { path = "../librustc" } +rustc_front = { path = "../librustc_front" } +syntax = { path = "../libsyntax" } diff --git a/src/librustc_platform_intrinsics/Cargo.toml b/src/librustc_platform_intrinsics/Cargo.toml new file mode 100644 index 0000000000000..97bf4f854ccb4 --- /dev/null +++ b/src/librustc_platform_intrinsics/Cargo.toml @@ -0,0 +1,13 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc_platform_intrinsics" +version = "0.0.0" + +[lib] +name = "rustc_platform_intrinsics" +path = "lib.rs" +crate-type = ["dylib"] + +[dependencies] +rustc_llvm = { path = "../librustc_llvm" } +rustc = { path = "../librustc" } diff --git a/src/librustc_plugin/Cargo.toml b/src/librustc_plugin/Cargo.toml new file mode 100644 index 0000000000000..59cfe158624f0 --- /dev/null +++ b/src/librustc_plugin/Cargo.toml @@ -0,0 +1,17 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc_plugin" +version = "0.0.0" + +[lib] +name = "rustc_plugin" +path = "lib.rs" +crate-type = ["dylib"] + +[dependencies] +log = { path = "../liblog" } +rustc = { path = "../librustc" } +rustc_front = { path = "../librustc_front" } +rustc_metadata = { path = "../librustc_metadata" } +rustc_mir = { path = "../librustc_mir" } +syntax = { path = "../libsyntax" } diff --git a/src/librustc_privacy/Cargo.toml b/src/librustc_privacy/Cargo.toml new file mode 100644 index 0000000000000..56d6ca5543a0e --- /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"] + +[dependencies] +log = { path = "../liblog" } +rustc = { path = "../librustc" } +rustc_front = { path = "../librustc_front" } +syntax = { path = "../libsyntax" } diff --git a/src/librustc_resolve/Cargo.toml b/src/librustc_resolve/Cargo.toml new file mode 100644 index 0000000000000..da01a36d76237 --- /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"] + +[dependencies] +log = { path = "../liblog" } +syntax = { path = "../libsyntax" } +rustc = { path = "../librustc" } +rustc_front = { path = "../librustc_front" } +arena = { path = "../libarena" } diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml new file mode 100644 index 0000000000000..24320c4d563bc --- /dev/null +++ b/src/librustc_trans/Cargo.toml @@ -0,0 +1,25 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc_trans" +version = "0.0.0" + +[lib] +name = "rustc_trans" +path = "lib.rs" +crate-type = ["dylib"] + +[dependencies] +arena = { path = "../libarena" } +flate = { path = "../libflate" } +getopts = { path = "../libgetopts" } +graphviz = { path = "../libgraphviz" } +log = { path = "../liblog" } +rustc = { path = "../librustc" } +rustc_back = { path = "../librustc_back" } +rustc_data_structures = { path = "../librustc_data_structures" } +rustc_front = { path = "../librustc_front" } +rustc_llvm = { path = "../librustc_llvm" } +rustc_mir = { path = "../librustc_mir" } +rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" } +serialize = { path = "../libserialize" } +syntax = { path = "../libsyntax" } diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml new file mode 100644 index 0000000000000..fd33e9da1f937 --- /dev/null +++ b/src/librustc_typeck/Cargo.toml @@ -0,0 +1,19 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc_typeck" +version = "0.0.0" + +[lib] +name = "rustc_typeck" +path = "lib.rs" +crate-type = ["dylib"] + +[dependencies] +log = { path = "../liblog" } +syntax = { path = "../libsyntax" } +arena = { path = "../libarena" } +fmt_macros = { path = "../libfmt_macros" } +rustc = { path = "../librustc" } +rustc_back = { path = "../librustc_back" } +rustc_front = { path = "../librustc_front" } +rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" } diff --git a/src/librustc_unicode/Cargo.toml b/src/librustc_unicode/Cargo.toml new file mode 100644 index 0000000000000..1f4213f0abe40 --- /dev/null +++ b/src/librustc_unicode/Cargo.toml @@ -0,0 +1,12 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc_unicode" +version = "0.0.0" + +[lib] +name = "rustc_unicode" +path = "lib.rs" +test = false + +[dependencies] +core = { path = "../libcore" } diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml new file mode 100644 index 0000000000000..6b0ad30f4509c --- /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"] + +[dependencies] +arena = { path = "../libarena" } +getopts = { path = "../libgetopts" } +rustc = { path = "../librustc" } +rustc_back = { path = "../librustc_back" } +rustc_driver = { path = "../librustc_driver" } +rustc_front = { path = "../librustc_front" } +rustc_lint = { path = "../librustc_lint" } +rustc_metadata = { path = "../librustc_metadata" } +rustc_resolve = { path = "../librustc_resolve" } +rustc_trans = { path = "../librustc_trans" } +serialize = { path = "../libserialize" } +syntax = { path = "../libsyntax" } +test = { path = "../libtest" } +log = { path = "../liblog" } + +[build-dependencies] +build_helper = { path = "../build_helper" } +gcc = "0.3" diff --git a/src/libserialize/Cargo.toml b/src/libserialize/Cargo.toml new file mode 100644 index 0000000000000..919cda49c004c --- /dev/null +++ b/src/libserialize/Cargo.toml @@ -0,0 +1,12 @@ +[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" } diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml new file mode 100644 index 0000000000000..390c64d740867 --- /dev/null +++ b/src/libstd/Cargo.toml @@ -0,0 +1,30 @@ +[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"] +test = false + +[dependencies] +alloc = { path = "../liballoc" } +alloc_jemalloc = { path = "../liballoc_jemalloc", optional = true } +alloc_system = { path = "../liballoc_system" } +collections = { path = "../libcollections" } +core = { path = "../libcore" } +libc = { path = "../rustc/libc_shim" } +rand = { path = "../librand" } +rustc_bitflags = { path = "../librustc_bitflags" } +rustc_unicode = { path = "../librustc_unicode" } + +[build-dependencies] +build_helper = { path = "../build_helper" } +gcc = "0.3" + +[features] +jemalloc = ["alloc_jemalloc"] +debug-jemalloc = ["alloc_jemalloc/debug"] diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml new file mode 100644 index 0000000000000..3a1d18b85b657 --- /dev/null +++ b/src/libsyntax/Cargo.toml @@ -0,0 +1,16 @@ +[package] +authors = ["The Rust Project Developers"] +name = "syntax" +version = "0.0.0" + +[lib] +name = "syntax" +path = "lib.rs" +crate-type = ["dylib"] + +[dependencies] +arena = { path = "../libarena" } +fmt_macros = { path = "../libfmt_macros" } +serialize = { path = "../libserialize" } +term = { path = "../libterm" } +log = { path = "../liblog" } diff --git a/src/libsyntax_ext/Cargo.toml b/src/libsyntax_ext/Cargo.toml new file mode 100644 index 0000000000000..e137815cd32fd --- /dev/null +++ b/src/libsyntax_ext/Cargo.toml @@ -0,0 +1,13 @@ +[package] +authors = ["The Rust Project Developers"] +name = "syntax_ext" +version = "0.0.0" + +[lib] +name = "syntax_ext" +path = "lib.rs" +crate-type = ["dylib"] + +[dependencies] +fmt_macros = { path = "../libfmt_macros" } +syntax = { path = "../libsyntax" } diff --git a/src/libterm/Cargo.toml b/src/libterm/Cargo.toml new file mode 100644 index 0000000000000..cdfc957297dee --- /dev/null +++ b/src/libterm/Cargo.toml @@ -0,0 +1,12 @@ +[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" } diff --git a/src/libtest/Cargo.toml b/src/libtest/Cargo.toml new file mode 100644 index 0000000000000..96a84496b9c9c --- /dev/null +++ b/src/libtest/Cargo.toml @@ -0,0 +1,14 @@ +[package] +authors = ["The Rust Project Developers"] +name = "test" +version = "0.0.0" + +[lib] +name = "test" +path = "lib.rs" +crate-type = ["dylib", "rlib"] + +[dependencies] +getopts = { path = "../libgetopts" } +term = { path = "../libterm" } +serialize = { path = "../libserialize" } diff --git a/src/rustbook/Cargo.toml b/src/rustbook/Cargo.toml new file mode 100644 index 0000000000000..c684c474efa9e --- /dev/null +++ b/src/rustbook/Cargo.toml @@ -0,0 +1,13 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustbook" +version = "0.0.0" + +[lib] +name = "rustbook" +path = "main.rs" +crate-type = ["dylib"] + +[dependencies] +rustc_back = { path = "../librustc_back" } +rustdoc = { path = "../librustdoc" } diff --git a/src/rustc/Cargo.lock b/src/rustc/Cargo.lock index db1a87679c271..2a7da33bb68dd 100644 --- a/src/rustc/Cargo.lock +++ b/src/rustc/Cargo.lock @@ -140,6 +140,7 @@ dependencies = [ "rustc_llvm 0.0.0", "rustc_metadata 0.0.0", "rustc_mir 0.0.0", + "rustc_passes 0.0.0", "rustc_plugin 0.0.0", "rustc_privacy 0.0.0", "rustc_resolve 0.0.0", @@ -206,6 +207,16 @@ dependencies = [ "syntax 0.0.0", ] +[[package]] +name = "rustc_passes" +version = "0.0.0" +dependencies = [ + "log 0.0.0", + "rustc 0.0.0", + "rustc_front 0.0.0", + "syntax 0.0.0", +] + [[package]] name = "rustc_platform_intrinsics" version = "0.0.0" @@ -222,6 +233,7 @@ dependencies = [ "rustc 0.0.0", "rustc_front 0.0.0", "rustc_metadata 0.0.0", + "rustc_mir 0.0.0", "syntax 0.0.0", ] From 4da4970767ae8fc2e3b6d0c280312bb0f4efeed6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 21 Jan 2016 15:21:13 -0800 Subject: [PATCH 05/10] bootstrap: Add build scripts for crates This commits adds build scripts to the necessary Rust crates for all the native dependencies. This is currently a duplication of the support found in mk/rt.mk and is my best effort at representing the logic twice, but there may be some unfortunate-and-inevitable divergence. As a summary: * alloc_jemalloc - build script to compile jemallocal * flate - build script to compile miniz.c * rustc_llvm - build script to run llvm-config and learn about how to link it. Note that this crucially (and will not ever) compile LLVM as that would take far too long. * rustdoc - build script to compile hoedown * std - script to determine lots of libraries/linkages as well as compile libbacktrace --- src/liballoc_jemalloc/build.rs | 104 ++++++++++++++++++++++++++ src/libflate/build.rs | 17 +++++ src/librustc_llvm/build.rs | 130 +++++++++++++++++++++++++++++++++ src/librustdoc/build.rs | 26 +++++++ src/libstd/build.rs | 110 ++++++++++++++++++++++++++++ 5 files changed, 387 insertions(+) create mode 100644 src/liballoc_jemalloc/build.rs create mode 100644 src/libflate/build.rs create mode 100644 src/librustc_llvm/build.rs create mode 100644 src/librustdoc/build.rs create mode 100644 src/libstd/build.rs diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs new file mode 100644 index 0000000000000..18f0527425a15 --- /dev/null +++ b/src/liballoc_jemalloc/build.rs @@ -0,0 +1,104 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate build_helper; +extern crate gcc; + +use std::env; +use std::path::PathBuf; +use std::process::Command; +use build_helper::run; + +fn main() { + let target = env::var("TARGET").unwrap(); + let host = env::var("HOST").unwrap(); + let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + let src_dir = env::current_dir().unwrap(); + + if let Some(jemalloc) = env::var_os("JEMALLOC_OVERRIDE") { + let jemalloc = PathBuf::from(jemalloc); + println!("cargo:rustc-link-search=native={}", + jemalloc.parent().unwrap().display()); + let stem = jemalloc.file_stem().unwrap().to_str().unwrap(); + let name = jemalloc.file_name().unwrap().to_str().unwrap(); + let kind = if name.ends_with(".a") {"static"} else {"dylib"}; + println!("cargo:rustc-link-lib={}={}", kind, &stem[3..]); + return + } + + let compiler = gcc::Config::new().get_compiler(); + let ar = build_helper::cc2ar(compiler.path(), &target); + let cflags = compiler.args().iter().map(|s| s.to_str().unwrap()) + .collect::>().join(" "); + + let mut cmd = Command::new("sh"); + cmd.arg(src_dir.join("../jemalloc/configure").to_str().unwrap() + .replace("C:\\", "/c/") + .replace("\\", "/")) + .current_dir(&build_dir) + .env("CC", compiler.path()) + .env("EXTRA_CFLAGS", cflags) + .env("AR", &ar) + .env("RANLIB", format!("{} s", ar.display())); + + if target.contains("windows-gnu") { + // A bit of history here, this used to be --enable-lazy-lock added in + // #14006 which was filed with jemalloc in jemalloc/jemalloc#83 which + // was also reported to MinGW: + // + // http://sourceforge.net/p/mingw-w64/bugs/395/ + // + // When updating jemalloc to 4.0, however, it was found that binaries + // would exit with the status code STATUS_RESOURCE_NOT_OWNED indicating + // that a thread was unlocking a mutex it never locked. Disabling this + // "lazy lock" option seems to fix the issue, but it was enabled by + // default for MinGW targets in 13473c7 for jemalloc. + // + // As a result of all that, force disabling lazy lock on Windows, and + // after reading some code it at least *appears* that the initialization + // of mutexes is otherwise ok in jemalloc, so shouldn't cause problems + // hopefully... + // + // tl;dr: make windows behave like other platforms by disabling lazy + // locking, but requires passing an option due to a historical + // default with jemalloc. + cmd.arg("--disable-lazy-lock"); + } else if target.contains("ios") || target.contains("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"); + cmd.arg("--with-jemalloc-prefix=je_"); + cmd.arg(format!("--host={}", build_helper::gnu_target(&target))); + cmd.arg(format!("--build={}", build_helper::gnu_target(&host))); + + run(&mut cmd); + run(Command::new("make") + .current_dir(&build_dir) + .arg("build_lib_static") + .arg("-j").arg(env::var("NUM_JOBS").unwrap())); + + if target.contains("windows") { + println!("cargo:rustc-link-lib=static=jemalloc"); + } else { + println!("cargo:rustc-link-lib=static=jemalloc_pic"); + } + println!("cargo:rustc-link-search=native={}/lib", build_dir.display()); + if target.contains("android") { + println!("cargo:rustc-link-lib=gcc"); + } else if !target.contains("windows") { + println!("cargo:rustc-link-lib=pthread"); + } +} diff --git a/src/libflate/build.rs b/src/libflate/build.rs new file mode 100644 index 0000000000000..12016980a2c65 --- /dev/null +++ b/src/libflate/build.rs @@ -0,0 +1,17 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate gcc; + +fn main() { + gcc::Config::new() + .file("../rt/miniz.c") + .compile("libminiz.a"); +} diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs new file mode 100644 index 0000000000000..4f2fee6943f38 --- /dev/null +++ b/src/librustc_llvm/build.rs @@ -0,0 +1,130 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate gcc; +extern crate build_helper; + +use std::process::Command; +use std::env; +use std::path::PathBuf; + +use build_helper::output; + +fn main() { + let target = env::var("TARGET").unwrap(); + let llvm_config = env::var_os("LLVM_CONFIG").map(PathBuf::from) + .unwrap_or_else(|| { + match env::var_os("CARGO_TARGET_DIR").map(PathBuf::from) { + Some(dir) => { + let to_test = dir.parent().unwrap().parent().unwrap() + .join(&target).join("llvm/bin/llvm-config"); + if Command::new(&to_test).output().is_ok() { + return to_test + } + } + None => {} + } + PathBuf::from("llvm-config") + }); + + println!("cargo:rerun-if-changed={}", llvm_config.display()); + + let optional_components = ["x86", "arm", "aarch64", "mips", "powerpc", + "pnacl"]; + + // FIXME: surely we don't need all these components, right? Stuff like mcjit + // or interpreter the compiler itself never uses. + let required_components = &["ipo", "bitreader", "bitwriter", "linker", + "asmparser", "mcjit", "interpreter", + "instrumentation"]; + + let components = output(Command::new(&llvm_config).arg("--components")); + let mut components = components.split_whitespace().collect::>(); + components.retain(|c| { + optional_components.contains(c) || required_components.contains(c) + }); + + for component in required_components { + if !components.contains(component) { + panic!("require llvm component {} but wasn't found", component); + } + } + + for component in components.iter() { + println!("cargo:rustc-cfg=llvm_component=\"{}\"", component); + } + + // Link in our own LLVM shims, compiled with the same flags as LLVM + let mut cmd = Command::new(&llvm_config); + cmd.arg("--cxxflags"); + let cxxflags = output(&mut cmd); + let mut cfg = gcc::Config::new(); + for flag in cxxflags.split_whitespace() { + cfg.flag(flag); + } + cfg.file("../rustllvm/ExecutionEngineWrapper.cpp") + .file("../rustllvm/PassWrapper.cpp") + .file("../rustllvm/RustWrapper.cpp") + .file("../rustllvm/ArchiveWrapper.cpp") + .cpp(true) + .cpp_link_stdlib(None) // we handle this below + .compile("librustllvm.a"); + + // Link in all LLVM libraries + let mut cmd = Command::new(&llvm_config); + cmd.arg("--libs").arg("--system-libs").args(&components[..]); + for lib in output(&mut cmd).split_whitespace() { + let name = if lib.starts_with("-l") { + &lib[2..] + } else if lib.starts_with("-") { + &lib[1..] + } else { + continue + }; + + // Don't need or want this library, but LLVM's CMake build system + // doesn't provide a way to disable it, so filter it here even though we + // may or may not have built it. We don't reference anything from this + // library and it otherwise may just pull in extra dependencies on + // libedit which we don't want + if name == "LLVMLineEditor" { + continue + } + + let kind = if name.starts_with("LLVM") {"static"} else {"dylib"}; + println!("cargo:rustc-link-lib={}={}", kind, name); + } + + // LLVM ldflags + let mut cmd = Command::new(&llvm_config); + cmd.arg("--ldflags"); + for lib in output(&mut cmd).split_whitespace() { + if lib.starts_with("-l") { + println!("cargo:rustc-link-lib={}", &lib[2..]); + } else if lib.starts_with("-L") { + println!("cargo:rustc-link-search=native={}", &lib[2..]); + } + } + + // C++ runtime library + if !target.contains("msvc") { + if let Some(s) = env::var_os("LLVM_STATIC_STDCPP") { + assert!(!cxxflags.contains("stdlib=libc++")); + let path = PathBuf::from(s); + println!("cargo:rustc-link-search=native={}", + path.parent().unwrap().display()); + println!("cargo:rustc-link-lib=static=stdc++"); + } else if cxxflags.contains("stdlib=libc++") { + println!("cargo:rustc-link-lib=c++"); + } else { + println!("cargo:rustc-link-lib=stdc++"); + } + } +} diff --git a/src/librustdoc/build.rs b/src/librustdoc/build.rs new file mode 100644 index 0000000000000..fcb7af11dce2f --- /dev/null +++ b/src/librustdoc/build.rs @@ -0,0 +1,26 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate gcc; + +fn main() { + let mut cfg = gcc::Config::new(); + cfg.file("../rt/hoedown/src/autolink.c") + .file("../rt/hoedown/src/buffer.c") + .file("../rt/hoedown/src/document.c") + .file("../rt/hoedown/src/escape.c") + .file("../rt/hoedown/src/html.c") + .file("../rt/hoedown/src/html_blocks.c") + .file("../rt/hoedown/src/html_smartypants.c") + .file("../rt/hoedown/src/stack.c") + .file("../rt/hoedown/src/version.c") + .include("../rt/hoedown/src") + .compile("libhoedown.a"); +} diff --git a/src/libstd/build.rs b/src/libstd/build.rs new file mode 100644 index 0000000000000..8561d53a0d361 --- /dev/null +++ b/src/libstd/build.rs @@ -0,0 +1,110 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate gcc; +extern crate build_helper; + +use std::env; +use std::fs; +use std::path::PathBuf; +use std::process::Command; + +use build_helper::run; + +fn main() { + let target = env::var("TARGET").unwrap(); + let host = env::var("HOST").unwrap(); + if !target.contains("apple") && !target.contains("msvc") { + build_libbacktrace(&host, &target); + } + + if target.contains("unknown-linux") { + if target.contains("musl") { + println!("cargo:rustc-link-lib=static=unwind"); + } else { + println!("cargo:rustc-link-lib=dl"); + println!("cargo:rustc-link-lib=rt"); + println!("cargo:rustc-link-lib=pthread"); + println!("cargo:rustc-link-lib=gcc_s"); + } + } else if target.contains("android") { + println!("cargo:rustc-link-lib=dl"); + println!("cargo:rustc-link-lib=log"); + println!("cargo:rustc-link-lib=gcc"); + } else if target.contains("freebsd") { + println!("cargo:rustc-link-lib=execinfo"); + println!("cargo:rustc-link-lib=pthread"); + println!("cargo:rustc-link-lib=gcc_s"); + } else if target.contains("dragonfly") || target.contains("bitrig") || + target.contains("netbsd") || target.contains("openbsd") { + println!("cargo:rustc-link-lib=pthread"); + + if target.contains("rumprun") { + println!("cargo:rustc-link-lib=unwind"); + } else if target.contains("netbsd") || target.contains("openbsd") { + println!("cargo:rustc-link-lib=gcc"); + } else if target.contains("bitrig") { + println!("cargo:rustc-link-lib=c++abi"); + } else if target.contains("dragonfly") { + println!("cargo:rustc-link-lib=gcc_pic"); + } + } else if target.contains("apple-darwin") { + println!("cargo:rustc-link-lib=System"); + } else if target.contains("apple-ios") { + println!("cargo:rustc-link-lib=System"); + println!("cargo:rustc-link-lib=objc"); + println!("cargo:rustc-link-lib=framework=Security"); + println!("cargo:rustc-link-lib=framework=Foundation"); + } else if target.contains("windows") { + if target.contains("windows-gnu") { + println!("cargo:rustc-link-lib=gcc_eh"); + } + println!("cargo:rustc-link-lib=advapi32"); + println!("cargo:rustc-link-lib=ws2_32"); + println!("cargo:rustc-link-lib=userenv"); + println!("cargo:rustc-link-lib=shell32"); + } +} + +fn build_libbacktrace(host: &str, target: &str) { + let src_dir = env::current_dir().unwrap().join("../libbacktrace"); + let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + + println!("cargo:rustc-link-lib=static=backtrace"); + println!("cargo:rustc-link-search=native={}/.libs", build_dir.display()); + + if fs::metadata(&build_dir.join(".libs/libbacktrace.a")).is_ok() { + return + } + + let compiler = gcc::Config::new().get_compiler(); + let ar = build_helper::cc2ar(compiler.path(), target); + let cflags = compiler.args().iter().map(|s| s.to_str().unwrap()) + .collect::>().join(" "); + run(Command::new("sh") + .current_dir(&build_dir) + .arg(src_dir.join("configure").to_str().unwrap() + .replace("C:\\", "/c/") + .replace("\\", "/")) + .arg("--with-pic") + .arg("--disable-multilib") + .arg("--disable-shared") + .arg("--disable-host-shared") + .arg(format!("--host={}", build_helper::gnu_target(target))) + .arg(format!("--build={}", build_helper::gnu_target(host))) + .env("CC", compiler.path()) + .env("AR", &ar) + .env("RANLIB", format!("{} s", ar.display())) + .env("CFLAGS", cflags)); + run(Command::new("make") + .current_dir(&build_dir) + .arg(format!("INCDIR={}", src_dir.display())) + .arg("-j").arg(env::var("NUM_JOBS").unwrap())); +} From eac0a8bc3070e45047fff57e7b024a059289a36d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 21 Jan 2016 15:36:25 -0800 Subject: [PATCH 06/10] bootstrap: Add directives to not double-link libs Have all Cargo-built crates pass `--cfg cargobuild` and then add appropriate `#[cfg]` definitions to all crates to avoid linking anything if this is passed. This should help allow libstd to compile with both the makefiles and with Cargo. --- src/liballoc_jemalloc/build.rs | 2 ++ src/liballoc_jemalloc/lib.rs | 5 ++++- src/libflate/build.rs | 1 + src/libflate/lib.rs | 5 ++++- src/librustc_llvm/build.rs | 2 ++ src/librustc_llvm/lib.rs | 4 ++++ src/librustdoc/build.rs | 1 + src/librustdoc/html/markdown.rs | 3 +++ src/libstd/build.rs | 2 ++ src/libstd/rand/os.rs | 5 ++++- src/libstd/rtdeps.rs | 2 ++ src/libstd/sys/common/gnu/libbacktrace.rs | 2 +- src/libstd/sys/common/unwind/gcc.rs | 3 +++ src/libstd/sys/unix/os.rs | 3 ++- src/libstd/sys/windows/c.rs | 3 +++ 15 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs index 18f0527425a15..4bc752af48eee 100644 --- a/src/liballoc_jemalloc/build.rs +++ b/src/liballoc_jemalloc/build.rs @@ -17,6 +17,8 @@ use std::process::Command; use build_helper::run; fn main() { + println!("cargo:rustc-cfg=cargobuild"); + let target = env::var("TARGET").unwrap(); let host = env::var("HOST").unwrap(); let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs index d02e9e4ba130b..2c46e37ac32b2 100644 --- a/src/liballoc_jemalloc/lib.rs +++ b/src/liballoc_jemalloc/lib.rs @@ -38,7 +38,10 @@ use libc::{c_int, c_void, size_t}; not(target_os = "android"), not(target_env = "musl")), link(name = "pthread"))] -extern "C" { +#[cfg(not(cargobuild))] +extern {} + +extern { fn je_mallocx(size: size_t, flags: c_int) -> *mut c_void; fn je_rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void; fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t; diff --git a/src/libflate/build.rs b/src/libflate/build.rs index 12016980a2c65..245c705dfcc2a 100644 --- a/src/libflate/build.rs +++ b/src/libflate/build.rs @@ -11,6 +11,7 @@ extern crate gcc; fn main() { + println!("cargo:rustc-cfg=cargobuild"); gcc::Config::new() .file("../rt/miniz.c") .compile("libminiz.a"); diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs index f316250d96d71..a6bf735e459de 100644 --- a/src/libflate/lib.rs +++ b/src/libflate/lib.rs @@ -79,7 +79,10 @@ impl Drop for Bytes { } #[link(name = "miniz", kind = "static")] -extern "C" { +#[cfg(not(cargobuild))] +extern {} + +extern { /// Raw miniz compression function. fn tdefl_compress_mem_to_heap(psrc_buf: *const c_void, src_buf_len: size_t, diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 4f2fee6943f38..1c9982790cf4a 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -18,6 +18,8 @@ use std::path::PathBuf; use build_helper::output; fn main() { + println!("cargo:rustc-cfg=cargobuild"); + let target = env::var("TARGET").unwrap(); let llvm_config = env::var_os("LLVM_CONFIG").map(PathBuf::from) .unwrap_or_else(|| { diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 059287ccb5ec3..8877479104e55 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -609,6 +609,9 @@ pub mod debuginfo { // automatically updated whenever LLVM is updated to include an up-to-date // set of the libraries we need to link to LLVM for. #[link(name = "rustllvm", kind = "static")] +#[cfg(not(cargobuild))] +extern {} + #[linked_from = "rustllvm"] // not quite true but good enough extern { /* Create and destroy contexts. */ @@ -2486,6 +2489,7 @@ impl Drop for OperandBundleDef { // 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(cargobuild))] mod llvmdeps { include! { env!("CFG_LLVM_LINKAGE_FILE") } } diff --git a/src/librustdoc/build.rs b/src/librustdoc/build.rs index fcb7af11dce2f..171954f325a5e 100644 --- a/src/librustdoc/build.rs +++ b/src/librustdoc/build.rs @@ -11,6 +11,7 @@ extern crate gcc; fn main() { + println!("cargo:rustc-cfg=cargobuild"); let mut cfg = gcc::Config::new(); cfg.file("../rt/hoedown/src/autolink.c") .file("../rt/hoedown/src/buffer.c") diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index a5436886a7e8c..c0846cae68701 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -157,6 +157,9 @@ struct hoedown_buffer { // hoedown FFI #[link(name = "hoedown", kind = "static")] +#[cfg(not(cargobuild))] +extern {} + extern { fn hoedown_html_renderer_new(render_flags: libc::c_uint, nesting_level: libc::c_int) diff --git a/src/libstd/build.rs b/src/libstd/build.rs index 8561d53a0d361..8fb49a1be4ea6 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -19,6 +19,8 @@ use std::process::Command; use build_helper::run; fn main() { + println!("cargo:rustc-cfg=cargobuild"); + let target = env::var("TARGET").unwrap(); let host = env::var("HOST").unwrap(); if !target.contains("apple") && !target.contains("msvc") { diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index 8d92909faf528..8a422246514bc 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -269,7 +269,10 @@ mod imp { const kSecRandomDefault: *const SecRandom = ptr::null(); #[link(name = "Security", kind = "framework")] - extern "C" { + #[cfg(not(cargobuild))] + extern {} + + extern { fn SecRandomCopyBytes(rnd: *const SecRandom, count: size_t, bytes: *mut u8) -> c_int; } diff --git a/src/libstd/rtdeps.rs b/src/libstd/rtdeps.rs index b1b9ffc4dc63d..a11200873d500 100644 --- a/src/libstd/rtdeps.rs +++ b/src/libstd/rtdeps.rs @@ -12,6 +12,8 @@ //! the standard library This varies per-platform, but these libraries are //! necessary for running libstd. +#![cfg(not(cargobuild))] + // LLVM implements the `frem` instruction as a call to `fmod`, which lives in // libm. Hence, we must explicitly link to it. // diff --git a/src/libstd/sys/common/gnu/libbacktrace.rs b/src/libstd/sys/common/gnu/libbacktrace.rs index f8463388384f5..8b3cb04030c82 100644 --- a/src/libstd/sys/common/gnu/libbacktrace.rs +++ b/src/libstd/sys/common/gnu/libbacktrace.rs @@ -40,7 +40,7 @@ pub fn print(w: &mut Write, idx: isize, addr: *mut libc::c_void, errnum: libc::c_int); enum backtrace_state {} #[link(name = "backtrace", kind = "static")] - #[cfg(not(test))] + #[cfg(all(not(test), not(cargobuild)))] extern {} extern { diff --git a/src/libstd/sys/common/unwind/gcc.rs b/src/libstd/sys/common/unwind/gcc.rs index 12cd07a4f4f18..7cf9e2a54bd90 100644 --- a/src/libstd/sys/common/unwind/gcc.rs +++ b/src/libstd/sys/common/unwind/gcc.rs @@ -252,6 +252,9 @@ pub mod eh_frame_registry { // See also: rtbegin.rs, `unwind` module. #[link(name = "gcc_eh")] + #[cfg(not(cargobuild))] + extern {} + extern { fn __register_frame_info(eh_frame_begin: *const u8, object: *mut u8); fn __deregister_frame_info(eh_frame_begin: *const u8, object: *mut u8); diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index 9def3adc30343..b6a0bd844094b 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -339,7 +339,6 @@ pub fn args() -> Args { pub fn args() -> Args { use mem; - #[link(name = "objc")] extern { fn sel_registerName(name: *const libc::c_uchar) -> Sel; fn objc_msgSend(obj: NsId, sel: Sel, ...) -> NsId; @@ -347,6 +346,8 @@ pub fn args() -> Args { } #[link(name = "Foundation", kind = "framework")] + #[link(name = "objc")] + #[cfg(not(cargobuild))] extern {} type Sel = *const libc::c_void; diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 6e8090a223516..9fdeb0aef14c8 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -966,6 +966,9 @@ pub enum EXCEPTION_DISPOSITION { #[link(name = "userenv")] #[link(name = "shell32")] #[link(name = "advapi32")] +#[cfg(not(cargobuild))] +extern {} + extern "system" { pub fn WSAStartup(wVersionRequested: WORD, lpWSAData: LPWSADATA) -> c_int; From 32c56138ec338b001875c3df7c97c67af266a324 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 21 Jan 2016 15:37:15 -0800 Subject: [PATCH 07/10] rustbook: Make `main` a public function This will allow it to be used as a crate in a Cargo-based build --- src/rustbook/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rustbook/main.rs b/src/rustbook/main.rs index e8345dc9586d1..bd4fc8992930e 100644 --- a/src/rustbook/main.rs +++ b/src/rustbook/main.rs @@ -36,7 +36,7 @@ mod test; static EXIT_STATUS: AtomicIsize = ATOMIC_ISIZE_INIT; -fn main() { +pub fn main() { let mut term = Term::new(); let cmd: Vec<_> = env::args().collect(); From 34f7364332c95b63a742709b96141142f6cfe3d8 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 21 Jan 2016 15:39:22 -0800 Subject: [PATCH 08/10] rustc_llvm: Tweak how initialization is performed Refactor a bit to have less repetition and #[cfg] and try to bury it all inside of a macro. --- mk/llvm.mk | 2 +- src/librustc_llvm/lib.rs | 117 +++++++++++++-------------------------- 2 files changed, 40 insertions(+), 79 deletions(-) diff --git a/mk/llvm.mk b/mk/llvm.mk index a4174efa5efa9..2bdbef35badf9 100644 --- a/mk/llvm.mk +++ b/mk/llvm.mk @@ -102,7 +102,7 @@ $(foreach host,$(CFG_HOST), \ define LLVM_LINKAGE_DEPS $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.rustc_llvm: $$(LLVM_LINKAGE_PATH_$(2)) RUSTFLAGS$(1)_rustc_llvm_T_$(2) += $$(shell echo $$(LLVM_ALL_COMPONENTS_$(2)) | tr '-' '_' |\ - sed -e 's/^ //;s/\([^ ]*\)/\-\-cfg have_component_\1/g') + sed -e 's/^ //;s/\([^ ]*\)/\-\-cfg "llvm_component=\\"\1\\""/g') endef $(foreach source,$(CFG_HOST), \ diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 8877479104e55..1933c926e3018 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -2166,53 +2166,6 @@ extern { pub fn LLVMRustFreeOperandBundleDef(Bundle: OperandBundleDefRef); } -#[cfg(have_component_x86)] -extern { - pub fn LLVMInitializeX86TargetInfo(); - pub fn LLVMInitializeX86Target(); - pub fn LLVMInitializeX86TargetMC(); - pub fn LLVMInitializeX86AsmPrinter(); - pub fn LLVMInitializeX86AsmParser(); -} -#[cfg(have_component_arm)] -extern { - pub fn LLVMInitializeARMTargetInfo(); - pub fn LLVMInitializeARMTarget(); - pub fn LLVMInitializeARMTargetMC(); - pub fn LLVMInitializeARMAsmPrinter(); - pub fn LLVMInitializeARMAsmParser(); -} -#[cfg(have_component_aarch64)] -extern { - pub fn LLVMInitializeAArch64TargetInfo(); - pub fn LLVMInitializeAArch64Target(); - pub fn LLVMInitializeAArch64TargetMC(); - pub fn LLVMInitializeAArch64AsmPrinter(); - pub fn LLVMInitializeAArch64AsmParser(); -} -#[cfg(have_component_mips)] -extern { - pub fn LLVMInitializeMipsTargetInfo(); - pub fn LLVMInitializeMipsTarget(); - pub fn LLVMInitializeMipsTargetMC(); - pub fn LLVMInitializeMipsAsmPrinter(); - pub fn LLVMInitializeMipsAsmParser(); -} -#[cfg(have_component_powerpc)] -extern { - pub fn LLVMInitializePowerPCTargetInfo(); - pub fn LLVMInitializePowerPCTarget(); - pub fn LLVMInitializePowerPCTargetMC(); - pub fn LLVMInitializePowerPCAsmPrinter(); - pub fn LLVMInitializePowerPCAsmParser(); -} -#[cfg(have_component_pnacl)] -extern { - pub fn LLVMInitializePNaClTargetInfo(); - pub fn LLVMInitializePNaClTarget(); - pub fn LLVMInitializePNaClTargetMC(); -} - // LLVM requires symbols from this library, but apparently they're not printed // during llvm-config? #[cfg(windows)] @@ -2399,20 +2352,14 @@ pub unsafe fn debug_loc_to_string(c: ContextRef, tr: DebugLocRef) -> String { pub fn initialize_available_targets() { macro_rules! init_target( - ($cfg:ident $arch:ident) => { { + ($cfg:meta, $($method:ident),*) => { { #[cfg($cfg)] fn init() { + extern { + $(fn $method();)* + } unsafe { - let f = concat_idents!(LLVMInitialize, $arch, TargetInfo); - f(); - let f = concat_idents!(LLVMInitialize, $arch, Target); - f(); - let f = concat_idents!(LLVMInitialize, $arch, TargetMC); - f(); - let f = concat_idents!(LLVMInitialize, $arch, AsmPrinter); - f(); - let f = concat_idents!(LLVMInitialize, $arch, AsmParser); - f(); + $($method();)* } } #[cfg(not($cfg))] @@ -2420,26 +2367,40 @@ pub fn initialize_available_targets() { init(); } } ); - - init_target!(have_component_powerpc PowerPC); - init_target!(have_component_mips Mips); - init_target!(have_component_aarch64 AArch64); - init_target!(have_component_arm ARM); - init_target!(have_component_x86 X86); - - // PNaCl doesn't provide some of the optional target components, so we - // manually initialize it here. - #[cfg(have_component_pnacl)] - fn init_pnacl() { - unsafe { - LLVMInitializePNaClTargetInfo(); - LLVMInitializePNaClTarget(); - LLVMInitializePNaClTargetMC(); - } - } - #[cfg(not(have_component_pnacl))] - fn init_pnacl() { } - init_pnacl(); + init_target!(llvm_component = "x86", + LLVMInitializeX86TargetInfo, + LLVMInitializeX86Target, + LLVMInitializeX86TargetMC, + LLVMInitializeX86AsmPrinter, + LLVMInitializeX86AsmParser); + init_target!(llvm_component = "arm", + LLVMInitializeARMTargetInfo, + LLVMInitializeARMTarget, + LLVMInitializeARMTargetMC, + LLVMInitializeARMAsmPrinter, + LLVMInitializeARMAsmParser); + init_target!(llvm_component = "aarch64", + LLVMInitializeAArch64TargetInfo, + LLVMInitializeAArch64Target, + LLVMInitializeAArch64TargetMC, + LLVMInitializeAArch64AsmPrinter, + LLVMInitializeAArch64AsmParser); + init_target!(llvm_component = "mips", + LLVMInitializeMipsTargetInfo, + LLVMInitializeMipsTarget, + LLVMInitializeMipsTargetMC, + LLVMInitializeMipsAsmPrinter, + LLVMInitializeMipsAsmParser); + init_target!(llvm_component = "powerpc", + LLVMInitializePowerPCTargetInfo, + LLVMInitializePowerPCTarget, + LLVMInitializePowerPCTargetMC, + LLVMInitializePowerPCAsmPrinter, + LLVMInitializePowerPCAsmParser); + init_target!(llvm_component = "pnacl", + LLVMInitializePNaClTargetInfo, + LLVMInitializePNaClTarget, + LLVMInitializePNaClTargetMC); } pub fn last_error() -> Option { From bb2e92171fb95c911572ef58a6110c1c53fdd34c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 21 Jan 2016 17:05:04 -0800 Subject: [PATCH 09/10] configure: Add an option to use the cargo build system This commit adds a `--enable-rustbuild` option to the configure script which will copy a different `Makefile.in` into place to intercept all `make` invocations. Currently this makefile only has one target, but it's expected to be filled out quite a bit over time! --- configure | 18 +++++++++++++++--- src/bootstrap/mk/Makefile.in | 23 +++++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 src/bootstrap/mk/Makefile.in diff --git a/configure b/configure index 631c5f49f0643..7958ac9bfcfe3 100755 --- a/configure +++ b/configure @@ -606,6 +606,7 @@ opt stage0-landing-pads 1 "enable landing pads during bootstrap with stage0" opt dist-host-only 0 "only install bins for the host architecture" opt inject-std-version 1 "inject the current compiler version of libstd into programs" opt llvm-version-check 1 "check if the LLVM version is supported, build anyway" +opt rustbuild 0 "use the rust and cargo based build system" # Optimization and debugging options. These may be overridden by the release channel, etc. opt_nosave optimize 1 "build optimized rust code" @@ -1422,7 +1423,7 @@ done step_msg "configuring submodules" # Have to be in the top of src directory for this -if [ -z $CFG_DISABLE_MANAGE_SUBMODULES ] +if [ -z $CFG_DISABLE_MANAGE_SUBMODULES ] && [ -z $CFG_ENABLE_RUSTBUILD ] then cd ${CFG_SRC_DIR} @@ -1481,7 +1482,11 @@ do ;; esac - if [ -z $CFG_LLVM_ROOT ] + if [ -n "$CFG_ENABLE_RUSTBUILD" ] + then + msg "not configuring LLVM, rustbuild in use" + do_reconfigure=0 + elif [ -z $CFG_LLVM_ROOT ] then LLVM_BUILD_DIR=${CFG_BUILD_DIR}$t/llvm if [ -n "$CFG_DISABLE_OPTIMIZE_LLVM" ] @@ -1812,8 +1817,15 @@ do putvar $CFG_LLVM_INST_DIR done +if [ -n "$CFG_ENABLE_RUSTBUILD" ] +then + INPUT_MAKEFILE=src/bootstrap/mk/Makefile.in +else + INPUT_MAKEFILE=Makefile.in +fi + msg -copy_if_changed ${CFG_SRC_DIR}Makefile.in ./Makefile +copy_if_changed ${CFG_SRC_DIR}${INPUT_MAKEFILE} ./Makefile move_if_changed config.tmp config.mk rm -f config.tmp touch config.stamp diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in new file mode 100644 index 0000000000000..1157346d774ab --- /dev/null +++ b/src/bootstrap/mk/Makefile.in @@ -0,0 +1,23 @@ +# Copyright 20126 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 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +include config.mk +include $(CFG_SRC_DIR)mk/util.mk + +ifdef VERBOSE +BOOTSTRAP_ARGS := -v +else +BOOTSTRAP_ARGS := +endif + +BOOTSTRAP := $(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap.py $(BOOTSTRAP_ARGS) + +all: + $(Q)$(BOOTSTRAP) From 55dd595c081f76c90f212811ccb55fdf0861784b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 21 Jan 2016 18:37:46 -0800 Subject: [PATCH 10/10] rustc_back: Fix disabling jemalloc When building with Cargo we need to detect `feature = "jemalloc"` to enable jemalloc, so propagate this same change to the build system to pass the right `--cfg` argument. --- mk/crates.mk | 3 +-- src/librustc_back/target/mod.rs | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/mk/crates.mk b/mk/crates.mk index 3021727cb109f..bfd054ae988f2 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -144,8 +144,7 @@ TARGET_CRATES += alloc_jemalloc DEPS_std += alloc_jemalloc DEPS_alloc_jemalloc := core libc native:jemalloc ONLY_RLIB_alloc_jemalloc := 1 -else -RUSTFLAGS_rustc_back := --cfg disable_jemalloc +RUSTFLAGS_rustc_back := --cfg 'feature="jemalloc"' endif ################################################################################ diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index a6aef52caf6ed..0920155ef423d 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -501,9 +501,9 @@ impl Target { } fn maybe_jemalloc() -> String { - if cfg!(disable_jemalloc) { - "alloc_system".to_string() - } else { + if cfg!(feature = "jemalloc") { "alloc_jemalloc".to_string() + } else { + "alloc_system".to_string() } }