Skip to content

Commit ada49fc

Browse files
authored
Rollup merge of rust-lang#74033 - ehuss:std-compile-all-platforms, r=Mark-Simulacrum
Add build support for Cargo's build-std feature. This makes some changes to the standard library to make it easier to use with Cargo's build-std feature. The primary goal is to make it so that Cargo and its users do not need to know which crates to build and which features to use for every platform. Conditional cfgs are adjusted so that there is usually a fall-through for unsupported platforms. Additionally, there is a "restricted-std" feature to mark `std` as unstable when used with build-std on no_std platforms. There is no intent to stabilize this feature for the foreseeable future. This borrows some of the implementation for wasm which already does what this needs. More code sharing can be done with some other platforms (there is a lot of duplication with cloudabi, hermit, and sgx), but I figure that can be done in a future PR. There are some small changes to stable behavior in this PR: - `std::env::consts::ARCH` on asmjs now reports "wasm32", to match its actual architecture. - Some of the wasm error messages for unsupported features report a slightly different error message so that the code can be reused. There should otherwise not be any changes to how std is built for distribution via bootstrap. This does not yet support all platforms when used with build-std. - It doesn't work with 16-bit targets (hashbrown does not support that). - It does not work with JSON spec targets. - In particular, all target triple snooping will need to be replaced with appropriate target option checking. - Switching to gimli (rust-lang#73441) will make cross-building *much* easier. - There are still a ton of issues on the Cargo side to resolve. A big one is panic strategy support. Future PRs are intended to address some of these issues.
2 parents 6423e43 + 3d44d3c commit ada49fc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+437
-345
lines changed

Cargo.lock

+2
Original file line numberDiff line numberDiff line change
@@ -2056,6 +2056,7 @@ dependencies = [
20562056
name = "panic_abort"
20572057
version = "0.0.0"
20582058
dependencies = [
2059+
"cfg-if",
20592060
"compiler_builtins",
20602061
"core",
20612062
"libc",
@@ -4552,6 +4553,7 @@ dependencies = [
45524553
name = "test"
45534554
version = "0.0.0"
45544555
dependencies = [
4556+
"cfg-if",
45554557
"core",
45564558
"getopts",
45574559
"libc",

src/libpanic_abort/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ bench = false
1111
doc = false
1212

1313
[dependencies]
14+
cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] }
1415
core = { path = "../libcore" }
1516
libc = { version = "0.2", default-features = false }
1617
compiler_builtins = "0.1.0"

src/libpanic_abort/lib.rs

+19-16
Original file line numberDiff line numberDiff line change
@@ -40,23 +40,26 @@ pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Sen
4040
pub unsafe extern "C" fn __rust_start_panic(_payload: usize) -> u32 {
4141
abort();
4242

43-
#[cfg(any(unix, target_os = "cloudabi"))]
44-
unsafe fn abort() -> ! {
45-
libc::abort();
46-
}
47-
48-
#[cfg(any(windows, all(target_arch = "wasm32", not(target_os = "emscripten"))))]
49-
unsafe fn abort() -> ! {
50-
core::intrinsics::abort();
51-
}
52-
53-
#[cfg(any(target_os = "hermit", all(target_vendor = "fortanix", target_env = "sgx")))]
54-
unsafe fn abort() -> ! {
55-
// call std::sys::abort_internal
56-
extern "C" {
57-
pub fn __rust_abort() -> !;
43+
cfg_if::cfg_if! {
44+
if #[cfg(any(unix, target_os = "cloudabi"))] {
45+
unsafe fn abort() -> ! {
46+
libc::abort();
47+
}
48+
} else if #[cfg(any(target_os = "hermit",
49+
all(target_vendor = "fortanix", target_env = "sgx")
50+
))] {
51+
unsafe fn abort() -> ! {
52+
// call std::sys::abort_internal
53+
extern "C" {
54+
pub fn __rust_abort() -> !;
55+
}
56+
__rust_abort();
57+
}
58+
} else {
59+
unsafe fn abort() -> ! {
60+
core::intrinsics::abort();
61+
}
5862
}
59-
__rust_abort();
6063
}
6164
}
6265

