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/configure b/configure index dde17e76d8a86..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" @@ -625,7 +626,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" @@ -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/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/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/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..744c30aa08f07 --- /dev/null +++ b/src/bootstrap/bootstrap.py @@ -0,0 +1,316 @@ +# 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 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: + 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 + 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): + 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 + config = self.get_mk('CFG_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 +try: + rb.config_mk = open('config.mk').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..c22648b471098 --- /dev/null +++ b/src/bootstrap/build/compile.rs @@ -0,0 +1,249 @@ +// 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("CFG_PREFIX", build.config.prefix.clone().unwrap_or(String::new())) + .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..1e67c4a9a3e8d --- /dev/null +++ b/src/bootstrap/build/config.rs @@ -0,0 +1,361 @@ +// 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, + pub prefix: 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 + } + + 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) { + 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/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) 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/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_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs new file mode 100644 index 0000000000000..4bc752af48eee --- /dev/null +++ b/src/liballoc_jemalloc/build.rs @@ -0,0 +1,106 @@ +// 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() { + 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()); + 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/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/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/libflate/build.rs b/src/libflate/build.rs new file mode 100644 index 0000000000000..245c705dfcc2a --- /dev/null +++ b/src/libflate/build.rs @@ -0,0 +1,18 @@ +// 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() { + 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/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_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() } } 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_llvm/build.rs b/src/librustc_llvm/build.rs new file mode 100644 index 0000000000000..1c9982790cf4a --- /dev/null +++ b/src/librustc_llvm/build.rs @@ -0,0 +1,132 @@ +// 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() { + 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(|| { + 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/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 059287ccb5ec3..1933c926e3018 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. */ @@ -2163,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)] @@ -2396,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))] @@ -2417,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 { @@ -2486,6 +2450,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/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/librustdoc/build.rs b/src/librustdoc/build.rs new file mode 100644 index 0000000000000..171954f325a5e --- /dev/null +++ b/src/librustdoc/build.rs @@ -0,0 +1,27 @@ +// 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() { + println!("cargo:rustc-cfg=cargobuild"); + 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/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/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/libstd/build.rs b/src/libstd/build.rs new file mode 100644 index 0000000000000..8fb49a1be4ea6 --- /dev/null +++ b/src/libstd/build.rs @@ -0,0 +1,112 @@ +// 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() { + println!("cargo:rustc-cfg=cargobuild"); + + 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())); +} 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; 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/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/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/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(); diff --git a/src/rustc/Cargo.lock b/src/rustc/Cargo.lock new file mode 100644 index 0000000000000..2a7da33bb68dd --- /dev/null +++ b/src/rustc/Cargo.lock @@ -0,0 +1,368 @@ +[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_passes 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_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" +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", + "rustc_mir 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