Auto merge of #7425 - alexcrichton:kind-string, r=ehuss

Refactor `Kind` to carry target name in `Target`

This commit is an internal refactoring of Cargo's compilation backend to
eventually support compiling multiple target simultaneously. The
original motivation for this came up in discussion of #7297 and this has
long been something I've intended to update Cargo for. Nothing in the
backend currently exposes the ability to actually build multiple target
simultaneously, but this should have no function change with respect to
all current consumers. Eventually we'll need to refactor APIs of how you
enter the compilation backend to compile for multiple targets.
This commit is contained in:
bors 2019-09-26 17:12:00 +00:00
commit d8e62ee121
26 changed files with 436 additions and 388 deletions

View File

@ -1678,7 +1678,7 @@ pub static RUSTC: Rustc = Rustc::new(
/// The rustc host such as `x86_64-unknown-linux-gnu`.
pub fn rustc_host() -> String {
RUSTC.with(|r| r.host.clone())
RUSTC.with(|r| r.host.to_string())
}
pub fn is_nightly() -> bool {

View File

@ -1,17 +1,16 @@
use std::cell::RefCell;
use std::path::Path;
use serde::ser;
use crate::core::compiler::{CompileKind, CompileTarget};
use crate::util::ProcessBuilder;
use crate::util::{CargoResult, CargoResultExt, Config, RustfixDiagnosticServer};
use crate::util::{CargoResult, Config, RustfixDiagnosticServer};
/// Configuration information for a rustc build.
#[derive(Debug)]
pub struct BuildConfig {
/// The target arch triple.
/// Default: host arch.
pub requested_target: Option<String>,
/// The requested kind of compilation for this session
pub requested_kind: CompileKind,
/// Number of rustc jobs to run in parallel.
pub jobs: u32,
/// `true` if we are building for release.
@ -46,36 +45,21 @@ impl BuildConfig {
requested_target: &Option<String>,
mode: CompileMode,
) -> CargoResult<BuildConfig> {
let requested_target = match requested_target {
&Some(ref target) if target.ends_with(".json") => {
let path = Path::new(target).canonicalize().chain_err(|| {
failure::format_err!("Target path {:?} is not a valid file", target)
})?;
Some(
path.into_os_string()
.into_string()
.map_err(|_| failure::format_err!("Target path is not valid unicode"))?,
)
}
other => other.clone(),
let requested_kind = match requested_target {
Some(s) => CompileKind::Target(CompileTarget::new(s)?),
None => match config.get_string("build.target")? {
Some(cfg) => {
let value = if cfg.val.ends_with(".json") {
let path = cfg.definition.root(config).join(&cfg.val);
path.to_str().expect("must be utf-8 in toml").to_string()
} else {
cfg.val
};
CompileKind::Target(CompileTarget::new(&value)?)
}
None => CompileKind::Host,
},
};
if let Some(ref s) = requested_target {
if s.trim().is_empty() {
failure::bail!("target was empty")
}
}
let cfg_target = match config.get_string("build.target")? {
Some(ref target) if target.val.ends_with(".json") => {
let path = target.definition.root(config).join(&target.val);
let path_string = path
.into_os_string()
.into_string()
.map_err(|_| failure::format_err!("Target path is not valid unicode"));
Some(path_string?)
}
other => other.map(|t| t.val),
};
let target = requested_target.or(cfg_target);
if jobs == Some(0) {
failure::bail!("jobs must be at least 1")
@ -91,7 +75,7 @@ impl BuildConfig {
let jobs = jobs.or(cfg_jobs).unwrap_or(::num_cpus::get() as u32);
Ok(BuildConfig {
requested_target: target,
requested_kind,
jobs,
release: false,
mode,

View File

@ -1,18 +1,16 @@
use crate::core::compiler::unit::UnitInterner;
use crate::core::compiler::CompileTarget;
use crate::core::compiler::{BuildConfig, BuildOutput, CompileKind, Unit};
use crate::core::profiles::Profiles;
use crate::core::{Dependency, InternedString, Workspace};
use crate::core::{PackageId, PackageSet};
use crate::util::errors::CargoResult;
use crate::util::{Config, Rustc};
use cargo_platform::Cfg;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::str;
use cargo_platform::Cfg;
use log::debug;
use crate::core::compiler::unit::UnitInterner;
use crate::core::compiler::{BuildConfig, BuildOutput, Kind, Unit};
use crate::core::profiles::Profiles;
use crate::core::{Dependency, Workspace};
use crate::core::{PackageId, PackageSet};
use crate::util::errors::CargoResult;
use crate::util::{profile, Config, Rustc};
mod target_info;
pub use self::target_info::{FileFlavor, TargetInfo};
@ -33,15 +31,24 @@ pub struct BuildContext<'a, 'cfg> {
pub extra_compiler_args: HashMap<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,
/// Source of interning new units as they're created.
pub units: &'a UnitInterner<'a>,
/// Information about the compiler that we've detected on the local system.
pub rustc: Rustc,
/// Build information for the "host", which is information about when
/// `rustc` is invoked without a `--target` flag. This is used for
/// procedural macros, build scripts, etc.
host_config: TargetConfig,
host_info: TargetInfo,
/// Build information for targets that we're building for. This will be
/// empty if the `--target` flag is not passed, and currently also only ever
/// has at most one entry, but eventually we'd like to support multi-target
/// builds with Cargo.
target_config: HashMap<CompileTarget, TargetConfig>,
target_info: HashMap<CompileTarget, TargetInfo>,
}
impl<'a, 'cfg> BuildContext<'a, 'cfg> {
@ -57,19 +64,26 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> {
let rustc = config.load_global_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.requested_target, &rustc, Kind::Host)?;
let target_info =
TargetInfo::new(config, &build_config.requested_target, &rustc, Kind::Target)?;
(host_info, target_info)
};
let host_info = TargetInfo::new(
config,
build_config.requested_kind,
&rustc,
CompileKind::Host,
)?;
let mut target_config = HashMap::new();
let mut target_info = HashMap::new();
if let CompileKind::Target(target) = build_config.requested_kind {
target_config.insert(target, TargetConfig::new(config, target.short_name())?);
target_info.insert(
target,
TargetInfo::new(
config,
build_config.requested_kind,
&rustc,
CompileKind::Target(target),
)?,
);
}
Ok(BuildContext {
ws,
@ -88,38 +102,31 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> {
}
/// Whether a dependency should be compiled for the host or target platform,
/// specified by `Kind`.
pub fn dep_platform_activated(&self, dep: &Dependency, kind: Kind) -> bool {
/// specified by `CompileKind`.
pub fn dep_platform_activated(&self, dep: &Dependency, kind: CompileKind) -> bool {
// If this dependency is only available for certain platforms,
// make sure we're only enabling it for that platform.
let platform = match dep.platform() {
Some(p) => p,
None => return true,
};
let (name, info) = match kind {
Kind::Host => (self.host_triple(), &self.host_info),
Kind::Target => (self.target_triple(), &self.target_info),
};
platform.matches(name, info.cfg())
let name = kind.short_name(self);
platform.matches(&name, self.cfg(kind))
}
/// Gets the user-specified linker for a particular host or target.
pub fn linker(&self, kind: Kind) -> Option<&Path> {
pub fn linker(&self, kind: CompileKind) -> Option<&Path> {
self.target_config(kind).linker.as_ref().map(|s| s.as_ref())
}
/// Gets the user-specified `ar` program for a particular host or target.
pub fn ar(&self, kind: Kind) -> Option<&Path> {
pub fn ar(&self, kind: CompileKind) -> Option<&Path> {
self.target_config(kind).ar.as_ref().map(|s| s.as_ref())
}
/// Gets the list of `cfg`s printed out from the compiler for the specified kind.
pub fn cfg(&self, kind: Kind) -> &[Cfg] {
let info = match kind {
Kind::Host => &self.host_info,
Kind::Target => &self.target_info,
};
info.cfg()
pub fn cfg(&self, kind: CompileKind) -> &[Cfg] {
self.info(kind).cfg()
}
/// Gets the host architecture triple.
@ -128,23 +135,15 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> {
/// - 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.build_config
.requested_target
.as_ref()
.map(|s| s.as_str())
.unwrap_or_else(|| self.host_triple())
pub fn host_triple(&self) -> InternedString {
self.rustc.host
}
/// Gets the target configuration for a particular host or target.
fn target_config(&self, kind: Kind) -> &TargetConfig {
pub fn target_config(&self, kind: CompileKind) -> &TargetConfig {
match kind {
Kind::Host => &self.host_config,
Kind::Target => &self.target_config,
CompileKind::Host => &self.host_config,
CompileKind::Target(s) => &self.target_config[&s],
}
}
@ -165,10 +164,10 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> {
pkg.source_id().is_path() || self.config.extra_verbose()
}
fn info(&self, kind: Kind) -> &TargetInfo {
pub fn info(&self, kind: CompileKind) -> &TargetInfo {
match kind {
Kind::Host => &self.host_info,
Kind::Target => &self.target_info,
CompileKind::Host => &self.host_info,
CompileKind::Target(s) => &self.target_info[&s],
}
}
@ -180,11 +179,8 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> {
///
/// `lib_name` is the `links` library name and `kind` is whether it is for
/// Host or Target.
pub fn script_override(&self, lib_name: &str, kind: Kind) -> Option<&BuildOutput> {
match kind {
Kind::Host => self.host_config.overrides.get(lib_name),
Kind::Target => self.target_config.overrides.get(lib_name),
}
pub fn script_override(&self, lib_name: &str, kind: CompileKind) -> Option<&BuildOutput> {
self.target_config(kind).overrides.get(lib_name)
}
}

View File

@ -4,7 +4,7 @@ use std::env;
use std::path::PathBuf;
use std::str::{self, FromStr};
use crate::core::compiler::Kind;
use crate::core::compiler::CompileKind;
use crate::core::TargetKind;
use crate::util::{CargoResult, CargoResultExt, Config, ProcessBuilder, Rustc};
use cargo_platform::{Cfg, CfgExpr};
@ -80,18 +80,11 @@ impl FileType {
impl TargetInfo {
pub fn new(
config: &Config,
requested_target: &Option<String>,
requested_kind: CompileKind,
rustc: &Rustc,
kind: Kind,
kind: CompileKind,
) -> CargoResult<TargetInfo> {
let rustflags = env_args(
config,
requested_target,
&rustc.host,
None,
kind,
"RUSTFLAGS",
)?;
let rustflags = env_args(config, requested_kind, &rustc.host, None, kind, "RUSTFLAGS")?;
let mut process = rustc.process();
process
.arg("-")
@ -101,12 +94,8 @@ impl TargetInfo {
.args(&rustflags)
.env_remove("RUSTC_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(target_triple);
if let CompileKind::Target(target) = kind {
process.arg("--target").arg(target.rustc_target());
}
let crate_type_process = process.clone();
@ -140,7 +129,7 @@ impl TargetInfo {
};
let mut rustlib = PathBuf::from(line);
let sysroot_libdir = match kind {
Kind::Host => {
CompileKind::Host => {
if cfg!(windows) {
rustlib.push("bin");
} else {
@ -148,10 +137,10 @@ impl TargetInfo {
}
rustlib
}
Kind::Target => {
CompileKind::Target(target) => {
rustlib.push("lib");
rustlib.push("rustlib");
rustlib.push(target_triple);
rustlib.push(target.short_name());
rustlib.push("lib");
rustlib
}
@ -175,7 +164,7 @@ impl TargetInfo {
// information
rustflags: env_args(
config,
requested_target,
requested_kind,
&rustc.host,
Some(&cfg),
kind,
@ -183,7 +172,7 @@ impl TargetInfo {
)?,
rustdocflags: env_args(
config,
requested_target,
requested_kind,
&rustc.host,
Some(&cfg),
kind,
@ -381,10 +370,10 @@ fn output_err_info(cmd: &ProcessBuilder, stdout: &str, stderr: &str) -> String {
/// scripts, ...), even if it is the same as the target.
fn env_args(
config: &Config,
requested_target: &Option<String>,
requested_kind: CompileKind,
host_triple: &str,
target_cfg: Option<&[Cfg]>,
kind: Kind,
kind: CompileKind,
name: &str,
) -> CargoResult<Vec<String>> {
// We *want* to apply RUSTFLAGS only to builds for the
@ -406,10 +395,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 = requested_target.is_some();
let is_target_kind = kind == Kind::Target;
if compiling_with_target && !is_target_kind {
if !requested_kind.is_host() && kind.is_host() {
// This is probably a build script or plugin and we're
// compiling with --target. In this scenario there are
// no rustflags we can apply.
@ -433,10 +419,10 @@ fn env_args(
.flat_map(|c| c.to_lowercase())
.collect::<String>();
// Then the target.*.rustflags value...
let target = requested_target
.as_ref()
.map(|s| s.as_str())
.unwrap_or(host_triple);
let target = match &kind {
CompileKind::Host => host_triple,
CompileKind::Target(target) => target.short_name(),
};
let key = format!("target.{}.{}", target, name);
if let Some(args) = config.get_list_or_split_string(&key)? {
let args = args.val.into_iter();

View File

@ -12,7 +12,7 @@ use std::path::PathBuf;
use serde::Serialize;
use super::context::OutputFile;
use super::{CompileMode, Context, Kind, Unit};
use super::{CompileKind, CompileMode, Context, Unit};
use crate::core::TargetKind;
use crate::util::{internal, CargoResult, ProcessBuilder};
@ -21,7 +21,7 @@ struct Invocation {
package_name: String,
package_version: semver::Version,
target_kind: TargetKind,
kind: Kind,
kind: CompileKind,
compile_mode: CompileMode,
deps: Vec<usize>,
outputs: Vec<PathBuf>,

View File

@ -7,6 +7,7 @@ use cargo_platform::CfgExpr;
use semver::Version;
use super::BuildContext;
use crate::core::compiler::CompileKind;
use crate::core::{Edition, InternedString, Package, PackageId, Target};
use crate::util::{self, join_paths, process, rustc::Rustc, CargoResult, Config, ProcessBuilder};
@ -78,7 +79,10 @@ pub struct Compilation<'cfg> {
}
impl<'cfg> Compilation<'cfg> {
pub fn new<'a>(bcx: &BuildContext<'a, 'cfg>) -> CargoResult<Compilation<'cfg>> {
pub fn new<'a>(
bcx: &BuildContext<'a, 'cfg>,
default_kind: CompileKind,
) -> CargoResult<Compilation<'cfg>> {
let mut rustc = bcx.rustc.process();
let mut primary_unit_rustc_process = bcx.build_config.primary_unit_rustc.clone();
@ -97,8 +101,8 @@ impl<'cfg> Compilation<'cfg> {
root_output: PathBuf::from("/"),
deps_output: PathBuf::from("/"),
host_deps_output: PathBuf::from("/"),
host_dylib_path: bcx.host_info.sysroot_libdir.clone(),
target_dylib_path: bcx.target_info.sysroot_libdir.clone(),
host_dylib_path: bcx.info(CompileKind::Host).sysroot_libdir.clone(),
target_dylib_path: bcx.info(default_kind).sysroot_libdir.clone(),
tests: Vec::new(),
binaries: Vec::new(),
extra_env: HashMap::new(),
@ -109,8 +113,8 @@ impl<'cfg> Compilation<'cfg> {
rustc_process: rustc,
primary_unit_rustc_process,
host: bcx.host_triple().to_string(),
target: bcx.target_triple().to_string(),
target_runner: target_runner(bcx)?,
target: default_kind.short_name(bcx).to_string(),
target_runner: target_runner(bcx, default_kind)?,
supports_rustdoc_crate_type: supports_rustdoc_crate_type(bcx.config, &bcx.rustc)?,
})
}
@ -289,8 +293,11 @@ fn pre_version_component(v: &Version) -> String {
ret
}
fn target_runner(bcx: &BuildContext<'_, '_>) -> CargoResult<Option<(PathBuf, Vec<String>)>> {
let target = bcx.target_triple();
fn target_runner(
bcx: &BuildContext<'_, '_>,
kind: CompileKind,
) -> CargoResult<Option<(PathBuf, Vec<String>)>> {
let target = kind.short_name(bcx);
// try target.{}.runner
let key = format!("target.{}.runner", target);
@ -303,7 +310,7 @@ fn target_runner(bcx: &BuildContext<'_, '_>) -> CargoResult<Option<(PathBuf, Vec
let mut matching_runner = None;
for key in table.val.keys() {
if CfgExpr::matches_key(key, bcx.target_info.cfg()) {
if CfgExpr::matches_key(key, bcx.info(kind).cfg()) {
let key = format!("target.{}.runner", key);
if let Some(runner) = bcx.config.get_path_and_args(&key)? {
// more than one match, error out

View File

@ -0,0 +1,128 @@
use crate::core::compiler::BuildContext;
use crate::core::{InternedString, Target};
use crate::util::errors::{CargoResult, CargoResultExt};
use serde::Serialize;
use std::path::Path;
/// Indicator for how a unit is being compiled.
///
/// This is used primarily for organizing cross compilations vs host
/// compilations, where cross compilations happen at the request of `--target`
/// and host compilations happen for things like build scripts and procedural
/// macros.
#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy, PartialOrd, Ord, Serialize)]
pub enum CompileKind {
/// Attached to a unit that is compiled for the "host" system or otherwise
/// is compiled without a `--target` flag. This is used for procedural
/// macros and build scripts, or if the `--target` flag isn't passed.
Host,
/// Attached to a unit to be compiled for a particular target. This is used
/// for units when the `--target` flag is passed.
Target(CompileTarget),
}
impl CompileKind {
pub fn is_host(&self) -> bool {
match self {
CompileKind::Host => true,
_ => false,
}
}
pub fn for_target(self, target: &Target) -> CompileKind {
// Once we start compiling for the `Host` kind we continue doing so, but
// if we are a `Target` kind and then we start compiling for a target
// that needs to be on the host we lift ourselves up to `Host`.
match self {
CompileKind::Host => CompileKind::Host,
CompileKind::Target(_) if target.for_host() => CompileKind::Host,
CompileKind::Target(n) => CompileKind::Target(n),
}
}
/// Returns a "short" name for this kind, suitable for keying off
/// configuration in Cargo or presenting to users.
pub fn short_name(&self, bcx: &BuildContext<'_, '_>) -> &str {
match self {
CompileKind::Host => bcx.host_triple().as_str(),
CompileKind::Target(target) => target.short_name(),
}
}
}
/// Abstraction for the representation of a compilation target that Cargo has.
///
/// Compilation targets are one of two things right now:
///
/// 1. A raw target string, like `x86_64-unknown-linux-gnu`.
/// 2. The path to a JSON file, such as `/path/to/my-target.json`.
///
/// Raw target strings are typically dictated by `rustc` itself and represent
/// built-in targets. Custom JSON files are somewhat unstable, but supported
/// here in Cargo. Note that for JSON target files this `CompileTarget` stores a
/// full canonicalized path to the target.
///
/// The main reason for this existence is to handle JSON target files where when
/// we call rustc we pass full paths but when we use it for Cargo's purposes
/// like naming directories or looking up configuration keys we only check the
/// file stem of JSON target files. For built-in rustc targets this is just an
/// uninterpreted string basically.
#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy, PartialOrd, Ord, Serialize)]
pub struct CompileTarget {
name: InternedString,
}
impl CompileTarget {
pub fn new(name: &str) -> CargoResult<CompileTarget> {
let name = name.trim();
if name.is_empty() {
failure::bail!("target was empty");
}
if !name.ends_with(".json") {
return Ok(CompileTarget { name: name.into() });
}
// If `name` ends in `.json` then it's likely a custom target
// specification. Canonicalize the path to ensure that different builds
// with different paths always produce the same result.
let path = Path::new(name)
.canonicalize()
.chain_err(|| failure::format_err!("target path {:?} is not a valid file", name))?;
let name = path
.into_os_string()
.into_string()
.map_err(|_| failure::format_err!("target path is not valid unicode"))?;
Ok(CompileTarget { name: name.into() })
}
/// Returns the full unqualified name of this target, suitable for passing
/// to `rustc` directly.
///
/// Typically this is pretty much the same as `short_name`, but for the case
/// of JSON target files this will be a full canonicalized path name for the
/// current filesystem.
pub fn rustc_target(&self) -> &str {
&self.name
}
/// Returns a "short" version of the target name suitable for usage within
/// Cargo for configuration and such.
///
/// This is typically the same as `rustc_target`, or the full name, but for
/// JSON target files this returns just the file stem (e.g. `foo` out of
/// `foo.json`) instead of the full path.
pub fn short_name(&self) -> &str {
// Flexible target specifications often point at json files, so if it
// looks like we've got one of those just use the file stem (the file
// name without ".json") as a short name for this target. Note that the
// `unwrap()` here should never trigger since we have a nonempty name
// and it starts as utf-8 so it's always utf-8
if self.name.ends_with(".json") {
Path::new(&self.name).file_stem().unwrap().to_str().unwrap()
} else {
&self.name
}
}
}

View File

@ -8,8 +8,8 @@ use std::sync::Arc;
use lazycell::LazyCell;
use log::info;
use super::{BuildContext, Context, FileFlavor, Kind, Layout};
use crate::core::compiler::{CompileMode, Unit};
use super::{BuildContext, CompileKind, Context, FileFlavor, Layout};
use crate::core::compiler::{CompileMode, CompileTarget, Unit};
use crate::core::{TargetKind, Workspace};
use crate::util::{self, CargoResult};
@ -54,7 +54,7 @@ pub struct CompilationFiles<'a, 'cfg> {
/// The target directory layout for the host (and target if it is the same as host).
pub(super) host: Layout,
/// The target directory layout for the target (if different from then host).
pub(super) target: Option<Layout>,
pub(super) target: HashMap<CompileTarget, Layout>,
/// Additional directory to include a copy of the outputs.
export_dir: Option<PathBuf>,
/// The root targets requested by the user on the command line (does not
@ -93,7 +93,7 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
pub(super) fn new(
roots: &[Unit<'a>],
host: Layout,
target: Option<Layout>,
target: HashMap<CompileTarget, Layout>,
export_dir: Option<PathBuf>,
ws: &'a Workspace<'cfg>,
cx: &Context<'a, 'cfg>,
@ -119,10 +119,10 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
}
/// Returns the appropriate directory layout for either a plugin or not.
pub fn layout(&self, kind: Kind) -> &Layout {
pub fn layout(&self, kind: CompileKind) -> &Layout {
match kind {
Kind::Host => &self.host,
Kind::Target => self.target.as_ref().unwrap_or(&self.host),
CompileKind::Host => &self.host,
CompileKind::Target(target) => &self.target[&target],
}
}
@ -200,7 +200,7 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
assert!(unit.target.is_custom_build());
assert!(!unit.mode.is_run_custom_build());
let dir = self.pkg_dir(unit);
self.layout(Kind::Host).build().join(dir)
self.layout(CompileKind::Host).build().join(dir)
}
/// Returns the directory where information about running a build script
@ -345,11 +345,7 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
let out_dir = self.out_dir(unit);
let link_stem = self.link_stem(unit);
let info = if unit.kind == Kind::Host {
&bcx.host_info
} else {
&bcx.target_info
};
let info = bcx.info(unit.kind);
let file_stem = self.file_stem(unit);
let mut add = |crate_type: &str, flavor: FileFlavor| -> CargoResult<()> {
@ -358,8 +354,12 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
} else {
crate_type
};
let file_types =
info.file_types(crate_type, flavor, unit.target.kind(), bcx.target_triple())?;
let file_types = info.file_types(
crate_type,
flavor,
unit.target.kind(),
unit.kind.short_name(bcx),
)?;
match file_types {
Some(types) => {
@ -432,14 +432,14 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
does not support these crate types",
unsupported.join(", "),
unit.pkg,
bcx.target_triple()
unit.kind.short_name(bcx),
)
}
failure::bail!(
"cannot compile `{}` as the target `{}` does not \
support any of the output crate types",
unit.pkg,
bcx.target_triple()
unit.kind.short_name(bcx),
);
}
Ok(ret)
@ -495,7 +495,7 @@ fn compute_metadata<'a, 'cfg>(
if !(unit.mode.is_any_test() || unit.mode.is_check())
&& (unit.target.is_dylib()
|| unit.target.is_cdylib()
|| (unit.target.is_executable() && bcx.target_triple().starts_with("wasm32-")))
|| (unit.target.is_executable() && unit.kind.short_name(bcx).starts_with("wasm32-")))
&& unit.pkg.package_id().source_id().is_path()
&& __cargo_default_lib_metadata.is_err()
{

View File

@ -20,7 +20,7 @@ use super::job_queue::JobQueue;
use super::layout::Layout;
use super::standard_lib;
use super::unit_dependencies::{UnitDep, UnitGraph};
use super::{BuildContext, Compilation, CompileMode, Executor, FileFlavor, Kind};
use super::{BuildContext, Compilation, CompileKind, CompileMode, Executor, FileFlavor};
mod compilation_files;
use self::compilation_files::CompilationFiles;
@ -79,6 +79,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
config: &'cfg Config,
bcx: &'a BuildContext<'a, 'cfg>,
unit_dependencies: UnitGraph<'a>,
default_kind: CompileKind,
) -> CargoResult<Self> {
// Load up the jobserver that we'll use to manage our parallelism. This
// is the same as the GNU make implementation of a jobserver, and
@ -105,7 +106,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
Ok(Self {
bcx,
compilation: Compilation::new(bcx)?,
compilation: Compilation::new(bcx, default_kind)?,
build_script_outputs: Arc::new(Mutex::new(BuildScriptOutputs::default())),
fingerprints: HashMap::new(),
mtime_cache: HashMap::new(),
@ -303,27 +304,19 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
"debug"
};
let host_layout = Layout::new(self.bcx.ws, None, dest)?;
let target_layout = match self.bcx.build_config.requested_target.as_ref() {
Some(target) => {
let layout = Layout::new(self.bcx.ws, Some(target), dest)?;
standard_lib::prepare_sysroot(&layout)?;
Some(layout)
}
None => None,
};
let mut targets = HashMap::new();
if let CompileKind::Target(target) = self.bcx.build_config.requested_kind {
let layout = Layout::new(self.bcx.ws, Some(target), dest)?;
standard_lib::prepare_sysroot(&layout)?;
targets.insert(target, layout);
}
self.primary_packages
.extend(units.iter().map(|u| u.pkg.package_id()));
self.record_units_requiring_metadata();
let files = CompilationFiles::new(
units,
host_layout,
target_layout,
export_dir,
self.bcx.ws,
self,
);
let files =
CompilationFiles::new(units, host_layout, targets, export_dir, self.bcx.ws, self);
self.files = Some(files);
Ok(())
}
@ -337,7 +330,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
.host
.prepare()
.chain_err(|| internal("couldn't prepare build directories"))?;
if let Some(ref mut target) = self.files.as_mut().unwrap().target {
for target in self.files.as_mut().unwrap().target.values_mut() {
target
.prepare()
.chain_err(|| internal("couldn't prepare build directories"))?;
@ -346,7 +339,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
self.compilation.host_deps_output = self.files_mut().host.deps().to_path_buf();
let files = self.files.as_ref().unwrap();
let layout = files.target.as_ref().unwrap_or(&files.host);
let layout = files.layout(self.bcx.build_config.requested_kind);
self.compilation.root_output = layout.dest().to_path_buf();
self.compilation.deps_output = layout.deps().to_path_buf();
Ok(())
@ -450,8 +443,11 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
Second unit: {:?}",
describe_collision(unit, other_unit, path),
suggestion,
crate::version(), self.bcx.host_triple(), self.bcx.target_triple(),
unit, other_unit))
crate::version(),
self.bcx.host_triple(),
unit.kind.short_name(self.bcx),
unit,
other_unit))
}
};

View File

@ -12,7 +12,7 @@ use crate::util::machine_message::{self, Message};
use crate::util::{self, internal, paths, profile};
use super::job::{Freshness, Job, Work};
use super::{fingerprint, Context, Kind, Unit};
use super::{fingerprint, CompileKind, Context, Unit};
/// Contains the parsed output of a custom build script.
#[derive(Clone, Debug, Hash)]
@ -43,7 +43,7 @@ pub struct BuildOutput {
/// This initially starts out as empty. Overridden build scripts get
/// inserted during `build_map`. The rest of the entries are added
/// immediately after each build script runs.
pub type BuildScriptOutputs = HashMap<(PackageId, Kind), BuildOutput>;
pub type BuildScriptOutputs = HashMap<(PackageId, CompileKind), BuildOutput>;
/// Linking information for a `Unit`.
///
@ -63,9 +63,9 @@ pub struct BuildScripts {
/// usage here doesn't blow up too much.
///
/// For more information, see #2354.
pub to_link: Vec<(PackageId, Kind)>,
pub to_link: Vec<(PackageId, CompileKind)>,
/// This is only used while constructing `to_link` to avoid duplicates.
seen_to_link: HashSet<(PackageId, Kind)>,
seen_to_link: HashSet<(PackageId, CompileKind)>,
/// Host-only dependencies that have build scripts.
///
/// This is the set of transitive dependencies that are host-only
@ -158,13 +158,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes
cmd.env("OUT_DIR", &script_out_dir)
.env("CARGO_MANIFEST_DIR", unit.pkg.root())
.env("NUM_JOBS", &bcx.jobs().to_string())
.env(
"TARGET",
&match unit.kind {
Kind::Host => bcx.host_triple(),
Kind::Target => bcx.target_triple(),
},
)
.env("TARGET", unit.kind.short_name(bcx))
.env("DEBUG", debug.to_string())
.env("OPT_LEVEL", &unit.profile.opt_level.to_string())
.env(
@ -180,7 +174,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes
.env("RUSTDOC", &*bcx.config.rustdoc()?)
.inherit_jobserver(&cx.jobserver);
if let Some(ref linker) = bcx.target_config.linker {
if let Some(linker) = &bcx.target_config(unit.kind).linker {
cmd.env("RUSTC_LINKER", linker);
}
@ -694,7 +688,7 @@ pub fn build_map<'b, 'cfg>(cx: &mut Context<'b, 'cfg>, units: &[Unit<'b>]) -> Ca
// When adding an entry to 'to_link' we only actually push it on if the
// script hasn't seen it yet (e.g., we don't push on duplicates).
fn add_to_link(scripts: &mut BuildScripts, pkg: PackageId, kind: Kind) {
fn add_to_link(scripts: &mut BuildScripts, pkg: PackageId, kind: CompileKind) {
if scripts.seen_to_link.insert((pkg, kind)) {
scripts.to_link.push((pkg, kind));
}

View File

@ -47,7 +47,7 @@
//! `cargo rustc` extra args | ✓ | ✓
//! CompileMode | ✓ | ✓
//! Target Name | ✓ | ✓
//! Target Kind (bin/lib/etc.) | ✓ | ✓
//! Target CompileKind (bin/lib/etc.) | ✓ | ✓
//! Enabled Features | ✓ | ✓
//! Immediate dependencys hashes | ✓[^1] | ✓
//! Target or Host mode | | ✓

View File

@ -618,7 +618,7 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> {
Artifact::All => self.timings.unit_finished(id, unlocked),
Artifact::Metadata => self.timings.unit_rmeta_finished(id, unlocked),
}
if unit.is_std && unit.kind == super::Kind::Target && !cx.bcx.build_config.build_plan {
if unit.is_std && !unit.kind.is_host() && !cx.bcx.build_config.build_plan {
// This is a bit of an unusual place to copy files around, and
// ideally this would be somewhere like the Work closure
// (`link_targets`). The tricky issue is handling rmeta files for

View File

@ -99,6 +99,7 @@
//! When cross-compiling, the layout is the same, except it appears in
//! `target/$TRIPLE`.
use crate::core::compiler::CompileTarget;
use crate::core::Workspace;
use crate::util::paths;
use crate::util::{CargoResult, FileLock};
@ -147,26 +148,15 @@ impl Layout {
///
/// `dest` should be the final artifact directory name. Currently either
/// "debug" or "release".
pub fn new(ws: &Workspace<'_>, triple: Option<&str>, dest: &str) -> CargoResult<Layout> {
pub fn new(
ws: &Workspace<'_>,
target: Option<CompileTarget>,
dest: &str,
) -> CargoResult<Layout> {
let mut root = ws.target_dir();
// Flexible target specifications often point at json files, so interpret
// the target triple as a Path and then just use the file stem as the
// component for the directory name in that case.
let triple_path = if let Some(s) = triple {
let p = Path::new(s);
let tp = if p.extension().and_then(|s| s.to_str()) == Some("json") {
Path::new(
p.file_stem()
.ok_or_else(|| failure::format_err!("invalid target"))?,
)
} else {
p
};
root.push(tp);
Some(tp)
} else {
None
};
if let Some(target) = target {
root.push(target.short_name());
}
let dest = root.join(dest);
// If the root directory doesn't already exist go ahead and create it
// here. Use this opportunity to exclude it from backups as well if the
@ -185,10 +175,14 @@ impl Layout {
// Compute the sysroot path for the build-std feature.
let build_std = ws.config().cli_unstable().build_std.as_ref();
let (sysroot, sysroot_libdir) = if let Some(tp) = build_std.and(triple_path) {
let (sysroot, sysroot_libdir) = if let Some(target) = build_std.and(target) {
// This uses a leading dot to avoid collision with named profiles.
let sysroot = dest.join(".sysroot");
let sysroot_libdir = sysroot.join("lib").join("rustlib").join(tp).join("lib");
let sysroot_libdir = sysroot
.join("lib")
.join("rustlib")
.join(target.short_name())
.join("lib");
(Some(sysroot), Some(sysroot_libdir))
} else {
(None, None)

View File

@ -2,6 +2,7 @@ mod build_config;
mod build_context;
mod build_plan;
mod compilation;
mod compile_kind;
mod context;
mod custom_build;
mod fingerprint;
@ -25,12 +26,12 @@ use std::sync::Arc;
use failure::Error;
use lazycell::LazyCell;
use log::debug;
use serde::Serialize;
pub use self::build_config::{BuildConfig, CompileMode, MessageFormat};
pub use self::build_context::{BuildContext, FileFlavor, TargetConfig, TargetInfo};
use self::build_plan::BuildPlan;
pub use self::compilation::{Compilation, Doctest};
pub use self::compile_kind::{CompileKind, CompileTarget};
pub use self::context::Context;
pub use self::custom_build::{BuildOutput, BuildScriptOutputs, BuildScripts};
pub use self::job::Freshness;
@ -50,15 +51,6 @@ use crate::util::paths;
use crate::util::{self, machine_message, ProcessBuilder};
use crate::util::{internal, join_paths, profile};
/// Indicates whether an object is for the host architecture or the target architecture.
///
/// These will be the same unless cross-compiling.
#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy, PartialOrd, Ord, Serialize)]
pub enum Kind {
Host,
Target,
}
/// A glorified callback for executing calls to rustc. Rather than calling rustc
/// directly, we'll use an `Executor`, giving clients an opportunity to intercept
/// the build calls.
@ -386,7 +378,7 @@ fn rustc<'a, 'cfg>(
rustc: &mut ProcessBuilder,
build_script_outputs: &BuildScriptOutputs,
current_id: PackageId,
kind: Kind,
kind: CompileKind,
) -> CargoResult<()> {
let key = (current_id, kind);
if let Some(output) = build_script_outputs.get(&key) {
@ -490,7 +482,7 @@ fn add_plugin_deps(
let mut search_path = env::split_paths(&search_path).collect::<Vec<_>>();
for &id in build_scripts.plugins.iter() {
let output = build_script_outputs
.get(&(id, Kind::Host))
.get(&(id, CompileKind::Host))
.ok_or_else(|| internal(format!("couldn't find libs for plugin dep {}", id)))?;
search_path.append(&mut filter_dynamic_search_path(
output.library_paths.iter(),
@ -565,10 +557,8 @@ fn rustdoc<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult
add_path_args(bcx, unit, &mut rustdoc);
add_cap_lints(bcx, unit, &mut rustdoc);
if unit.kind != Kind::Host {
if let Some(ref target) = bcx.build_config.requested_target {
rustdoc.arg("--target").arg(target);
}
if let CompileKind::Target(target) = unit.kind {
rustdoc.arg("--target").arg(target.rustc_target());
}
let doc_dir = cx.files().out_dir(unit);
@ -892,16 +882,8 @@ fn build_base_args<'a, 'cfg>(
}
}
if unit.kind == Kind::Target {
opt(
cmd,
"--target",
"",
bcx.build_config
.requested_target
.as_ref()
.map(|s| s.as_ref()),
);
if let CompileKind::Target(n) = unit.kind {
cmd.arg("--target").arg(n.rustc_target());
}
opt(cmd, "-C", "ar=", bcx.ar(unit.kind).map(|s| s.as_ref()));
@ -942,7 +924,7 @@ fn build_deps_args<'a, 'cfg>(
// Be sure that the host path is also listed. This'll ensure that proc macro
// dependencies are correctly found (for reexported macros).
if let Kind::Target = unit.kind {
if !unit.kind.is_host() {
cmd.arg("-L").arg(&{
let mut deps = OsString::from("dependency=");
deps.push(cx.files().host_deps());
@ -978,8 +960,8 @@ fn build_deps_args<'a, 'cfg>(
let mut unstable_opts = false;
if let Some(sysroot) = cx.files().layout(Kind::Target).sysroot() {
if unit.kind == Kind::Target {
if let Some(sysroot) = cx.files().layout(unit.kind).sysroot() {
if !unit.kind.is_host() {
cmd.arg("--sysroot").arg(sysroot);
}
}
@ -1066,19 +1048,6 @@ fn envify(s: &str) -> String {
.collect()
}
impl Kind {
fn for_target(self, target: &Target) -> Kind {
// Once we start compiling for the `Host` kind we continue doing so, but
// if we are a `Target` kind and then we start compiling for a target
// that needs to be on the host we lift ourselves up to `Host`.
match self {
Kind::Host => Kind::Host,
Kind::Target if target.for_host() => Kind::Host,
Kind::Target => Kind::Target,
}
}
}
struct OutputOptions {
/// What format we're emitting from Cargo itself.
format: MessageFormat,

View File

@ -1,7 +1,7 @@
//! Code for building the standard library.
use super::layout::Layout;
use crate::core::compiler::{BuildContext, CompileMode, Context, FileFlavor, Kind, Unit};
use crate::core::compiler::{BuildContext, CompileKind, CompileMode, Context, FileFlavor, Unit};
use crate::core::profiles::UnitFor;
use crate::core::resolver::ResolveOpts;
use crate::core::{Dependency, PackageId, PackageSet, Resolve, SourceId, Workspace};
@ -113,6 +113,7 @@ pub fn generate_std_roots<'a>(
bcx: &BuildContext<'a, '_>,
crates: &[String],
std_resolve: &'a Resolve,
kind: CompileKind,
) -> CargoResult<Vec<Unit<'a>>> {
// Generate the root Units for the standard library.
let std_ids = crates
@ -144,13 +145,7 @@ pub fn generate_std_roots<'a>(
);
let features = std_resolve.features_sorted(pkg.package_id());
Ok(bcx.units.intern(
pkg,
lib,
profile,
Kind::Target,
mode,
features,
/*is_std*/ true,
pkg, lib, profile, kind, mode, features, /*is_std*/ true,
))
})
.collect::<CargoResult<Vec<_>>>()
@ -205,7 +200,7 @@ pub fn add_sysroot_artifact<'a>(
.filter(|output| output.flavor == FileFlavor::Linkable { rmeta })
.map(|output| &output.path);
for path in outputs {
let libdir = cx.files().layout(Kind::Target).sysroot_libdir().unwrap();
let libdir = cx.files().layout(unit.kind).sysroot_libdir().unwrap();
let dst = libdir.join(path.file_name().unwrap());
paths::link_or_copy(path, dst)?;
}

View File

@ -572,11 +572,7 @@ fn render_rustc_info(bcx: &BuildContext<'_, '_>) -> String {
.lines()
.next()
.expect("rustc version");
let requested_target = bcx
.build_config
.requested_target
.as_ref()
.map_or("Host", String::as_str);
let requested_target = bcx.build_config.requested_kind.short_name(bcx);
format!(
"{}<br>Host: {}<br>Target: {}",
version, bcx.rustc.host, requested_target

View File

@ -1,4 +1,4 @@
use crate::core::compiler::{CompileMode, Kind};
use crate::core::compiler::{CompileKind, CompileMode};
use crate::core::{profiles::Profile, Package, Target};
use crate::util::hex::short_hash;
use std::cell::RefCell;
@ -45,7 +45,7 @@ pub struct UnitInner<'a> {
/// cross compiling and using a custom build script, the build script needs to be compiled for
/// the host architecture so the host rustc can use it (when compiling to the target
/// architecture).
pub kind: Kind,
pub kind: CompileKind,
/// The "mode" this unit is being compiled for. See [`CompileMode`] for more details.
pub mode: CompileMode,
/// The `cfg` features to enable for this unit.
@ -143,7 +143,7 @@ impl<'a> UnitInterner<'a> {
pkg: &'a Package,
target: &'a Target,
profile: Profile,
kind: Kind,
kind: CompileKind,
mode: CompileMode,
features: Vec<&'a str>,
is_std: bool,

View File

@ -16,7 +16,7 @@
//! graph of `Unit`s, which capture these properties.
use crate::core::compiler::Unit;
use crate::core::compiler::{BuildContext, CompileMode, Kind};
use crate::core::compiler::{BuildContext, CompileKind, CompileMode};
use crate::core::dependency::Kind as DepKind;
use crate::core::package::Downloads;
use crate::core::profiles::{Profile, UnitFor};
@ -125,7 +125,7 @@ fn attach_std_deps<'a, 'cfg>(
) {
// Attach the standard library as a dependency of every target unit.
for (unit, deps) in state.unit_dependencies.iter_mut() {
if unit.kind == Kind::Target && !unit.mode.is_run_custom_build() {
if !unit.kind.is_host() && !unit.mode.is_run_custom_build() {
deps.extend(std_roots.iter().map(|unit| UnitDep {
unit: *unit,
unit_for: UnitFor::new_normal(),
@ -270,13 +270,11 @@ fn compute_deps<'a, 'cfg>(
let mode = check_or_build_mode(unit.mode, lib);
let dep_unit_for = unit_for.with_for_host(lib.for_host());
if bcx.config.cli_unstable().dual_proc_macros
&& lib.proc_macro()
&& unit.kind == Kind::Target
{
let unit_dep = new_unit_dep(state, unit, pkg, lib, dep_unit_for, Kind::Target, mode)?;
if bcx.config.cli_unstable().dual_proc_macros && lib.proc_macro() && !unit.kind.is_host() {
let unit_dep = new_unit_dep(state, unit, pkg, lib, dep_unit_for, unit.kind, mode)?;
ret.push(unit_dep);
let unit_dep = new_unit_dep(state, unit, pkg, lib, dep_unit_for, Kind::Host, mode)?;
let unit_dep =
new_unit_dep(state, unit, pkg, lib, dep_unit_for, CompileKind::Host, mode)?;
ret.push(unit_dep);
} else {
let unit_dep = new_unit_dep(
@ -378,7 +376,7 @@ fn compute_deps_custom_build<'a, 'cfg>(
// builds.
UnitFor::new_build(),
// Build scripts always compiled for the host.
Kind::Host,
CompileKind::Host,
CompileMode::Build,
)?;
Ok(vec![unit_dep])
@ -537,7 +535,7 @@ fn new_unit_dep<'a>(
pkg: &'a Package,
target: &'a Target,
unit_for: UnitFor,
kind: Kind,
kind: CompileKind,
mode: CompileMode,
) -> CargoResult<UnitDep<'a>> {
let profile = state.bcx.profiles.get_profile(
@ -556,7 +554,7 @@ fn new_unit_dep_with_profile<'a>(
pkg: &'a Package,
target: &'a Target,
unit_for: UnitFor,
kind: Kind,
kind: CompileKind,
mode: CompileMode,
profile: Profile,
) -> CargoResult<UnitDep<'a>> {

View File

@ -1,11 +1,12 @@
use serde::{Serialize, Serializer};
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::collections::HashSet;
use std::ffi::OsStr;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::ops::Deref;
use std::path::Path;
use std::ptr;
use std::str;
use std::sync::Mutex;
@ -35,6 +36,12 @@ impl<'a> From<&'a String> for InternedString {
}
}
impl From<String> for InternedString {
fn from(item: String) -> Self {
InternedString::new(&item)
}
}
impl PartialEq for InternedString {
fn eq(&self, other: &InternedString) -> bool {
ptr::eq(self.as_str(), other.as_str())
@ -74,6 +81,18 @@ impl AsRef<str> for InternedString {
}
}
impl AsRef<OsStr> for InternedString {
fn as_ref(&self) -> &OsStr {
self.as_str().as_ref()
}
}
impl AsRef<Path> for InternedString {
fn as_ref(&self) -> &Path {
self.as_str().as_ref()
}
}
impl Hash for InternedString {
// N.B., we can't implement this as `identity(self).hash(state)`,
// because we use this for on-disk fingerprints and so need

View File

@ -4,7 +4,7 @@ use std::path::Path;
use crate::core::compiler::unit_dependencies;
use crate::core::compiler::UnitInterner;
use crate::core::compiler::{BuildConfig, BuildContext, CompileMode, Context, Kind};
use crate::core::compiler::{BuildConfig, BuildContext, CompileKind, CompileMode, Context};
use crate::core::profiles::UnitFor;
use crate::core::Workspace;
use crate::ops;
@ -73,7 +73,7 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
// Generate all relevant `Unit` targets for this package
for target in pkg.targets() {
for kind in [Kind::Host, Kind::Target].iter() {
for kind in [CompileKind::Host, build_config.requested_kind].iter() {
for mode in CompileMode::all_modes() {
for unit_for in UnitFor::all_values() {
let profile = if mode.is_run_custom_build() {
@ -105,7 +105,7 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
let unit_dependencies =
unit_dependencies::build_unit_dependencies(&bcx, &resolve, None, &units, &[])?;
let mut cx = Context::new(config, &bcx, unit_dependencies)?;
let mut cx = Context::new(config, &bcx, unit_dependencies, build_config.requested_kind)?;
cx.prepare_units(None, &units)?;
for unit in units.iter() {

View File

@ -31,7 +31,7 @@ use std::sync::Arc;
use crate::core::compiler::standard_lib;
use crate::core::compiler::unit_dependencies::build_unit_dependencies;
use crate::core::compiler::{BuildConfig, BuildContext, Compilation, Context};
use crate::core::compiler::{CompileMode, Kind, Unit};
use crate::core::compiler::{CompileKind, CompileMode, Unit};
use crate::core::compiler::{DefaultExecutor, Executor, UnitInterner};
use crate::core::profiles::{Profiles, UnitFor};
use crate::core::resolver::{Resolve, ResolveOpts};
@ -294,12 +294,6 @@ pub fn compile_ws<'a>(
}
}
let default_arch_kind = if build_config.requested_target.is_some() {
Kind::Target
} else {
Kind::Host
};
let profiles = ws.profiles();
let specs = spec.to_package_id_specs(ws)?;
@ -314,7 +308,7 @@ pub fn compile_ws<'a>(
.shell()
.warn("-Zbuild-std does not currently fully support --build-plan")?;
}
if build_config.requested_target.is_none() {
if build_config.requested_kind.is_host() {
// TODO: This should eventually be fixed. Unfortunately it is not
// easy to get the host triple in BuildConfig. Consider changing
// requested_target to an enum, or some other approach.
@ -390,7 +384,7 @@ pub fn compile_ws<'a>(
profiles,
&to_builds,
filter,
default_arch_kind,
build_config.requested_kind,
&resolve_with_overrides,
&bcx,
)?;
@ -408,7 +402,12 @@ pub fn compile_ws<'a>(
crates.push("test".to_string());
}
}
standard_lib::generate_std_roots(&bcx, &crates, std_resolve.as_ref().unwrap())?
standard_lib::generate_std_roots(
&bcx,
&crates,
std_resolve.as_ref().unwrap(),
build_config.requested_kind,
)?
} else {
Vec::new()
};
@ -442,7 +441,7 @@ pub fn compile_ws<'a>(
let ret = {
let _p = profile::start("compiling");
let cx = Context::new(config, &bcx, unit_dependencies)?;
let cx = Context::new(config, &bcx, unit_dependencies, build_config.requested_kind)?;
cx.compile(&units, export_dir.clone(), exec)?
};
@ -634,7 +633,7 @@ fn generate_targets<'a>(
profiles: &Profiles,
packages: &[&'a Package],
filter: &CompileFilter,
default_arch_kind: Kind,
default_arch_kind: CompileKind,
resolve: &'a Resolve,
bcx: &BuildContext<'a, '_>,
) -> CargoResult<Vec<Unit<'a>>> {
@ -694,12 +693,7 @@ fn generate_targets<'a>(
CompileMode::Bench => CompileMode::Test,
_ => target_mode,
};
// Plugins or proc macros should be built for the host.
let kind = if target.for_host() {
Kind::Host
} else {
default_arch_kind
};
let kind = default_arch_kind.for_target(target);
let profile = profiles.get_profile(
pkg.package_id(),
ws.is_member(pkg),

View File

@ -1,14 +1,10 @@
use std::collections::HashMap;
use std::fs;
use std::path::Path;
use failure::Fail;
use opener;
use crate::core::resolver::ResolveOpts;
use crate::core::Workspace;
use crate::ops;
use crate::util::CargoResult;
use failure::Fail;
use opener;
use std::collections::HashMap;
/// Strongly typed options for the `cargo doc` command.
#[derive(Debug)]
@ -67,24 +63,19 @@ pub fn doc(ws: &Workspace<'_>, options: &DocOptions<'_>) -> CargoResult<()> {
}
}
ops::compile(ws, &options.compile_opts)?;
let compilation = ops::compile(ws, &options.compile_opts)?;
if options.open_result {
let name = match names.first() {
Some(s) => s.to_string(),
None => return Ok(()),
};
// Don't bother locking here as if this is getting deleted there's
// nothing we can do about it and otherwise if it's getting overwritten
// then that's also ok!
let mut target_dir = ws.target_dir();
if let Some(ref triple) = options.compile_opts.build_config.requested_target {
target_dir.push(Path::new(triple).file_stem().unwrap());
}
let path = target_dir.join("doc").join(&name).join("index.html");
let path = path.into_path_unlocked();
if fs::metadata(&path).is_ok() {
let path = compilation
.root_output
.with_file_name("doc")
.join(&name)
.join("index.html");
if path.exists() {
let mut shell = options.compile_opts.config.shell();
shell.status("Opening", path.display())?;
if let Err(e) = opener::open(&path) {

View File

@ -1,4 +1,4 @@
use crate::core::compiler::{BuildConfig, CompileMode, Kind, TargetInfo};
use crate::core::compiler::{BuildConfig, CompileMode, TargetInfo};
use crate::core::{PackageSet, Resolve, Workspace};
use crate::ops;
use crate::util::CargoResult;
@ -23,44 +23,46 @@ pub fn fetch<'a>(
let config = ws.config();
let build_config = BuildConfig::new(config, jobs, &options.target, CompileMode::Build)?;
let rustc = config.load_global_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 to_download = Vec::new();
let target_info = TargetInfo::new(
config,
build_config.requested_kind,
&rustc,
build_config.requested_kind,
)?;
let mut fetched_packages = HashSet::new();
let mut deps_to_fetch = ws.members().map(|p| p.package_id()).collect::<Vec<_>>();
let mut to_download = Vec::new();
while let Some(id) = deps_to_fetch.pop() {
if !fetched_packages.insert(id) {
continue;
}
to_download.push(id);
let deps = resolve
.deps(id)
.filter(|&(_id, deps)| {
deps.iter().any(|d| {
// If no target was specified then all dependencies can
// be fetched.
let target = match options.target {
Some(ref t) => t,
None => return true,
};
// If this dependency is only available for certain
// platforms, make sure we're only fetching it for that
// platform.
let platform = match d.platform() {
Some(p) => p,
None => return true,
};
platform.matches(target, target_info.cfg())
})
})
.map(|(id, _deps)| id);
deps_to_fetch.extend(deps);
while let Some(id) = deps_to_fetch.pop() {
if !fetched_packages.insert(id) {
continue;
}
packages.get_many(to_download)?;
to_download.push(id);
let deps = resolve
.deps(id)
.filter(|&(_id, deps)| {
deps.iter().any(|d| {
// If no target was specified then all dependencies can
// be fetched.
let target = match options.target {
Some(ref t) => t,
None => return true,
};
// If this dependency is only available for certain
// platforms, make sure we're only fetching it for that
// platform.
let platform = match d.platform() {
Some(p) => p,
None => return true,
};
platform.matches(target, target_info.cfg())
})
})
.map(|(id, _deps)| id);
deps_to_fetch.extend(deps);
}
packages.get_many(to_download)?;
Ok((resolve, packages))
}

View File

@ -7,7 +7,7 @@ use failure::{bail, format_err};
use tempfile::Builder as TempFileBuilder;
use crate::core::compiler::Freshness;
use crate::core::compiler::{DefaultExecutor, Executor};
use crate::core::compiler::{CompileKind, DefaultExecutor, Executor};
use crate::core::resolver::ResolveOpts;
use crate::core::{Edition, Package, PackageId, PackageIdSpec, Source, SourceId, Workspace};
use crate::ops;
@ -256,12 +256,10 @@ fn install_one(
// anything if we're gonna throw it away anyway.
let dst = root.join("bin").into_path_unlocked();
let rustc = config.load_global_rustc(Some(&ws))?;
let target = opts
.build_config
.requested_target
.as_ref()
.unwrap_or(&rustc.host)
.clone();
let target = match &opts.build_config.requested_kind {
CompileKind::Host => rustc.host.as_str(),
CompileKind::Target(target) => target.short_name(),
};
// Helper for --no-track flag to make sure it doesn't overwrite anything.
let no_track_duplicates = || -> CargoResult<BTreeMap<String, Option<PackageId>>> {
@ -410,8 +408,8 @@ fn install_one(
&successful_bins,
vers.map(|s| s.to_string()),
opts,
target,
rustc.verbose_version,
&target,
&rustc.verbose_version,
);
if let Err(e) = remove_orphaned_bins(&ws, &mut tracker, &duplicates, pkg, &dst) {

View File

@ -283,8 +283,8 @@ impl InstallTracker {
bins: &BTreeSet<String>,
version_req: Option<String>,
opts: &CompileOptions<'_>,
target: String,
rustc: String,
target: &str,
rustc: &str,
) {
if self.unstable_upgrade {
self.v2
@ -430,8 +430,8 @@ impl CrateListingV2 {
bins: &BTreeSet<String>,
version_req: Option<String>,
opts: &CompileOptions<'_>,
target: String,
rustc: String,
target: &str,
rustc: &str,
) {
// Remove bins from any other packages.
for info in &mut self.installs.values_mut() {
@ -456,8 +456,8 @@ impl CrateListingV2 {
info.all_features = opts.all_features;
info.no_default_features = opts.no_default_features;
info.profile = profile_name(opts.build_config.release).to_string();
info.target = Some(target);
info.rustc = Some(rustc);
info.target = Some(target.to_string());
info.rustc = Some(rustc.to_string());
} else {
self.installs.insert(
pkg.package_id(),
@ -468,8 +468,8 @@ impl CrateListingV2 {
all_features: opts.all_features,
no_default_features: opts.no_default_features,
profile: profile_name(opts.build_config.release).to_string(),
target: Some(target),
rustc: Some(rustc),
target: Some(target.to_string()),
rustc: Some(rustc.to_string()),
other: BTreeMap::new(),
},
);

View File

@ -9,6 +9,7 @@ use std::sync::Mutex;
use log::{debug, info, warn};
use serde::{Deserialize, Serialize};
use crate::core::InternedString;
use crate::util::paths;
use crate::util::{self, internal, profile, CargoResult, ProcessBuilder};
@ -23,7 +24,7 @@ pub struct Rustc {
/// Verbose version information (the output of `rustc -vV`)
pub verbose_version: String,
/// The host triple (arch-platform-OS), this comes from verbose_version.
pub host: String,
pub host: InternedString,
cache: Mutex<Cache>,
}
@ -58,7 +59,7 @@ impl Rustc {
verbose_version
)
})?;
triple.to_string()
InternedString::new(triple)
};
Ok(Rustc {