src/libpanic_unwind/lib.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,33 @@ cfg_if::cfg_if! {
4141
if #[cfg(target_os = "emscripten")] {
4242
#[path = "emcc.rs"]
4343
mod real_imp;
44-
} else if #[cfg(target_arch = "wasm32")] {
45-
#[path = "dummy.rs"]
46-
mod real_imp;
4744
} else if #[cfg(target_os = "hermit")] {
4845
#[path = "hermit.rs"]
4946
mod real_imp;
5047
} else if #[cfg(target_env = "msvc")] {
5148
#[path = "seh.rs"]
5249
mod real_imp;
53-
} else {
50+
} else if #[cfg(any(
51+
all(target_family = "windows", target_env = "gnu"),
52+
target_os = "cloudabi",
53+
target_family = "unix",
54+
all(target_vendor = "fortanix", target_env = "sgx"),
55+
))] {
5456
// Rust runtime's startup objects depend on these symbols, so make them public.
5557
#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
5658
pub use real_imp::eh_frame_registry::*;
5759
#[path = "gcc.rs"]
5860
mod real_imp;
61+
} else {
62+
// Targets that don't support unwinding.
63+
// - arch=wasm32
64+
// - os=none ("bare metal" targets)
65+
// - os=uefi
66+
// - nvptx64-nvidia-cuda
67+
// - avr-unknown-unknown
68+
// - mipsel-sony-psp
69+
#[path = "dummy.rs"]
70+
mod real_imp;
5971
}
6072
}
6173

src/libproc_macro/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#![feature(in_band_lifetimes)]
2727
#![feature(negative_impls)]
2828
#![feature(optin_builtin_traits)]
29+
#![feature(restricted_std)]
2930
#![feature(rustc_attrs)]
3031
#![feature(min_specialization)]
3132
#![recursion_limit = "256"]

