Skip to content

Commit

Permalink
Rollup merge of #74033 - ehuss:std-compile-all-platforms, r=Mark-Simu…
Browse files Browse the repository at this point in the history
…lacrum

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 (#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.
  • Loading branch information
Manishearth authored Jul 17, 2020
2 parents 41d956b + 3d44d3c commit 5751c7f
Show file tree
Hide file tree
Showing 42 changed files with 437 additions and 345 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2056,6 +2056,7 @@ dependencies = [
name = "panic_abort"
version = "0.0.0"
dependencies = [
"cfg-if",
"compiler_builtins",
"core",
"libc",
Expand Down Expand Up @@ -4552,6 +4553,7 @@ dependencies = [
name = "test"
version = "0.0.0"
dependencies = [
"cfg-if",
"core",
"getopts",
"libc",
Expand Down
1 change: 1 addition & 0 deletions src/libpanic_abort/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ bench = false
doc = false

[dependencies]
cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] }
core = { path = "../libcore" }
libc = { version = "0.2", default-features = false }
compiler_builtins = "0.1.0"
35 changes: 19 additions & 16 deletions src/libpanic_abort/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,26 @@ pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Sen
pub unsafe extern "C" fn __rust_start_panic(_payload: usize) -> u32 {
abort();

#[cfg(any(unix, target_os = "cloudabi"))]
unsafe fn abort() -> ! {
libc::abort();
}

#[cfg(any(windows, all(target_arch = "wasm32", not(target_os = "emscripten"))))]
unsafe fn abort() -> ! {
core::intrinsics::abort();
}

#[cfg(any(target_os = "hermit", all(target_vendor = "fortanix", target_env = "sgx")))]
unsafe fn abort() -> ! {
// call std::sys::abort_internal
extern "C" {
pub fn __rust_abort() -> !;
cfg_if::cfg_if! {
if #[cfg(any(unix, target_os = "cloudabi"))] {
unsafe fn abort() -> ! {
libc::abort();
}
} else if #[cfg(any(target_os = "hermit",
all(target_vendor = "fortanix", target_env = "sgx")
))] {
unsafe fn abort() -> ! {
// call std::sys::abort_internal
extern "C" {
pub fn __rust_abort() -> !;
}
__rust_abort();
}
} else {
unsafe fn abort() -> ! {
core::intrinsics::abort();
}
}
__rust_abort();
}
}

Expand Down
20 changes: 16 additions & 4 deletions src/libpanic_unwind/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,33 @@ cfg_if::cfg_if! {
if #[cfg(target_os = "emscripten")] {
#[path = "emcc.rs"]
mod real_imp;
} else if #[cfg(target_arch = "wasm32")] {
#[path = "dummy.rs"]
mod real_imp;
} else if #[cfg(target_os = "hermit")] {
#[path = "hermit.rs"]
mod real_imp;
} else if #[cfg(target_env = "msvc")] {
#[path = "seh.rs"]
mod real_imp;
} else {
} else if #[cfg(any(
all(target_family = "windows", target_env = "gnu"),
target_os = "cloudabi",
target_family = "unix",
all(target_vendor = "fortanix", target_env = "sgx"),
))] {
// Rust runtime's startup objects depend on these symbols, so make them public.
#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
pub use real_imp::eh_frame_registry::*;
#[path = "gcc.rs"]
mod real_imp;
} else {
// Targets that don't support unwinding.
// - arch=wasm32
// - os=none ("bare metal" targets)
// - os=uefi
// - nvptx64-nvidia-cuda
// - avr-unknown-unknown
// - mipsel-sony-psp
#[path = "dummy.rs"]
mod real_imp;
}
}

