-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<String>,
- /// 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
config: &Config,
jobs: Option<u32>,
requested_target: &Option<String>,
- ws: Option<&Workspace>,
mode: CompileMode,
) -> CargoResult<BuildConfig> {
let requested_target = match requested_target {
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
}
&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<PathBuf>,
- /// The path of the linker for this target.
- pub linker: Option<PathBuf>,
- /// Special build options for any necessary input files (filename -> options)
- pub overrides: HashMap<String, BuildOutput>,
-}
-
-impl TargetConfig {
- pub fn new(config: &Config, triple: &str) -> CargoResult<TargetConfig> {
- 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)
- }
-}
+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};
pub extra_compiler_args: Option<(Unit<'a>, Vec<String>)>,
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<bool>,
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)
};
resolve,
packages,
config,
+ rustc,
+ target_config,
target_info,
+ host_config,
host_info,
build_config,
profiles,
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,
}
}
pub fn rustflags_args(&self, unit: &Unit) -> CargoResult<Vec<String>> {
env_args(
self.config,
- &self.build_config,
+ &self.build_config.requested_target,
+ self.host_triple(),
self.info(&unit.kind).cfg(),
unit.kind,
"RUSTFLAGS",
pub fn rustdocflags_args(&self, unit: &Unit) -> CargoResult<Vec<String>> {
env_args(
self.config,
- &self.build_config,
+ &self.build_config.requested_target,
+ self.host_triple(),
self.info(&unit.kind).cfg(),
unit.kind,
"RUSTDOCFLAGS",
}
}
+/// 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<PathBuf>,
+ /// The path of the linker for this target.
+ pub linker: Option<PathBuf>,
+ /// Special build options for any necessary input files (filename -> options)
+ pub overrides: HashMap<String, BuildOutput>,
+}
+
+impl TargetConfig {
+ pub fn new(config: &Config, triple: &str) -> CargoResult<TargetConfig> {
+ 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:
/// scripts, ...), even if it is the same as the target.
fn env_args(
config: &Config,
- build_config: &BuildConfig,
+ requested_target: &Option<String>,
+ host_triple: &str,
target_cfg: Option<&[Cfg]>,
kind: Kind,
name: &str,
// 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 {
.flat_map(|c| c.to_lowercase())
.collect::<String>();
// 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();
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;
}
impl TargetInfo {
- pub fn new(config: &Config, build_config: &BuildConfig, kind: Kind) -> CargoResult<TargetInfo> {
- 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<String>,
+ rustc: &Rustc,
+ kind: Kind,
+ ) -> CargoResult<TargetInfo> {
+ let rustflags = env_args(
+ config,
+ requested_target,
+ &rustc.host,
+ None,
+ kind,
+ "RUSTFLAGS",
+ )?;
+ let mut process = rustc.process();
process
.arg("-")
.arg("--crate-name")
.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();
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")?;
} else {
rustlib.push("lib");
rustlib.push("rustlib");
- rustlib.push(build_config.target_triple());
+ rustlib.push(target_triple);
rustlib.push("lib");
sysroot_libdir = Some(rustlib);
}
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(),
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.
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(),
},
)
.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);
}
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
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};
}
}
- 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,
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() {
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::<Vec<_>>();
+ let mut deps_to_fetch = ws.members().map(|p| p.package_id()).collect::<Vec<_>>();
while let Some(id) = deps_to_fetch.pop() {
if !fetched_packages.insert(id) {