From 44ffb61623741f86fca9f2f51d49dc1778310ee1 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Sat, 29 Jul 2017 22:12:53 -0600 Subject: [PATCH] Unify flags into config. This introduces a slight change in behavior, where we unilaterally respect the --host and --target parameters passed for all sanity checking and runtime configuration. --- src/bootstrap/bin/main.rs | 7 ++-- src/bootstrap/builder.rs | 31 +++++++----------- src/bootstrap/cc.rs | 31 ++++++++---------- src/bootstrap/check.rs | 19 +++-------- src/bootstrap/clean.rs | 2 +- src/bootstrap/compile.rs | 4 +-- src/bootstrap/config.rs | 67 ++++++++++++++++++++++++++++++++------- src/bootstrap/dist.rs | 2 +- src/bootstrap/flags.rs | 15 ++++++--- src/bootstrap/install.rs | 2 +- src/bootstrap/lib.rs | 55 +++++++++++--------------------- src/bootstrap/sanity.rs | 8 ++--- 12 files changed, 126 insertions(+), 117 deletions(-) diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs index 5ef18b89841f0..d02bc7972ae9a 100644 --- a/src/bootstrap/bin/main.rs +++ b/src/bootstrap/bin/main.rs @@ -21,11 +21,10 @@ extern crate bootstrap; use std::env; -use bootstrap::{Flags, Config, Build}; +use bootstrap::{Config, Build}; fn main() { let args = env::args().skip(1).collect::>(); - let flags = Flags::parse(&args); - let config = Config::parse(&flags.build, flags.config.clone()); - Build::new(flags, config).build(); + let config = Config::parse(&args); + Build::new(config).build(); } diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index d7f795e405534..a6cbb0134127d 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -120,28 +120,21 @@ impl StepDescription { fn maybe_run(&self, builder: &Builder, path: Option<&Path>) { let build = builder.build; let hosts = if self.only_build_targets || self.only_build { - &build.config.host[..1] + build.build_triple() } else { &build.hosts }; - // Determine the actual targets participating in this rule. - // NOTE: We should keep the full projection from build triple to - // the hosts for the dist steps, now that the hosts array above is - // truncated to avoid duplication of work in that case. Therefore - // the original non-shadowed hosts array is used below. + // Determine the targets participating in this rule. let targets = if self.only_hosts { - // 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`. - if build.flags.host.len() > 0 { - &build.flags.host[..] - } else if build.flags.target.len() > 0 { + // If --target was specified but --host wasn't specified, don't run + // any host-only tests. + if build.config.hosts.is_empty() && !build.config.targets.is_empty() { &[] } else if self.only_build { - &build.config.host[..1] + build.build_triple() } else { - &build.config.host[..] + &build.hosts } } else { &build.targets @@ -288,7 +281,7 @@ impl<'a> Builder<'a> { let builder = Builder { build: build, - top_stage: build.flags.stage.unwrap_or(2), + top_stage: build.config.stage.unwrap_or(2), kind: kind, cache: Cache::new(), stack: RefCell::new(Vec::new()), @@ -307,7 +300,7 @@ impl<'a> Builder<'a> { } pub fn run(build: &Build) { - let (kind, paths) = match build.flags.cmd { + let (kind, paths) = match build.config.cmd { Subcommand::Build { ref paths } => (Kind::Build, &paths[..]), Subcommand::Doc { ref paths } => (Kind::Doc, &paths[..]), Subcommand::Test { ref paths, .. } => (Kind::Test, &paths[..]), @@ -319,7 +312,7 @@ impl<'a> Builder<'a> { let builder = Builder { build: build, - top_stage: build.flags.stage.unwrap_or(2), + top_stage: build.config.stage.unwrap_or(2), kind: kind, cache: Cache::new(), stack: RefCell::new(Vec::new()), @@ -543,12 +536,12 @@ impl<'a> Builder<'a> { // Ignore incremental modes except for stage0, since we're // not guaranteeing correctness across builds if the compiler // is changing under your feet.` - if self.flags.incremental && compiler.stage == 0 { + if self.config.incremental && compiler.stage == 0 { let incr_dir = self.incremental_dir(compiler); cargo.env("RUSTC_INCREMENTAL", incr_dir); } - if let Some(ref on_fail) = self.flags.on_fail { + if let Some(ref on_fail) = self.config.on_fail { cargo.env("RUSTC_ON_FAIL", on_fail); } diff --git a/src/bootstrap/cc.rs b/src/bootstrap/cc.rs index 739904e4f7c58..0f25da8a238d0 100644 --- a/src/bootstrap/cc.rs +++ b/src/bootstrap/cc.rs @@ -32,6 +32,7 @@ //! everything. use std::process::Command; +use std::iter; use build_helper::{cc2ar, output}; use gcc; @@ -43,47 +44,41 @@ use cache::Interned; 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. - // - // This includes targets that aren't necessarily passed on the commandline - // (FIXME: Perhaps it shouldn't?) - for target in &build.config.target { + for target in build.targets.iter().chain(&build.hosts).cloned().chain(iter::once(build.build)) { let mut cfg = gcc::Config::new(); cfg.cargo_metadata(false).opt_level(0).debug(false) - .target(target).host(&build.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()) { cfg.compiler(cc); } else { - set_compiler(&mut cfg, "gcc", *target, config, build); + set_compiler(&mut cfg, "gcc", target, config, build); } let compiler = cfg.get_compiler(); - let ar = cc2ar(compiler.path(), target); - build.verbose(&format!("CC_{} = {:?}", target, compiler.path())); + let ar = cc2ar(compiler.path(), &target); + build.verbose(&format!("CC_{} = {:?}", &target, compiler.path())); if let Some(ref ar) = ar { - build.verbose(&format!("AR_{} = {:?}", target, ar)); + build.verbose(&format!("AR_{} = {:?}", &target, ar)); } - build.cc.insert(*target, (compiler, ar)); + build.cc.insert(target, (compiler, ar)); } // For all host triples we need to find a C++ compiler as well - // - // This includes hosts that aren't necessarily passed on the commandline - // (FIXME: Perhaps it shouldn't?) - for host in &build.config.host { + for host in build.hosts.iter().cloned().chain(iter::once(build.build)) { let mut cfg = gcc::Config::new(); cfg.cargo_metadata(false).opt_level(0).debug(false).cpp(true) - .target(host).host(&build.build); - let config = build.config.target_config.get(host); + .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); } else { - set_compiler(&mut cfg, "g++", *host, config, build); + set_compiler(&mut cfg, "g++", host, config, build); } let compiler = cfg.get_compiler(); build.verbose(&format!("CXX_{} = {:?}", host, compiler.path())); - build.cxx.insert(*host, compiler); + build.cxx.insert(host, compiler); } } diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index c65f5a9fb48bf..0351e9b81585f 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -625,7 +625,7 @@ impl Step for Compiletest { cmd.arg("--system-llvm"); } - cmd.args(&build.flags.cmd.test_args()); + cmd.args(&build.config.cmd.test_args()); if build.is_verbose() { cmd.arg("--verbose"); @@ -820,7 +820,7 @@ fn markdown_test(builder: &Builder, compiler: Compiler, markdown: &Path) { cmd.arg(markdown); cmd.env("RUSTC_BOOTSTRAP", "1"); - let test_args = build.flags.cmd.test_args().join(" "); + let test_args = build.config.cmd.test_args().join(" "); cmd.arg("--test-args").arg(test_args); if build.config.quiet_tests { @@ -1051,7 +1051,7 @@ impl Step for Crate { cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); cargo.arg("--"); - cargo.args(&build.flags.cmd.test_args()); + cargo.args(&build.config.cmd.test_args()); if build.config.quiet_tests { cargo.arg("--quiet"); @@ -1147,6 +1147,7 @@ pub struct Distcheck; impl Step for Distcheck { type Output = (); + const ONLY_BUILD: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { run.path("distcheck") @@ -1160,16 +1161,6 @@ impl Step for Distcheck { fn run(self, builder: &Builder) { let build = builder.build; - if *build.build != *"x86_64-unknown-linux-gnu" { - return - } - if !build.config.host.iter().any(|s| s == "x86_64-unknown-linux-gnu") { - return - } - if !build.config.target.iter().any(|s| s == "x86_64-unknown-linux-gnu") { - return - } - println!("Distcheck"); let dir = build.out.join("tmp").join("distcheck"); let _ = fs::remove_dir_all(&dir); @@ -1236,7 +1227,7 @@ impl Step for Bootstrap { if !build.fail_fast { cmd.arg("--no-fail-fast"); } - cmd.arg("--").args(&build.flags.cmd.test_args()); + cmd.arg("--").args(&build.config.cmd.test_args()); try_run(build, &mut cmd); } diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs index 308a0ab3076dd..119340a0190c4 100644 --- a/src/bootstrap/clean.rs +++ b/src/bootstrap/clean.rs @@ -26,7 +26,7 @@ pub fn clean(build: &Build) { rm_rf(&build.out.join("tmp")); rm_rf(&build.out.join("dist")); - for host in build.config.host.iter() { + for host in &build.hosts { let entries = match build.out.join(host).read_dir() { Ok(iter) => iter, Err(_) => continue, diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 92a42b59212b4..a6702300c811f 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -679,10 +679,10 @@ impl Step for Assemble { // link to these. (FIXME: Is that correct? It seems to be correct most // of the time but I think we do link to these for stage2/bin compilers // when not performing a full bootstrap). - if builder.build.flags.keep_stage.map_or(false, |s| target_compiler.stage <= s) { + if builder.build.config.keep_stage.map_or(false, |s| target_compiler.stage <= s) { builder.verbose("skipping compilation of compiler due to --keep-stage"); let compiler = build_compiler; - for stage in 0..min(target_compiler.stage, builder.flags.keep_stage.unwrap()) { + for stage in 0..min(target_compiler.stage, builder.config.keep_stage.unwrap()) { let target_compiler = builder.compiler(stage, target_compiler.host); let target = target_compiler.host; builder.ensure(StdLink { compiler, target_compiler, target }); diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index c4d5d43152118..c0494bd7fd083 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -19,11 +19,14 @@ use std::fs::{self, File}; use std::io::prelude::*; use std::path::PathBuf; use std::process; +use std::cmp; use num_cpus; use toml; use util::{exe, push_exe_path}; use cache::{INTERNER, Interned}; +use flags::Flags; +pub use flags::Subcommand; /// Global configuration for the entire build and/or bootstrap. /// @@ -52,6 +55,14 @@ pub struct Config { pub sanitizers: bool, pub profiler: bool, + pub on_fail: Option, + pub stage: Option, + pub keep_stage: Option, + pub src: PathBuf, + pub jobs: Option, + pub cmd: Subcommand, + pub incremental: bool, + // llvm codegen options pub llvm_enabled: bool, pub llvm_assertions: bool, @@ -79,8 +90,8 @@ pub struct Config { pub rust_dist_src: bool, pub build: Interned, - pub host: Vec>, - pub target: Vec>, + pub hosts: Vec>, + pub targets: Vec>, pub local_rebuild: bool, // dist misc @@ -265,7 +276,9 @@ struct TomlTarget { } impl Config { - pub fn parse(build: &str, file: Option) -> Config { + pub fn parse(args: &[String]) -> Config { + let flags = Flags::parse(&args); + let file = flags.config.clone(); let mut config = Config::default(); config.llvm_enabled = true; config.llvm_optimize = true; @@ -277,11 +290,19 @@ impl Config { config.docs = true; config.rust_rpath = true; config.rust_codegen_units = 1; - config.build = INTERNER.intern_str(build); + config.build = flags.build; config.channel = "dev".to_string(); config.codegen_tests = true; config.rust_dist_src = true; + config.on_fail = flags.on_fail; + config.stage = flags.stage; + config.src = flags.src; + config.jobs = flags.jobs; + config.cmd = flags.cmd; + config.incremental = flags.incremental; + config.keep_stage = flags.keep_stage; + let toml = file.map(|file| { let mut f = t!(File::open(&file)); let mut contents = String::new(); @@ -298,20 +319,41 @@ impl Config { let build = toml.build.clone().unwrap_or(Build::default()); set(&mut config.build, build.build.clone().map(|x| INTERNER.intern_string(x))); - config.host.push(config.build.clone()); + config.hosts.push(config.build.clone()); for host in build.host.iter() { let host = INTERNER.intern_str(host); - if !config.host.contains(&host) { - config.host.push(host); + if !config.hosts.contains(&host) { + config.hosts.push(host); } } - for target in config.host.iter().cloned() + for target in config.hosts.iter().cloned() .chain(build.target.iter().map(|s| INTERNER.intern_str(s))) { - if !config.target.contains(&target) { - config.target.push(target); + if !config.targets.contains(&target) { + config.targets.push(target); } } + config.hosts = if !flags.host.is_empty() { + for host in flags.host.iter() { + if !config.hosts.contains(host) { + panic!("specified host `{}` is not in configuration", host); + } + } + flags.host + } else { + config.hosts + }; + config.targets = if !flags.target.is_empty() { + for target in flags.target.iter() { + if !config.targets.contains(target) { + panic!("specified target `{}` is not in configuration", target); + } + } + flags.target + } else { + config.targets + }; + config.nodejs = build.nodejs.map(PathBuf::from); config.gdb = build.gdb.map(PathBuf::from); config.python = build.python.map(PathBuf::from); @@ -327,6 +369,7 @@ impl Config { set(&mut config.sanitizers, build.sanitizers); set(&mut config.profiler, build.profiler); set(&mut config.openssl_static, build.openssl_static); + config.verbose = cmp::max(config.verbose, flags.verbose); if let Some(ref install) = toml.install { config.prefix = install.prefix.clone().map(PathBuf::from); @@ -505,11 +548,11 @@ impl Config { match key { "CFG_BUILD" if value.len() > 0 => self.build = INTERNER.intern_str(value), "CFG_HOST" if value.len() > 0 => { - self.host.extend(value.split(" ").map(|s| INTERNER.intern_str(s))); + self.hosts.extend(value.split(" ").map(|s| INTERNER.intern_str(s))); } "CFG_TARGET" if value.len() > 0 => { - self.target.extend(value.split(" ").map(|s| INTERNER.intern_str(s))); + self.targets.extend(value.split(" ").map(|s| INTERNER.intern_str(s))); } "CFG_EXPERIMENTAL_TARGETS" if value.len() > 0 => { self.llvm_experimental_targets = Some(value.to_string()); diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index c322d75dd5b45..e467ba49b9734 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -546,7 +546,7 @@ impl Step for Std { // We want to package up as many target libraries as possible // for the `rust-std` package, so if this is a host target we // depend on librustc and otherwise we just depend on libtest. - if build.config.host.iter().any(|t| t == target) { + if build.hosts.iter().any(|t| t == target) { builder.ensure(compile::Rustc { compiler, target }); } else { builder.ensure(compile::Test { compiler, target }); diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 1a3a008ed2614..b20801971f19d 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -34,6 +34,7 @@ pub struct Flags { pub stage: Option, pub keep_stage: Option, pub build: Interned, + pub host: Vec>, pub target: Vec>, pub config: Option, @@ -68,6 +69,14 @@ pub enum Subcommand { }, } +impl Default for Subcommand { + fn default() -> Subcommand { + Subcommand::Build { + paths: vec![PathBuf::from("nowhere")], + } + } +} + impl Flags { pub fn parse(args: &[String]) -> Flags { let mut extra_help = String::new(); @@ -243,10 +252,8 @@ Arguments: // All subcommands can have an optional "Available paths" section if matches.opt_present("verbose") { - let flags = Flags::parse(&["build".to_string()]); - let mut config = Config::parse(&flags.build, cfg_file.clone()); - config.build = flags.build.clone(); - let mut build = Build::new(flags, config); + let config = Config::parse(&["build".to_string()]); + let mut build = Build::new(config); metadata::build(&mut build); let maybe_rules_help = Builder::get_help(&build, subcommand.as_str()); diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index ebfda1e619bd8..89690e444d1f6 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -28,7 +28,7 @@ pub fn install_docs(builder: &Builder, stage: u32, host: Interned) { } pub fn install_std(builder: &Builder, stage: u32) { - for target in builder.build.config.target.iter() { + for target in &builder.build.targets { install_sh(builder, "std", "rust-std", stage, Some(*target)); } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index a8485d1d152d1..e1d2779057f9d 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -136,13 +136,13 @@ extern crate toml; extern crate libc; use std::cell::Cell; -use std::cmp; use std::collections::{HashSet, HashMap}; use std::env; use std::fs::{self, File}; use std::io::Read; use std::path::{PathBuf, Path}; use std::process::Command; +use std::slice; use build_helper::{run_silent, run_suppressed, try_run_silent, try_run_suppressed, output, mtime}; @@ -187,7 +187,7 @@ mod job { } pub use config::Config; -pub use flags::{Flags, Subcommand}; +use flags::Subcommand; use cache::{Interned, INTERNER}; /// A structure representing a Rust compiler. @@ -215,9 +215,6 @@ 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 src: PathBuf, out: PathBuf, @@ -288,9 +285,9 @@ impl Build { /// line and the filesystem `config`. /// /// By default all build output will be placed in the current directory. - pub fn new(flags: Flags, config: Config) -> Build { + pub fn new(config: Config) -> Build { let cwd = t!(env::current_dir()); - let src = flags.src.clone(); + let src = config.src.clone(); let out = cwd.join("build"); let is_sudo = match env::var_os("SUDO_USER") { @@ -306,39 +303,17 @@ impl Build { let cargo_info = channel::GitInfo::new(&src.join("src/tools/cargo")); let rls_info = channel::GitInfo::new(&src.join("src/tools/rls")); - 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), + fail_fast: config.cmd.fail_fast(), + verbosity: config.verbose, - build: config.host[0].clone(), - hosts: hosts, - targets: targets, + build: config.build, + hosts: config.hosts.clone(), + targets: config.targets.clone(), - flags: flags, config: config, src: src, out: out, @@ -357,13 +332,19 @@ impl Build { } } + pub fn build_triple(&self) -> &[Interned] { + unsafe { + slice::from_raw_parts(&self.build, 1) + } + } + /// Executes the entire build, as configured by the flags and configuration. pub fn build(&mut self) { unsafe { job::setup(self); } - if let Subcommand::Clean = self.flags.cmd { + if let Subcommand::Clean = self.config.cmd { return clean::clean(self); } @@ -608,7 +589,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_else(|| num_cpus::get() as u32) + self.config.jobs.unwrap_or_else(|| num_cpus::get() as u32) } /// Returns the path to the C compiler for the target specified. @@ -727,7 +708,7 @@ impl Build { fn force_use_stage1(&self, compiler: Compiler, target: Interned) -> bool { !self.config.full_bootstrap && compiler.stage >= 2 && - self.config.host.iter().any(|h| *h == target) + self.hosts.iter().any(|h| *h == target) } /// Returns the directory that OpenSSL artifacts are compiled into if diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 7063b28f19d01..436a13500f254 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -85,7 +85,7 @@ pub fn check(build: &mut Build) { } // We need cmake, but only if we're actually building LLVM or sanitizers. - let building_llvm = build.config.host.iter() + let building_llvm = build.hosts.iter() .filter_map(|host| build.config.target_config.get(host)) .any(|config| config.llvm_config.is_none()); if building_llvm || build.config.sanitizers { @@ -114,7 +114,7 @@ pub fn check(build: &mut Build) { // 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 { + for target in &build.targets { // 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. @@ -128,7 +128,7 @@ pub fn check(build: &mut Build) { } } - for host in build.config.host.iter() { + for host in &build.hosts { cmd_finder.must_have(build.cxx(*host).unwrap()); // The msvc hosts don't use jemalloc, turn it off globally to @@ -144,7 +144,7 @@ pub fn check(build: &mut Build) { panic!("FileCheck executable {:?} does not exist", filecheck); } - for target in &build.config.target { + for target in &build.targets { // Can't compile for iOS unless we're on macOS if target.contains("apple-ios") && !build.build.contains("apple-darwin") {