src/librustc_passes/stability.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,8 @@ impl Visitor<'tcx> for Checker<'tcx> {
502502
match item.kind {
503503
hir::ItemKind::ExternCrate(_) => {
504504
// compiler-generated `extern crate` items have a dummy span.
505-
if item.span.is_dummy() {
505+
// `std` is still checked for the `restricted-std` feature.
506+
if item.span.is_dummy() && item.ident.as_str() != "std" {
506507
return;
507508
}
508509

src/libstd/build.rs

+24
Original file line numberDiff line numberDiff line change
@@ -62,5 +62,29 @@ fn main() {
6262
}
6363
println!("cargo:rustc-link-lib=c");
6464
println!("cargo:rustc-link-lib=compiler_rt");
65+
} else if (target.contains("sgx") && target.contains("fortanix"))
66+
|| target.contains("hermit")
67+
|| target.contains("l4re")
68+
|| target.contains("redox")
69+
|| target.contains("haiku")
70+
|| target.contains("vxworks")
71+
|| target.contains("wasm32")
72+
|| target.contains("asmjs")
73+
{
74+
// These platforms don't have any special requirements.
75+
} else {
76+
// This is for Cargo's build-std support, to mark std as unstable for
77+
// typically no_std platforms.
78+
// This covers:
79+
// - os=none ("bare metal" targets)
80+
// - mipsel-sony-psp
81+
// - nvptx64-nvidia-cuda
82+
// - avr-unknown-unknown
83+
// - tvos (aarch64-apple-tvos, x86_64-apple-tvos)
84+
// - uefi (x86_64-unknown-uefi, i686-unknown-uefi)
85+
// - JSON targets
86+
// - Any new targets that have not been explicitly added above.
87+
println!("cargo:rustc-cfg=feature=\"restricted-std\"");
6588
}
89+
println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap());
6690
}

src/libstd/env.rs

+1-76
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,7 @@ pub mod consts {
882882
/// - s390x
883883
/// - sparc64
884884
#[stable(feature = "env", since = "1.0.0")]
885-
pub const ARCH: &str = super::arch::ARCH;
885+
pub const ARCH: &str = env!("STD_ENV_ARCH");
886886

887887
/// The family of the operating system. Example value is `unix`.
888888
///
@@ -966,81 +966,6 @@ pub mod consts {
966966
pub const EXE_EXTENSION: &str = os::EXE_EXTENSION;
967967
}
968968

969-
#[cfg(target_arch = "x86")]
970-
mod arch {
971-
pub const ARCH: &str = "x86";
972-
}
973-
974-
#[cfg(target_arch = "x86_64")]
975-
mod arch {
976-
pub const ARCH: &str = "x86_64";
977-
}
978-
979-
#[cfg(target_arch = "arm")]
980-
mod arch {
981-
pub const ARCH: &str = "arm";
982-
}
983-
984-
#[cfg(target_arch = "aarch64")]
985-
mod arch {
986-
pub const ARCH: &str = "aarch64";
987-
}
988-
989-
#[cfg(target_arch = "mips")]
990-
mod arch {
991-
pub const ARCH: &str = "mips";
992-
}
993-
994-
#[cfg(target_arch = "mips64")]
995-
mod arch {
996-
pub const ARCH: &str = "mips64";
997-
}
998-
999-
#[cfg(target_arch = "powerpc")]
1000-
mod arch {
1001-
pub const ARCH: &str = "powerpc";
1002-
}
1003-
1004-
#[cfg(target_arch = "powerpc64")]
1005-
mod arch {
1006-
pub const ARCH: &str = "powerpc64";
1007-
}
1008-
1009-
#[cfg(target_arch = "s390x")]
1010-
mod arch {
1011-
pub const ARCH: &str = "s390x";
1012-
}
1013-
1014-
#[cfg(target_arch = "sparc64")]
1015-
mod arch {
1016-
pub const ARCH: &str = "sparc64";
1017-
}
1018-
1019-
#[cfg(target_arch = "le32")]
1020-
mod arch {
1021-
pub const ARCH: &str = "le32";
1022-
}
1023-
1024-
#[cfg(target_arch = "asmjs")]
1025-
mod arch {
1026-
pub const ARCH: &str = "asmjs";
1027-
}
1028-
1029-
#[cfg(target_arch = "wasm32")]
1030-
mod arch {
1031-
pub const ARCH: &str = "wasm32";
1032-
}
1033-
1034-
#[cfg(target_arch = "hexagon")]
1035-
mod arch {
1036-
pub const ARCH: &'static str = "hexagon";
1037-
}
1038-
1039-
#[cfg(target_arch = "riscv64")]
1040-
mod arch {
1041-
pub const ARCH: &'static str = "riscv64";
1042-
}
1043-
1044969
#[cfg(test)]
1045970
mod tests {
1046971
use super::*;

src/libstd/lib.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,8 @@
198198
//! [primitive types]: ../book/ch03-02-data-types.html
199199
//! [rust-discord]: https://discord.gg/rust-lang
200200
201-
#![stable(feature = "rust1", since = "1.0.0")]
201+
#![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))]
202+
#![cfg_attr(feature = "restricted-std", unstable(feature = "restricted_std", issue = "none"))]
202203
#![doc(
203204
html_root_url = "https://doc.rust-lang.org/nightly/",
204205
html_playground_url = "https://play.rust-lang.org/",
@@ -554,3 +555,9 @@ include!("primitive_docs.rs");
554555
// the rustdoc documentation for the existing keywords. Using `include!`
555556
// because rustdoc only looks for these modules at the crate level.
556557
include!("keyword_docs.rs");
558+
559+
// This is required to avoid an unstable error when `restricted-std` is not
560+
// enabled. The use of #![feature(restricted_std)] in rustc-std-workspace-std
561+
// is unconditional, so the unstable feature needs to be defined somewhere.
562+
#[cfg_attr(not(feature = "restricted-std"), unstable(feature = "restricted_std", issue = "none"))]
563+
mod __restricted_std_workaround {}

src/libstd/sys/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ cfg_if::cfg_if! {
4848
mod sgx;
4949
pub use self::sgx::*;
5050
} else {
51-
compile_error!("libstd doesn't compile for this platform yet");
51+
mod unsupported;
52+
pub use self::unsupported::*;
5253
}
5354
}
5455

src/libstd/sys/unsupported/alloc.rs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
use crate::alloc::{GlobalAlloc, Layout, System};
2+
3+
#[stable(feature = "alloc_system_type", since = "1.28.0")]
4+
unsafe impl GlobalAlloc for System {
5+
#[inline]
6+
unsafe fn alloc(&self, _layout: Layout) -> *mut u8 {
7+
0 as *mut u8
8+
}
9+
10+
#[inline]
11+
unsafe fn alloc_zeroed(&self, _layout: Layout) -> *mut u8 {
12+
0 as *mut u8
13+
}
14+
15+
#[inline]
16+
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
17+
18+
#[inline]
19+
unsafe fn realloc(&self, _ptr: *mut u8, _layout: Layout, _new_size: usize) -> *mut u8 {
20+
0 as *mut u8
21+
}
22+
}

src/libstd/sys/unsupported/args.rs

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
use crate::ffi::OsString;
2+
3+
pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
4+
pub unsafe fn cleanup() {}
5+
6+
pub struct Args {}
7+
8+
pub fn args() -> Args {
9+
Args {}
10+
}
11+
12+
impl Args {
13+
pub fn inner_debug(&self) -> &[OsString] {
14+
&[]
15+
}
16+
}
17+
18+
impl Iterator for Args {
19+
type Item = OsString;
20+
fn next(&mut self) -> Option<OsString> {
21+
None
22+
}
23+
fn size_hint(&self) -> (usize, Option<usize>) {
24+
(0, Some(0))
25+
}
26+
}
27+
28+
impl ExactSizeIterator for Args {
29+
fn len(&self) -> usize {
30+
0
31+
}
32+
}
33+
34+
impl DoubleEndedIterator for Args {
35+
fn next_back(&mut self) -> Option<OsString> {
36+
None
37+
}
38+
}
File renamed without changes.

src/libstd/sys/unsupported/common.rs

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use crate::io as std_io;
2+
3+
pub mod memchr {
4+
pub use core::slice::memchr::{memchr, memrchr};
5+
}
6+
7+
pub use crate::sys_common::os_str_bytes as os_str;
8+
9+
// This is not necessarily correct. May want to consider making it part of the
10+
// spec definition?
11+
use crate::os::raw::c_char;
12+
13+
#[cfg(not(test))]
14+
pub fn init() {}
15+
16+
pub fn unsupported<T>() -> std_io::Result<T> {
17+
Err(unsupported_err())
18+
}
19+
20+
pub fn unsupported_err() -> std_io::Error {
21+
std_io::Error::new(std_io::ErrorKind::Other, "operation not supported on this platform")
22+
}
23+
24+
pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind {
25+
crate::io::ErrorKind::Other
26+
}
27+
28+
pub fn abort_internal() -> ! {
29+
core::intrinsics::abort();
30+
}
31+
32+
pub fn hashmap_random_keys() -> (u64, u64) {
33+
(1, 2)
34+
}
35+
36+
// This enum is used as the storage for a bunch of types which can't actually
37+
// exist.
38+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
39+
pub enum Void {}
40+
41+
pub unsafe fn strlen(mut s: *const c_char) -> usize {
42+
let mut n = 0;
43+
while *s != 0 {
44+
n += 1;
45+
s = s.offset(1);
46+
}
47+
return n;
48+
}

src/libstd/sys/wasm/condvar.rs src/libstd/sys/unsupported/condvar.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ impl Condvar {
1818
pub unsafe fn notify_all(&self) {}
1919

2020
pub unsafe fn wait(&self, _mutex: &Mutex) {
21-
panic!("can't block with web assembly")
21+
panic!("condvar wait not supported")
2222
}
2323

2424
pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
25-
panic!("can't block with web assembly");
25+
panic!("condvar wait not supported");
2626
}
2727

2828
#[inline]

0 commit comments

Comments
 (0)