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:
Alex Crichton 2019-09-24 10:53:32 -07:00
parent 494cbd8c8d
commit 593a02f2d7
19 changed files with 204 additions and 200 deletions

View file

@ -1680,7 +1680,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

@ -3,6 +3,7 @@ use std::path::Path;
use serde::ser;
use crate::core::InternedString;
use crate::util::ProcessBuilder;
use crate::util::{CargoResult, CargoResultExt, Config, RustfixDiagnosticServer};
@ -11,7 +12,7 @@ use crate::util::{CargoResult, CargoResultExt, Config, RustfixDiagnosticServer};
pub struct BuildConfig {
/// The target arch triple.
/// Default: host arch.
pub requested_target: Option<String>,
pub requested_target: Option<InternedString>,
/// Number of rustc jobs to run in parallel.
pub jobs: u32,
/// `true` if we are building for release.
@ -91,7 +92,7 @@ impl BuildConfig {
let jobs = jobs.or(cfg_jobs).unwrap_or(::num_cpus::get() as u32);
Ok(BuildConfig {
requested_target: target,
requested_target: target.as_ref().map(|s| s.into()),
jobs,
release: false,
mode,

View file

@ -1,17 +1,14 @@
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::{Dependency, InternedString, Workspace};
use crate::core::{PackageId, PackageSet};
use crate::util::errors::CargoResult;
use crate::util::{profile, Config, Rustc};
use crate::util::{Config, Rustc};
use cargo_platform::Cfg;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::str;
mod target_info;
pub use self::target_info::{FileFlavor, TargetInfo};
@ -36,11 +33,11 @@ pub struct BuildContext<'a, 'cfg> {
/// Information about the compiler.
pub rustc: Rustc,
/// Build information for the host arch.
pub host_config: TargetConfig,
host_config: TargetConfig,
/// Build information for the target.
pub target_config: TargetConfig,
pub target_info: TargetInfo,
pub host_info: TargetInfo,
target_config: HashMap<InternedString, TargetConfig>,
target_info: HashMap<InternedString, TargetInfo>,
host_info: TargetInfo,
pub units: &'a UnitInterner<'a>,
}
@ -57,19 +54,16 @@ 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_target, &rustc, Kind::Host)?;
let mut target_config = HashMap::new();
let mut target_info = HashMap::new();
if let Some(target) = build_config.requested_target {
target_config.insert(target, TargetConfig::new(config, &target)?);
target_info.insert(
target,
TargetInfo::new(config, Some(target), &rustc, Kind::Target(target))?,
);
}
Ok(BuildContext {
ws,
@ -96,11 +90,8 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> {
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 = self.target_triple(kind);
platform.matches(&name, self.cfg(kind))
}
/// Gets the user-specified linker for a particular host or target.
@ -115,11 +106,7 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> {
/// 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()
self.info(kind).cfg()
}
/// Gets the host architecture triple.
@ -128,23 +115,23 @@ 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 host_triple(&self) -> InternedString {
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())
/// Returns the target triple associated with a `Kind`
pub fn target_triple(&self, kind: Kind) -> InternedString {
match kind {
Kind::Host => self.host_triple(),
Kind::Target(name) => name,
}
}
/// Gets the target configuration for a particular host or target.
fn target_config(&self, kind: Kind) -> &TargetConfig {
pub fn target_config(&self, kind: Kind) -> &TargetConfig {
match kind {
Kind::Host => &self.host_config,
Kind::Target => &self.target_config,
Kind::Target(s) => &self.target_config[&s],
}
}
@ -165,10 +152,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: Kind) -> &TargetInfo {
match kind {
Kind::Host => &self.host_info,
Kind::Target => &self.target_info,
Kind::Target(s) => &self.target_info[&s],
}
}
@ -181,10 +168,7 @@ 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),
}
self.target_config(kind).overrides.get(lib_name)
}
}

View file

@ -5,6 +5,7 @@ use std::path::PathBuf;
use std::str::{self, FromStr};
use crate::core::compiler::Kind;
use crate::core::InternedString;
use crate::core::TargetKind;
use crate::util::{CargoResult, CargoResultExt, Config, ProcessBuilder, Rustc};
use cargo_platform::{Cfg, CfgExpr};
@ -80,7 +81,7 @@ impl FileType {
impl TargetInfo {
pub fn new(
config: &Config,
requested_target: &Option<String>,
requested_target: Option<InternedString>,
rustc: &Rustc,
kind: Kind,
) -> CargoResult<TargetInfo> {
@ -101,12 +102,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 Kind::Target(target) = kind {
process.arg("--target").arg(target);
}
let crate_type_process = process.clone();
@ -148,10 +145,10 @@ impl TargetInfo {
}
rustlib
}
Kind::Target => {
Kind::Target(target) => {
rustlib.push("lib");
rustlib.push("rustlib");
rustlib.push(target_triple);
rustlib.push(target);
rustlib.push("lib");
rustlib
}
@ -381,7 +378,7 @@ 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_target: Option<InternedString>,
host_triple: &str,
target_cfg: Option<&[Cfg]>,
kind: Kind,
@ -407,9 +404,7 @@ fn env_args(
// 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 compiling_with_target && 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.

View file

@ -7,6 +7,7 @@ use cargo_platform::CfgExpr;
use semver::Version;
use super::BuildContext;
use crate::core::compiler::Kind;
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: Kind,
) -> 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(Kind::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: bcx.target_triple(default_kind).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: Kind,
) -> CargoResult<Option<(PathBuf, Vec<String>)>> {
let target = bcx.target_triple(kind);
// 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

@ -10,7 +10,7 @@ use log::info;
use super::{BuildContext, Context, FileFlavor, Kind, Layout};
use crate::core::compiler::{CompileMode, Unit};
use crate::core::{TargetKind, Workspace};
use crate::core::{InternedString, TargetKind, Workspace};
use crate::util::{self, CargoResult};
/// The `Metadata` is a hash used to make unique file names for each unit in a build.
@ -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<InternedString, 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<InternedString, Layout>,
export_dir: Option<PathBuf>,
ws: &'a Workspace<'cfg>,
cx: &Context<'a, 'cfg>,
@ -122,7 +122,7 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
pub fn layout(&self, kind: Kind) -> &Layout {
match kind {
Kind::Host => &self.host,
Kind::Target => self.target.as_ref().unwrap_or(&self.host),
Kind::Target(name) => self.target.get(&name).unwrap_or(&self.host),
}
}
@ -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(),
&bcx.target_triple(unit.kind),
)?;
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()
bcx.target_triple(unit.kind),
)
}
failure::bail!(
"cannot compile `{}` as the target `{}` does not \
support any of the output crate types",
unit.pkg,
bcx.target_triple()
bcx.target_triple(unit.kind),
);
}
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() && bcx.target_triple(unit.kind).starts_with("wasm32-")))
&& unit.pkg.package_id().source_id().is_path()
&& __cargo_default_lib_metadata.is_err()
{

View file

@ -79,6 +79,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
config: &'cfg Config,
bcx: &'a BuildContext<'a, 'cfg>,
unit_dependencies: UnitGraph<'a>,
default_kind: Kind,
) -> 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 Some(target) = self.bcx.build_config.requested_target {
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,10 @@ 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 = match self.bcx.build_config.requested_target {
Some(target) => &files.target[&target],
None => &files.host,
};
self.compilation.root_output = layout.dest().to_path_buf();
self.compilation.deps_output = layout.deps().to_path_buf();
Ok(())
@ -450,8 +446,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(),
self.bcx.target_triple(unit.kind),
unit,
other_unit))
}
};

