Skip to content

Commit 1665ecf

Browse files
committed
Avoid probing for std in build.rs to support -Z build-std
1 parent 98e4062 commit 1665ecf

File tree

6 files changed

+57
-104
lines changed

6 files changed

+57
-104
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ harness = false
3333
level = "warn"
3434
check-cfg = [
3535
"cfg(abort, values(\"std\", \"core\"))",
36-
"cfg(backend, values(\"itanium\", \"seh\", \"emscripten\", \"wasm\", \"panic\", \"unimplemented\"))",
37-
"cfg(thread_local, values(\"std\", \"attribute\", \"unimplemented\"))",
36+
"cfg(backend, values(\"itanium\", \"seh\", \"emscripten\", \"wasm\", \"panic\"))",
37+
"cfg(thread_local, values(\"std\", \"attribute\"))",
3838
]
3939

4040
[profile.dev]

build.rs

Lines changed: 47 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ fn cfg(name: &str) -> String {
88
std::env::var(format!("CARGO_CFG_{}", name.to_uppercase())).unwrap_or_default()
99
}
1010

11+
fn make_overridable_cfg(name: &str, logic: impl FnOnce() -> &'static str) -> String {
12+
let env_name = format!("LITHIUM_{}", name.to_uppercase());
13+
println!("cargo::rerun-if-env-changed={env_name}");
14+
let value = std::env::var(env_name).unwrap_or_else(|_| logic().to_string());
15+
println!("cargo::rustc-cfg={name}=\"{value}\"");
16+
value
17+
}
18+
1119
fn main() {
1220
println!("cargo::rerun-if-env-changed=MIRIFLAGS");
1321
let is_miri = has_cfg("miri");
@@ -17,66 +25,49 @@ fn main() {
1725
println!("cargo::rustc-cfg=feature=\"sound-under-stacked-borrows\"");
1826
}
1927

20-
let ac = autocfg::new();
2128
let is_nightly = version_meta().unwrap().channel == Channel::Nightly;
2229

23-
// `ac.probe_raw` calls need to be very careful here: under certain configurations, like
24-
// `cargo clippy -- -D warnings`, warnigns in the tested snippets can cause probing to give
25-
// false negatives. It's important to make sure that, for example, there's no unused items or
26-
// variables. See https://github.com/cuviper/autocfg/issues/41.
30+
// We've previously used `autocfg` to check if `std` is available, and emitted errors when
31+
// compiling without `std` on stable. But that didn't work well: when std is available due to
32+
// `-Z build-std`, autocfg doesn't notice it [1], so the tests within this build script would
33+
// fail even though using `std` from within the crate would work. So instead, we just assume
34+
// that `std` is present if nothing else works -- that leads to worse diagnostics in the failure
35+
// case, but makes the common one actually work.
36+
//
37+
// [1]: https://github.com/cuviper/autocfg/issues/34
2738

28-
println!("cargo::rerun-if-env-changed=LITHIUM_THREAD_LOCAL");
29-
if let Ok(thread_local) = std::env::var("LITHIUM_THREAD_LOCAL") {
30-
println!("cargo::rustc-cfg=thread_local=\"{thread_local}\"");
31-
} else if is_nightly && has_cfg("target_thread_local") {
32-
println!("cargo::rustc-cfg=thread_local=\"attribute\"");
33-
} else if ac
34-
.probe_raw(
35-
r"
36-
#![no_std]
37-
extern crate std;
38-
std::thread_local! {
39-
static FOO: () = const {};
39+
make_overridable_cfg("thread_local", || {
40+
if is_nightly && has_cfg("target_thread_local") {
41+
"attribute"
42+
} else {
43+
"std"
4044
}
41-
",
42-
)
43-
.is_ok()
44-
{
45-
println!("cargo::rustc-cfg=thread_local=\"std\"");
46-
} else {
47-
println!("cargo::rustc-cfg=thread_local=\"unimplemented\"");
48-
}
45+
});
4946

50-
println!("cargo::rerun-if-env-changed=LITHIUM_BACKEND");
51-
if let Ok(backend) = std::env::var("LITHIUM_BACKEND") {
52-
println!("cargo::rustc-cfg=backend=\"{backend}\"");
53-
} else if is_nightly && cfg("target_os") == "emscripten" && !has_cfg("emscripten_wasm_eh") {
54-
println!("cargo::rustc-cfg=backend=\"emscripten\"");
55-
} else if is_nightly && cfg("target_arch") == "wasm32" {
56-
println!("cargo::rustc-cfg=backend=\"wasm\"");
57-
} else if is_nightly && (has_cfg("unix") || (has_cfg("windows") && cfg("target_env") == "gnu"))
58-
{
59-
println!("cargo::rustc-cfg=backend=\"itanium\"");
60-
} else if is_nightly && (has_cfg("windows") && cfg("target_env") == "msvc") && !is_miri {
61-
println!("cargo::rustc-cfg=backend=\"seh\"");
62-
} else if ac
63-
.probe_raw(
64-
r"
65-
#![no_std]
66-
extern crate std;
67-
pub use std::panic::{catch_unwind, resume_unwind};
68-
",
69-
)
70-
.is_ok()
71-
{
72-
println!("cargo::rustc-cfg=backend=\"panic\"");
73-
} else {
74-
println!("cargo::rustc-cfg=backend=\"unimplemented\"");
75-
}
47+
let backend = make_overridable_cfg("backend", || {
48+
if is_nightly && cfg("target_os") == "emscripten" && !has_cfg("emscripten_wasm_eh") {
49+
"emscripten"
50+
} else if is_nightly && cfg("target_arch") == "wasm32" {
51+
"wasm"
52+
} else if is_nightly
53+
&& (has_cfg("unix") || (has_cfg("windows") && cfg("target_env") == "gnu"))
54+
{
55+
"itanium"
56+
} else if is_nightly && has_cfg("windows") && cfg("target_env") == "msvc" && !is_miri {
57+
"seh"
58+
} else {
59+
"panic"
60+
}
61+
});
7662

77-
if ac
78-
.probe_raw(
79-
r#"
63+
// Since the panic backend can use `abort` and is available on stable, we need to set
64+
// `abort = "std"` whenever the panic backend is used, even if we don't readily know if `std` is
65+
// available. But that's fine, since the panic backend requires `std` anyway.
66+
let ac = autocfg::new();
67+
if backend == "panic"
68+
|| ac
69+
.probe_raw(
70+
r#"
8071
#![no_std]
8172
extern crate std;
8273
use std::io::Write;
@@ -85,8 +76,8 @@ fn main() {
8576
std::process::abort();
8677
}
8778
"#,
88-
)
89-
.is_ok()
79+
)
80+
.is_ok()
9081
{
9182
println!("cargo::rustc-cfg=abort=\"std\"");
9283
} else {

src/backend/mod.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,10 +177,6 @@ mod imp;
177177
#[path = "wasm.rs"]
178178
mod imp;
179179

180-
#[cfg(backend = "unimplemented")]
181-
#[path = "unimplemented.rs"]
182-
mod imp;
183-
184180
pub(crate) use imp::ActiveBackend;
185181

186182
#[cfg(test)]

src/backend/unimplemented.rs

Lines changed: 0 additions & 26 deletions
This file was deleted.

src/lib.rs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,11 @@
5757
//! Lithium strives to support all targets that Rust panics support. If Lithium does not work
5858
//! correctly on such a target, please [open an issue](https://github.com/iex-rs/lithium/issues/).
5959
//!
60-
//! On nightly, Lithium can work without `std` on certain platforms that expose native thread
61-
//! locals and link in an Itanium-style unwinder. Such situations are best handled on a case-by-case
62-
//! basis: [open an issue](https://github.com/iex-rs/lithium/issues/) if you would like to see
63-
//! support for a certain `std`-less target.
60+
//! On nightly exclusively, Lithium can work without `std` on certain platforms that expose native
61+
//! thread locals and link in an Itanium-style unwinder, such as `x86_64-unknown-linux-gnu`. Such
62+
//! situations are best handled on a case-by-case basis:
63+
//! [open an issue](https://github.com/iex-rs/lithium/issues/) if you would like to see support for
64+
//! a certain `std`-less target.
6465
//!
6566
//!
6667
//! # Safety
@@ -288,12 +289,7 @@ pub use api::{InFlightException, catch, intercept, throw};
288289
/// Abort the process with a message.
289290
///
290291
/// If `std` is available, this also outputs a message to stderr before aborting.
291-
#[cfg(any(
292-
backend = "itanium",
293-
backend = "seh",
294-
backend = "emscripten",
295-
backend = "wasm"
296-
))]
292+
#[allow(dead_code, reason = "not used by all backends")]
297293
#[cold]
298294
#[inline(never)]
299295
fn abort(message: &str) -> ! {
@@ -304,9 +300,8 @@ fn abort(message: &str) -> ! {
304300
std::process::abort();
305301
}
306302

307-
// This is a nightly-only method, but all three backends this is enabled under require nightly
308-
// anyway, so this is no big deal.
309-
#[cfg(not(abort = "std"))]
303+
// This is a nightly-only method, but build.rs sets `abort = "std"` for stable backends.
304+
#[cfg(abort = "core")]
310305
{
311306
let _ = message;
312307
core::intrinsics::abort();

src/stacked_exceptions.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,6 @@ unsafe fn get_stack() -> &'static Stack<Header> {
165165
// SAFETY: We require the caller to not use the reference anywhere near the end of the thread,
166166
// so if `&STACK` is sound in the first place, there is no problem.
167167
return unsafe { core::mem::transmute::<&Stack<Header>, &'static Stack<Header>>(&STACK) };
168-
169-
#[cfg(thread_local = "unimplemented")]
170-
compile_error!("Unable to compile Lithium on a platform does not support thread locals")
171168
}
172169

173170
const fn get_alloc_size<E>() -> usize {

0 commit comments

Comments
 (0)