Expand Down
1 change: 1 addition & 0 deletions src/libproc_macro/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#![feature(in_band_lifetimes)]
#![feature(negative_impls)]
#![feature(optin_builtin_traits)]
#![feature(restricted_std)]
#![feature(rustc_attrs)]
#![feature(min_specialization)]
#![recursion_limit = "256"]
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_passes/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,8 @@ impl Visitor<'tcx> for Checker<'tcx> {
match item.kind {
hir::ItemKind::ExternCrate(_) => {
// compiler-generated `extern crate` items have a dummy span.
if item.span.is_dummy() {
// `std` is still checked for the `restricted-std` feature.
if item.span.is_dummy() && item.ident.as_str() != "std" {
return;
}

Expand Down
24 changes: 24 additions & 0 deletions src/libstd/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,29 @@ fn main() {
}
println!("cargo:rustc-link-lib=c");
println!("cargo:rustc-link-lib=compiler_rt");
} else if (target.contains("sgx") && target.contains("fortanix"))
|| target.contains("hermit")
|| target.contains("l4re")
|| target.contains("redox")
|| target.contains("haiku")
|| target.contains("vxworks")
|| target.contains("wasm32")
|| target.contains("asmjs")
{
// These platforms don't have any special requirements.
} else {
// This is for Cargo's build-std support, to mark std as unstable for
// typically no_std platforms.
// This covers:
// - os=none ("bare metal" targets)
// - mipsel-sony-psp
// - nvptx64-nvidia-cuda
// - avr-unknown-unknown
// - tvos (aarch64-apple-tvos, x86_64-apple-tvos)
// - uefi (x86_64-unknown-uefi, i686-unknown-uefi)
// - JSON targets
// - Any new targets that have not been explicitly added above.
println!("cargo:rustc-cfg=feature=\"restricted-std\"");
}
println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap());
}
77 changes: 1 addition & 76 deletions src/libstd/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -882,7 +882,7 @@ pub mod consts {
/// - s390x
/// - sparc64
#[stable(feature = "env", since = "1.0.0")]
pub const ARCH: &str = super::arch::ARCH;
pub const ARCH: &str = env!("STD_ENV_ARCH");

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

#[cfg(target_arch = "x86")]
mod arch {
pub const ARCH: &str = "x86";
}

#[cfg(target_arch = "x86_64")]
mod arch {
pub const ARCH: &str = "x86_64";
}

#[cfg(target_arch = "arm")]
mod arch {
pub const ARCH: &str = "arm";
}

#[cfg(target_arch = "aarch64")]
mod arch {
pub const ARCH: &str = "aarch64";
}

#[cfg(target_arch = "mips")]
mod arch {
pub const ARCH: &str = "mips";
}

#[cfg(target_arch = "mips64")]
mod arch {
pub const ARCH: &str = "mips64";
}

#[cfg(target_arch = "powerpc")]
mod arch {
pub const ARCH: &str = "powerpc";
}

#[cfg(target_arch = "powerpc64")]
mod arch {
pub const ARCH: &str = "powerpc64";
}

#[cfg(target_arch = "s390x")]
mod arch {
pub const ARCH: &str = "s390x";
}

#[cfg(target_arch = "sparc64")]
mod arch {
pub const ARCH: &str = "sparc64";
}

#[cfg(target_arch = "le32")]
mod arch {
pub const ARCH: &str = "le32";
}

#[cfg(target_arch = "asmjs")]
mod arch {
pub const ARCH: &str = "asmjs";
}

#[cfg(target_arch = "wasm32")]
mod arch {
pub const ARCH: &str = "wasm32";
}

#[cfg(target_arch = "hexagon")]
mod arch {
pub const ARCH: &'static str = "hexagon";
}

#[cfg(target_arch = "riscv64")]
mod arch {
pub const ARCH: &'static str = "riscv64";
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
9 changes: 8 additions & 1 deletion src/libstd/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,8 @@
//! [primitive types]: ../book/ch03-02-data-types.html
//! [rust-discord]: https://discord.gg/rust-lang

#![stable(feature = "rust1", since = "1.0.0")]
#![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))]
#![cfg_attr(feature = "restricted-std", unstable(feature = "restricted_std", issue = "none"))]
#![doc(
html_root_url = "https://doc.rust-lang.org/nightly/",
html_playground_url = "https://play.rust-lang.org/",
Expand Down Expand Up @@ -554,3 +555,9 @@ include!("primitive_docs.rs");
// the rustdoc documentation for the existing keywords. Using `include!`
// because rustdoc only looks for these modules at the crate level.
include!("keyword_docs.rs");

// This is required to avoid an unstable error when `restricted-std` is not
// enabled. The use of #![feature(restricted_std)] in rustc-std-workspace-std
// is unconditional, so the unstable feature needs to be defined somewhere.
#[cfg_attr(not(feature = "restricted-std"), unstable(feature = "restricted_std", issue = "none"))]
mod __restricted_std_workaround {}
3 changes: 2 additions & 1 deletion src/libstd/sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ cfg_if::cfg_if! {
mod sgx;
pub use self::sgx::*;
} else {
compile_error!("libstd doesn't compile for this platform yet");
mod unsupported;
pub use self::unsupported::*;
}
}

Expand Down
22 changes: 22 additions & 0 deletions src/libstd/sys/unsupported/alloc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use crate::alloc::{GlobalAlloc, Layout, System};

#[stable(feature = "alloc_system_type", since = "1.28.0")]
unsafe impl GlobalAlloc for System {
#[inline]
unsafe fn alloc(&self, _layout: Layout) -> *mut u8 {
0 as *mut u8
}

#[inline]
unsafe fn alloc_zeroed(&self, _layout: Layout) -> *mut u8 {
0 as *mut u8
}

#[inline]
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}

#[inline]
unsafe fn realloc(&self, _ptr: *mut u8, _layout: Layout, _new_size: usize) -> *mut u8 {
0 as *mut u8
}
}
38 changes: 38 additions & 0 deletions src/libstd/sys/unsupported/args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use crate::ffi::OsString;

pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
pub unsafe fn cleanup() {}

pub struct Args {}

pub fn args() -> Args {
Args {}
}

impl Args {
pub fn inner_debug(&self) -> &[OsString] {
&[]
}
}

impl Iterator for Args {
type Item = OsString;
fn next(&mut self) -> Option<OsString> {
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, Some(0))
}
}