View file

@ -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", bcx.target_triple(unit.kind))
.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);
}

View file

@ -43,7 +43,7 @@ pub use crate::core::compiler::unit::{Unit, UnitInterner};
use crate::core::manifest::TargetSourcePath;
use crate::core::profiles::{Lto, PanicStrategy, Profile};
use crate::core::Feature;
use crate::core::{PackageId, Target};
use crate::core::{InternedString, PackageId, Target};
use crate::util::errors::{CargoResult, CargoResultExt, Internal, ProcessError};
use crate::util::machine_message::Message;
use crate::util::paths;
@ -56,7 +56,16 @@ use crate::util::{internal, join_paths, profile};
#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy, PartialOrd, Ord, Serialize)]
pub enum Kind {
Host,
Target,
Target(InternedString),
}
impl Kind {
pub fn is_host(&self) -> bool {
match self {
Kind::Host => true,
_ => false,
}
}
}
/// A glorified callback for executing calls to rustc. Rather than calling rustc
@ -565,10 +574,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 Kind::Target(target) = unit.kind {
rustdoc.arg("--target").arg(target);
}
let doc_dir = cx.files().out_dir(unit);
@ -892,16 +899,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 Kind::Target(n) = unit.kind {
cmd.arg("--target").arg(n);
}
opt(cmd, "-C", "ar=", bcx.ar(unit.kind).map(|s| s.as_ref()));
@ -942,7 +941,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 let Kind::Target(_) = unit.kind {
cmd.arg("-L").arg(&{
let mut deps = OsString::from("dependency=");
deps.push(cx.files().host_deps());
@ -1073,8 +1072,8 @@ impl Kind {
// 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,
Kind::Target(_) if target.for_host() => Kind::Host,
Kind::Target(n) => Kind::Target(n),
}
}
}

View file

@ -113,6 +113,7 @@ pub fn generate_std_roots<'a>(
bcx: &BuildContext<'a, '_>,
crates: &[String],
std_resolve: &'a Resolve,
kind: Kind,
) -> CargoResult<Vec<Unit<'a>>> {
// Generate the root Units for the standard library.
let std_ids = crates
@ -147,7 +148,7 @@ pub fn generate_std_roots<'a>(
pkg,
lib,
profile,
Kind::Target,
kind,
mode,
features,
/*is_std*/ true,

