From 46533783526e1db93f0482fa3a2eaa39a8134325 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Sat, 28 Apr 2018 15:14:51 +0200 Subject: [PATCH] Move rustc and target configs from BuildConfig into BuildContext --- src/cargo/core/compiler/build_config.rs | 130 +-------------- src/cargo/core/compiler/build_context/mod.rs | 153 ++++++++++++++++-- .../compiler/build_context/target_info.rs | 35 ++-- src/cargo/core/compiler/compilation.rs | 2 +- .../compiler/context/compilation_files.rs | 2 +- src/cargo/core/compiler/context/mod.rs | 5 +- src/cargo/core/compiler/custom_build.rs | 4 +- src/cargo/core/compiler/fingerprint.rs | 2 +- src/cargo/core/compiler/mod.rs | 4 +- src/cargo/ops/cargo_clean.rs | 3 +- src/cargo/ops/cargo_compile.rs | 2 +- src/cargo/ops/cargo_fetch.rs | 12 +- 12 files changed, 180 insertions(+), 174 deletions(-) diff --git a/src/cargo/core/compiler/build_config.rs b/src/cargo/core/compiler/build_config.rs index abd71e0fe..e336105f1 100644 --- a/src/cargo/core/compiler/build_config.rs +++ b/src/cargo/core/compiler/build_config.rs @@ -1,18 +1,10 @@ -use std::collections::HashMap; -use std::path::{Path, PathBuf}; -use util::{CargoResult, CargoResultExt, Config, Rustc}; -use core::Workspace; -use super::BuildOutput; +use std::path::Path; +use util::{CargoResult, CargoResultExt, Config}; /// Configuration information for a rustc build. pub struct BuildConfig { - pub rustc: Rustc, - /// Build information for the host arch - pub host: TargetConfig, /// The target arch triple, defaults to host arch pub requested_target: Option, - /// Build information for the target - pub target: TargetConfig, /// How many rustc jobs to run in parallel pub jobs: u32, /// Whether we are building for release @@ -36,7 +28,6 @@ impl BuildConfig { config: &Config, jobs: Option, requested_target: &Option, - ws: Option<&Workspace>, mode: CompileMode, ) -> CargoResult { let requested_target = match requested_target { @@ -89,41 +80,15 @@ impl BuildConfig { None => None, }; let jobs = jobs.or(cfg_jobs).unwrap_or(::num_cpus::get() as u32); - let rustc = config.rustc(ws)?; - let host_config = TargetConfig::new(config, &rustc.host)?; - let target_config = match target.as_ref() { - Some(triple) => TargetConfig::new(config, triple)?, - None => host_config.clone(), - }; Ok(BuildConfig { - rustc, requested_target: target, jobs, - host: host_config, - target: target_config, release: false, mode, message_format: MessageFormat::Human, }) } - /// The host arch triple - /// - /// e.g. x86_64-unknown-linux-gnu, would be - /// - machine: x86_64 - /// - hardware-platform: unknown - /// - operating system: linux-gnu - pub fn host_triple(&self) -> &str { - &self.rustc.host - } - - pub fn target_triple(&self) -> &str { - self.requested_target - .as_ref() - .map(|s| s.as_str()) - .unwrap_or(self.host_triple()) - } - pub fn json_messages(&self) -> bool { self.message_format == MessageFormat::Json } @@ -222,94 +187,3 @@ impl CompileMode { &ALL } } - -/// Information required to build for a target -#[derive(Clone, Default)] -pub struct TargetConfig { - /// The path of archiver (lib builder) for this target. - pub ar: Option, - /// The path of the linker for this target. - pub linker: Option, - /// Special build options for any necessary input files (filename -> options) - pub overrides: HashMap, -} - -impl TargetConfig { - pub fn new(config: &Config, triple: &str) -> CargoResult { - let key = format!("target.{}", triple); - let mut ret = TargetConfig { - ar: config.get_path(&format!("{}.ar", key))?.map(|v| v.val), - linker: config.get_path(&format!("{}.linker", key))?.map(|v| v.val), - overrides: HashMap::new(), - }; - let table = match config.get_table(&key)? { - Some(table) => table.val, - None => return Ok(ret), - }; - for (lib_name, value) in table { - match lib_name.as_str() { - "ar" | "linker" | "runner" | "rustflags" => continue, - _ => {} - } - - let mut output = BuildOutput { - library_paths: Vec::new(), - library_links: Vec::new(), - cfgs: Vec::new(), - env: Vec::new(), - metadata: Vec::new(), - rerun_if_changed: Vec::new(), - rerun_if_env_changed: Vec::new(), - warnings: Vec::new(), - }; - // We require deterministic order of evaluation, so we must sort the pairs by key first. - let mut pairs = Vec::new(); - for (k, value) in value.table(&lib_name)?.0 { - pairs.push((k, value)); - } - pairs.sort_by_key(|p| p.0); - for (k, value) in pairs { - let key = format!("{}.{}", key, k); - match &k[..] { - "rustc-flags" => { - let (flags, definition) = value.string(k)?; - let whence = format!("in `{}` (in {})", key, definition.display()); - let (paths, links) = BuildOutput::parse_rustc_flags(flags, &whence)?; - output.library_paths.extend(paths); - output.library_links.extend(links); - } - "rustc-link-lib" => { - let list = value.list(k)?; - output - .library_links - .extend(list.iter().map(|v| v.0.clone())); - } - "rustc-link-search" => { - let list = value.list(k)?; - output - .library_paths - .extend(list.iter().map(|v| PathBuf::from(&v.0))); - } - "rustc-cfg" => { - let list = value.list(k)?; - output.cfgs.extend(list.iter().map(|v| v.0.clone())); - } - "rustc-env" => for (name, val) in value.table(k)?.0 { - let val = val.string(name)?.0; - output.env.push((name.clone(), val.to_string())); - }, - "warning" | "rerun-if-changed" | "rerun-if-env-changed" => { - bail!("`{}` is not supported in build script overrides", k); - } - _ => { - let val = value.string(k)?.0; - output.metadata.push((k.clone(), val.to_string())); - } - } - } - ret.overrides.insert(lib_name, output); - } - - Ok(ret) - } -} diff --git a/src/cargo/core/compiler/build_context/mod.rs b/src/cargo/core/compiler/build_context/mod.rs index 0c7eb51bf..1e7112b9a 100644 --- a/src/cargo/core/compiler/build_context/mod.rs +++ b/src/cargo/core/compiler/build_context/mod.rs @@ -1,14 +1,15 @@ +use std::collections::HashMap; use std::env; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::str::{self, FromStr}; use core::profiles::Profiles; use core::{Dependency, Workspace}; use core::{Package, PackageId, PackageSet, Resolve}; use util::errors::CargoResult; -use util::{profile, Cfg, CfgExpr, Config}; +use util::{profile, Cfg, CfgExpr, Config, Rustc}; -use super::{BuildConfig, Kind, TargetConfig, Unit}; +use super::{BuildConfig, BuildOutput, Kind, Unit}; mod target_info; pub use self::target_info::{FileFlavor, TargetInfo}; @@ -31,6 +32,12 @@ pub struct BuildContext<'a, 'cfg: 'a> { pub extra_compiler_args: Option<(Unit<'a>, Vec)>, pub packages: &'a PackageSet<'cfg>, + /// Information about the compiler + pub rustc: Rustc, + /// Build information for the host arch + pub host_config: TargetConfig, + /// Build information for the target + pub target_config: TargetConfig, pub target_info: TargetInfo, pub host_info: TargetInfo, pub incremental_env: Option, @@ -51,11 +58,19 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> { Err(_) => None, }; + let rustc = config.rustc(Some(ws))?; + let host_config = TargetConfig::new(config, &rustc.host)?; + let target_config = match build_config.requested_target.as_ref() { + Some(triple) => TargetConfig::new(config, triple)?, + None => host_config.clone(), + }; let (host_info, target_info) = { let _p = profile::start("BuildContext::probe_target_info"); debug!("probe_target_info"); - let host_info = TargetInfo::new(config, &build_config, Kind::Host)?; - let target_info = TargetInfo::new(config, &build_config, Kind::Target)?; + let host_info = + TargetInfo::new(config, &build_config.requested_target, &rustc, Kind::Host)?; + let target_info = + TargetInfo::new(config, &build_config.requested_target, &rustc, Kind::Target)?; (host_info, target_info) }; @@ -64,7 +79,10 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> { resolve, packages, config, + rustc, + target_config, target_info, + host_config, host_info, build_config, profiles, @@ -139,19 +157,29 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> { info.cfg().unwrap_or(&[]) } + /// The host arch triple + /// + /// e.g. x86_64-unknown-linux-gnu, would be + /// - machine: x86_64 + /// - hardware-platform: unknown + /// - operating system: linux-gnu pub fn host_triple(&self) -> &str { - self.build_config.host_triple() + &self.rustc.host } pub fn target_triple(&self) -> &str { - self.build_config.target_triple() + self.build_config + .requested_target + .as_ref() + .map(|s| s.as_str()) + .unwrap_or(self.host_triple()) } /// Get the target configuration for a particular host or target fn target_config(&self, kind: Kind) -> &TargetConfig { match kind { - Kind::Host => &self.build_config.host, - Kind::Target => &self.build_config.target, + Kind::Host => &self.host_config, + Kind::Target => &self.target_config, } } @@ -163,7 +191,8 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> { pub fn rustflags_args(&self, unit: &Unit) -> CargoResult> { env_args( self.config, - &self.build_config, + &self.build_config.requested_target, + self.host_triple(), self.info(&unit.kind).cfg(), unit.kind, "RUSTFLAGS", @@ -173,7 +202,8 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> { pub fn rustdocflags_args(&self, unit: &Unit) -> CargoResult> { env_args( self.config, - &self.build_config, + &self.build_config.requested_target, + self.host_triple(), self.info(&unit.kind).cfg(), unit.kind, "RUSTDOCFLAGS", @@ -201,6 +231,97 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> { } } +/// Information required to build for a target +#[derive(Clone, Default)] +pub struct TargetConfig { + /// The path of archiver (lib builder) for this target. + pub ar: Option, + /// The path of the linker for this target. + pub linker: Option, + /// Special build options for any necessary input files (filename -> options) + pub overrides: HashMap, +} + +impl TargetConfig { + pub fn new(config: &Config, triple: &str) -> CargoResult { + let key = format!("target.{}", triple); + let mut ret = TargetConfig { + ar: config.get_path(&format!("{}.ar", key))?.map(|v| v.val), + linker: config.get_path(&format!("{}.linker", key))?.map(|v| v.val), + overrides: HashMap::new(), + }; + let table = match config.get_table(&key)? { + Some(table) => table.val, + None => return Ok(ret), + }; + for (lib_name, value) in table { + match lib_name.as_str() { + "ar" | "linker" | "runner" | "rustflags" => continue, + _ => {} + } + + let mut output = BuildOutput { + library_paths: Vec::new(), + library_links: Vec::new(), + cfgs: Vec::new(), + env: Vec::new(), + metadata: Vec::new(), + rerun_if_changed: Vec::new(), + rerun_if_env_changed: Vec::new(), + warnings: Vec::new(), + }; + // We require deterministic order of evaluation, so we must sort the pairs by key first. + let mut pairs = Vec::new(); + for (k, value) in value.table(&lib_name)?.0 { + pairs.push((k, value)); + } + pairs.sort_by_key(|p| p.0); + for (k, value) in pairs { + let key = format!("{}.{}", key, k); + match &k[..] { + "rustc-flags" => { + let (flags, definition) = value.string(k)?; + let whence = format!("in `{}` (in {})", key, definition.display()); + let (paths, links) = BuildOutput::parse_rustc_flags(flags, &whence)?; + output.library_paths.extend(paths); + output.library_links.extend(links); + } + "rustc-link-lib" => { + let list = value.list(k)?; + output + .library_links + .extend(list.iter().map(|v| v.0.clone())); + } + "rustc-link-search" => { + let list = value.list(k)?; + output + .library_paths + .extend(list.iter().map(|v| PathBuf::from(&v.0))); + } + "rustc-cfg" => { + let list = value.list(k)?; + output.cfgs.extend(list.iter().map(|v| v.0.clone())); + } + "rustc-env" => for (name, val) in value.table(k)?.0 { + let val = val.string(name)?.0; + output.env.push((name.clone(), val.to_string())); + }, + "warning" | "rerun-if-changed" | "rerun-if-env-changed" => { + bail!("`{}` is not supported in build script overrides", k); + } + _ => { + let val = value.string(k)?.0; + output.metadata.push((k.clone(), val.to_string())); + } + } + } + ret.overrides.insert(lib_name, output); + } + + Ok(ret) + } +} + /// Acquire extra flags to pass to the compiler from various locations. /// /// The locations are: @@ -220,7 +341,8 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> { /// scripts, ...), even if it is the same as the target. fn env_args( config: &Config, - build_config: &BuildConfig, + requested_target: &Option, + host_triple: &str, target_cfg: Option<&[Cfg]>, kind: Kind, name: &str, @@ -244,7 +366,7 @@ fn env_args( // This means that, e.g. even if the specified --target is the // same as the host, build scripts in plugins won't get // RUSTFLAGS. - let compiling_with_target = build_config.requested_target.is_some(); + let compiling_with_target = requested_target.is_some(); let is_target_kind = kind == Kind::Target; if compiling_with_target && !is_target_kind { @@ -269,11 +391,10 @@ fn env_args( .flat_map(|c| c.to_lowercase()) .collect::(); // Then the target.*.rustflags value... - let target = build_config - .requested_target + let target = requested_target .as_ref() .map(|s| s.as_str()) - .unwrap_or(build_config.host_triple()); + .unwrap_or(host_triple); let key = format!("target.{}.{}", target, name); if let Some(args) = config.get_list_or_split_string(&key)? { let args = args.val.into_iter(); diff --git a/src/cargo/core/compiler/build_context/target_info.rs b/src/cargo/core/compiler/build_context/target_info.rs index ff691ff2a..84950bd0d 100644 --- a/src/cargo/core/compiler/build_context/target_info.rs +++ b/src/cargo/core/compiler/build_context/target_info.rs @@ -3,8 +3,8 @@ use std::collections::hash_map::{Entry, HashMap}; use std::path::PathBuf; use std::str::{self, FromStr}; -use super::{env_args, BuildConfig}; -use util::{CargoResult, CargoResultExt, Cfg, Config, ProcessBuilder}; +use super::env_args; +use util::{CargoResult, CargoResultExt, Cfg, Config, ProcessBuilder, Rustc}; use core::TargetKind; use super::Kind; @@ -51,9 +51,21 @@ impl FileType { } impl TargetInfo { - pub fn new(config: &Config, build_config: &BuildConfig, kind: Kind) -> CargoResult { - let rustflags = env_args(config, build_config, None, kind, "RUSTFLAGS")?; - let mut process = build_config.rustc.process(); + pub fn new( + config: &Config, + requested_target: &Option, + rustc: &Rustc, + kind: Kind, + ) -> CargoResult { + let rustflags = env_args( + config, + requested_target, + &rustc.host, + None, + kind, + "RUSTFLAGS", + )?; + let mut process = rustc.process(); process .arg("-") .arg("--crate-name") @@ -62,8 +74,12 @@ impl TargetInfo { .args(&rustflags) .env_remove("RUST_LOG"); + let target_triple = requested_target + .as_ref() + .map(|s| s.as_str()) + .unwrap_or(&rustc.host); if kind == Kind::Target { - process.arg("--target").arg(&build_config.target_triple()); + process.arg("--target").arg(target_triple); } let crate_type_process = process.clone(); @@ -78,12 +94,11 @@ impl TargetInfo { with_cfg.arg("--print=cfg"); let mut has_cfg_and_sysroot = true; - let (output, error) = build_config - .rustc + let (output, error) = rustc .cached_output(&with_cfg) .or_else(|_| { has_cfg_and_sysroot = false; - build_config.rustc.cached_output(&process) + rustc.cached_output(&process) }) .chain_err(|| "failed to run `rustc` to learn about target-specific information")?; @@ -114,7 +129,7 @@ impl TargetInfo { } else { rustlib.push("lib"); rustlib.push("rustlib"); - rustlib.push(build_config.target_triple()); + rustlib.push(target_triple); rustlib.push("lib"); sysroot_libdir = Some(rustlib); } diff --git a/src/cargo/core/compiler/compilation.rs b/src/cargo/core/compiler/compilation.rs index e30b0dce8..e6900e64c 100644 --- a/src/cargo/core/compiler/compilation.rs +++ b/src/cargo/core/compiler/compilation.rs @@ -84,7 +84,7 @@ impl<'cfg> Compilation<'cfg> { cfgs: HashMap::new(), rustdocflags: HashMap::new(), config: bcx.config, - rustc_process: bcx.build_config.rustc.process(), + rustc_process: bcx.rustc.process(), host: bcx.host_triple().to_string(), target: bcx.target_triple().to_string(), target_runner: LazyCell::new(), diff --git a/src/cargo/core/compiler/context/compilation_files.rs b/src/cargo/core/compiler/context/compilation_files.rs index 8875317f5..3eb32c60e 100644 --- a/src/cargo/core/compiler/context/compilation_files.rs +++ b/src/cargo/core/compiler/context/compilation_files.rs @@ -442,7 +442,7 @@ fn compute_metadata<'a, 'cfg>( unit.target.name().hash(&mut hasher); unit.target.kind().hash(&mut hasher); - bcx.build_config.rustc.verbose_version.hash(&mut hasher); + bcx.rustc.verbose_version.hash(&mut hasher); // Seed the contents of __CARGO_DEFAULT_LIB_METADATA to the hasher if present. // This should be the release channel, to get a different hash for each channel. diff --git a/src/cargo/core/compiler/context/mod.rs b/src/cargo/core/compiler/context/mod.rs index 907ccdf06..4fcd1beb7 100644 --- a/src/cargo/core/compiler/context/mod.rs +++ b/src/cargo/core/compiler/context/mod.rs @@ -97,10 +97,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> { Ok(Self { bcx, compilation: Compilation::new(bcx), - build_state: Arc::new(BuildState::new( - &bcx.build_config.host, - &bcx.build_config.target, - )), + build_state: Arc::new(BuildState::new(&bcx.host_config, &bcx.target_config)), fingerprints: HashMap::new(), compiled: HashSet::new(), build_scripts: HashMap::new(), diff --git a/src/cargo/core/compiler/custom_build.rs b/src/cargo/core/compiler/custom_build.rs index 566b851b8..f358a5eaa 100644 --- a/src/cargo/core/compiler/custom_build.rs +++ b/src/cargo/core/compiler/custom_build.rs @@ -146,11 +146,11 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes }, ) .env("HOST", &bcx.host_triple()) - .env("RUSTC", &bcx.build_config.rustc.path) + .env("RUSTC", &bcx.rustc.path) .env("RUSTDOC", &*bcx.config.rustdoc()?) .inherit_jobserver(&cx.jobserver); - if let Some(ref linker) = bcx.build_config.target.linker { + if let Some(ref linker) = bcx.target_config.linker { cmd.env("RUSTC_LINKER", linker); } diff --git a/src/cargo/core/compiler/fingerprint.rs b/src/cargo/core/compiler/fingerprint.rs index 551aab143..284bc5993 100644 --- a/src/cargo/core/compiler/fingerprint.rs +++ b/src/cargo/core/compiler/fingerprint.rs @@ -462,7 +462,7 @@ fn calculate<'a, 'cfg>( cx.used_in_plugin.contains(unit), // used when passing panic=abort )); let fingerprint = Arc::new(Fingerprint { - rustc: util::hash_u64(&bcx.build_config.rustc.verbose_version), + rustc: util::hash_u64(&bcx.rustc.verbose_version), target: util::hash_u64(&unit.target), profile: profile_hash, // Note that .0 is hashed here, not .1 which is the cwd. That doesn't diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index f81965b05..8b503aaae 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -21,8 +21,8 @@ use self::job_queue::JobQueue; use self::output_depinfo::output_depinfo; -pub use self::build_context::{BuildContext, FileFlavor, TargetInfo}; -pub use self::build_config::{BuildConfig, CompileMode, MessageFormat, TargetConfig}; +pub use self::build_context::{BuildContext, FileFlavor, TargetConfig, TargetInfo}; +pub use self::build_config::{BuildConfig, CompileMode, MessageFormat}; pub use self::compilation::Compilation; pub use self::context::{Context, Unit}; pub use self::custom_build::{BuildMap, BuildOutput, BuildScripts}; diff --git a/src/cargo/ops/cargo_clean.rs b/src/cargo/ops/cargo_clean.rs index 6d5a2b7d9..65e47fb9a 100644 --- a/src/cargo/ops/cargo_clean.rs +++ b/src/cargo/ops/cargo_clean.rs @@ -88,8 +88,7 @@ pub fn clean(ws: &Workspace, opts: &CleanOptions) -> CargoResult<()> { } } - let mut build_config = - BuildConfig::new(config, Some(1), &opts.target, None, CompileMode::Build)?; + let mut build_config = BuildConfig::new(config, Some(1), &opts.target, CompileMode::Build)?; build_config.release = opts.release; let bcx = BuildContext::new( ws, diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index c2dad7a78..161d05a7b 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -229,7 +229,7 @@ pub fn compile_ws<'a>( ref export_dir, } = *options; - let mut build_config = BuildConfig::new(config, jobs, &target, Some(ws), mode)?; + let mut build_config = BuildConfig::new(config, jobs, &target, mode)?; build_config.release = release; build_config.message_format = message_format; let default_arch_kind = if build_config.requested_target.is_some() { diff --git a/src/cargo/ops/cargo_fetch.rs b/src/cargo/ops/cargo_fetch.rs index 0bf64ba19..ce9a788bc 100644 --- a/src/cargo/ops/cargo_fetch.rs +++ b/src/cargo/ops/cargo_fetch.rs @@ -19,14 +19,14 @@ pub fn fetch<'a>( let (packages, resolve) = ops::resolve_ws(ws)?; let jobs = Some(1); - let build_config = - BuildConfig::new(ws.config(), jobs, &options.target, None, CompileMode::Build)?; - let target_info = TargetInfo::new(ws.config(), &build_config, Kind::Target)?; + let config = ws.config(); + let build_config = BuildConfig::new(config, jobs, &options.target, CompileMode::Build)?; + let rustc = config.rustc(Some(ws))?; + let target_info = + TargetInfo::new(config, &build_config.requested_target, &rustc, Kind::Target)?; { let mut fetched_packages = HashSet::new(); - let mut deps_to_fetch = ws.members() - .map(|p| p.package_id()) - .collect::>(); + let mut deps_to_fetch = ws.members().map(|p| p.package_id()).collect::>(); while let Some(id) = deps_to_fetch.pop() { if !fetched_packages.insert(id) { -- 2.30.2