mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +00:00
Auto merge of #43051 - Mark-Simulacrum:rollup, r=Mark-Simulacrum
Rollup of 8 pull requests - Successful merges: #42227, #42836, #42975, #42994, #43041, #43042, #43043, #43045 - Failed merges:
This commit is contained in:
commit
2fbba5bdba
1
.gitignore
vendored
1
.gitignore
vendored
@ -51,6 +51,7 @@
|
||||
.hg/
|
||||
.hgignore
|
||||
.idea
|
||||
*.iml
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
@ -40,8 +40,9 @@ Read ["Installation"] from [The Book].
|
||||
|
||||
> ***Note:*** Install locations can be adjusted by copying the config file
|
||||
> from `./src/bootstrap/config.toml.example` to `./config.toml`, and
|
||||
> adjusting the `prefix` option under `[install]`. Various other options are
|
||||
> also supported, and are documented in the config file.
|
||||
> adjusting the `prefix` option under `[install]`. Various other options, such
|
||||
> as enabling debug information, are also supported, and are documented in
|
||||
> the config file.
|
||||
|
||||
When complete, `sudo ./x.py install` will place several programs into
|
||||
`/usr/local/bin`: `rustc`, the Rust compiler, and `rustdoc`, the
|
||||
|
@ -75,16 +75,11 @@ fn main() {
|
||||
Err(_) => 0,
|
||||
};
|
||||
|
||||
// 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.
|
||||
//
|
||||
// Also note that cargo will detect the version of the compiler to trigger
|
||||
// a rebuild when the compiler changes. If this happens, we want to make
|
||||
// sure to use the actual compiler instead of the snapshot compiler becase
|
||||
// that's the one that's actually changing.
|
||||
// Use a different compiler for build scripts, since there may not yet be a
|
||||
// libstd for the real compiler to use. However, if Cargo is attempting to
|
||||
// determine the version of the compiler, the real compiler needs to be
|
||||
// used. Currently, these two states are differentiated based on whether
|
||||
// --target and -vV is/isn't passed.
|
||||
let (rustc, libdir) = if target.is_none() && version.is_none() {
|
||||
("RUSTC_SNAPSHOT", "RUSTC_SNAPSHOT_LIBDIR")
|
||||
} else {
|
||||
|
@ -42,10 +42,13 @@ use 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() {
|
||||
//
|
||||
// This includes targets that aren't necessarily passed on the commandline
|
||||
// (FIXME: Perhaps it shouldn't?)
|
||||
for target in &build.config.target {
|
||||
let mut cfg = gcc::Config::new();
|
||||
cfg.cargo_metadata(false).opt_level(0).debug(false)
|
||||
.target(target).host(&build.config.build);
|
||||
.target(target).host(&build.build);
|
||||
|
||||
let config = build.config.target_config.get(target);
|
||||
if let Some(cc) = config.and_then(|c| c.cc.as_ref()) {
|
||||
@ -64,10 +67,13 @@ pub fn find(build: &mut Build) {
|
||||
}
|
||||
|
||||
// For all host triples we need to find a C++ compiler as well
|
||||
for host in build.config.host.iter() {
|
||||
//
|
||||
// This includes hosts that aren't necessarily passed on the commandline
|
||||
// (FIXME: Perhaps it shouldn't?)
|
||||
for host in &build.config.host {
|
||||
let mut cfg = gcc::Config::new();
|
||||
cfg.cargo_metadata(false).opt_level(0).debug(false).cpp(true)
|
||||
.target(host).host(&build.config.build);
|
||||
.target(host).host(&build.build);
|
||||
let config = build.config.target_config.get(host);
|
||||
if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) {
|
||||
cfg.compiler(cxx);
|
||||
|
@ -23,12 +23,12 @@ use build_helper::output;
|
||||
use Build;
|
||||
|
||||
// The version number
|
||||
pub const CFG_RELEASE_NUM: &'static str = "1.20.0";
|
||||
pub const CFG_RELEASE_NUM: &str = "1.20.0";
|
||||
|
||||
// An optional number to put after the label, e.g. '.2' -> '-beta.2'
|
||||
// Be sure to make this starts with a dot to conform to semver pre-release
|
||||
// versions (section 9)
|
||||
pub const CFG_PRERELEASE_VERSION: &'static str = ".1";
|
||||
pub const CFG_PRERELEASE_VERSION: &str = ".1";
|
||||
|
||||
pub struct GitInfo {
|
||||
inner: Option<Info>,
|
||||
@ -99,6 +99,10 @@ impl GitInfo {
|
||||
version.push_str(&inner.commit_date);
|
||||
version.push_str(")");
|
||||
}
|
||||
return version
|
||||
version
|
||||
}
|
||||
|
||||
pub fn is_git(&self) -> bool {
|
||||
self.inner.is_some()
|
||||
}
|
||||
}
|
||||
|
@ -13,23 +13,22 @@
|
||||
//! This file implements the various regression test suites that we execute on
|
||||
//! our CI.
|
||||
|
||||
extern crate build_helper;
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::iter;
|
||||
use std::fmt;
|
||||
use std::fs::{self, File};
|
||||
use std::path::{PathBuf, Path};
|
||||
use std::process::Command;
|
||||
use std::io::Read;
|
||||
|
||||
use build_helper::output;
|
||||
use build_helper::{self, output};
|
||||
|
||||
use {Build, Compiler, Mode};
|
||||
use dist;
|
||||
use util::{self, dylib_path, dylib_path_var, exe};
|
||||
|
||||
const ADB_TEST_DIR: &'static str = "/data/tmp/work";
|
||||
const ADB_TEST_DIR: &str = "/data/tmp/work";
|
||||
|
||||
/// The two modes of the test runner; tests or benchmarks.
|
||||
#[derive(Copy, Clone)]
|
||||
@ -60,7 +59,7 @@ impl fmt::Display for TestKind {
|
||||
}
|
||||
|
||||
fn try_run(build: &Build, cmd: &mut Command) {
|
||||
if build.flags.cmd.no_fail_fast() {
|
||||
if !build.fail_fast {
|
||||
if !build.try_run(cmd) {
|
||||
let failures = build.delayed_failures.get();
|
||||
build.delayed_failures.set(failures + 1);
|
||||
@ -71,7 +70,7 @@ fn try_run(build: &Build, cmd: &mut Command) {
|
||||
}
|
||||
|
||||
fn try_run_quiet(build: &Build, cmd: &mut Command) {
|
||||
if build.flags.cmd.no_fail_fast() {
|
||||
if !build.fail_fast {
|
||||
if !build.try_run_quiet(cmd) {
|
||||
let failures = build.delayed_failures.get();
|
||||
build.delayed_failures.set(failures + 1);
|
||||
@ -99,7 +98,7 @@ pub fn linkcheck(build: &Build, host: &str) {
|
||||
/// This tool in `src/tools` will check out a few Rust projects and run `cargo
|
||||
/// test` to ensure that we don't regress the test suites there.
|
||||
pub fn cargotest(build: &Build, stage: u32, host: &str) {
|
||||
let ref compiler = Compiler::new(stage, host);
|
||||
let compiler = Compiler::new(stage, host);
|
||||
|
||||
// Note that this is a short, cryptic, and not scoped directory name. This
|
||||
// is currently to minimize the length of path on Windows where we otherwise
|
||||
@ -109,11 +108,11 @@ pub fn cargotest(build: &Build, stage: u32, host: &str) {
|
||||
|
||||
let _time = util::timeit();
|
||||
let mut cmd = Command::new(build.tool(&Compiler::new(0, host), "cargotest"));
|
||||
build.prepare_tool_cmd(compiler, &mut cmd);
|
||||
try_run(build, cmd.arg(&build.cargo)
|
||||
build.prepare_tool_cmd(&compiler, &mut cmd);
|
||||
try_run(build, cmd.arg(&build.initial_cargo)
|
||||
.arg(&out_dir)
|
||||
.env("RUSTC", build.compiler_path(compiler))
|
||||
.env("RUSTDOC", build.rustdoc(compiler)));
|
||||
.env("RUSTC", build.compiler_path(&compiler))
|
||||
.env("RUSTDOC", build.rustdoc(&compiler)));
|
||||
}
|
||||
|
||||
/// Runs `cargo test` for `cargo` packaged with Rust.
|
||||
@ -124,13 +123,12 @@ pub fn cargo(build: &Build, stage: u32, host: &str) {
|
||||
// and not RUSTC because the Cargo test suite has tests that will
|
||||
// fail if rustc is not spelled `rustc`.
|
||||
let path = build.sysroot(compiler).join("bin");
|
||||
let old_path = ::std::env::var("PATH").expect("");
|
||||
let sep = if cfg!(windows) { ";" } else {":" };
|
||||
let ref newpath = format!("{}{}{}", path.display(), sep, old_path);
|
||||
let old_path = env::var_os("PATH").unwrap_or_default();
|
||||
let newpath = env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("");
|
||||
|
||||
let mut cargo = build.cargo(compiler, Mode::Tool, host, "test");
|
||||
cargo.arg("--manifest-path").arg(build.src.join("src/tools/cargo/Cargo.toml"));
|
||||
if build.flags.cmd.no_fail_fast() {
|
||||
if !build.fail_fast {
|
||||
cargo.arg("--no-fail-fast");
|
||||
}
|
||||
|
||||
@ -198,9 +196,9 @@ pub fn compiletest(build: &Build,
|
||||
cmd.arg("--mode").arg(mode);
|
||||
cmd.arg("--target").arg(target);
|
||||
cmd.arg("--host").arg(compiler.host);
|
||||
cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.config.build));
|
||||
cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.build));
|
||||
|
||||
if let Some(nodejs) = build.config.nodejs.as_ref() {
|
||||
if let Some(ref nodejs) = build.config.nodejs {
|
||||
cmd.arg("--nodejs").arg(nodejs);
|
||||
}
|
||||
|
||||
@ -224,7 +222,7 @@ pub fn compiletest(build: &Build,
|
||||
|
||||
cmd.arg("--docck-python").arg(build.python());
|
||||
|
||||
if build.config.build.ends_with("apple-darwin") {
|
||||
if build.build.ends_with("apple-darwin") {
|
||||
// Force /usr/bin/python on macOS for LLDB tests because we're loading the
|
||||
// LLDB plugin's compiled module which only works with the system python
|
||||
// (namely not Homebrew-installed python)
|
||||
@ -251,7 +249,7 @@ pub fn compiletest(build: &Build,
|
||||
|
||||
cmd.args(&build.flags.cmd.test_args());
|
||||
|
||||
if build.config.verbose() || build.flags.verbose() {
|
||||
if build.is_verbose() {
|
||||
cmd.arg("--verbose");
|
||||
}
|
||||
|
||||
@ -279,7 +277,7 @@ pub fn compiletest(build: &Build,
|
||||
|
||||
if build.remote_tested(target) {
|
||||
cmd.arg("--remote-test-client")
|
||||
.arg(build.tool(&Compiler::new(0, &build.config.build),
|
||||
.arg(build.tool(&Compiler::new(0, &build.build),
|
||||
"remote-test-client"));
|
||||
}
|
||||
|
||||
@ -368,7 +366,7 @@ pub fn error_index(build: &Build, compiler: &Compiler) {
|
||||
"error_index_generator")
|
||||
.arg("markdown")
|
||||
.arg(&output)
|
||||
.env("CFG_BUILD", &build.config.build));
|
||||
.env("CFG_BUILD", &build.build));
|
||||
|
||||
markdown_test(build, compiler, &output);
|
||||
}
|
||||
@ -450,7 +448,7 @@ pub fn krate(build: &Build,
|
||||
cargo.arg("--manifest-path")
|
||||
.arg(build.src.join(path).join("Cargo.toml"))
|
||||
.arg("--features").arg(features);
|
||||
if test_kind.subcommand() == "test" && build.flags.cmd.no_fail_fast() {
|
||||
if test_kind.subcommand() == "test" && !build.fail_fast {
|
||||
cargo.arg("--no-fail-fast");
|
||||
}
|
||||
|
||||
@ -520,16 +518,14 @@ fn krate_emscripten(build: &Build,
|
||||
compiler: &Compiler,
|
||||
target: &str,
|
||||
mode: Mode) {
|
||||
let mut tests = Vec::new();
|
||||
let out_dir = build.cargo_out(compiler, mode, target);
|
||||
find_tests(&out_dir.join("deps"), target, &mut tests);
|
||||
let tests = find_tests(&out_dir.join("deps"), target);
|
||||
|
||||
let nodejs = build.config.nodejs.as_ref().expect("nodejs not configured");
|
||||
for test in tests {
|
||||
let test_file_name = test.to_string_lossy().into_owned();
|
||||
println!("running {}", test_file_name);
|
||||
let nodejs = build.config.nodejs.as_ref().expect("nodejs not configured");
|
||||
println!("running {}", test.display());
|
||||
let mut cmd = Command::new(nodejs);
|
||||
cmd.arg(&test_file_name);
|
||||
cmd.arg(&test);
|
||||
if build.config.quiet_tests {
|
||||
cmd.arg("--quiet");
|
||||
}
|
||||
@ -541,11 +537,10 @@ fn krate_remote(build: &Build,
|
||||
compiler: &Compiler,
|
||||
target: &str,
|
||||
mode: Mode) {
|
||||
let mut tests = Vec::new();
|
||||
let out_dir = build.cargo_out(compiler, mode, target);
|
||||
find_tests(&out_dir.join("deps"), target, &mut tests);
|
||||
let tests = find_tests(&out_dir.join("deps"), target);
|
||||
|
||||
let tool = build.tool(&Compiler::new(0, &build.config.build),
|
||||
let tool = build.tool(&Compiler::new(0, &build.build),
|
||||
"remote-test-client");
|
||||
for test in tests {
|
||||
let mut cmd = Command::new(&tool);
|
||||
@ -559,9 +554,8 @@ fn krate_remote(build: &Build,
|
||||
}
|
||||
}
|
||||
|
||||
fn find_tests(dir: &Path,
|
||||
target: &str,
|
||||
dst: &mut Vec<PathBuf>) {
|
||||
fn find_tests(dir: &Path, target: &str) -> Vec<PathBuf> {
|
||||
let mut dst = Vec::new();
|
||||
for e in t!(dir.read_dir()).map(|e| t!(e)) {
|
||||
let file_type = t!(e.file_type());
|
||||
if !file_type.is_file() {
|
||||
@ -576,6 +570,7 @@ fn find_tests(dir: &Path,
|
||||
dst.push(e.path());
|
||||
}
|
||||
}
|
||||
dst
|
||||
}
|
||||
|
||||
pub fn remote_copy_libs(build: &Build, compiler: &Compiler, target: &str) {
|
||||
@ -590,7 +585,7 @@ pub fn remote_copy_libs(build: &Build, compiler: &Compiler, target: &str) {
|
||||
.join(exe("remote-test-server", target));
|
||||
|
||||
// Spawn the emulator and wait for it to come online
|
||||
let tool = build.tool(&Compiler::new(0, &build.config.build),
|
||||
let tool = build.tool(&Compiler::new(0, &build.build),
|
||||
"remote-test-client");
|
||||
let mut cmd = Command::new(&tool);
|
||||
cmd.arg("spawn-emulator")
|
||||
@ -616,7 +611,7 @@ pub fn remote_copy_libs(build: &Build, compiler: &Compiler, target: &str) {
|
||||
|
||||
/// Run "distcheck", a 'make check' from a tarball
|
||||
pub fn distcheck(build: &Build) {
|
||||
if build.config.build != "x86_64-unknown-linux-gnu" {
|
||||
if build.build != "x86_64-unknown-linux-gnu" {
|
||||
return
|
||||
}
|
||||
if !build.config.host.iter().any(|s| s == "x86_64-unknown-linux-gnu") {
|
||||
@ -641,7 +636,7 @@ pub fn distcheck(build: &Build) {
|
||||
.args(&build.config.configure_args)
|
||||
.arg("--enable-vendor")
|
||||
.current_dir(&dir));
|
||||
build.run(Command::new(build_helper::make(&build.config.build))
|
||||
build.run(Command::new(build_helper::make(&build.build))
|
||||
.arg("check")
|
||||
.current_dir(&dir));
|
||||
|
||||
@ -659,7 +654,7 @@ pub fn distcheck(build: &Build) {
|
||||
build.run(&mut cmd);
|
||||
|
||||
let toml = dir.join("rust-src/lib/rustlib/src/rust/src/libstd/Cargo.toml");
|
||||
build.run(Command::new(&build.cargo)
|
||||
build.run(Command::new(&build.initial_cargo)
|
||||
.arg("generate-lockfile")
|
||||
.arg("--manifest-path")
|
||||
.arg(&toml)
|
||||
@ -668,13 +663,13 @@ pub fn distcheck(build: &Build) {
|
||||
|
||||
/// Test the build system itself
|
||||
pub fn bootstrap(build: &Build) {
|
||||
let mut cmd = Command::new(&build.cargo);
|
||||
let mut cmd = Command::new(&build.initial_cargo);
|
||||
cmd.arg("test")
|
||||
.current_dir(build.src.join("src/bootstrap"))
|
||||
.env("CARGO_TARGET_DIR", build.out.join("bootstrap"))
|
||||
.env("RUSTC_BOOTSTRAP", "1")
|
||||
.env("RUSTC", &build.rustc);
|
||||
if build.flags.cmd.no_fail_fast() {
|
||||
.env("RUSTC", &build.initial_rustc);
|
||||
if !build.fail_fast {
|
||||
cmd.arg("--no-fail-fast");
|
||||
}
|
||||
cmd.arg("--").args(&build.flags.cmd.test_args());
|
||||
|
@ -50,7 +50,7 @@ pub fn std(build: &Build, target: &str, compiler: &Compiler) {
|
||||
let mut cargo = build.cargo(compiler, Mode::Libstd, target, "build");
|
||||
let mut features = build.std_features();
|
||||
|
||||
if let Ok(target) = env::var("MACOSX_STD_DEPLOYMENT_TARGET") {
|
||||
if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
|
||||
cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
|
||||
}
|
||||
|
||||
@ -158,7 +158,7 @@ pub fn build_startup_objects(build: &Build, for_compiler: &Compiler, target: &st
|
||||
return
|
||||
}
|
||||
|
||||
let compiler = Compiler::new(0, &build.config.build);
|
||||
let compiler = Compiler::new(0, &build.build);
|
||||
let compiler_path = build.compiler_path(&compiler);
|
||||
let src_dir = &build.src.join("src/rtstartup");
|
||||
let dst_dir = &build.native_dir(target).join("rtstartup");
|
||||
@ -199,7 +199,7 @@ pub fn test(build: &Build, target: &str, compiler: &Compiler) {
|
||||
let out_dir = build.cargo_out(compiler, Mode::Libtest, target);
|
||||
build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target));
|
||||
let mut cargo = build.cargo(compiler, Mode::Libtest, target, "build");
|
||||
if let Ok(target) = env::var("MACOSX_STD_DEPLOYMENT_TARGET") {
|
||||
if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
|
||||
cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
|
||||
}
|
||||
cargo.arg("--manifest-path")
|
||||
@ -247,7 +247,7 @@ pub fn rustc(build: &Build, target: &str, compiler: &Compiler) {
|
||||
cargo.env("CFG_RELEASE", build.rust_release())
|
||||
.env("CFG_RELEASE_CHANNEL", &build.config.channel)
|
||||
.env("CFG_VERSION", build.rust_version())
|
||||
.env("CFG_PREFIX", build.config.prefix.clone().unwrap_or(PathBuf::new()));
|
||||
.env("CFG_PREFIX", build.config.prefix.clone().unwrap_or_default());
|
||||
|
||||
if compiler.stage == 0 {
|
||||
cargo.env("CFG_LIBDIR_RELATIVE", "lib");
|
||||
@ -351,7 +351,7 @@ pub fn create_sysroot(build: &Build, compiler: &Compiler) {
|
||||
/// Prepare a new compiler from the artifacts in `stage`
|
||||
///
|
||||
/// This will assemble a compiler in `build/$host/stage$stage`. The compiler
|
||||
/// must have been previously produced by the `stage - 1` build.config.build
|
||||
/// must have been previously produced by the `stage - 1` build.build
|
||||
/// compiler.
|
||||
pub fn assemble_rustc(build: &Build, stage: u32, host: &str) {
|
||||
// nothing to do in stage0
|
||||
@ -365,7 +365,7 @@ pub fn assemble_rustc(build: &Build, stage: u32, host: &str) {
|
||||
let target_compiler = Compiler::new(stage, host);
|
||||
|
||||
// The compiler that compiled the compiler we're assembling
|
||||
let build_compiler = Compiler::new(stage - 1, &build.config.build);
|
||||
let build_compiler = Compiler::new(stage - 1, &build.build);
|
||||
|
||||
// Link in all dylibs to the libdir
|
||||
let sysroot = build.sysroot(&target_compiler);
|
||||
@ -385,7 +385,7 @@ pub fn assemble_rustc(build: &Build, stage: u32, host: &str) {
|
||||
let rustc = out_dir.join(exe("rustc", host));
|
||||
let bindir = sysroot.join("bin");
|
||||
t!(fs::create_dir_all(&bindir));
|
||||
let compiler = build.compiler_path(&Compiler::new(stage, host));
|
||||
let compiler = build.compiler_path(&target_compiler);
|
||||
let _ = fs::remove_file(&compiler);
|
||||
copy(&rustc, &compiler);
|
||||
|
||||
@ -407,6 +407,8 @@ fn add_to_sysroot(sysroot_dst: &Path, stamp: &Path) {
|
||||
t!(fs::create_dir_all(&sysroot_dst));
|
||||
let mut contents = Vec::new();
|
||||
t!(t!(File::open(stamp)).read_to_end(&mut contents));
|
||||
// This is the method we use for extracting paths from the stamp file passed to us. See
|
||||
// run_cargo for more information (in this file).
|
||||
for part in contents.split(|b| *b == 0) {
|
||||
if part.is_empty() {
|
||||
continue
|
||||
@ -421,7 +423,7 @@ fn add_to_sysroot(sysroot_dst: &Path, stamp: &Path) {
|
||||
/// This will build the specified tool with the specified `host` compiler in
|
||||
/// `stage` into the normal cargo output directory.
|
||||
pub fn maybe_clean_tools(build: &Build, stage: u32, target: &str, mode: Mode) {
|
||||
let compiler = Compiler::new(stage, &build.config.build);
|
||||
let compiler = Compiler::new(stage, &build.build);
|
||||
|
||||
let stamp = match mode {
|
||||
Mode::Libstd => libstd_stamp(build, &compiler, target),
|
||||
@ -441,7 +443,7 @@ pub fn tool(build: &Build, stage: u32, target: &str, tool: &str) {
|
||||
let _folder = build.fold_output(|| format!("stage{}-{}", stage, tool));
|
||||
println!("Building stage{} tool {} ({})", stage, tool, target);
|
||||
|
||||
let compiler = Compiler::new(stage, &build.config.build);
|
||||
let compiler = Compiler::new(stage, &build.build);
|
||||
|
||||
let mut cargo = build.cargo(&compiler, Mode::Tool, target, "build");
|
||||
let dir = build.src.join("src/tools").join(tool);
|
||||
@ -557,23 +559,24 @@ fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path) {
|
||||
// If this was an output file in the "host dir" we don't actually
|
||||
// worry about it, it's not relevant for us.
|
||||
if filename.starts_with(&host_root_dir) {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
|
||||
// If this was output in the `deps` dir then this is a precise file
|
||||
// name (hash included) so we start tracking it.
|
||||
} else if filename.starts_with(&target_deps_dir) {
|
||||
if filename.starts_with(&target_deps_dir) {
|
||||
deps.push(filename.to_path_buf());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise this was a "top level artifact" which right now doesn't
|
||||
// have a hash in the name, but there's a version of this file in
|
||||
// the `deps` folder which *does* have a hash in the name. That's
|
||||
// the one we'll want to we'll probe for it later.
|
||||
} else {
|
||||
toplevel.push((filename.file_stem().unwrap()
|
||||
.to_str().unwrap().to_string(),
|
||||
filename.extension().unwrap().to_owned()
|
||||
.to_str().unwrap().to_string()));
|
||||
}
|
||||
toplevel.push((filename.file_stem().unwrap()
|
||||
.to_str().unwrap().to_string(),
|
||||
filename.extension().unwrap().to_owned()
|
||||
.to_str().unwrap().to_string()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,8 +81,6 @@ pub struct Config {
|
||||
pub build: String,
|
||||
pub host: Vec<String>,
|
||||
pub target: Vec<String>,
|
||||
pub rustc: Option<PathBuf>,
|
||||
pub cargo: Option<PathBuf>,
|
||||
pub local_rebuild: bool,
|
||||
|
||||
// dist misc
|
||||
@ -114,11 +112,18 @@ pub struct Config {
|
||||
pub python: Option<PathBuf>,
|
||||
pub configure_args: Vec<String>,
|
||||
pub openssl_static: bool,
|
||||
|
||||
|
||||
// These are either the stage0 downloaded binaries or the locally installed ones.
|
||||
pub initial_cargo: PathBuf,
|
||||
pub initial_rustc: PathBuf,
|
||||
|
||||
}
|
||||
|
||||
/// Per-target configuration stored in the global configuration structure.
|
||||
#[derive(Default)]
|
||||
pub struct Target {
|
||||
/// Some(path to llvm-config) if using an external LLVM.
|
||||
pub llvm_config: Option<PathBuf>,
|
||||
pub jemalloc: Option<PathBuf>,
|
||||
pub cc: Option<PathBuf>,
|
||||
@ -307,8 +312,6 @@ impl Config {
|
||||
config.target.push(target.clone());
|
||||
}
|
||||
}
|
||||
config.rustc = build.rustc.map(PathBuf::from);
|
||||
config.cargo = build.cargo.map(PathBuf::from);
|
||||
config.nodejs = build.nodejs.map(PathBuf::from);
|
||||
config.gdb = build.gdb.map(PathBuf::from);
|
||||
config.python = build.python.map(PathBuf::from);
|
||||
@ -410,13 +413,25 @@ impl Config {
|
||||
set(&mut config.rust_dist_src, t.src_tarball);
|
||||
}
|
||||
|
||||
let cwd = t!(env::current_dir());
|
||||
let out = cwd.join("build");
|
||||
|
||||
let stage0_root = out.join(&config.build).join("stage0/bin");
|
||||
config.initial_rustc = match build.rustc {
|
||||
Some(s) => PathBuf::from(s),
|
||||
None => stage0_root.join(exe("rustc", &config.build)),
|
||||
};
|
||||
config.initial_cargo = match build.cargo {
|
||||
Some(s) => PathBuf::from(s),
|
||||
None => stage0_root.join(exe("cargo", &config.build)),
|
||||
};
|
||||
|
||||
// compat with `./configure` while we're still using that
|
||||
if fs::metadata("config.mk").is_ok() {
|
||||
config.update_with_config_mk();
|
||||
}
|
||||
|
||||
return config
|
||||
config
|
||||
}
|
||||
|
||||
/// "Temporary" routine to parse `config.mk` into this configuration.
|
||||
@ -609,8 +624,8 @@ impl Config {
|
||||
}
|
||||
"CFG_LOCAL_RUST_ROOT" if value.len() > 0 => {
|
||||
let path = parse_configure_path(value);
|
||||
self.rustc = Some(push_exe_path(path.clone(), &["bin", "rustc"]));
|
||||
self.cargo = Some(push_exe_path(path, &["bin", "cargo"]));
|
||||
self.initial_rustc = push_exe_path(path.clone(), &["bin", "rustc"]);
|
||||
self.initial_cargo = push_exe_path(path, &["bin", "cargo"]);
|
||||
}
|
||||
"CFG_PYTHON" if value.len() > 0 => {
|
||||
let path = parse_configure_path(value);
|
||||
|
@ -50,7 +50,7 @@ pub fn tmpdir(build: &Build) -> PathBuf {
|
||||
}
|
||||
|
||||
fn rust_installer(build: &Build) -> Command {
|
||||
build.tool_cmd(&Compiler::new(0, &build.config.build), "rust-installer")
|
||||
build.tool_cmd(&Compiler::new(0, &build.build), "rust-installer")
|
||||
}
|
||||
|
||||
/// Builds the `rust-docs` installer component.
|
||||
@ -89,7 +89,7 @@ pub fn docs(build: &Build, stage: u32, host: &str) {
|
||||
|
||||
// As part of this step, *also* copy the docs directory to a directory which
|
||||
// buildbot typically uploads.
|
||||
if host == build.config.build {
|
||||
if host == build.build {
|
||||
let dst = distdir(build).join("doc").join(build.rust_package_vers());
|
||||
t!(fs::create_dir_all(&dst));
|
||||
cp_r(&src, &dst);
|
||||
@ -97,7 +97,7 @@ pub fn docs(build: &Build, stage: u32, host: &str) {
|
||||
}
|
||||
|
||||
fn find_files(files: &[&str], path: &[PathBuf]) -> Vec<PathBuf> {
|
||||
let mut found = Vec::new();
|
||||
let mut found = Vec::with_capacity(files.len());
|
||||
|
||||
for file in files {
|
||||
let file_path =
|
||||
@ -119,17 +119,9 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build:
|
||||
//Ask gcc where it keeps its stuff
|
||||
let mut cmd = Command::new(build.cc(target_triple));
|
||||
cmd.arg("-print-search-dirs");
|
||||
build.run_quiet(&mut cmd);
|
||||
let gcc_out =
|
||||
String::from_utf8(
|
||||
cmd
|
||||
.output()
|
||||
.expect("failed to execute gcc")
|
||||
.stdout).expect("gcc.exe output was not utf8");
|
||||
let gcc_out = output(&mut cmd);
|
||||
|
||||
let mut bin_path: Vec<_> =
|
||||
env::split_paths(&env::var_os("PATH").unwrap_or_default())
|
||||
.collect();
|
||||
let mut bin_path: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect();
|
||||
let mut lib_path = Vec::new();
|
||||
|
||||
for line in gcc_out.lines() {
|
||||
@ -140,7 +132,7 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build:
|
||||
line[(idx + 1)..]
|
||||
.trim_left_matches(trim_chars)
|
||||
.split(';')
|
||||
.map(|s| PathBuf::from(s));
|
||||
.map(PathBuf::from);
|
||||
|
||||
if key == "programs" {
|
||||
bin_path.extend(value);
|
||||
@ -149,7 +141,7 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build:
|
||||
}
|
||||
}
|
||||
|
||||
let target_tools = vec!["gcc.exe", "ld.exe", "ar.exe", "dlltool.exe", "libwinpthread-1.dll"];
|
||||
let target_tools = ["gcc.exe", "ld.exe", "ar.exe", "dlltool.exe", "libwinpthread-1.dll"];
|
||||
let mut rustc_dlls = vec!["libstdc++-6.dll", "libwinpthread-1.dll"];
|
||||
if target_triple.starts_with("i686-") {
|
||||
rustc_dlls.push("libgcc_s_dw2-1.dll");
|
||||
@ -157,7 +149,7 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build:
|
||||
rustc_dlls.push("libgcc_s_seh-1.dll");
|
||||
}
|
||||
|
||||
let target_libs = vec![ //MinGW libs
|
||||
let target_libs = [ //MinGW libs
|
||||
"libgcc.a",
|
||||
"libgcc_eh.a",
|
||||
"libgcc_s.a",
|
||||
@ -203,7 +195,7 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build:
|
||||
let target_libs = find_files(&target_libs, &lib_path);
|
||||
|
||||
fn copy_to_folder(src: &Path, dest_folder: &Path) {
|
||||
let file_name = src.file_name().unwrap().to_os_string();
|
||||
let file_name = src.file_name().unwrap();
|
||||
let dest = dest_folder.join(file_name);
|
||||
copy(src, &dest);
|
||||
}
|
||||
@ -234,8 +226,6 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build:
|
||||
///
|
||||
/// This contains all the bits and pieces to run the MinGW Windows targets
|
||||
/// without any extra installed software (e.g. we bundle gcc, libraries, etc).
|
||||
/// Currently just shells out to a python script, but that should be rewritten
|
||||
/// in Rust.
|
||||
pub fn mingw(build: &Build, host: &str) {
|
||||
println!("Dist mingw ({})", host);
|
||||
let name = pkgname(build, "rust-mingw");
|
||||
@ -366,9 +356,9 @@ pub fn rustc(build: &Build, stage: u32, host: &str) {
|
||||
pub fn debugger_scripts(build: &Build,
|
||||
sysroot: &Path,
|
||||
host: &str) {
|
||||
let dst = sysroot.join("lib/rustlib/etc");
|
||||
t!(fs::create_dir_all(&dst));
|
||||
let cp_debugger_script = |file: &str| {
|
||||
let dst = sysroot.join("lib/rustlib/etc");
|
||||
t!(fs::create_dir_all(&dst));
|
||||
install(&build.src.join("src/etc/").join(file), &dst, 0o644);
|
||||
};
|
||||
if host.contains("windows-msvc") {
|
||||
@ -404,7 +394,7 @@ pub fn std(build: &Build, compiler: &Compiler, target: &str) {
|
||||
|
||||
// The only true set of target libraries came from the build triple, so
|
||||
// let's reduce redundant work by only producing archives from that host.
|
||||
if compiler.host != build.config.build {
|
||||
if compiler.host != build.build {
|
||||
println!("\tskipping, not a build host");
|
||||
return
|
||||
}
|
||||
@ -450,7 +440,7 @@ pub fn analysis(build: &Build, compiler: &Compiler, target: &str) {
|
||||
assert!(build.config.extended);
|
||||
println!("Dist analysis");
|
||||
|
||||
if compiler.host != build.config.build {
|
||||
if compiler.host != build.build {
|
||||
println!("\tskipping, not a build host");
|
||||
return;
|
||||
}
|
||||
@ -498,12 +488,11 @@ fn copy_src_dirs(build: &Build, src_dirs: &[&str], exclude_dirs: &[&str], dst_di
|
||||
if spath.ends_with("~") || spath.ends_with(".pyc") {
|
||||
return false
|
||||
}
|
||||
if spath.contains("llvm/test") || spath.contains("llvm\\test") {
|
||||
if spath.ends_with(".ll") ||
|
||||
spath.ends_with(".td") ||
|
||||
spath.ends_with(".s") {
|
||||
return false
|
||||
}
|
||||
if (spath.contains("llvm/test") || spath.contains("llvm\\test")) &&
|
||||
(spath.ends_with(".ll") ||
|
||||
spath.ends_with(".td") ||
|
||||
spath.ends_with(".s")) {
|
||||
return false
|
||||
}
|
||||
|
||||
let full_path = Path::new(dir).join(path);
|
||||
@ -595,7 +584,7 @@ pub fn rust_src(build: &Build) {
|
||||
t!(fs::remove_dir_all(&image));
|
||||
}
|
||||
|
||||
const CARGO_VENDOR_VERSION: &'static str = "0.1.4";
|
||||
const CARGO_VENDOR_VERSION: &str = "0.1.4";
|
||||
|
||||
/// Creates the plain source tarball
|
||||
pub fn plain_source_tarball(build: &Build) {
|
||||
@ -634,26 +623,26 @@ pub fn plain_source_tarball(build: &Build) {
|
||||
write_file(&plain_dst_src.join("version"), build.rust_version().as_bytes());
|
||||
|
||||
// If we're building from git sources, we need to vendor a complete distribution.
|
||||
if build.src_is_git {
|
||||
if build.rust_info.is_git() {
|
||||
// Get cargo-vendor installed, if it isn't already.
|
||||
let mut has_cargo_vendor = false;
|
||||
let mut cmd = Command::new(&build.cargo);
|
||||
let mut cmd = Command::new(&build.initial_cargo);
|
||||
for line in output(cmd.arg("install").arg("--list")).lines() {
|
||||
has_cargo_vendor |= line.starts_with("cargo-vendor ");
|
||||
}
|
||||
if !has_cargo_vendor {
|
||||
let mut cmd = Command::new(&build.cargo);
|
||||
let mut cmd = Command::new(&build.initial_cargo);
|
||||
cmd.arg("install")
|
||||
.arg("--force")
|
||||
.arg("--debug")
|
||||
.arg("--vers").arg(CARGO_VENDOR_VERSION)
|
||||
.arg("cargo-vendor")
|
||||
.env("RUSTC", &build.rustc);
|
||||
.env("RUSTC", &build.initial_rustc);
|
||||
build.run(&mut cmd);
|
||||
}
|
||||
|
||||
// Vendor all Cargo dependencies
|
||||
let mut cmd = Command::new(&build.cargo);
|
||||
let mut cmd = Command::new(&build.initial_cargo);
|
||||
cmd.arg("vendor")
|
||||
.current_dir(&plain_dst_src.join("src"));
|
||||
build.run(&mut cmd);
|
||||
@ -716,7 +705,7 @@ fn write_file(path: &Path, data: &[u8]) {
|
||||
|
||||
pub fn cargo(build: &Build, stage: u32, target: &str) {
|
||||
println!("Dist cargo stage{} ({})", stage, target);
|
||||
let compiler = Compiler::new(stage, &build.config.build);
|
||||
let compiler = Compiler::new(stage, &build.build);
|
||||
|
||||
let src = build.src.join("src/tools/cargo");
|
||||
let etc = src.join("src/etc");
|
||||
@ -777,7 +766,7 @@ pub fn cargo(build: &Build, stage: u32, target: &str) {
|
||||
pub fn rls(build: &Build, stage: u32, target: &str) {
|
||||
assert!(build.config.extended);
|
||||
println!("Dist RLS stage{} ({})", stage, target);
|
||||
let compiler = Compiler::new(stage, &build.config.build);
|
||||
let compiler = Compiler::new(stage, &build.build);
|
||||
|
||||
let src = build.src.join("src/tools/rls");
|
||||
let release_num = build.release_num("rls");
|
||||
@ -1209,7 +1198,7 @@ fn add_env(build: &Build, cmd: &mut Command, target: &str) {
|
||||
}
|
||||
|
||||
pub fn hash_and_sign(build: &Build) {
|
||||
let compiler = Compiler::new(0, &build.config.build);
|
||||
let compiler = Compiler::new(0, &build.build);
|
||||
let mut cmd = build.tool_cmd(&compiler, "build-manifest");
|
||||
let sign = build.config.dist_sign_folder.as_ref().unwrap_or_else(|| {
|
||||
panic!("\n\nfailed to specify `dist.sign-folder` in `config.toml`\n\n")
|
||||
|
@ -45,7 +45,7 @@ pub fn rustbook_src(build: &Build, target: &str, name: &str, src: &Path) {
|
||||
t!(fs::create_dir_all(&out));
|
||||
|
||||
let out = out.join(name);
|
||||
let compiler = Compiler::new(0, &build.config.build);
|
||||
let compiler = Compiler::new(0, &build.build);
|
||||
let src = src.join(name);
|
||||
let index = out.join("index.html");
|
||||
let rustbook = build.tool(&compiler, "rustbook");
|
||||
@ -95,7 +95,7 @@ pub fn book(build: &Build, target: &str, name: &str) {
|
||||
fn invoke_rustdoc(build: &Build, target: &str, markdown: &str) {
|
||||
let out = build.doc_out(target);
|
||||
|
||||
let compiler = Compiler::new(0, &build.config.build);
|
||||
let compiler = Compiler::new(0, &build.build);
|
||||
|
||||
let path = build.src.join("src/doc").join(markdown);
|
||||
|
||||
@ -150,7 +150,7 @@ pub fn standalone(build: &Build, target: &str) {
|
||||
let out = build.doc_out(target);
|
||||
t!(fs::create_dir_all(&out));
|
||||
|
||||
let compiler = Compiler::new(0, &build.config.build);
|
||||
let compiler = Compiler::new(0, &build.build);
|
||||
|
||||
let favicon = build.src.join("src/doc/favicon.inc");
|
||||
let footer = build.src.join("src/doc/footer.inc");
|
||||
@ -217,7 +217,7 @@ pub fn std(build: &Build, stage: u32, target: &str) {
|
||||
println!("Documenting stage{} std ({})", stage, target);
|
||||
let out = build.doc_out(target);
|
||||
t!(fs::create_dir_all(&out));
|
||||
let compiler = Compiler::new(stage, &build.config.build);
|
||||
let compiler = Compiler::new(stage, &build.build);
|
||||
let compiler = if build.force_use_stage1(&compiler, target) {
|
||||
Compiler::new(1, compiler.host)
|
||||
} else {
|
||||
@ -276,7 +276,7 @@ pub fn test(build: &Build, stage: u32, target: &str) {
|
||||
println!("Documenting stage{} test ({})", stage, target);
|
||||
let out = build.doc_out(target);
|
||||
t!(fs::create_dir_all(&out));
|
||||
let compiler = Compiler::new(stage, &build.config.build);
|
||||
let compiler = Compiler::new(stage, &build.build);
|
||||
let compiler = if build.force_use_stage1(&compiler, target) {
|
||||
Compiler::new(1, compiler.host)
|
||||
} else {
|
||||
@ -306,7 +306,7 @@ pub fn rustc(build: &Build, stage: u32, target: &str) {
|
||||
println!("Documenting stage{} compiler ({})", stage, target);
|
||||
let out = build.doc_out(target);
|
||||
t!(fs::create_dir_all(&out));
|
||||
let compiler = Compiler::new(stage, &build.config.build);
|
||||
let compiler = Compiler::new(stage, &build.build);
|
||||
let compiler = if build.force_use_stage1(&compiler, target) {
|
||||
Compiler::new(1, compiler.host)
|
||||
} else {
|
||||
@ -351,13 +351,13 @@ pub fn error_index(build: &Build, target: &str) {
|
||||
println!("Documenting error index ({})", target);
|
||||
let out = build.doc_out(target);
|
||||
t!(fs::create_dir_all(&out));
|
||||
let compiler = Compiler::new(0, &build.config.build);
|
||||
let compiler = Compiler::new(0, &build.build);
|
||||
let mut index = build.tool_cmd(&compiler, "error_index_generator");
|
||||
index.arg("html");
|
||||
index.arg(out.join("error-index.html"));
|
||||
|
||||
// FIXME: shouldn't have to pass this env var
|
||||
index.env("CFG_BUILD", &build.config.build);
|
||||
index.env("CFG_BUILD", &build.build);
|
||||
|
||||
build.run(&mut index);
|
||||
}
|
||||
@ -367,7 +367,7 @@ pub fn unstable_book_gen(build: &Build, target: &str) {
|
||||
let out = build.md_doc_out(target).join("unstable-book");
|
||||
t!(fs::create_dir_all(&out));
|
||||
t!(fs::remove_dir_all(&out));
|
||||
let compiler = Compiler::new(0, &build.config.build);
|
||||
let compiler = Compiler::new(0, &build.build);
|
||||
let mut cmd = build.tool_cmd(&compiler, "unstable-book-gen");
|
||||
cmd.arg(build.src.join("src"));
|
||||
cmd.arg(out);
|
||||
|
@ -35,22 +35,12 @@ pub struct Flags {
|
||||
pub host: Vec<String>,
|
||||
pub target: Vec<String>,
|
||||
pub config: Option<PathBuf>,
|
||||
pub src: Option<PathBuf>,
|
||||
pub src: PathBuf,
|
||||
pub jobs: Option<u32>,
|
||||
pub cmd: Subcommand,
|
||||
pub incremental: bool,
|
||||
}
|
||||
|
||||
impl Flags {
|
||||
pub fn verbose(&self) -> bool {
|
||||
self.verbose > 0
|
||||
}
|
||||
|
||||
pub fn very_verbose(&self) -> bool {
|
||||
self.verbose > 1
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Subcommand {
|
||||
Build {
|
||||
paths: Vec<PathBuf>,
|
||||
@ -61,7 +51,7 @@ pub enum Subcommand {
|
||||
Test {
|
||||
paths: Vec<PathBuf>,
|
||||
test_args: Vec<String>,
|
||||
no_fail_fast: bool,
|
||||
fail_fast: bool,
|
||||
},
|
||||
Bench {
|
||||
paths: Vec<PathBuf>,
|
||||
@ -122,16 +112,15 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
|
||||
// the subcommand. Therefore we must manually identify the subcommand first, so that we can
|
||||
// complete the definition of the options. Then we can use the getopt::Matches object from
|
||||
// there on out.
|
||||
let mut possible_subcommands = args.iter().collect::<Vec<_>>();
|
||||
possible_subcommands.retain(|&s|
|
||||
(s == "build")
|
||||
|| (s == "test")
|
||||
|| (s == "bench")
|
||||
|| (s == "doc")
|
||||
|| (s == "clean")
|
||||
|| (s == "dist")
|
||||
|| (s == "install"));
|
||||
let subcommand = match possible_subcommands.first() {
|
||||
let subcommand = args.iter().find(|&s|
|
||||
(s == "build")
|
||||
|| (s == "test")
|
||||
|| (s == "bench")
|
||||
|| (s == "doc")
|
||||
|| (s == "clean")
|
||||
|| (s == "dist")
|
||||
|| (s == "install"));
|
||||
let subcommand = match subcommand {
|
||||
Some(s) => s,
|
||||
None => {
|
||||
// No subcommand -- show the general usage and subcommand help
|
||||
@ -164,7 +153,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
|
||||
let mut pass_sanity_check = true;
|
||||
match matches.free.get(0) {
|
||||
Some(check_subcommand) => {
|
||||
if &check_subcommand != subcommand {
|
||||
if check_subcommand != subcommand {
|
||||
pass_sanity_check = false;
|
||||
}
|
||||
},
|
||||
@ -279,7 +268,7 @@ Arguments:
|
||||
Subcommand::Test {
|
||||
paths: paths,
|
||||
test_args: matches.opt_strs("test-args"),
|
||||
no_fail_fast: matches.opt_present("no-fail-fast"),
|
||||
fail_fast: !matches.opt_present("no-fail-fast"),
|
||||
}
|
||||
}
|
||||
"bench" => {
|
||||
@ -316,12 +305,15 @@ Arguments:
|
||||
|
||||
let mut stage = matches.opt_str("stage").map(|j| j.parse().unwrap());
|
||||
|
||||
if matches.opt_present("incremental") {
|
||||
if stage.is_none() {
|
||||
stage = Some(1);
|
||||
}
|
||||
if matches.opt_present("incremental") && stage.is_none() {
|
||||
stage = Some(1);
|
||||
}
|
||||
|
||||
let cwd = t!(env::current_dir());
|
||||
let src = matches.opt_str("src").map(PathBuf::from)
|
||||
.or_else(|| env::var_os("SRC").map(PathBuf::from))
|
||||
.unwrap_or(cwd);
|
||||
|
||||
Flags {
|
||||
verbose: matches.opt_count("verbose"),
|
||||
stage: stage,
|
||||
@ -333,7 +325,7 @@ Arguments:
|
||||
host: split(matches.opt_strs("host")),
|
||||
target: split(matches.opt_strs("target")),
|
||||
config: cfg_file,
|
||||
src: matches.opt_str("src").map(PathBuf::from),
|
||||
src: src,
|
||||
jobs: matches.opt_str("jobs").map(|j| j.parse().unwrap()),
|
||||
cmd: cmd,
|
||||
incremental: matches.opt_present("incremental"),
|
||||
@ -352,9 +344,9 @@ impl Subcommand {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn no_fail_fast(&self) -> bool {
|
||||
pub fn fail_fast(&self) -> bool {
|
||||
match *self {
|
||||
Subcommand::Test { no_fail_fast, .. } => no_fail_fast,
|
||||
Subcommand::Test { fail_fast, .. } => fail_fast,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -146,5 +146,5 @@ fn add_destdir(path: &Path, destdir: &Option<PathBuf>) -> PathBuf {
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
ret
|
||||
}
|
||||
|
@ -161,25 +161,35 @@ pub struct Build {
|
||||
flags: Flags,
|
||||
|
||||
// Derived properties from the above two configurations
|
||||
cargo: PathBuf,
|
||||
rustc: PathBuf,
|
||||
src: PathBuf,
|
||||
out: PathBuf,
|
||||
rust_info: channel::GitInfo,
|
||||
cargo_info: channel::GitInfo,
|
||||
rls_info: channel::GitInfo,
|
||||
local_rebuild: bool,
|
||||
fail_fast: bool,
|
||||
verbosity: usize,
|
||||
|
||||
// Targets for which to build.
|
||||
build: String,
|
||||
hosts: Vec<String>,
|
||||
targets: Vec<String>,
|
||||
|
||||
// Stage 0 (downloaded) compiler and cargo or their local rust equivalents.
|
||||
initial_rustc: PathBuf,
|
||||
initial_cargo: PathBuf,
|
||||
|
||||
// Probed tools at runtime
|
||||
lldb_version: Option<String>,
|
||||
lldb_python_dir: Option<String>,
|
||||
|
||||
// Runtime state filled in later on
|
||||
// target -> (cc, ar)
|
||||
cc: HashMap<String, (gcc::Tool, Option<PathBuf>)>,
|
||||
// host -> (cc, ar)
|
||||
cxx: HashMap<String, gcc::Tool>,
|
||||
crates: HashMap<String, Crate>,
|
||||
is_sudo: bool,
|
||||
src_is_git: bool,
|
||||
ci_env: CiEnv,
|
||||
delayed_failures: Cell<usize>,
|
||||
}
|
||||
@ -202,20 +212,16 @@ struct Crate {
|
||||
/// build system, with each mod generating output in a different directory.
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Mode {
|
||||
/// This cargo is going to build the standard library, placing output in the
|
||||
/// "stageN-std" directory.
|
||||
/// Build the standard library, placing output in the "stageN-std" directory.
|
||||
Libstd,
|
||||
|
||||
/// This cargo is going to build libtest, placing output in the
|
||||
/// "stageN-test" directory.
|
||||
/// Build libtest, placing output in the "stageN-test" directory.
|
||||
Libtest,
|
||||
|
||||
/// This cargo is going to build librustc and compiler libraries, placing
|
||||
/// output in the "stageN-rustc" directory.
|
||||
/// Build librustc and compiler libraries, placing output in the "stageN-rustc" directory.
|
||||
Librustc,
|
||||
|
||||
/// This cargo is going to build some tool, placing output in the
|
||||
/// "stageN-tools" directory.
|
||||
/// Build some tool, placing output in the "stageN-tools" directory.
|
||||
Tool,
|
||||
}
|
||||
|
||||
@ -226,22 +232,9 @@ impl Build {
|
||||
/// By default all build output will be placed in the current directory.
|
||||
pub fn new(flags: Flags, config: Config) -> Build {
|
||||
let cwd = t!(env::current_dir());
|
||||
let src = flags.src.clone().or_else(|| {
|
||||
env::var_os("SRC").map(|x| x.into())
|
||||
}).unwrap_or(cwd.clone());
|
||||
let src = flags.src.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)),
|
||||
};
|
||||
let local_rebuild = config.local_rebuild;
|
||||
|
||||
let is_sudo = match env::var_os("SUDO_USER") {
|
||||
Some(sudo_user) => {
|
||||
match env::var_os("USER") {
|
||||
@ -254,32 +247,64 @@ impl Build {
|
||||
let rust_info = channel::GitInfo::new(&src);
|
||||
let cargo_info = channel::GitInfo::new(&src.join("src/tools/cargo"));
|
||||
let rls_info = channel::GitInfo::new(&src.join("src/tools/rls"));
|
||||
let src_is_git = src.join(".git").exists();
|
||||
|
||||
let hosts = if !flags.host.is_empty() {
|
||||
for host in flags.host.iter() {
|
||||
if !config.host.contains(host) {
|
||||
panic!("specified host `{}` is not in configuration", host);
|
||||
}
|
||||
}
|
||||
flags.host.clone()
|
||||
} else {
|
||||
config.host.clone()
|
||||
};
|
||||
let targets = if !flags.target.is_empty() {
|
||||
for target in flags.target.iter() {
|
||||
if !config.target.contains(target) {
|
||||
panic!("specified target `{}` is not in configuration", target);
|
||||
}
|
||||
}
|
||||
flags.target.clone()
|
||||
} else {
|
||||
config.target.clone()
|
||||
};
|
||||
|
||||
Build {
|
||||
initial_rustc: config.initial_rustc.clone(),
|
||||
initial_cargo: config.initial_cargo.clone(),
|
||||
local_rebuild: config.local_rebuild,
|
||||
fail_fast: flags.cmd.fail_fast(),
|
||||
verbosity: cmp::max(flags.verbose, config.verbose),
|
||||
|
||||
build: config.host[0].clone(),
|
||||
hosts: hosts,
|
||||
targets: targets,
|
||||
|
||||
flags: flags,
|
||||
config: config,
|
||||
cargo: cargo,
|
||||
rustc: rustc,
|
||||
src: src,
|
||||
out: out,
|
||||
|
||||
rust_info: rust_info,
|
||||
cargo_info: cargo_info,
|
||||
rls_info: rls_info,
|
||||
local_rebuild: local_rebuild,
|
||||
cc: HashMap::new(),
|
||||
cxx: HashMap::new(),
|
||||
crates: HashMap::new(),
|
||||
lldb_version: None,
|
||||
lldb_python_dir: None,
|
||||
is_sudo: is_sudo,
|
||||
src_is_git: src_is_git,
|
||||
ci_env: CiEnv::current(),
|
||||
delayed_failures: Cell::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_slice(&self) -> &[String] {
|
||||
unsafe {
|
||||
std::slice::from_raw_parts(&self.build, 1)
|
||||
}
|
||||
}
|
||||
|
||||
/// Executes the entire build, as configured by the flags and configuration.
|
||||
pub fn build(&mut self) {
|
||||
unsafe {
|
||||
@ -296,7 +321,7 @@ impl Build {
|
||||
sanity::check(self);
|
||||
// If local-rust is the same major.minor as the current version, then force a local-rebuild
|
||||
let local_version_verbose = output(
|
||||
Command::new(&self.rustc).arg("--version").arg("--verbose"));
|
||||
Command::new(&self.initial_rustc).arg("--version").arg("--verbose"));
|
||||
let local_release = local_version_verbose
|
||||
.lines().filter(|x| x.starts_with("release:"))
|
||||
.next().unwrap().trim_left_matches("release:").trim();
|
||||
@ -338,7 +363,7 @@ impl Build {
|
||||
mode: Mode,
|
||||
target: &str,
|
||||
cmd: &str) -> Command {
|
||||
let mut cargo = Command::new(&self.cargo);
|
||||
let mut cargo = Command::new(&self.initial_cargo);
|
||||
let out_dir = self.stage_out(compiler, mode);
|
||||
cargo.env("CARGO_TARGET_DIR", out_dir)
|
||||
.arg(cmd)
|
||||
@ -422,7 +447,7 @@ impl Build {
|
||||
// library up and running, so we can use the normal compiler to compile
|
||||
// build scripts in that situation.
|
||||
if mode == Mode::Libstd {
|
||||
cargo.env("RUSTC_SNAPSHOT", &self.rustc)
|
||||
cargo.env("RUSTC_SNAPSHOT", &self.initial_rustc)
|
||||
.env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir());
|
||||
} else {
|
||||
cargo.env("RUSTC_SNAPSHOT", self.compiler_path(compiler))
|
||||
@ -441,8 +466,7 @@ impl Build {
|
||||
cargo.env("RUSTC_ON_FAIL", on_fail);
|
||||
}
|
||||
|
||||
let verbose = cmp::max(self.config.verbose, self.flags.verbose);
|
||||
cargo.env("RUSTC_VERBOSE", format!("{}", verbose));
|
||||
cargo.env("RUSTC_VERBOSE", format!("{}", self.verbosity));
|
||||
|
||||
// Specify some various options for build scripts used throughout
|
||||
// the build.
|
||||
@ -480,7 +504,7 @@ impl Build {
|
||||
// FIXME: should update code to not require this env var
|
||||
cargo.env("CFG_COMPILER_HOST_TRIPLE", target);
|
||||
|
||||
if self.config.verbose() || self.flags.verbose() {
|
||||
if self.is_verbose() {
|
||||
cargo.arg("-v");
|
||||
}
|
||||
// FIXME: cargo bench does not accept `--release`
|
||||
@ -496,13 +520,13 @@ impl Build {
|
||||
|
||||
self.ci_env.force_coloring_in_ci(&mut cargo);
|
||||
|
||||
return cargo
|
||||
cargo
|
||||
}
|
||||
|
||||
/// Get a path to the compiler specified.
|
||||
fn compiler_path(&self, compiler: &Compiler) -> PathBuf {
|
||||
if compiler.is_snapshot(self) {
|
||||
self.rustc.clone()
|
||||
self.initial_rustc.clone()
|
||||
} else {
|
||||
self.sysroot(compiler).join("bin").join(exe("rustc", compiler.host))
|
||||
}
|
||||
@ -519,7 +543,7 @@ impl Build {
|
||||
let mut rustdoc = self.compiler_path(compiler);
|
||||
rustdoc.pop();
|
||||
rustdoc.push(exe("rustdoc", compiler.host));
|
||||
return rustdoc
|
||||
rustdoc
|
||||
}
|
||||
|
||||
/// Get a `Command` which is ready to run `tool` in `stage` built for
|
||||
@ -527,7 +551,7 @@ impl Build {
|
||||
fn tool_cmd(&self, compiler: &Compiler, tool: &str) -> Command {
|
||||
let mut cmd = Command::new(self.tool(&compiler, tool));
|
||||
self.prepare_tool_cmd(compiler, &mut cmd);
|
||||
return cmd
|
||||
cmd
|
||||
}
|
||||
|
||||
/// Prepares the `cmd` provided to be able to run the `compiler` provided.
|
||||
@ -578,7 +602,7 @@ impl Build {
|
||||
if self.config.profiler {
|
||||
features.push_str(" profiler");
|
||||
}
|
||||
return features
|
||||
features
|
||||
}
|
||||
|
||||
/// Get the space-separated set of activated features for the compiler.
|
||||
@ -587,7 +611,7 @@ impl Build {
|
||||
if self.config.use_jemalloc {
|
||||
features.push_str(" jemalloc");
|
||||
}
|
||||
return features
|
||||
features
|
||||
}
|
||||
|
||||
/// Component directory that Cargo will produce output into (e.g.
|
||||
@ -760,7 +784,7 @@ impl Build {
|
||||
|
||||
/// Returns the libdir of the snapshot compiler.
|
||||
fn rustc_snapshot_libdir(&self) -> PathBuf {
|
||||
self.rustc.parent().unwrap().parent().unwrap()
|
||||
self.initial_rustc.parent().unwrap().parent().unwrap()
|
||||
.join(libdir(&self.config.build))
|
||||
}
|
||||
|
||||
@ -792,9 +816,17 @@ impl Build {
|
||||
try_run_suppressed(cmd)
|
||||
}
|
||||
|
||||
pub fn is_verbose(&self) -> bool {
|
||||
self.verbosity > 0
|
||||
}
|
||||
|
||||
pub fn is_very_verbose(&self) -> bool {
|
||||
self.verbosity > 1
|
||||
}
|
||||
|
||||
/// Prints a message if this build is configured in verbose mode.
|
||||
fn verbose(&self, msg: &str) {
|
||||
if self.flags.verbose() || self.config.verbose() {
|
||||
if self.is_verbose() {
|
||||
println!("{}", msg);
|
||||
}
|
||||
}
|
||||
@ -802,7 +834,7 @@ impl Build {
|
||||
/// Returns the number of parallel jobs that have been configured for this
|
||||
/// build.
|
||||
fn jobs(&self) -> u32 {
|
||||
self.flags.jobs.unwrap_or(num_cpus::get() as u32)
|
||||
self.flags.jobs.unwrap_or_else(|| num_cpus::get() as u32)
|
||||
}
|
||||
|
||||
/// Returns the path to the C compiler for the target specified.
|
||||
@ -834,7 +866,7 @@ impl Build {
|
||||
if target == "i686-pc-windows-gnu" {
|
||||
base.push("-fno-omit-frame-pointer".into());
|
||||
}
|
||||
return base
|
||||
base
|
||||
}
|
||||
|
||||
/// Returns the path to the `ar` archive utility for the target specified.
|
||||
@ -866,7 +898,7 @@ impl Build {
|
||||
!target.contains("emscripten") {
|
||||
base.push(format!("-Clinker={}", self.cc(target).display()));
|
||||
}
|
||||
return base
|
||||
base
|
||||
}
|
||||
|
||||
/// Returns the "musl root" for this `target`, if defined
|
||||
@ -1047,7 +1079,7 @@ impl<'a> Compiler<'a> {
|
||||
|
||||
/// Returns whether this is a snapshot compiler for `build`'s configuration
|
||||
fn is_snapshot(&self, build: &Build) -> bool {
|
||||
self.stage == 0 && self.host == build.config.build
|
||||
self.stage == 0 && self.host == build.build
|
||||
}
|
||||
|
||||
/// Returns if this compiler should be treated as a final stage one in the
|
||||
|
@ -56,7 +56,7 @@ fn build_krate(build: &mut Build, krate: &str) {
|
||||
// of packages we're going to have to know what `-p` arguments to pass it
|
||||
// to know what crates to test. Here we run `cargo metadata` to learn about
|
||||
// the dependency graph and what `-p` arguments there are.
|
||||
let mut cargo = Command::new(&build.cargo);
|
||||
let mut cargo = Command::new(&build.initial_cargo);
|
||||
cargo.arg("metadata")
|
||||
.arg("--format-version").arg("1")
|
||||
.arg("--manifest-path").arg(build.src.join(krate).join("Cargo.toml"));
|
||||
|
@ -94,7 +94,7 @@ pub fn llvm(build: &Build, target: &str) {
|
||||
let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"};
|
||||
|
||||
cfg.target(target)
|
||||
.host(&build.config.build)
|
||||
.host(&build.build)
|
||||
.out_dir(&out_dir)
|
||||
.profile(profile)
|
||||
.define("LLVM_ENABLE_ASSERTIONS", assertions)
|
||||
@ -129,11 +129,11 @@ pub fn llvm(build: &Build, target: &str) {
|
||||
}
|
||||
|
||||
// http://llvm.org/docs/HowToCrossCompileLLVM.html
|
||||
if target != build.config.build {
|
||||
if target != build.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");
|
||||
let host = build.llvm_out(&build.build).join("bin/llvm-tblgen");
|
||||
cfg.define("CMAKE_CROSSCOMPILING", "True")
|
||||
.define("LLVM_TABLEGEN", &host);
|
||||
}
|
||||
@ -243,7 +243,7 @@ pub fn test_helpers(build: &Build, target: &str) {
|
||||
cfg.cargo_metadata(false)
|
||||
.out_dir(&dst)
|
||||
.target(target)
|
||||
.host(&build.config.build)
|
||||
.host(&build.build)
|
||||
.opt_level(0)
|
||||
.debug(false)
|
||||
.file(build.src.join("src/rt/rust_test_helpers.c"))
|
||||
|
@ -18,9 +18,9 @@
|
||||
//! In theory if we get past this phase it's a bug if a build fails, but in
|
||||
//! practice that's likely not true!
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::ffi::{OsString, OsStr};
|
||||
use std::fs;
|
||||
use std::process::Command;
|
||||
use std::path::PathBuf;
|
||||
@ -29,45 +29,59 @@ use build_helper::output;
|
||||
|
||||
use Build;
|
||||
|
||||
struct Finder {
|
||||
cache: HashMap<OsString, Option<PathBuf>>,
|
||||
path: OsString,
|
||||
}
|
||||
|
||||
impl Finder {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
cache: HashMap::new(),
|
||||
path: env::var_os("PATH").unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
fn maybe_have<S: AsRef<OsStr>>(&mut self, cmd: S) -> Option<PathBuf> {
|
||||
let cmd: OsString = cmd.as_ref().into();
|
||||
let path = self.path.clone();
|
||||
self.cache.entry(cmd.clone()).or_insert_with(|| {
|
||||
for path in env::split_paths(&path) {
|
||||
let target = path.join(&cmd);
|
||||
let mut cmd_alt = cmd.clone();
|
||||
cmd_alt.push(".exe");
|
||||
if target.is_file() || // some/path/git
|
||||
target.with_extension("exe").exists() || // some/path/git.exe
|
||||
target.join(&cmd_alt).exists() { // some/path/git/git.exe
|
||||
return Some(target);
|
||||
}
|
||||
}
|
||||
None
|
||||
}).clone()
|
||||
}
|
||||
|
||||
fn must_have<S: AsRef<OsStr>>(&mut self, cmd: S) -> PathBuf {
|
||||
self.maybe_have(&cmd).unwrap_or_else(|| {
|
||||
panic!("\n\ncouldn't find required command: {:?}\n\n", cmd.as_ref());
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check(build: &mut Build) {
|
||||
let mut checked = HashSet::new();
|
||||
let path = env::var_os("PATH").unwrap_or(OsString::new());
|
||||
let path = env::var_os("PATH").unwrap_or_default();
|
||||
// On Windows, quotes are invalid characters for filename paths, and if
|
||||
// one is present as part of the PATH then that can lead to the system
|
||||
// being unable to identify the files properly. See
|
||||
// https://github.com/rust-lang/rust/issues/34959 for more details.
|
||||
if cfg!(windows) {
|
||||
if path.to_string_lossy().contains("\"") {
|
||||
panic!("PATH contains invalid character '\"'");
|
||||
}
|
||||
if cfg!(windows) && path.to_string_lossy().contains("\"") {
|
||||
panic!("PATH contains invalid character '\"'");
|
||||
}
|
||||
let have_cmd = |cmd: &OsStr| {
|
||||
for path in env::split_paths(&path) {
|
||||
let target = path.join(cmd);
|
||||
let mut cmd_alt = cmd.to_os_string();
|
||||
cmd_alt.push(".exe");
|
||||
if target.is_file() ||
|
||||
target.with_extension("exe").exists() ||
|
||||
target.join(cmd_alt).exists() {
|
||||
return Some(target);
|
||||
}
|
||||
}
|
||||
return None;
|
||||
};
|
||||
|
||||
let mut need_cmd = |cmd: &OsStr| {
|
||||
if !checked.insert(cmd.to_owned()) {
|
||||
return
|
||||
}
|
||||
if have_cmd(cmd).is_none() {
|
||||
panic!("\n\ncouldn't find required command: {:?}\n\n", cmd);
|
||||
}
|
||||
};
|
||||
|
||||
let mut cmd_finder = Finder::new();
|
||||
// If we've got a git directory we're gona need git to update
|
||||
// submodules and learn about various other aspects.
|
||||
if build.src_is_git {
|
||||
need_cmd("git".as_ref());
|
||||
if build.rust_info.is_git() {
|
||||
cmd_finder.must_have("git");
|
||||
}
|
||||
|
||||
// We need cmake, but only if we're actually building LLVM or sanitizers.
|
||||
@ -75,57 +89,32 @@ pub fn check(build: &mut Build) {
|
||||
.filter_map(|host| build.config.target_config.get(host))
|
||||
.any(|config| config.llvm_config.is_none());
|
||||
if building_llvm || build.config.sanitizers {
|
||||
need_cmd("cmake".as_ref());
|
||||
cmd_finder.must_have("cmake");
|
||||
}
|
||||
|
||||
// Ninja is currently only used for LLVM itself.
|
||||
if building_llvm && build.config.ninja {
|
||||
// Some Linux distros rename `ninja` to `ninja-build`.
|
||||
// CMake can work with either binary name.
|
||||
if have_cmd("ninja-build".as_ref()).is_none() {
|
||||
need_cmd("ninja".as_ref());
|
||||
}
|
||||
// Some Linux distros rename `ninja` to `ninja-build`.
|
||||
// CMake can work with either binary name.
|
||||
if building_llvm && build.config.ninja && cmd_finder.maybe_have("ninja-build").is_none() {
|
||||
cmd_finder.must_have("ninja");
|
||||
}
|
||||
|
||||
if build.config.python.is_none() {
|
||||
// set by bootstrap.py
|
||||
if let Some(v) = env::var_os("BOOTSTRAP_PYTHON") {
|
||||
build.config.python = Some(PathBuf::from(v));
|
||||
}
|
||||
}
|
||||
if build.config.python.is_none() {
|
||||
build.config.python = have_cmd("python2.7".as_ref());
|
||||
}
|
||||
if build.config.python.is_none() {
|
||||
build.config.python = have_cmd("python2".as_ref());
|
||||
}
|
||||
if build.config.python.is_none() {
|
||||
need_cmd("python".as_ref());
|
||||
build.config.python = Some("python".into());
|
||||
}
|
||||
need_cmd(build.config.python.as_ref().unwrap().as_ref());
|
||||
build.config.python = build.config.python.take().map(|p| cmd_finder.must_have(p))
|
||||
.or_else(|| env::var_os("BOOTSTRAP_PYTHON").map(PathBuf::from)) // set by bootstrap.py
|
||||
.or_else(|| cmd_finder.maybe_have("python2.7"))
|
||||
.or_else(|| cmd_finder.maybe_have("python2"))
|
||||
.or_else(|| Some(cmd_finder.must_have("python")));
|
||||
|
||||
build.config.nodejs = build.config.nodejs.take().map(|p| cmd_finder.must_have(p))
|
||||
.or_else(|| cmd_finder.maybe_have("node"))
|
||||
.or_else(|| cmd_finder.maybe_have("nodejs"));
|
||||
|
||||
if let Some(ref s) = build.config.nodejs {
|
||||
need_cmd(s.as_ref());
|
||||
} else {
|
||||
// Look for the nodejs command, needed for emscripten testing
|
||||
if let Some(node) = have_cmd("node".as_ref()) {
|
||||
build.config.nodejs = Some(node);
|
||||
} else if let Some(node) = have_cmd("nodejs".as_ref()) {
|
||||
build.config.nodejs = Some(node);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref gdb) = build.config.gdb {
|
||||
need_cmd(gdb.as_ref());
|
||||
} else {
|
||||
build.config.gdb = have_cmd("gdb".as_ref());
|
||||
}
|
||||
build.config.gdb = build.config.gdb.take().map(|p| cmd_finder.must_have(p))
|
||||
.or_else(|| cmd_finder.maybe_have("gdb"));
|
||||
|
||||
// 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() {
|
||||
for target in &build.config.target {
|
||||
// On emscripten we don't actually need the C compiler to just
|
||||
// build the target artifacts, only for testing. For the sake
|
||||
// of easier bot configuration, just skip detection.
|
||||
@ -133,33 +122,32 @@ pub fn check(build: &mut Build) {
|
||||
continue;
|
||||
}
|
||||
|
||||
need_cmd(build.cc(target).as_ref());
|
||||
cmd_finder.must_have(build.cc(target));
|
||||
if let Some(ar) = build.ar(target) {
|
||||
need_cmd(ar.as_ref());
|
||||
cmd_finder.must_have(ar);
|
||||
}
|
||||
}
|
||||
for host in build.config.host.iter() {
|
||||
need_cmd(build.cxx(host).unwrap().as_ref());
|
||||
}
|
||||
|
||||
// The msvc hosts don't use jemalloc, turn it off globally to
|
||||
// avoid packaging the dummy liballoc_jemalloc on that platform.
|
||||
for host in build.config.host.iter() {
|
||||
cmd_finder.must_have(build.cxx(host).unwrap());
|
||||
|
||||
// The msvc hosts don't use jemalloc, turn it off globally to
|
||||
// avoid packaging the dummy liballoc_jemalloc on that platform.
|
||||
if host.contains("msvc") {
|
||||
build.config.use_jemalloc = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Externally configured LLVM requires FileCheck to exist
|
||||
let filecheck = build.llvm_filecheck(&build.config.build);
|
||||
let filecheck = build.llvm_filecheck(&build.build);
|
||||
if !filecheck.starts_with(&build.out) && !filecheck.exists() && build.config.codegen_tests {
|
||||
panic!("FileCheck executable {:?} does not exist", filecheck);
|
||||
}
|
||||
|
||||
for target in build.config.target.iter() {
|
||||
for target in &build.config.target {
|
||||
// Can't compile for iOS unless we're on macOS
|
||||
if target.contains("apple-ios") &&
|
||||
!build.config.build.contains("apple-darwin") {
|
||||
!build.build.contains("apple-darwin") {
|
||||
panic!("the iOS target is only supported on macOS");
|
||||
}
|
||||
|
||||
@ -206,18 +194,6 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake
|
||||
}
|
||||
}
|
||||
|
||||
for host in build.flags.host.iter() {
|
||||
if !build.config.host.contains(host) {
|
||||
panic!("specified host `{}` is not in the ./configure list", host);
|
||||
}
|
||||
}
|
||||
for target in build.flags.target.iter() {
|
||||
if !build.config.target.contains(target) {
|
||||
panic!("specified target `{}` is not in the ./configure list",
|
||||
target);
|
||||
}
|
||||
}
|
||||
|
||||
let run = |cmd: &mut Command| {
|
||||
cmd.output().map(|output| {
|
||||
String::from_utf8_lossy(&output.stdout)
|
||||
@ -231,6 +207,6 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake
|
||||
}
|
||||
|
||||
if let Some(ref s) = build.config.ccache {
|
||||
need_cmd(s.as_ref());
|
||||
cmd_finder.must_have(s);
|
||||
}
|
||||
}
|
||||
|
@ -104,10 +104,10 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
||||
rules.build("llvm", "src/llvm")
|
||||
.host(true)
|
||||
.dep(move |s| {
|
||||
if s.target == build.config.build {
|
||||
if s.target == build.build {
|
||||
Step::noop()
|
||||
} else {
|
||||
s.target(&build.config.build)
|
||||
s.target(&build.build)
|
||||
}
|
||||
})
|
||||
.run(move |s| native::llvm(build, s.target));
|
||||
@ -124,7 +124,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
||||
Step::noop()
|
||||
} else {
|
||||
s.name("librustc")
|
||||
.host(&build.config.build)
|
||||
.host(&build.build)
|
||||
.stage(s.stage - 1)
|
||||
}
|
||||
})
|
||||
@ -148,7 +148,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
ret
|
||||
};
|
||||
|
||||
// ========================================================================
|
||||
@ -215,29 +215,29 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
||||
let mut rule = rules.build(&krate, "path/to/nowhere");
|
||||
rule.dep(move |s| {
|
||||
if build.force_use_stage1(&s.compiler(), s.target) {
|
||||
s.host(&build.config.build).stage(1)
|
||||
} else if s.host == build.config.build {
|
||||
s.host(&build.build).stage(1)
|
||||
} else if s.host == build.build {
|
||||
s.name(dep)
|
||||
} else {
|
||||
s.host(&build.config.build)
|
||||
s.host(&build.build)
|
||||
}
|
||||
})
|
||||
.run(move |s| {
|
||||
if build.force_use_stage1(&s.compiler(), s.target) {
|
||||
link(build,
|
||||
&s.stage(1).host(&build.config.build).compiler(),
|
||||
&s.stage(1).host(&build.build).compiler(),
|
||||
&s.compiler(),
|
||||
s.target)
|
||||
} else if s.host == build.config.build {
|
||||
} else if s.host == build.build {
|
||||
link(build, &s.compiler(), &s.compiler(), s.target)
|
||||
} else {
|
||||
link(build,
|
||||
&s.host(&build.config.build).compiler(),
|
||||
&s.host(&build.build).compiler(),
|
||||
&s.compiler(),
|
||||
s.target)
|
||||
}
|
||||
});
|
||||
return rule
|
||||
rule
|
||||
}
|
||||
|
||||
// Similar to the `libstd`, `libtest`, and `librustc` rules above, except
|
||||
@ -269,7 +269,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
||||
for (krate, path, _default) in krates("std") {
|
||||
rules.build(&krate.build_step, path)
|
||||
.dep(|s| s.name("startup-objects"))
|
||||
.dep(move |s| s.name("rustc").host(&build.config.build).target(s.host))
|
||||
.dep(move |s| s.name("rustc").host(&build.build).target(s.host))
|
||||
.run(move |s| compile::std(build, s.target, &s.compiler()));
|
||||
}
|
||||
for (krate, path, _default) in krates("test") {
|
||||
@ -280,7 +280,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
||||
for (krate, path, _default) in krates("rustc-main") {
|
||||
rules.build(&krate.build_step, path)
|
||||
.dep(|s| s.name("libtest-link"))
|
||||
.dep(move |s| s.name("llvm").host(&build.config.build).stage(0))
|
||||
.dep(move |s| s.name("llvm").host(&build.build).stage(0))
|
||||
.dep(|s| s.name("may-run-build-script"))
|
||||
.run(move |s| compile::rustc(build, s.target, &s.compiler()));
|
||||
}
|
||||
@ -291,8 +291,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
||||
rules.build("may-run-build-script", "path/to/nowhere")
|
||||
.dep(move |s| {
|
||||
s.name("libstd-link")
|
||||
.host(&build.config.build)
|
||||
.target(&build.config.build)
|
||||
.host(&build.build)
|
||||
.target(&build.build)
|
||||
});
|
||||
rules.build("startup-objects", "src/rtstartup")
|
||||
.dep(|s| s.name("create-sysroot").target(s.host))
|
||||
@ -332,7 +332,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
||||
"incremental");
|
||||
}
|
||||
|
||||
if build.config.build.contains("msvc") {
|
||||
if build.build.contains("msvc") {
|
||||
// nothing to do for debuginfo tests
|
||||
} else {
|
||||
rules.test("check-debuginfo-lldb", "src/test/debuginfo-lldb")
|
||||
@ -352,7 +352,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
||||
"debuginfo-gdb", "debuginfo"));
|
||||
let mut rule = rules.test("check-debuginfo", "src/test/debuginfo");
|
||||
rule.default(true);
|
||||
if build.config.build.contains("apple") {
|
||||
if build.build.contains("apple") {
|
||||
rule.dep(|s| s.name("check-debuginfo-lldb"));
|
||||
} else {
|
||||
rule.dep(|s| s.name("check-debuginfo-gdb"));
|
||||
@ -594,8 +594,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
||||
// Cargo depends on procedural macros, which requires a full host
|
||||
// compiler to be available, so we need to depend on that.
|
||||
s.name("librustc-link")
|
||||
.target(&build.config.build)
|
||||
.host(&build.config.build)
|
||||
.target(&build.build)
|
||||
.host(&build.build)
|
||||
})
|
||||
.run(move |s| compile::tool(build, s.stage, s.target, "cargo"));
|
||||
rules.build("tool-rls", "src/tools/rls")
|
||||
@ -606,8 +606,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
||||
.dep(move |s| {
|
||||
// rls, like cargo, uses procedural macros
|
||||
s.name("librustc-link")
|
||||
.target(&build.config.build)
|
||||
.host(&build.config.build)
|
||||
.target(&build.build)
|
||||
.host(&build.build)
|
||||
})
|
||||
.run(move |s| compile::tool(build, s.stage, s.target, "rls"));
|
||||
|
||||
@ -635,8 +635,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
||||
rules.doc("doc-book", "src/doc/book")
|
||||
.dep(move |s| {
|
||||
s.name("tool-rustbook")
|
||||
.host(&build.config.build)
|
||||
.target(&build.config.build)
|
||||
.host(&build.build)
|
||||
.target(&build.build)
|
||||
.stage(0)
|
||||
})
|
||||
.default(build.config.docs)
|
||||
@ -644,8 +644,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
||||
rules.doc("doc-nomicon", "src/doc/nomicon")
|
||||
.dep(move |s| {
|
||||
s.name("tool-rustbook")
|
||||
.host(&build.config.build)
|
||||
.target(&build.config.build)
|
||||
.host(&build.build)
|
||||
.target(&build.build)
|
||||
.stage(0)
|
||||
})
|
||||
.default(build.config.docs)
|
||||
@ -653,8 +653,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
||||
rules.doc("doc-reference", "src/doc/reference")
|
||||
.dep(move |s| {
|
||||
s.name("tool-rustbook")
|
||||
.host(&build.config.build)
|
||||
.target(&build.config.build)
|
||||
.host(&build.build)
|
||||
.target(&build.build)
|
||||
.stage(0)
|
||||
})
|
||||
.default(build.config.docs)
|
||||
@ -662,8 +662,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
||||
rules.doc("doc-unstable-book", "src/doc/unstable-book")
|
||||
.dep(move |s| {
|
||||
s.name("tool-rustbook")
|
||||
.host(&build.config.build)
|
||||
.target(&build.config.build)
|
||||
.host(&build.build)
|
||||
.target(&build.build)
|
||||
.stage(0)
|
||||
})
|
||||
.dep(move |s| s.name("doc-unstable-book-gen"))
|
||||
@ -675,14 +675,14 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
||||
rules.doc("doc-standalone", "src/doc")
|
||||
.dep(move |s| {
|
||||
s.name("rustc")
|
||||
.host(&build.config.build)
|
||||
.target(&build.config.build)
|
||||
.host(&build.build)
|
||||
.target(&build.build)
|
||||
.stage(0)
|
||||
})
|
||||
.default(build.config.docs)
|
||||
.run(move |s| doc::standalone(build, s.target));
|
||||
rules.doc("doc-error-index", "src/tools/error_index_generator")
|
||||
.dep(move |s| s.name("tool-error-index").target(&build.config.build).stage(0))
|
||||
.dep(move |s| s.name("tool-error-index").target(&build.build).stage(0))
|
||||
.dep(move |s| s.name("librustc-link"))
|
||||
.default(build.config.docs)
|
||||
.host(true)
|
||||
@ -690,8 +690,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
||||
rules.doc("doc-unstable-book-gen", "src/tools/unstable-book-gen")
|
||||
.dep(move |s| {
|
||||
s.name("tool-unstable-book-gen")
|
||||
.host(&build.config.build)
|
||||
.target(&build.config.build)
|
||||
.host(&build.build)
|
||||
.target(&build.build)
|
||||
.stage(0)
|
||||
})
|
||||
.dep(move |s| s.name("libstd-link"))
|
||||
@ -725,7 +725,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
||||
// ========================================================================
|
||||
// Distribution targets
|
||||
rules.dist("dist-rustc", "src/librustc")
|
||||
.dep(move |s| s.name("rustc").host(&build.config.build))
|
||||
.dep(move |s| s.name("rustc").host(&build.build))
|
||||
.host(true)
|
||||
.only_host_build(true)
|
||||
.default(true)
|
||||
@ -811,7 +811,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
||||
.host(true)
|
||||
.only_build(true)
|
||||
.only_host_build(true)
|
||||
.dep(move |s| s.name("tool-build-manifest").target(&build.config.build).stage(0))
|
||||
.dep(move |s| s.name("tool-build-manifest").target(&build.build).stage(0))
|
||||
.run(move |_| dist::hash_and_sign(build));
|
||||
|
||||
rules.install("install-docs", "src/doc")
|
||||
@ -861,8 +861,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
||||
/// Helper to depend on a stage0 build-only rust-installer tool.
|
||||
fn tool_rust_installer<'a>(build: &'a Build, step: &Step<'a>) -> Step<'a> {
|
||||
step.name("tool-rust-installer")
|
||||
.host(&build.config.build)
|
||||
.target(&build.config.build)
|
||||
.host(&build.build)
|
||||
.target(&build.build)
|
||||
.stage(0)
|
||||
}
|
||||
}
|
||||
@ -1058,8 +1058,8 @@ impl<'a> Rules<'a> {
|
||||
build: build,
|
||||
sbuild: Step {
|
||||
stage: build.flags.stage.unwrap_or(2),
|
||||
target: &build.config.build,
|
||||
host: &build.config.build,
|
||||
target: &build.build,
|
||||
host: &build.build,
|
||||
name: "",
|
||||
},
|
||||
rules: BTreeMap::new(),
|
||||
@ -1218,16 +1218,9 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd?
|
||||
|
||||
rules.into_iter().flat_map(|(rule, _)| {
|
||||
let hosts = if rule.only_host_build || rule.only_build {
|
||||
&self.build.config.host[..1]
|
||||
} else if self.build.flags.host.len() > 0 {
|
||||
&self.build.flags.host
|
||||
self.build.build_slice()
|
||||
} else {
|
||||
&self.build.config.host
|
||||
};
|
||||
let targets = if self.build.flags.target.len() > 0 {
|
||||
&self.build.flags.target
|
||||
} else {
|
||||
&self.build.config.target
|
||||
&self.build.hosts
|
||||
};
|
||||
// Determine the actual targets participating in this rule.
|
||||
// NOTE: We should keep the full projection from build triple to
|
||||
@ -1236,19 +1229,18 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd?
|
||||
// the original non-shadowed hosts array is used below.
|
||||
let arr = if rule.host {
|
||||
// If --target was specified but --host wasn't specified,
|
||||
// don't run any host-only tests. Also, respect any `--host`
|
||||
// overrides as done for `hosts`.
|
||||
// don't run any host-only tests.
|
||||
if self.build.flags.host.len() > 0 {
|
||||
&self.build.flags.host[..]
|
||||
&self.build.hosts
|
||||
} else if self.build.flags.target.len() > 0 {
|
||||
&[]
|
||||
} else if rule.only_build {
|
||||
&self.build.config.host[..1]
|
||||
self.build.build_slice()
|
||||
} else {
|
||||
&self.build.config.host[..]
|
||||
&self.build.hosts
|
||||
}
|
||||
} else {
|
||||
targets
|
||||
&self.build.targets
|
||||
};
|
||||
|
||||
hosts.iter().flat_map(move |host| {
|
||||
@ -1326,7 +1318,7 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd?
|
||||
for idx in 0..nodes.len() {
|
||||
self.topo_sort(idx, &idx_to_node, &edges, &mut visited, &mut order);
|
||||
}
|
||||
return order
|
||||
order
|
||||
}
|
||||
|
||||
/// Builds the dependency graph rooted at `step`.
|
||||
@ -1365,7 +1357,7 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd?
|
||||
}
|
||||
|
||||
edges.entry(idx).or_insert(HashSet::new()).extend(deps);
|
||||
return idx
|
||||
idx
|
||||
}
|
||||
|
||||
/// Given a dependency graph with a finished list of `nodes`, fill out more
|
||||
@ -1494,8 +1486,8 @@ mod tests {
|
||||
let step = super::Step {
|
||||
name: "",
|
||||
stage: 2,
|
||||
host: &build.config.build,
|
||||
target: &build.config.build,
|
||||
host: &build.build,
|
||||
target: &build.build,
|
||||
};
|
||||
|
||||
assert!(plan.contains(&step.name("dist-docs")));
|
||||
@ -1517,8 +1509,8 @@ mod tests {
|
||||
let step = super::Step {
|
||||
name: "",
|
||||
stage: 2,
|
||||
host: &build.config.build,
|
||||
target: &build.config.build,
|
||||
host: &build.build,
|
||||
target: &build.build,
|
||||
};
|
||||
|
||||
assert!(plan.contains(&step.name("dist-docs")));
|
||||
@ -1545,8 +1537,8 @@ mod tests {
|
||||
let step = super::Step {
|
||||
name: "",
|
||||
stage: 2,
|
||||
host: &build.config.build,
|
||||
target: &build.config.build,
|
||||
host: &build.build,
|
||||
target: &build.build,
|
||||
};
|
||||
|
||||
assert!(!plan.iter().any(|s| s.host == "B"));
|
||||
@ -1575,8 +1567,8 @@ mod tests {
|
||||
let step = super::Step {
|
||||
name: "",
|
||||
stage: 2,
|
||||
host: &build.config.build,
|
||||
target: &build.config.build,
|
||||
host: &build.build,
|
||||
target: &build.build,
|
||||
};
|
||||
|
||||
assert!(!plan.iter().any(|s| s.host == "B"));
|
||||
@ -1612,8 +1604,8 @@ mod tests {
|
||||
let step = super::Step {
|
||||
name: "",
|
||||
stage: 2,
|
||||
host: &build.config.build,
|
||||
target: &build.config.build,
|
||||
host: &build.build,
|
||||
target: &build.build,
|
||||
};
|
||||
|
||||
assert!(!plan.iter().any(|s| s.target == "A"));
|
||||
@ -1639,8 +1631,8 @@ mod tests {
|
||||
let step = super::Step {
|
||||
name: "",
|
||||
stage: 2,
|
||||
host: &build.config.build,
|
||||
target: &build.config.build,
|
||||
host: &build.build,
|
||||
target: &build.build,
|
||||
};
|
||||
|
||||
assert!(!plan.iter().any(|s| s.target == "A"));
|
||||
@ -1683,8 +1675,8 @@ mod tests {
|
||||
let step = super::Step {
|
||||
name: "",
|
||||
stage: 2,
|
||||
host: &build.config.build,
|
||||
target: &build.config.build,
|
||||
host: &build.build,
|
||||
target: &build.build,
|
||||
};
|
||||
|
||||
// rustc built for all for of (A, B) x (A, B)
|
||||
|
@ -14,7 +14,6 @@
|
||||
//! not a lot of interesting happenings here unfortunately.
|
||||
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::fs;
|
||||
use std::io::{self, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
@ -32,16 +31,9 @@ pub fn staticlib(name: &str, target: &str) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
/// Copies a file from `src` to `dst`, attempting to use hard links and then
|
||||
/// falling back to an actually filesystem copy if necessary.
|
||||
/// Copies a file from `src` to `dst`
|
||||
pub fn copy(src: &Path, dst: &Path) {
|
||||
// A call to `hard_link` will fail if `dst` exists, so remove it if it
|
||||
// already exists so we can try to help `hard_link` succeed.
|
||||
let _ = fs::remove_file(&dst);
|
||||
|
||||
// Attempt to "easy copy" by creating a hard link (symlinks don't work on
|
||||
// windows), but if that fails just fall back to a slow `copy` operation.
|
||||
// let res = fs::hard_link(src, dst);
|
||||
let res = fs::copy(src, dst);
|
||||
if let Err(e) = res {
|
||||
panic!("failed to copy `{}` to `{}`: {}", src.display(),
|
||||
@ -149,8 +141,7 @@ pub fn dylib_path_var() -> &'static str {
|
||||
/// Parses the `dylib_path_var()` environment variable, returning a list of
|
||||
/// paths that are members of this lookup path.
|
||||
pub fn dylib_path() -> Vec<PathBuf> {
|
||||
env::split_paths(&env::var_os(dylib_path_var()).unwrap_or(OsString::new()))
|
||||
.collect()
|
||||
env::split_paths(&env::var_os(dylib_path_var()).unwrap_or_default()).collect()
|
||||
}
|
||||
|
||||
/// `push` all components to `buf`. On windows, append `.exe` to the last component.
|
||||
|
@ -2008,10 +2008,10 @@ impl From<Box<str>> for String {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "box_from_str", since = "1.18.0")]
|
||||
impl Into<Box<str>> for String {
|
||||
fn into(self) -> Box<str> {
|
||||
self.into_boxed_str()
|
||||
#[stable(feature = "box_from_str", since = "1.20.0")]
|
||||
impl From<String> for Box<str> {
|
||||
fn from(s: String) -> Box<str> {
|
||||
s.into_boxed_str()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -274,6 +274,11 @@ fn test_dedup_by() {
|
||||
vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
|
||||
|
||||
assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
|
||||
|
||||
let mut vec = vec![("foo", 1), ("foo", 2), ("bar", 3), ("bar", 4), ("bar", 5)];
|
||||
vec.dedup_by(|a, b| a.0 == b.0 && { b.1 += a.1; true });
|
||||
|
||||
assert_eq!(vec, [("foo", 3), ("bar", 12)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -823,7 +823,8 @@ impl<T> Vec<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes consecutive elements in the vector that resolve to the same key.
|
||||
/// Removes all but the first of consecutive elements in the vector that resolve to the same
|
||||
/// key.
|
||||
///
|
||||
/// If the vector is sorted, this removes all duplicates.
|
||||
///
|
||||
@ -842,11 +843,13 @@ impl<T> Vec<T> {
|
||||
self.dedup_by(|a, b| key(a) == key(b))
|
||||
}
|
||||
|
||||
/// Removes consecutive elements in the vector according to a predicate.
|
||||
/// Removes all but the first of consecutive elements in the vector satisfying a given equality
|
||||
/// relation.
|
||||
///
|
||||
/// The `same_bucket` function is passed references to two elements from the vector, and
|
||||
/// returns `true` if the elements compare equal, or `false` if they do not. Only the first
|
||||
/// of adjacent equal items is kept.
|
||||
/// returns `true` if the elements compare equal, or `false` if they do not. The elements are
|
||||
/// passed in opposite order from their order in the vector, so if `same_bucket(a, b)` returns
|
||||
/// `true`, `a` is removed.
|
||||
///
|
||||
/// If the vector is sorted, this removes all duplicates.
|
||||
///
|
||||
|
@ -343,7 +343,7 @@ impl Ordering {
|
||||
/// ```
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
#[stable(feature = "reverse_cmp_key", since = "1.19.0")]
|
||||
pub struct Reverse<T>(pub T);
|
||||
pub struct Reverse<T>(#[stable(feature = "reverse_cmp_key", since = "1.19.0")] pub T);
|
||||
|
||||
#[stable(feature = "reverse_cmp_key", since = "1.19.0")]
|
||||
impl<T: PartialOrd> PartialOrd for Reverse<T> {
|
||||
|
@ -49,9 +49,37 @@ impl<'a, 'b: 'a> fmt::Write for PadAdapter<'a, 'b> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A struct to help with `fmt::Debug` implementations.
|
||||
/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations.
|
||||
///
|
||||
/// Constructed by the `Formatter::debug_struct` method.
|
||||
/// This is useful when you wish to output a formatted struct as a part of your
|
||||
/// [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation.
|
||||
///
|
||||
/// This can be constructed by the
|
||||
/// [`Formatter::debug_struct`](struct.Formatter.html#method.debug_struct)
|
||||
/// method.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo {
|
||||
/// bar: i32,
|
||||
/// baz: String,
|
||||
/// }
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
/// fmt.debug_struct("Foo")
|
||||
/// .field("bar", &self.bar)
|
||||
/// .field("baz", &self.baz)
|
||||
/// .finish()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // prints "Foo { bar: 10, baz: "Hello World" }"
|
||||
/// println!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() });
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
@ -116,9 +144,34 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A struct to help with `fmt::Debug` implementations.
|
||||
/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations.
|
||||
///
|
||||
/// Constructed by the `Formatter::debug_tuple` method.
|
||||
/// This is useful when you wish to output a formatted tuple as a part of your
|
||||
/// [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation.
|
||||
///
|
||||
/// This can be constructed by the
|
||||
/// [`Formatter::debug_tuple`](struct.Formatter.html#method.debug_tuple)
|
||||
/// method.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(i32, String);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
/// fmt.debug_tuple("Foo")
|
||||
/// .field(&self.0)
|
||||
/// .field(&self.1)
|
||||
/// .finish()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // prints "Foo(10, "Hello World")"
|
||||
/// println!("{:?}", Foo(10, "Hello World".to_string()));
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
@ -228,9 +281,31 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A struct to help with `fmt::Debug` implementations.
|
||||
/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations.
|
||||
///
|
||||
/// Constructed by the `Formatter::debug_set` method.
|
||||
/// This is useful when you wish to output a formatted set of items as a part
|
||||
/// of your [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation.
|
||||
///
|
||||
/// This can be constructed by the
|
||||
/// [`Formatter::debug_set`](struct.Formatter.html#method.debug_set)
|
||||
/// method.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(Vec<i32>);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
/// fmt.debug_set().entries(self.0.iter()).finish()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // prints "{10, 11}"
|
||||
/// println!("{:?}", Foo(vec![10, 11]));
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
@ -277,9 +352,31 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A struct to help with `fmt::Debug` implementations.
|
||||
/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations.
|
||||
///
|
||||
/// Constructed by the `Formatter::debug_list` method.
|
||||
/// This is useful when you wish to output a formatted list of items as a part
|
||||
/// of your [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation.
|
||||
///
|
||||
/// This can be constructed by the
|
||||
/// [`Formatter::debug_list`](struct.Formatter.html#method.debug_list)
|
||||
/// method.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(Vec<i32>);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
/// fmt.debug_list().entries(self.0.iter()).finish()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // prints "[10, 11]"
|
||||
/// println!("{:?}", Foo(vec![10, 11]));
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
@ -326,9 +423,31 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A struct to help with `fmt::Debug` implementations.
|
||||
/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations.
|
||||
///
|
||||
/// Constructed by the `Formatter::debug_map` method.
|
||||
/// This is useful when you wish to output a formatted map as a part of your
|
||||
/// [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation.
|
||||
///
|
||||
/// This can be constructed by the
|
||||
/// [`Formatter::debug_map`](struct.Formatter.html#method.debug_map)
|
||||
/// method.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(Vec<(String, i32)>);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
/// fmt.debug_map().entries(self.0.iter().map(|&(ref k, ref v)| (k, v))).finish()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // prints "{"A": 10, "B": 11}"
|
||||
/// println!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)]));
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
|
@ -585,11 +585,11 @@ impl From<Box<CStr>> for CString {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "box_from_c_string", since = "1.18.0")]
|
||||
impl Into<Box<CStr>> for CString {
|
||||
#[stable(feature = "box_from_c_string", since = "1.20.0")]
|
||||
impl From<CString> for Box<CStr> {
|
||||
#[inline]
|
||||
fn into(self) -> Box<CStr> {
|
||||
self.into_boxed_c_str()
|
||||
fn from(s: CString) -> Box<CStr> {
|
||||
s.into_boxed_c_str()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -540,10 +540,10 @@ impl From<Box<OsStr>> for OsString {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "box_from_os_string", since = "1.18.0")]
|
||||
impl Into<Box<OsStr>> for OsString {
|
||||
fn into(self) -> Box<OsStr> {
|
||||
self.into_boxed_os_str()
|
||||
#[stable(feature = "box_from_os_string", since = "1.20.0")]
|
||||
impl From<OsString> for Box<OsStr> {
|
||||
fn from(s: OsString) -> Box<OsStr> {
|
||||
s.into_boxed_os_str()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1348,10 +1348,10 @@ impl From<Box<Path>> for PathBuf {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "box_from_path_buf", since = "1.18.0")]
|
||||
impl Into<Box<Path>> for PathBuf {
|
||||
fn into(self) -> Box<Path> {
|
||||
self.into_boxed_path()
|
||||
#[stable(feature = "box_from_path_buf", since = "1.20.0")]
|
||||
impl From<PathBuf> for Box<Path> {
|
||||
fn from(p: PathBuf) -> Box<Path> {
|
||||
p.into_boxed_path()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -420,12 +420,19 @@ fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
|
||||
}
|
||||
|
||||
pub fn readlink(p: &Path) -> io::Result<PathBuf> {
|
||||
canonicalize(p)
|
||||
let fd = cvt(syscall::open(p.to_str().unwrap(), syscall::O_SYMLINK | syscall::O_RDONLY))?;
|
||||
let mut buf: [u8; 4096] = [0; 4096];
|
||||
let count = cvt(syscall::read(fd, &mut buf))?;
|
||||
cvt(syscall::close(fd))?;
|
||||
Ok(PathBuf::from(unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) }))
|
||||
}
|
||||
|
||||
pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> {
|
||||
::sys_common::util::dumb_print(format_args!("Symlink\n"));
|
||||
unimplemented!();
|
||||
pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
|
||||
let fd = cvt(syscall::open(dst.to_str().unwrap(),
|
||||
syscall::O_SYMLINK | syscall::O_CREAT | syscall::O_WRONLY | 0o777))?;
|
||||
cvt(syscall::write(fd, src.to_str().unwrap().as_bytes()))?;
|
||||
cvt(syscall::close(fd))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
|
||||
|
@ -33,6 +33,7 @@ pub const MAP_WRITE_COMBINE: usize = 2;
|
||||
pub const MODE_TYPE: u16 = 0xF000;
|
||||
pub const MODE_DIR: u16 = 0x4000;
|
||||
pub const MODE_FILE: u16 = 0x8000;
|
||||
pub const MODE_SYMLINK: u16 = 0xA000;
|
||||
|
||||
pub const MODE_PERM: u16 = 0x0FFF;
|
||||
pub const MODE_SETUID: u16 = 0o4000;
|
||||
@ -53,6 +54,7 @@ pub const O_TRUNC: usize = 0x0400_0000;
|
||||
pub const O_EXCL: usize = 0x0800_0000;
|
||||
pub const O_DIRECTORY: usize = 0x1000_0000;
|
||||
pub const O_STAT: usize = 0x2000_0000;
|
||||
pub const O_SYMLINK: usize = 0x4000_0000;
|
||||
pub const O_ACCMODE: usize = O_RDONLY | O_WRONLY | O_RDWR;
|
||||
|
||||
pub const SEEK_SET: usize = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user