Skip to content

Commit

Permalink
Fix CARGO_CFG_ vars for configs defined both with and without value
Browse files Browse the repository at this point in the history
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
vadorovsky committed Mar 3, 2023
1 parent c61b0f0 commit af4c358
Show file tree
Hide file tree
Showing 2 changed files with 73 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_insert_with(|| Vec::new());
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
69 changes: 69 additions & 0 deletions tests/testsuite/build_script_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,72 @@ 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_THREAD_LOCAL").unwrap();
eprintln!("CARGO_CFG_TARGET_THREAD_LOCAL={cfg}");
let cfg = std::env::var("CARGO_CFG_TARGET_HAS_ATOMIC").unwrap();
eprintln!("CARGO_CFG_TARGET_HAS_ATOMIC={cfg}");
let cfg = std::env::var("CARGO_CFG_TARGET_HAS_ATOMIC_LOAD_STORE").unwrap();
eprintln!("CARGO_CFG_TARGET_HAS_ATOMIC_LOAD_STORE={cfg}");
}
"#;

let p = project()
.file("src/lib.rs", r#""#)
.file("build.rs", build_rs)
.build();

#[cfg(target_os = "macos")]
p.cargo("check -vv")
.with_stderr_contains("[foo 0.0.1] CARGO_CFG_TARGET_THREAD_LOCAL=")
.with_stderr_contains("[foo 0.0.1] CARGO_CFG_TARGET_HAS_ATOMIC=128,16,32,64,8,ptr")
.with_stderr_contains(
"[foo 0.0.1] CARGO_CFG_TARGET_HAS_ATOMIC_LOAD_STORE=128,16,32,64,8,ptr",
)
.run();
#[cfg(not(target_os = "macos"))]
p.cargo("check -vv")
.with_stderr_contains("[foo 0.0.1] CARGO_CFG_TARGET_THREAD_LOCAL=")
.with_stderr_contains("[foo 0.0.1] CARGO_CFG_TARGET_HAS_ATOMIC=16,32,64,8,ptr")
.with_stderr_contains("[foo 0.0.1] CARGO_CFG_TARGET_HAS_ATOMIC_LOAD_STORE=16,32,64,8,ptr")
.run();
}

0 comments on commit af4c358

Please sign in to comment.