View file

@ -576,7 +576,8 @@ fn render_rustc_info(bcx: &BuildContext<'_, '_>) -> String {
.build_config
.requested_target
.as_ref()
.map_or("Host", String::as_str);
.map(|s| s.as_str())
.unwrap_or("Host");
format!(
"{}<br>Host: {}<br>Target: {}",
version, bcx.rustc.host, requested_target

View file

@ -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,11 +270,8 @@ 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)?;
ret.push(unit_dep);

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;
@ -74,6 +75,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

@ -66,6 +66,11 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
)?;
let mut units = Vec::new();
let mut kinds = vec![Kind::Host];
if let Some(target) = build_config.requested_target {
kinds.push(Kind::Target(target));
}
for spec in opts.spec.iter() {
// Translate the spec to a Package
let pkgid = resolve.query(spec)?;
@ -73,7 +78,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 kinds.iter() {
for mode in CompileMode::all_modes() {
for unit_for in UnitFor::all_values() {
let profile = if mode.is_run_custom_build() {
@ -105,7 +110,8 @@ 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 default_kind = kinds.last().cloned().unwrap();
let mut cx = Context::new(config, &bcx, unit_dependencies, default_kind)?;
cx.prepare_units(None, &units)?;
for unit in units.iter() {

View file

@ -294,8 +294,8 @@ pub fn compile_ws<'a>(
}
}
let default_arch_kind = if build_config.requested_target.is_some() {
Kind::Target
let default_arch_kind = if let Some(s) = build_config.requested_target {
Kind::Target(s)
} else {
Kind::Host
};
@ -408,7 +408,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(),
default_arch_kind,
)?
} else {
Vec::new()
};
@ -442,7 +447,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, default_arch_kind)?;
cx.compile(&units, export_dir.clone(), exec)?
};

View file

@ -23,44 +23,45 @@ 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 kind = match build_config.requested_target {
Some(t) => Kind::Target(t),
None => Kind::Host,
};
let target_info = TargetInfo::new(config, build_config.requested_target, &rustc, 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

@ -410,8 +410,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 {