Skip to content

Commit 76055d2

Browse files
committed
Support multitarget in .cargo/config.toml
For backward compatible reason, `build.target` starts accepting both array of string and a single string.
1 parent 20d96f3 commit 76055d2

File tree

2 files changed

+78
-12
lines changed

2 files changed

+78
-12
lines changed

src/cargo/core/compiler/compile_kind.rs

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::core::Target;
2+
use crate::util::config::BuildTargetConfigValue;
23
use crate::util::errors::CargoResult;
34
use crate::util::interning::InternedString;
45
use crate::util::{Config, StableHasher};
@@ -66,19 +67,34 @@ impl CompileKind {
6667
.into_iter()
6768
.collect());
6869
}
69-
let kind = match &config.build_config()?.target {
70-
Some(val) => {
71-
let value = if val.raw_value().ends_with(".json") {
72-
let path = val.clone().resolve_path(config);
73-
path.to_str().expect("must be utf-8 in toml").to_string()
74-
} else {
75-
val.raw_value().to_string()
76-
};
77-
CompileKind::Target(CompileTarget::new(&value)?)
70+
71+
let kinds = match &config.build_config()?.target {
72+
None => vec![CompileKind::Host],
73+
Some(build_target_config) => {
74+
let values = build_target_config.values(config);
75+
if values.len() > 1 && !config.cli_unstable().multitarget {
76+
bail!("specifying multiple `--target` flags requires `-Zmultitarget`")
77+
}
78+
values
79+
.into_iter()
80+
.map(|k| {
81+
use BuildTargetConfigValue::*;
82+
let value = match &k {
83+
Path(p) => p.to_str().expect("must be utf-8 in toml"),
84+
Simple(s) => s,
85+
};
86+
CompileTarget::new(value).map(CompileKind::Target)
87+
})
88+
// First collect into a set to deduplicate any `--target` passed
89+
// more than once...
90+
.collect::<CargoResult<BTreeSet<_>>>()?
91+
// ... then generate a flat list for everything else to use.
92+
.into_iter()
93+
.collect()
7894
}
79-
None => CompileKind::Host,
8095
};
81-
Ok(vec![kind])
96+
97+
Ok(kinds)
8298
}
8399

84100
/// Hash used for fingerprinting.

src/cargo/util/config/mod.rs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2169,7 +2169,7 @@ pub struct CargoBuildConfig {
21692169
pub dep_info_basedir: Option<ConfigRelativePath>,
21702170
pub target_dir: Option<ConfigRelativePath>,
21712171
pub incremental: Option<bool>,
2172-
pub target: Option<ConfigRelativePath>,
2172+
pub target: Option<BuildTargetConfig>,
21732173
pub jobs: Option<u32>,
21742174
pub rustflags: Option<StringList>,
21752175
pub rustdocflags: Option<StringList>,
@@ -2180,6 +2180,56 @@ pub struct CargoBuildConfig {
21802180
pub out_dir: Option<ConfigRelativePath>,
21812181
}
21822182

2183+
/// Configuration for `build.target`.
2184+
///
2185+
/// Accepts in the following forms:
2186+
///
2187+
/// ```toml
2188+
/// target = "a"
2189+
/// target = ["a"]
2190+
/// target = ["a", "b"]
2191+
/// ```
2192+
#[derive(Debug, Deserialize)]
2193+
#[serde(transparent)]
2194+
pub struct BuildTargetConfig {
2195+
inner: Value<BuildTargetConfigInner>,
2196+
}
2197+
2198+
#[derive(Debug, Deserialize)]
2199+
#[serde(untagged)]
2200+
enum BuildTargetConfigInner {
2201+
One(String),
2202+
Many(Vec<String>),
2203+
}
2204+
2205+
impl BuildTargetConfig {
2206+
/// Gets values of `build.target` as a list of [`BuildTargetConfigValue`].
2207+
pub fn values(&self, config: &Config) -> Vec<BuildTargetConfigValue<'_>> {
2208+
let def_root = self.inner.definition.root(config);
2209+
fn map<'a>(s: &'a str, root: &Path) -> BuildTargetConfigValue<'a> {
2210+
if s.ends_with(".json") {
2211+
// To absolute path.
2212+
BuildTargetConfigValue::Path(root.join(s))
2213+
} else {
2214+
BuildTargetConfigValue::Simple(s)
2215+
}
2216+
}
2217+
match &self.inner.val {
2218+
BuildTargetConfigInner::One(s) => vec![map(s, def_root)],
2219+
BuildTargetConfigInner::Many(v) => v.iter().map(|s| map(s, def_root)).collect(),
2220+
}
2221+
}
2222+
}
2223+
2224+
/// Represents a value of `build.target`.
2225+
pub enum BuildTargetConfigValue<'a> {
2226+
/// Path to a target specification file (in JSON).
2227+
/// <https://doc.rust-lang.org/rustc/targets/custom.html>
2228+
Path(PathBuf),
2229+
/// A string. Probably a target triple.
2230+
Simple(&'a str),
2231+
}
2232+
21832233
#[derive(Deserialize, Default)]
21842234
struct TermConfig {
21852235
verbose: Option<bool>,

0 commit comments

Comments
 (0)