impl ExactSizeIterator for Args {
fn len(&self) -> usize {
0
}
}

impl DoubleEndedIterator for Args {
fn next_back(&mut self) -> Option<OsString> {
None
}
}
File renamed without changes.
48 changes: 48 additions & 0 deletions src/libstd/sys/unsupported/common.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use crate::io as std_io;

pub mod memchr {
pub use core::slice::memchr::{memchr, memrchr};
}

pub use crate::sys_common::os_str_bytes as os_str;

// This is not necessarily correct. May want to consider making it part of the
// spec definition?
use crate::os::raw::c_char;

#[cfg(not(test))]
pub fn init() {}

pub fn unsupported<T>() -> std_io::Result<T> {
Err(unsupported_err())
}

pub fn unsupported_err() -> std_io::Error {
std_io::Error::new(std_io::ErrorKind::Other, "operation not supported on this platform")
}

pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind {
crate::io::ErrorKind::Other
}

pub fn abort_internal() -> ! {
core::intrinsics::abort();
}

pub fn hashmap_random_keys() -> (u64, u64) {
(1, 2)
}

// This enum is used as the storage for a bunch of types which can't actually
// exist.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub enum Void {}

pub unsafe fn strlen(mut s: *const c_char) -> usize {
let mut n = 0;
while *s != 0 {
n += 1;
s = s.offset(1);
}
return n;
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ impl Condvar {
pub unsafe fn notify_all(&self) {}

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

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

#[inline]
Expand Down
Loading

0 comments on commit 5751c7f

Please sign in to comment.