Skip to content

Commit ef425b7

Browse files
committed
Refactor how compile targets are handled
Rename `Kind` to `CompileKind` to reflect that it's intended for compilation. Additionally change the `Target` variant to have a newtype `CompileTarget` instead of just being a raw string. This new `CompileTarget` type has a fallible constructor and handles custom json target files internally. Two accessors are available for `CompileTarget`, one is `rustc_target()` which goes straight to rustc and everything else uses `short_name()` which is the raw target or file stem for json files. The `short_name` is used everywhere in Cargo for all purposes like configuration, env vars, target directory naming, etc.
1 parent 593a02f commit ef425b7

23 files changed

+273
-276
lines changed

src/cargo/core/compiler/build_config.rs

Lines changed: 19 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
use std::cell::RefCell;
2-
use std::path::Path;
32

43
use serde::ser;
54

6-
use crate::core::InternedString;
5+
use crate::core::compiler::{CompileKind, CompileTarget};
76
use crate::util::ProcessBuilder;
8-
use crate::util::{CargoResult, CargoResultExt, Config, RustfixDiagnosticServer};
7+
use crate::util::{CargoResult, Config, RustfixDiagnosticServer};
98

109
/// Configuration information for a rustc build.
1110
#[derive(Debug)]
1211
pub struct BuildConfig {
13-
/// The target arch triple.
14-
/// Default: host arch.
15-
pub requested_target: Option<InternedString>,
12+
/// The requested kind of compilation for this session
13+
pub requested_kind: CompileKind,
1614
/// Number of rustc jobs to run in parallel.
1715
pub jobs: u32,
1816
/// `true` if we are building for release.
@@ -47,36 +45,21 @@ impl BuildConfig {
4745
requested_target: &Option<String>,
4846
mode: CompileMode,
4947
) -> CargoResult<BuildConfig> {
50-
let requested_target = match requested_target {
51-
&Some(ref target) if target.ends_with(".json") => {
52-
let path = Path::new(target).canonicalize().chain_err(|| {
53-
failure::format_err!("Target path {:?} is not a valid file", target)
54-
})?;
55-
Some(
56-
path.into_os_string()
57-
.into_string()
58-
.map_err(|_| failure::format_err!("Target path is not valid unicode"))?,
59-
)
60-
}
61-
other => other.clone(),
48+
let requested_kind = match requested_target {
49+
Some(s) => CompileKind::Target(CompileTarget::new(s)?),
50+
None => match config.get_string("build.target")? {
51+
Some(cfg) => {
52+
let value = if cfg.val.ends_with(".json") {
53+
let path = cfg.definition.root(config).join(&cfg.val);
54+
path.to_str().expect("must be utf-8 in toml").to_string()
55+
} else {
56+
cfg.val
57+
};
58+
CompileKind::Target(CompileTarget::new(&value)?)
59+
}
60+
None => CompileKind::Host,
61+
},
6262
};
63-
if let Some(ref s) = requested_target {
64-
if s.trim().is_empty() {
65-
failure::bail!("target was empty")
66-
}
67-
}
68-
let cfg_target = match config.get_string("build.target")? {
69-
Some(ref target) if target.val.ends_with(".json") => {
70-
let path = target.definition.root(config).join(&target.val);
71-
let path_string = path
72-
.into_os_string()
73-
.into_string()
74-
.map_err(|_| failure::format_err!("Target path is not valid unicode"));
75-
Some(path_string?)
76-
}
77-
other => other.map(|t| t.val),
78-
};
79-
let target = requested_target.or(cfg_target);
8063

8164
if jobs == Some(0) {
8265
failure::bail!("jobs must be at least 1")
@@ -92,7 +75,7 @@ impl BuildConfig {
9275
let jobs = jobs.or(cfg_jobs).unwrap_or(::num_cpus::get() as u32);
9376

9477
Ok(BuildConfig {
95-
requested_target: target.as_ref().map(|s| s.into()),
78+
requested_kind,
9679
jobs,
9780
release: false,
9881
mode,

src/cargo/core/compiler/build_context/mod.rs

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::core::compiler::unit::UnitInterner;
2-
use crate::core::compiler::{BuildConfig, BuildOutput, Kind, Unit};
2+
use crate::core::compiler::CompileTarget;
3+
use crate::core::compiler::{BuildConfig, BuildOutput, CompileKind, Unit};
34
use crate::core::profiles::Profiles;
45
use crate::core::{Dependency, InternedString, Workspace};
56
use crate::core::{PackageId, PackageSet};
@@ -35,8 +36,8 @@ pub struct BuildContext<'a, 'cfg> {
3536
/// Build information for the host arch.
3637
host_config: TargetConfig,
3738
/// Build information for the target.
38-
target_config: HashMap<InternedString, TargetConfig>,
39-
target_info: HashMap<InternedString, TargetInfo>,
39+
target_config: HashMap<CompileTarget, TargetConfig>,
40+
target_info: HashMap<CompileTarget, TargetInfo>,
4041
host_info: TargetInfo,
4142
pub units: &'a UnitInterner<'a>,
4243
}
@@ -54,14 +55,24 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> {
5455
let rustc = config.load_global_rustc(Some(ws))?;
5556

5657
let host_config = TargetConfig::new(config, &rustc.host)?;
57-
let host_info = TargetInfo::new(config, build_config.requested_target, &rustc, Kind::Host)?;
58+
let host_info = TargetInfo::new(
59+
config,
60+
build_config.requested_kind,
61+
&rustc,
62+
CompileKind::Host,
63+
)?;
5864
let mut target_config = HashMap::new();
5965
let mut target_info = HashMap::new();
60-
if let Some(target) = build_config.requested_target {
61-
target_config.insert(target, TargetConfig::new(config, &target)?);
66+
if let CompileKind::Target(target) = build_config.requested_kind {
67+
target_config.insert(target, TargetConfig::new(config, target.short_name())?);
6268
target_info.insert(
6369
target,
64-
TargetInfo::new(config, Some(target), &rustc, Kind::Target(target))?,
70+
TargetInfo::new(
71+
config,
72+
build_config.requested_kind,
73+
&rustc,
74+
CompileKind::Target(target),
75+
)?,
6576
);
6677
}
6778

@@ -82,30 +93,30 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> {
8293
}
8394

8495
/// Whether a dependency should be compiled for the host or target platform,
85-
/// specified by `Kind`.
86-
pub fn dep_platform_activated(&self, dep: &Dependency, kind: Kind) -> bool {
96+
/// specified by `CompileKind`.
97+
pub fn dep_platform_activated(&self, dep: &Dependency, kind: CompileKind) -> bool {
8798
// If this dependency is only available for certain platforms,
8899
// make sure we're only enabling it for that platform.
89100
let platform = match dep.platform() {
90101
Some(p) => p,
91102
None => return true,
92103
};
93-
let name = self.target_triple(kind);
104+
let name = kind.short_name(self);
94105
platform.matches(&name, self.cfg(kind))
95106
}
96107

97108
/// Gets the user-specified linker for a particular host or target.
98-
pub fn linker(&self, kind: Kind) -> Option<&Path> {
109+
pub fn linker(&self, kind: CompileKind) -> Option<&Path> {
99110
self.target_config(kind).linker.as_ref().map(|s| s.as_ref())
100111
}
101112

102113
/// Gets the user-specified `ar` program for a particular host or target.
103-
pub fn ar(&self, kind: Kind) -> Option<&Path> {
114+
pub fn ar(&self, kind: CompileKind) -> Option<&Path> {
104115
self.target_config(kind).ar.as_ref().map(|s| s.as_ref())
105116
}
106117

107118
/// Gets the list of `cfg`s printed out from the compiler for the specified kind.
108-
pub fn cfg(&self, kind: Kind) -> &[Cfg] {
119+
pub fn cfg(&self, kind: CompileKind) -> &[Cfg] {
109120
self.info(kind).cfg()
110121
}
111122

@@ -119,19 +130,11 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> {
119130
self.rustc.host
120131
}
121132

122-
/// Returns the target triple associated with a `Kind`
123-
pub fn target_triple(&self, kind: Kind) -> InternedString {
124-
match kind {
125-
Kind::Host => self.host_triple(),
126-
Kind::Target(name) => name,
127-
}
128-
}
129-
130133
/// Gets the target configuration for a particular host or target.
131-
pub fn target_config(&self, kind: Kind) -> &TargetConfig {
134+
pub fn target_config(&self, kind: CompileKind) -> &TargetConfig {
132135
match kind {
133-
Kind::Host => &self.host_config,
134-
Kind::Target(s) => &self.target_config[&s],
136+
CompileKind::Host => &self.host_config,
137+
CompileKind::Target(s) => &self.target_config[&s],
135138
}
136139
}
137140

@@ -152,10 +155,10 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> {
152155
pkg.source_id().is_path() || self.config.extra_verbose()
153156
}
154157

155-
pub fn info(&self, kind: Kind) -> &TargetInfo {
158+
pub fn info(&self, kind: CompileKind) -> &TargetInfo {
156159
match kind {
157-
Kind::Host => &self.host_info,
158-
Kind::Target(s) => &self.target_info[&s],
160+
CompileKind::Host => &self.host_info,
161+
CompileKind::Target(s) => &self.target_info[&s],
159162
}
160163
}
161164

@@ -167,7 +170,7 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> {
167170
///
168171
/// `lib_name` is the `links` library name and `kind` is whether it is for
169172
/// Host or Target.
170-
pub fn script_override(&self, lib_name: &str, kind: Kind) -> Option<&BuildOutput> {
173+
pub fn script_override(&self, lib_name: &str, kind: CompileKind) -> Option<&BuildOutput> {
171174
self.target_config(kind).overrides.get(lib_name)
172175
}
173176
}

src/cargo/core/compiler/build_context/target_info.rs

Lines changed: 19 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ use std::env;
44
use std::path::PathBuf;
55
use std::str::{self, FromStr};
66

7-
use crate::core::compiler::Kind;
8-
use crate::core::InternedString;
7+
use crate::core::compiler::CompileKind;
98
use crate::core::TargetKind;
109
use crate::util::{CargoResult, CargoResultExt, Config, ProcessBuilder, Rustc};
1110
use cargo_platform::{Cfg, CfgExpr};
@@ -37,7 +36,7 @@ pub struct TargetInfo {
3736
pub rustdocflags: Vec<String>,
3837
}
3938

40-
/// Kind of each file generated by a Unit, part of `FileType`.
39+
/// CompileKind of each file generated by a Unit, part of `FileType`.
4140
#[derive(Clone, PartialEq, Eq, Debug)]
4241
pub enum FileFlavor {
4342
/// Not a special file type.
@@ -81,18 +80,11 @@ impl FileType {
8180
impl TargetInfo {
8281
pub fn new(
8382
config: &Config,
84-
requested_target: Option<InternedString>,
83+
requested_kind: CompileKind,
8584
rustc: &Rustc,
86-
kind: Kind,
85+
kind: CompileKind,
8786
) -> CargoResult<TargetInfo> {
88-
let rustflags = env_args(
89-
config,
90-
requested_target,
91-
&rustc.host,
92-
None,
93-
kind,
94-
"RUSTFLAGS",
95-
)?;
87+
let rustflags = env_args(config, requested_kind, &rustc.host, None, kind, "RUSTFLAGS")?;
9688
let mut process = rustc.process();
9789
process
9890
.arg("-")
@@ -102,8 +94,8 @@ impl TargetInfo {
10294
.args(&rustflags)
10395
.env_remove("RUSTC_LOG");
10496

105-
if let Kind::Target(target) = kind {
106-
process.arg("--target").arg(target);
97+
if let CompileKind::Target(target) = kind {
98+
process.arg("--target").arg(target.rustc_target());
10799
}
108100

109101
let crate_type_process = process.clone();
@@ -137,18 +129,18 @@ impl TargetInfo {
137129
};
138130
let mut rustlib = PathBuf::from(line);
139131
let sysroot_libdir = match kind {
140-
Kind::Host => {
132+
CompileKind::Host => {
141133
if cfg!(windows) {
142134
rustlib.push("bin");
143135
} else {
144136
rustlib.push("lib");
145137
}
146138
rustlib
147139
}
148-
Kind::Target(target) => {
140+
CompileKind::Target(target) => {
149141
rustlib.push("lib");
150142
rustlib.push("rustlib");
151-
rustlib.push(target);
143+
rustlib.push(target.short_name());
152144
rustlib.push("lib");
153145
rustlib
154146
}
@@ -172,15 +164,15 @@ impl TargetInfo {
172164
// information
173165
rustflags: env_args(
174166
config,
175-
requested_target,
167+
requested_kind,
176168
&rustc.host,
177169
Some(&cfg),
178170
kind,
179171
"RUSTFLAGS",
180172
)?,
181173
rustdocflags: env_args(
182174
config,
183-
requested_target,
175+
requested_kind,
184176
&rustc.host,
185177
Some(&cfg),
186178
kind,
@@ -378,10 +370,10 @@ fn output_err_info(cmd: &ProcessBuilder, stdout: &str, stderr: &str) -> String {
378370
/// scripts, ...), even if it is the same as the target.
379371
fn env_args(
380372
config: &Config,
381-
requested_target: Option<InternedString>,
373+
requested_kind: CompileKind,
382374
host_triple: &str,
383375
target_cfg: Option<&[Cfg]>,
384-
kind: Kind,
376+
kind: CompileKind,
385377
name: &str,
386378
) -> CargoResult<Vec<String>> {
387379
// We *want* to apply RUSTFLAGS only to builds for the
@@ -403,8 +395,7 @@ fn env_args(
403395
// This means that, e.g., even if the specified --target is the
404396
// same as the host, build scripts in plugins won't get
405397
// RUSTFLAGS.
406-
let compiling_with_target = requested_target.is_some();
407-
if compiling_with_target && kind.is_host() {
398+
if !requested_kind.is_host() && kind.is_host() {
408399
// This is probably a build script or plugin and we're
409400
// compiling with --target. In this scenario there are
410401
// no rustflags we can apply.
@@ -428,10 +419,10 @@ fn env_args(
428419
.flat_map(|c| c.to_lowercase())
429420
.collect::<String>();
430421
// Then the target.*.rustflags value...
431-
let target = requested_target
432-
.as_ref()
433-
.map(|s| s.as_str())
434-
.unwrap_or(host_triple);
422+
let target = match &kind {
423+
CompileKind::Host => host_triple,
424+
CompileKind::Target(target) => target.short_name(),
425+
};
435426
let key = format!("target.{}.{}", target, name);
436427
if let Some(args) = config.get_list_or_split_string(&key)? {
437428
let args = args.val.into_iter();

src/cargo/core/compiler/build_plan.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::path::PathBuf;
1212
use serde::Serialize;
1313

1414
use super::context::OutputFile;
15-
use super::{CompileMode, Context, Kind, Unit};
15+
use super::{CompileKind, CompileMode, Context, Unit};
1616
use crate::core::TargetKind;
1717
use crate::util::{internal, CargoResult, ProcessBuilder};
1818

@@ -21,7 +21,7 @@ struct Invocation {
2121
package_name: String,
2222
package_version: semver::Version,
2323
target_kind: TargetKind,
24-
kind: Kind,
24+
kind: CompileKind,
2525
compile_mode: CompileMode,
2626
deps: Vec<usize>,
2727
outputs: Vec<PathBuf>,

0 commit comments

Comments
 (0)