]> git.proxmox.com Git - cargo.git/commitdiff
Refactor `Kind` to carry target name in `Target`
authorAlex Crichton <alex@alexcrichton.com>
Tue, 24 Sep 2019 17:53:32 +0000 (10:53 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Thu, 26 Sep 2019 15:23:05 +0000 (08:23 -0700)
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.

19 files changed:
crates/cargo-test-support/src/lib.rs
src/cargo/core/compiler/build_config.rs
src/cargo/core/compiler/build_context/mod.rs
src/cargo/core/compiler/build_context/target_info.rs
src/cargo/core/compiler/compilation.rs
src/cargo/core/compiler/context/compilation_files.rs
src/cargo/core/compiler/context/mod.rs
src/cargo/core/compiler/custom_build.rs
src/cargo/core/compiler/mod.rs
src/cargo/core/compiler/standard_lib.rs
src/cargo/core/compiler/timings.rs
src/cargo/core/compiler/unit_dependencies.rs
src/cargo/core/interning.rs
src/cargo/ops/cargo_clean.rs
src/cargo/ops/cargo_compile.rs
src/cargo/ops/cargo_fetch.rs
src/cargo/ops/cargo_install.rs
src/cargo/ops/common_for_install_and_uninstall.rs
src/cargo/util/rustc.rs

index 0ee88e8d4b4e7b98ddcdeac5ca3eb713dd359d89..6aa37a4f3ff8b8551ae8b7627e7d0cd528d9b75d 100644 (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 {
index 958f8c1cab526f642b9a4c4a1148a5f387d680d6..abede0cb6f2d37e5cc4673f1ed05f4d31a9b242c 100644 (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,
index 7333b08c6808f49853ef3335bc8d01a3539247f2..e43721e1742aba9faa9a2303403bf13b5df74f70 100644 (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)
     }
 }
 
index 2a4f5545be53486948a93c5dfb69a4a0da29eb00..26ea0aa81af2ac2609d29a6423891085c55585e3 100644 (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.
index 2f0b190eb19d45e8d87f2d40029056ba3def54d1..ab28cee6b44046bfd08b138de02e0486a4c1fd87 100644 (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
index 743d7d821c5213dd36e2182bf52ff2beff81a51a..0af90c6683e1d90ac8e8cb4fe40c2e5e94d63983 100644 (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()
     {
index f9cee44a9f3aa8b6e23747588fc367483016a7cf..e6999209f6e82697934c172d11e0b0e8cf2b46ed 100644 (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))
             }
         };
 
index f727087ccfa70e2545c637886e800b9284d4fde1..3c883d2a16f599fe7a24f9341a78f0d9a43b495e 100644 (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);
     }
 
index 44bcc0afdf1e38c773933ad1cd0965f4d869e3de..afd847f343f7b994119d2ca3a90cef32b90eb00e 100644 (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),
         }
     }
 }
index 88a8c07af94138815b7b3033b00de54999cf9b24..c2a415479abbe2922e23032275b1dc0ba4bd6d0e 100644 (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,
index 6098e6dfa2c27a27cf0ff50dbe2f8ed63eb05606..d103a42394cfb0efc6d18930085aa3431fab153e 100644 (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
index 936adee365a44cea6e354467b759094178d5ee97..136672662fbfbabf6ad7b9af82615a44dd402399 100644 (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);
index f4223f414e4958cdce0d57dd0ae4d6c67f97f8aa..e0aa8c8922ab1b3fbd90199f893fbebcdcfb06d2 100644 (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
index ac8dd6d72eb9a85661b6b953e5752dc3a1acdd1f..3e7ff13e0f81716abc80a788287da43bda919c99 100644 (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() {
index 6c76cb7576ce040bb2db0b9116cac0e573befed4..4ce435e9e7e2fa98a5558a26c5537bccffe9bfd9 100644 (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)?
     };
 
index 6ffb62a23135e2475aacdde16dac6e9fda578c61..3ce5a91c0c8c48af6544c8ab41efef19f8e1f510 100644 (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;
-            }
+    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())
-                    })
+        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)?;
+            })
+            .map(|(id, _deps)| id);
+        deps_to_fetch.extend(deps);
     }
+    packages.get_many(to_download)?;
 
     Ok((resolve, packages))
 }
index 37adde31495e6f8bb69c7b0bfe4c584ad8e3e9ba..4ea5023b2bd5bb210b27d9cc3bc77dea2afa26a4 100644 (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) {
index f61a00d39a89111700cd51c1a8ec325ca7fd1cd9..af79e5513113a1ccf7625a4a79e743671c40ca14 100644 (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(),
                 },
             );
index d79b663aa990b79a4f4a1d875776de742c944ca7..eafdc8dd941f57ebdf830907939ccdd6cd49a116 100644 (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 {