Skip to content

Commit

Permalink
Auto merge of #10473 - weihanglo:multitarget-config, r=ehuss
Browse files Browse the repository at this point in the history
Support `-Zmultitarget` in cargo config
  • Loading branch information
bors committed Mar 31, 2022
2 parents 28afa1e + c18275b commit 1ef1e0a
Show file tree
Hide file tree
Showing 4 changed files with 231 additions and 21 deletions.
34 changes: 16 additions & 18 deletions src/cargo/core/compiler/compile_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,33 +52,31 @@ impl CompileKind {
config: &Config,
targets: &[String],
) -> CargoResult<Vec<CompileKind>> {
if targets.len() > 1 && !config.cli_unstable().multitarget {
bail!("specifying multiple `--target` flags requires `-Zmultitarget`")
}
if !targets.is_empty() {
return Ok(targets
let dedup = |targets: &[String]| {
Ok(targets
.iter()
.map(|value| Ok(CompileKind::Target(CompileTarget::new(value)?)))
// First collect into a set to deduplicate any `--target` passed
// more than once...
.collect::<CargoResult<BTreeSet<_>>>()?
// ... then generate a flat list for everything else to use.
.into_iter()
.collect());
}
let kind = match &config.build_config()?.target {
Some(val) => {
let value = if val.raw_value().ends_with(".json") {
let path = val.clone().resolve_path(config);
path.to_str().expect("must be utf-8 in toml").to_string()
} else {
val.raw_value().to_string()
};
CompileKind::Target(CompileTarget::new(&value)?)
.collect())
};

if !targets.is_empty() {
if targets.len() > 1 && !config.cli_unstable().multitarget {
bail!("specifying multiple `--target` flags requires `-Zmultitarget`")
}
None => CompileKind::Host,
return dedup(targets);
}

let kinds = match &config.build_config()?.target {
None => Ok(vec![CompileKind::Host]),
Some(build_target_config) => dedup(&build_target_config.values(config)?),
};
Ok(vec![kind])

kinds
}

/// Hash used for fingerprinting.
Expand Down
57 changes: 56 additions & 1 deletion src/cargo/util/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2169,7 +2169,7 @@ pub struct CargoBuildConfig {
pub dep_info_basedir: Option<ConfigRelativePath>,
pub target_dir: Option<ConfigRelativePath>,
pub incremental: Option<bool>,
pub target: Option<ConfigRelativePath>,
pub target: Option<BuildTargetConfig>,
pub jobs: Option<u32>,
pub rustflags: Option<StringList>,
pub rustdocflags: Option<StringList>,
Expand All @@ -2180,6 +2180,61 @@ pub struct CargoBuildConfig {
pub out_dir: Option<ConfigRelativePath>,
}

/// Configuration for `build.target`.
///
/// Accepts in the following forms:
///
/// ```toml
/// target = "a"
/// target = ["a"]
/// target = ["a", "b"]
/// ```
#[derive(Debug, Deserialize)]
#[serde(transparent)]
pub struct BuildTargetConfig {
inner: Value<BuildTargetConfigInner>,
}

#[derive(Debug, Deserialize)]
#[serde(untagged)]
enum BuildTargetConfigInner {
One(String),
Many(Vec<String>),
}

impl BuildTargetConfig {
/// Gets values of `build.target` as a list of strings.
pub fn values(&self, config: &Config) -> CargoResult<Vec<String>> {
let map = |s: &String| {
if s.ends_with(".json") {
// Path to a target specification file (in JSON).
// <https://doc.rust-lang.org/rustc/targets/custom.html>
self.inner
.definition
.root(config)
.join(s)
.to_str()
.expect("must be utf-8 in toml")
.to_string()
} else {
// A string. Probably a target triple.
s.to_string()
}
};
let values = match &self.inner.val {
BuildTargetConfigInner::One(s) => vec![map(s)],
BuildTargetConfigInner::Many(v) => {
if !config.cli_unstable().multitarget {
bail!("specifying an array in `build.target` config value requires `-Zmultitarget`")
} else {
v.iter().map(map).collect()
}
}
};
Ok(values)
}
}

#[derive(Deserialize, Default)]
struct TermConfig {
verbose: Option<bool>,
Expand Down
6 changes: 6 additions & 0 deletions src/doc/src/reference/unstable.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,12 @@ or running tests for both targets:
cargo test --target x86_64-unknown-linux-gnu --target i686-unknown-linux-gnu
```

This can also be specified in `.cargo/config.toml` files.

```toml
[build]
target = ["x86_64-unknown-linux-gnu", "i686-unknown-linux-gnu"]
```

#### New `dir-name` attribute

Expand Down
155 changes: 153 additions & 2 deletions tests/testsuite/multitarget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,44 @@ fn double_target_rejected() {
.build();

p.cargo("build --target a --target b")
.with_stderr("error: specifying multiple `--target` flags requires `-Zmultitarget`")
.with_stderr("[ERROR] specifying multiple `--target` flags requires `-Zmultitarget`")
.with_status(101)
.run();
}

#[cargo_test]
fn array_of_target_rejected_with_config() {
let p = project()
.file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
.file("src/main.rs", "fn main() {}")
.file(
".cargo/config.toml",
r#"
[build]
target = ["a", "b"]
"#,
)
.build();

p.cargo("build")
.with_stderr(
"[ERROR] specifying an array in `build.target` config value requires `-Zmultitarget`",
)
.with_status(101)
.run();

p.change_file(
".cargo/config.toml",
r#"
[build]
target = ["a"]
"#,
);

p.cargo("build")
.with_stderr(
"[ERROR] specifying an array in `build.target` config value requires `-Zmultitarget`",
)
.with_status(101)
.run();
}
Expand Down Expand Up @@ -39,6 +76,35 @@ fn simple_build() {
assert!(p.target_bin(t2, "foo").is_file());
}

#[cargo_test]
fn simple_build_with_config() {
if cross_compile::disabled() {
return;
}
let t1 = cross_compile::alternate();
let t2 = rustc_host();
let p = project()
.file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
.file("src/main.rs", "fn main() {}")
.file(
".cargo/config.toml",
&format!(
r#"
[unstable]
multitarget = true
[build]
target = ["{t1}", "{t2}"]
"#
),
)
.build();

p.cargo("build").masquerade_as_nightly_cargo().run();

assert!(p.target_bin(t1, "foo").is_file());
assert!(p.target_bin(t2, "foo").is_file());
}

#[cargo_test]
fn simple_test() {
if !cross_compile::can_run_on_host() {
Expand Down Expand Up @@ -70,7 +136,7 @@ fn simple_run() {
.build();

p.cargo("run -Z multitarget --target a --target b")
.with_stderr("error: only one `--target` argument is supported")
.with_stderr("[ERROR] only one `--target` argument is supported")
.with_status(101)
.masquerade_as_nightly_cargo()
.run();
Expand Down Expand Up @@ -142,3 +208,88 @@ fn same_value_twice() {

assert!(p.target_bin(t, "foo").is_file());
}

#[cargo_test]
fn same_value_twice_with_config() {
if cross_compile::disabled() {
return;
}
let t = rustc_host();
let p = project()
.file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
.file("src/main.rs", "fn main() {}")
.file(
".cargo/config.toml",
&format!(
r#"
[unstable]
multitarget = true
[build]
target = ["{t}", "{t}"]
"#
),
)
.build();

p.cargo("build").masquerade_as_nightly_cargo().run();

assert!(p.target_bin(t, "foo").is_file());
}

#[cargo_test]
fn works_with_config_in_both_string_or_list() {
if cross_compile::disabled() {
return;
}
let t = rustc_host();
let p = project()
.file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
.file("src/main.rs", "fn main() {}")
.file(
".cargo/config.toml",
&format!(
r#"
[unstable]
multitarget = true
[build]
target = "{t}"
"#
),
)
.build();

p.cargo("build").masquerade_as_nightly_cargo().run();

assert!(p.target_bin(t, "foo").is_file());

p.cargo("clean").run();

p.change_file(
".cargo/config.toml",
&format!(
r#"
[unstable]
multitarget = true
[build]
target = ["{t}"]
"#
),
);

p.cargo("build").masquerade_as_nightly_cargo().run();

assert!(p.target_bin(t, "foo").is_file());
}

#[cargo_test]
fn works_with_env() {
let t = rustc_host();
let p = project()
.file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
.file("src/main.rs", "fn main() {}")
.build();

p.cargo("build").env("CARGO_BUILD_TARGET", t).run();

assert!(p.target_bin(t, "foo").is_file());
}

0 comments on commit 1ef1e0a

Please sign in to comment.