Skip to content

Commit

Permalink
Auto merge of #11790 - vadorovsky:fix-cfg-target-env, r=arlosi
Browse files Browse the repository at this point in the history
Fix `CARGO_CFG_` vars for configs defined both with and without value

When a rustc cfg is defined both with and without value, the environment variable should provide all the values. Before this change, it ended up being empty.

Fixes: #11789
  • Loading branch information
bors committed Mar 6, 2023
2 parents 189ac0e + ccd9915 commit 87a997a
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 14 deletions.
18 changes: 4 additions & 14 deletions src/cargo/core/compiler/custom_build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,14 +231,11 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
for cfg in bcx.target_data.cfg(unit.kind) {
match *cfg {
Cfg::Name(ref n) => {
cfg_map.insert(n.clone(), None);
cfg_map.insert(n.clone(), Vec::new());
}
Cfg::KeyPair(ref k, ref v) => {
if let Some(ref mut values) =
*cfg_map.entry(k.clone()).or_insert_with(|| Some(Vec::new()))
{
values.push(v.clone())
}
let values = cfg_map.entry(k.clone()).or_default();
values.push(v.clone());
}
}
}
Expand All @@ -249,14 +246,7 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
continue;
}
let k = format!("CARGO_CFG_{}", super::envify(&k));
match v {
Some(list) => {
cmd.env(&k, list.join(","));
}
None => {
cmd.env(&k, "");
}
}
cmd.env(&k, v.join(","));
}

// Also inform the build script of the rustc compiler context.
Expand Down
62 changes: 62 additions & 0 deletions tests/testsuite/build_script_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,65 @@ fn cfg_paradox() {
.with_stderr_contains("[..]--cfg=bertrand[..]")
.run();
}

/// This test checks how Cargo handles rustc cfgs which are defined both with
/// and without a value. The expected behavior is that the environment variable
/// is going to contain all the values.
///
/// For example, this configuration:
/// ```
/// target_has_atomic
/// target_has_atomic="16"
/// target_has_atomic="32"
/// target_has_atomic="64"
/// target_has_atomic="8"
/// target_has_atomic="ptr"
/// ```
///
/// Should result in the following environment variable:
///
/// ```
/// CARGO_CFG_TARGET_HAS_ATOMIC=16,32,64,8,ptr
/// ```
///
/// On the other hand, configuration symbols without any value should result in
/// an empty string.
///
/// For example, this configuration:
///
/// ```
/// target_thread_local
/// ```
///
/// Should result in the following environment variable:
///
/// ```
/// CARGO_CFG_TARGET_THREAD_LOCAL=
/// ```
#[cargo_test(nightly, reason = "affected rustc cfg is unstable")]
#[cfg(target_arch = "x86_64")]
fn rustc_cfg_with_and_without_value() {
let build_rs = r#"
fn main() {
let cfg = std::env::var("CARGO_CFG_TARGET_HAS_ATOMIC");
eprintln!("CARGO_CFG_TARGET_HAS_ATOMIC={cfg:?}");
let cfg = std::env::var("CARGO_CFG_WINDOWS");
eprintln!("CARGO_CFG_WINDOWS={cfg:?}");
let cfg = std::env::var("CARGO_CFG_UNIX");
eprintln!("CARGO_CFG_UNIX={cfg:?}");
}
"#;
let p = project()
.file("src/lib.rs", r#""#)
.file("build.rs", build_rs)
.build();

let mut check = p.cargo("check -vv");
#[cfg(target_has_atomic = "64")]
check.with_stderr_contains("[foo 0.0.1] CARGO_CFG_TARGET_HAS_ATOMIC=Ok(\"[..]64[..]\")");
#[cfg(windows)]
check.with_stderr_contains("[foo 0.0.1] CARGO_CFG_WINDOWS=Ok(\"\")");
#[cfg(unix)]
check.with_stderr_contains("[foo 0.0.1] CARGO_CFG_UNIX=Ok(\"\")");
check.run();
}

0 comments on commit 87a997a

Please sign in to comment.