Add wasm32-wasi-threads target + WASI threads
This commit is contained in:
parent
f9f674f2bc
commit
5697f1620d
@ -1403,6 +1403,7 @@ fn $module() {
|
|||||||
("wasm32-unknown-emscripten", wasm32_unknown_emscripten),
|
("wasm32-unknown-emscripten", wasm32_unknown_emscripten),
|
||||||
("wasm32-unknown-unknown", wasm32_unknown_unknown),
|
("wasm32-unknown-unknown", wasm32_unknown_unknown),
|
||||||
("wasm32-wasi", wasm32_wasi),
|
("wasm32-wasi", wasm32_wasi),
|
||||||
|
("wasm32-wasi-preview1-threads", wasm32_wasi_preview1_threads),
|
||||||
("wasm64-unknown-unknown", wasm64_unknown_unknown),
|
("wasm64-unknown-unknown", wasm64_unknown_unknown),
|
||||||
|
|
||||||
("thumbv6m-none-eabi", thumbv6m_none_eabi),
|
("thumbv6m-none-eabi", thumbv6m_none_eabi),
|
||||||
|
134
compiler/rustc_target/src/spec/wasm32_wasi_preview1_threads.rs
Normal file
134
compiler/rustc_target/src/spec/wasm32_wasi_preview1_threads.rs
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
//! The `wasm32-wasi-preview1-threads` target is a new and still (as of July 2023) an
|
||||||
|
//! experimental target. The definition in this file is likely to be tweaked
|
||||||
|
//! over time and shouldn't be relied on too much.
|
||||||
|
//!
|
||||||
|
//! The `wasi-threads` target is a proposal to define a standardized set of syscalls
|
||||||
|
//! that WebAssembly files can interoperate with. This set of syscalls is
|
||||||
|
//! intended to empower WebAssembly binaries with native capabilities such as
|
||||||
|
//! threads, filesystem access, network access, etc.
|
||||||
|
//!
|
||||||
|
//! You can see more about the proposal at <https://github.com/WebAssembly/wasi-threads>.
|
||||||
|
//!
|
||||||
|
//! The Rust target definition here is interesting in a few ways. We want to
|
||||||
|
//! serve two use cases here with this target:
|
||||||
|
//!
|
||||||
|
//! * First, we want Rust usage of the target to be as hassle-free as possible,
|
||||||
|
//! ideally avoiding the need to configure and install a local wasm32-wasi-preview1-threads
|
||||||
|
//! toolchain.
|
||||||
|
//!
|
||||||
|
//! * Second, one of the primary use cases of LLVM's new wasm backend and the
|
||||||
|
//! wasm support in LLD is that any compiled language can interoperate with
|
||||||
|
//! any other. To that the `wasm32-wasi-preview1-threads` target is the first with a viable C
|
||||||
|
//! standard library and sysroot common definition, so we want Rust and C/C++
|
||||||
|
//! code to interoperate when compiled to `wasm32-unknown-unknown`.
|
||||||
|
//!
|
||||||
|
//! You'll note, however, that the two goals above are somewhat at odds with one
|
||||||
|
//! another. To attempt to solve both use cases in one go we define a target
|
||||||
|
//! that (ab)uses the `crt-static` target feature to indicate which one you're
|
||||||
|
//! in.
|
||||||
|
//!
|
||||||
|
//! ## No interop with C required
|
||||||
|
//!
|
||||||
|
//! By default the `crt-static` target feature is enabled, and when enabled
|
||||||
|
//! this means that the bundled version of `libc.a` found in `liblibc.rlib`
|
||||||
|
//! is used. This isn't intended really for interoperation with a C because it
|
||||||
|
//! may be the case that Rust's bundled C library is incompatible with a
|
||||||
|
//! foreign-compiled C library. In this use case, though, we use `rust-lld` and
|
||||||
|
//! some copied crt startup object files to ensure that you can download the
|
||||||
|
//! wasi target for Rust and you're off to the races, no further configuration
|
||||||
|
//! necessary.
|
||||||
|
//!
|
||||||
|
//! All in all, by default, no external dependencies are required. You can
|
||||||
|
//! compile `wasm32-wasi-preview1-threads` binaries straight out of the box. You can't, however,
|
||||||
|
//! reliably interoperate with C code in this mode (yet).
|
||||||
|
//!
|
||||||
|
//! ## Interop with C required
|
||||||
|
//!
|
||||||
|
//! For the second goal we repurpose the `target-feature` flag, meaning that
|
||||||
|
//! you'll need to do a few things to have C/Rust code interoperate.
|
||||||
|
//!
|
||||||
|
//! 1. All Rust code needs to be compiled with `-C target-feature=-crt-static`,
|
||||||
|
//! indicating that the bundled C standard library in the Rust sysroot will
|
||||||
|
//! not be used.
|
||||||
|
//!
|
||||||
|
//! 2. If you're using rustc to build a linked artifact then you'll need to
|
||||||
|
//! specify `-C linker` to a `clang` binary that supports
|
||||||
|
//! `wasm32-wasi-preview1-threads` and is configured with the `wasm32-wasi-preview1-threads` sysroot. This
|
||||||
|
//! will cause Rust code to be linked against the libc.a that the specified
|
||||||
|
//! `clang` provides.
|
||||||
|
//!
|
||||||
|
//! 3. If you're building a staticlib and integrating Rust code elsewhere, then
|
||||||
|
//! compiling with `-C target-feature=-crt-static` is all you need to do.
|
||||||
|
//!
|
||||||
|
//! You can configure the linker via Cargo using the
|
||||||
|
//! `CARGO_TARGET_WASM32_WASI_LINKER` env var. Be sure to also set
|
||||||
|
//! `CC_wasm32-wasi-preview1-threads` if any crates in the dependency graph are using the `cc`
|
||||||
|
//! crate.
|
||||||
|
//!
|
||||||
|
//! ## Remember, this is all in flux
|
||||||
|
//!
|
||||||
|
//! The wasi target is **very** new in its specification. It's likely going to
|
||||||
|
//! be a long effort to get it standardized and stable. We'll be following it as
|
||||||
|
//! best we can with this target. Don't start relying on too much here unless
|
||||||
|
//! you know what you're getting in to!
|
||||||
|
|
||||||
|
use super::crt_objects::{self, LinkSelfContainedDefault};
|
||||||
|
use super::{wasm_base, Cc, LinkerFlavor, Target};
|
||||||
|
|
||||||
|
pub fn target() -> Target {
|
||||||
|
let mut options = wasm_base::options();
|
||||||
|
|
||||||
|
options.os = "wasi".into();
|
||||||
|
|
||||||
|
options.add_pre_link_args(
|
||||||
|
LinkerFlavor::WasmLld(Cc::No),
|
||||||
|
&["--import-memory", "--export-memory", "--shared-memory"],
|
||||||
|
);
|
||||||
|
options.add_pre_link_args(
|
||||||
|
LinkerFlavor::WasmLld(Cc::Yes),
|
||||||
|
&[
|
||||||
|
"--target=wasm32-wasi-threads",
|
||||||
|
"-Wl,--import-memory",
|
||||||
|
"-Wl,--export-memory,",
|
||||||
|
"-Wl,--shared-memory",
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
options.pre_link_objects_self_contained = crt_objects::pre_wasi_self_contained();
|
||||||
|
options.post_link_objects_self_contained = crt_objects::post_wasi_self_contained();
|
||||||
|
|
||||||
|
// FIXME: Figure out cases in which WASM needs to link with a native toolchain.
|
||||||
|
options.link_self_contained = LinkSelfContainedDefault::True;
|
||||||
|
|
||||||
|
// Right now this is a bit of a workaround but we're currently saying that
|
||||||
|
// the target by default has a static crt which we're taking as a signal
|
||||||
|
// for "use the bundled crt". If that's turned off then the system's crt
|
||||||
|
// will be used, but this means that default usage of this target doesn't
|
||||||
|
// need an external compiler but it's still interoperable with an external
|
||||||
|
// compiler if configured correctly.
|
||||||
|
options.crt_static_default = true;
|
||||||
|
options.crt_static_respected = true;
|
||||||
|
|
||||||
|
// Allow `+crt-static` to create a "cdylib" output which is just a wasm file
|
||||||
|
// without a main function.
|
||||||
|
options.crt_static_allows_dylibs = true;
|
||||||
|
|
||||||
|
// WASI's `sys::args::init` function ignores its arguments; instead,
|
||||||
|
// `args::args()` makes the WASI API calls itself.
|
||||||
|
options.main_needs_argc_argv = false;
|
||||||
|
|
||||||
|
// And, WASI mangles the name of "main" to distinguish between different
|
||||||
|
// signatures.
|
||||||
|
options.entry_name = "__main_void".into();
|
||||||
|
|
||||||
|
options.singlethread = false;
|
||||||
|
options.features = "+atomics,+bulk-memory,+mutable-globals".into();
|
||||||
|
|
||||||
|
Target {
|
||||||
|
llvm_target: "wasm32-wasi".into(),
|
||||||
|
pointer_width: 32,
|
||||||
|
data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
|
||||||
|
arch: "wasm32".into(),
|
||||||
|
options,
|
||||||
|
}
|
||||||
|
}
|
@ -47,7 +47,7 @@ fortanix-sgx-abi = { version = "0.5.0", features = ['rustc-dep-of-std'], public
|
|||||||
[target.'cfg(target_os = "hermit")'.dependencies]
|
[target.'cfg(target_os = "hermit")'.dependencies]
|
||||||
hermit-abi = { version = "0.3.2", features = ['rustc-dep-of-std'], public = true }
|
hermit-abi = { version = "0.3.2", features = ['rustc-dep-of-std'], public = true }
|
||||||
|
|
||||||
[target.wasm32-wasi.dependencies]
|
[target.'cfg(target_os = "wasi")'.dependencies]
|
||||||
wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false }
|
wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
@ -29,8 +29,7 @@
|
|||||||
#[path = "../wasm/atomics/futex.rs"]
|
#[path = "../wasm/atomics/futex.rs"]
|
||||||
pub mod futex;
|
pub mod futex;
|
||||||
pub mod io;
|
pub mod io;
|
||||||
#[path = "../unsupported/locks/mod.rs"]
|
|
||||||
pub mod locks;
|
|
||||||
pub mod net;
|
pub mod net;
|
||||||
pub mod os;
|
pub mod os;
|
||||||
#[path = "../unix/os_str.rs"]
|
#[path = "../unix/os_str.rs"]
|
||||||
@ -47,14 +46,27 @@
|
|||||||
pub mod thread_local_dtor;
|
pub mod thread_local_dtor;
|
||||||
#[path = "../unsupported/thread_local_key.rs"]
|
#[path = "../unsupported/thread_local_key.rs"]
|
||||||
pub mod thread_local_key;
|
pub mod thread_local_key;
|
||||||
#[path = "../unsupported/thread_parking.rs"]
|
|
||||||
pub mod thread_parking;
|
|
||||||
pub mod time;
|
pub mod time;
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(not(target_feature = "atomics"))] {
|
if #[cfg(target_feature = "atomics")] {
|
||||||
|
#[path = "../unix/locks"]
|
||||||
|
pub mod locks {
|
||||||
|
#![allow(unsafe_op_in_unsafe_fn)]
|
||||||
|
mod futex_condvar;
|
||||||
|
mod futex_mutex;
|
||||||
|
mod futex_rwlock;
|
||||||
|
pub(crate) use futex_condvar::Condvar;
|
||||||
|
pub(crate) use futex_mutex::Mutex;
|
||||||
|
pub(crate) use futex_rwlock::RwLock;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#[path = "../unsupported/locks/mod.rs"]
|
||||||
|
pub mod locks;
|
||||||
#[path = "../unsupported/once.rs"]
|
#[path = "../unsupported/once.rs"]
|
||||||
pub mod once;
|
pub mod once;
|
||||||
|
#[path = "../unsupported/thread_parking.rs"]
|
||||||
|
pub mod thread_parking;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,6 +224,11 @@ pub fn unsetenv(n: &OsStr) -> io::Result<()> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn page_size() -> usize {
|
||||||
|
unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn temp_dir() -> PathBuf {
|
pub fn temp_dir() -> PathBuf {
|
||||||
panic!("no filesystem on wasm")
|
panic!("no filesystem on wasm")
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
#![deny(unsafe_op_in_unsafe_fn)]
|
|
||||||
|
|
||||||
use crate::ffi::CStr;
|
use crate::ffi::CStr;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
@ -7,14 +5,116 @@
|
|||||||
use crate::sys::unsupported;
|
use crate::sys::unsupported;
|
||||||
use crate::time::Duration;
|
use crate::time::Duration;
|
||||||
|
|
||||||
pub struct Thread(!);
|
cfg_if::cfg_if! {
|
||||||
|
if #[cfg(target_feature = "atomics")] {
|
||||||
|
use crate::cmp;
|
||||||
|
use crate::ptr;
|
||||||
|
use crate::sys::os;
|
||||||
|
// Add a few symbols not in upstream `libc` just yet.
|
||||||
|
mod libc {
|
||||||
|
pub use crate::ffi;
|
||||||
|
pub use crate::mem;
|
||||||
|
pub use libc::*;
|
||||||
|
|
||||||
|
// defined in wasi-libc
|
||||||
|
// https://github.com/WebAssembly/wasi-libc/blob/a6f871343313220b76009827ed0153586361c0d5/libc-top-half/musl/include/alltypes.h.in#L108
|
||||||
|
#[repr(C)]
|
||||||
|
union pthread_attr_union {
|
||||||
|
__i: [ffi::c_int; if mem::size_of::<ffi::c_int>() == 8 { 14 } else { 9 }],
|
||||||
|
__vi: [ffi::c_int; if mem::size_of::<ffi::c_int>() == 8 { 14 } else { 9 }],
|
||||||
|
__s: [ffi::c_ulong; if mem::size_of::<ffi::c_int>() == 8 { 7 } else { 9 }],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct pthread_attr_t {
|
||||||
|
__u: pthread_attr_union,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
pub type pthread_t = *mut ffi::c_void;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
pub fn pthread_create(
|
||||||
|
native: *mut pthread_t,
|
||||||
|
attr: *const pthread_attr_t,
|
||||||
|
f: extern "C" fn(*mut ffi::c_void) -> *mut ffi::c_void,
|
||||||
|
value: *mut ffi::c_void,
|
||||||
|
) -> ffi::c_int;
|
||||||
|
pub fn pthread_join(native: pthread_t, value: *mut *mut ffi::c_void) -> ffi::c_int;
|
||||||
|
pub fn pthread_attr_init(attrp: *mut pthread_attr_t) -> ffi::c_int;
|
||||||
|
pub fn pthread_attr_setstacksize(
|
||||||
|
attr: *mut pthread_attr_t,
|
||||||
|
stack_size: libc::size_t,
|
||||||
|
) -> ffi::c_int;
|
||||||
|
pub fn pthread_attr_destroy(attr: *mut pthread_attr_t) -> ffi::c_int;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Thread {
|
||||||
|
id: libc::pthread_t,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pub struct Thread(!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
|
pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
|
||||||
|
|
||||||
impl Thread {
|
impl Thread {
|
||||||
// unsafe: see thread::Builder::spawn_unchecked for safety requirements
|
// unsafe: see thread::Builder::spawn_unchecked for safety requirements
|
||||||
pub unsafe fn new(_stack: usize, _p: Box<dyn FnOnce()>) -> io::Result<Thread> {
|
cfg_if::cfg_if! {
|
||||||
unsupported()
|
if #[cfg(target_feature = "atomics")] {
|
||||||
|
pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
|
||||||
|
let p = Box::into_raw(Box::new(p));
|
||||||
|
let mut native: libc::pthread_t = mem::zeroed();
|
||||||
|
let mut attr: libc::pthread_attr_t = mem::zeroed();
|
||||||
|
assert_eq!(libc::pthread_attr_init(&mut attr), 0);
|
||||||
|
|
||||||
|
let stack_size = cmp::max(stack, DEFAULT_MIN_STACK_SIZE);
|
||||||
|
|
||||||
|
match libc::pthread_attr_setstacksize(&mut attr, stack_size) {
|
||||||
|
0 => {}
|
||||||
|
n => {
|
||||||
|
assert_eq!(n, libc::EINVAL);
|
||||||
|
// EINVAL means |stack_size| is either too small or not a
|
||||||
|
// multiple of the system page size. Because it's definitely
|
||||||
|
// >= PTHREAD_STACK_MIN, it must be an alignment issue.
|
||||||
|
// Round up to the nearest page and try again.
|
||||||
|
let page_size = os::page_size();
|
||||||
|
let stack_size =
|
||||||
|
(stack_size + page_size - 1) & (-(page_size as isize - 1) as usize - 1);
|
||||||
|
assert_eq!(libc::pthread_attr_setstacksize(&mut attr, stack_size), 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let ret = libc::pthread_create(&mut native, &attr, thread_start, p as *mut _);
|
||||||
|
// Note: if the thread creation fails and this assert fails, then p will
|
||||||
|
// be leaked. However, an alternative design could cause double-free
|
||||||
|
// which is clearly worse.
|
||||||
|
assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
|
||||||
|
|
||||||
|
return if ret != 0 {
|
||||||
|
// The thread failed to start and as a result p was not consumed. Therefore, it is
|
||||||
|
// safe to reconstruct the box so that it gets deallocated.
|
||||||
|
drop(Box::from_raw(p));
|
||||||
|
Err(io::Error::from_raw_os_error(ret))
|
||||||
|
} else {
|
||||||
|
Ok(Thread { id: native })
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void {
|
||||||
|
unsafe {
|
||||||
|
// Finally, let's run some code.
|
||||||
|
Box::from_raw(main as *mut Box<dyn FnOnce()>)();
|
||||||
|
}
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pub unsafe fn new(_stack: usize, _p: Box<dyn FnOnce()>) -> io::Result<Thread> {
|
||||||
|
unsupported()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn yield_now() {
|
pub fn yield_now() {
|
||||||
@ -62,7 +162,19 @@ pub fn sleep(dur: Duration) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn join(self) {
|
pub fn join(self) {
|
||||||
self.0
|
cfg_if::cfg_if! {
|
||||||
|
if #[cfg(target_feature = "atomics")] {
|
||||||
|
unsafe {
|
||||||
|
let ret = libc::pthread_join(self.id, ptr::null_mut());
|
||||||
|
mem::forget(self);
|
||||||
|
if ret != 0 {
|
||||||
|
rtabort!("failed to join thread: {}", io::Error::from_raw_os_error(ret));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,13 +287,14 @@ fn copy_self_contained_objects(
|
|||||||
let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
|
let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
|
||||||
target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
|
target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
|
||||||
}
|
}
|
||||||
} else if target.ends_with("-wasi") {
|
} else if target.contains("-wasi") {
|
||||||
let srcdir = builder
|
let srcdir = builder
|
||||||
.wasi_root(target)
|
.wasi_root(target)
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
panic!("Target {:?} does not have a \"wasi-root\" key", target.triple)
|
panic!("Target {:?} does not have a \"wasi-root\" key", target.triple)
|
||||||
})
|
})
|
||||||
.join("lib/wasm32-wasi");
|
.join("lib")
|
||||||
|
.join(target.to_string().replace("-preview1", ""));
|
||||||
for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
|
for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
|
||||||
copy_and_stamp(
|
copy_and_stamp(
|
||||||
builder,
|
builder,
|
||||||
@ -393,9 +394,13 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if target.ends_with("-wasi") {
|
if target.contains("-wasi") {
|
||||||
if let Some(p) = builder.wasi_root(target) {
|
if let Some(p) = builder.wasi_root(target) {
|
||||||
let root = format!("native={}/lib/wasm32-wasi", p.to_str().unwrap());
|
let root = format!(
|
||||||
|
"native={}/lib/{}",
|
||||||
|
p.to_str().unwrap(),
|
||||||
|
target.to_string().replace("-preview1", "")
|
||||||
|
);
|
||||||
cargo.rustflag("-L").rustflag(&root);
|
cargo.rustflag("-L").rustflag(&root);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,6 +93,9 @@ RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh
|
|||||||
COPY host-x86_64/dist-various-2/build-wasi-toolchain.sh /tmp/
|
COPY host-x86_64/dist-various-2/build-wasi-toolchain.sh /tmp/
|
||||||
RUN /tmp/build-wasi-toolchain.sh
|
RUN /tmp/build-wasi-toolchain.sh
|
||||||
|
|
||||||
|
COPY host-x86_64/dist-various-2/build-wasi-threads-toolchain.sh /tmp/
|
||||||
|
RUN /tmp/build-wasi-threads-toolchain.sh
|
||||||
|
|
||||||
COPY scripts/freebsd-toolchain.sh /tmp/
|
COPY scripts/freebsd-toolchain.sh /tmp/
|
||||||
RUN /tmp/freebsd-toolchain.sh i686
|
RUN /tmp/freebsd-toolchain.sh i686
|
||||||
|
|
||||||
@ -114,6 +117,7 @@ ENV TARGETS=x86_64-unknown-fuchsia
|
|||||||
ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia
|
ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia
|
||||||
ENV TARGETS=$TARGETS,wasm32-unknown-unknown
|
ENV TARGETS=$TARGETS,wasm32-unknown-unknown
|
||||||
ENV TARGETS=$TARGETS,wasm32-wasi
|
ENV TARGETS=$TARGETS,wasm32-wasi
|
||||||
|
ENV TARGETS=$TARGETS,wasm32-wasi-preview1-threads
|
||||||
ENV TARGETS=$TARGETS,sparcv9-sun-solaris
|
ENV TARGETS=$TARGETS,sparcv9-sun-solaris
|
||||||
ENV TARGETS=$TARGETS,x86_64-pc-solaris
|
ENV TARGETS=$TARGETS,x86_64-pc-solaris
|
||||||
ENV TARGETS=$TARGETS,x86_64-sun-solaris
|
ENV TARGETS=$TARGETS,x86_64-sun-solaris
|
||||||
@ -136,6 +140,7 @@ RUN ln -s /usr/include/asm-generic /usr/local/include/asm
|
|||||||
|
|
||||||
ENV RUST_CONFIGURE_ARGS --enable-extended --enable-lld --disable-docs \
|
ENV RUST_CONFIGURE_ARGS --enable-extended --enable-lld --disable-docs \
|
||||||
--set target.wasm32-wasi.wasi-root=/wasm32-wasi \
|
--set target.wasm32-wasi.wasi-root=/wasm32-wasi \
|
||||||
|
--set target.wasm32-wasi-preview1-threads.wasi-root=/wasm32-wasi-preview1-threads \
|
||||||
--musl-root-armv7=/musl-armv7
|
--musl-root-armv7=/musl-armv7
|
||||||
|
|
||||||
ENV SCRIPT python3 ../x.py dist --host='' --target $TARGETS
|
ENV SCRIPT python3 ../x.py dist --host='' --target $TARGETS
|
||||||
|
24
src/ci/docker/host-x86_64/dist-various-2/build-wasi-threads-toolchain.sh
Executable file
24
src/ci/docker/host-x86_64/dist-various-2/build-wasi-threads-toolchain.sh
Executable file
@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
# Originally from https://github.com/llvm/llvm-project/releases/download/llvmorg-16.0.4/clang+llvm-16.0.4-x86_64-linux-gnu-ubuntu-22.04.tar.xz
|
||||||
|
curl https://ci-mirrors.rust-lang.org/rustc/2023-05-17-clang%2Bllvm-16.0.4-x86_64-linux-gnu-ubuntu-22.04.tar.xz | \
|
||||||
|
tar xJf -
|
||||||
|
bin="$PWD/clang+llvm-16.0.4-x86_64-linux-gnu-ubuntu-22.04/bin"
|
||||||
|
|
||||||
|
git clone https://github.com/WebAssembly/wasi-libc
|
||||||
|
|
||||||
|
cd wasi-libc
|
||||||
|
git reset --hard 7018e24d8fe248596819d2e884761676f3542a04
|
||||||
|
make -j$(nproc) \
|
||||||
|
CC="$bin/clang" \
|
||||||
|
NM="$bin/llvm-nm" \
|
||||||
|
AR="$bin/llvm-ar" \
|
||||||
|
THREAD_MODEL=posix \
|
||||||
|
INSTALL_DIR=/wasm32-wasi-preview1-threads \
|
||||||
|
install
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
rm -rf wasi-libc
|
||||||
|
rm -rf clang+llvm*
|
@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
set -ex
|
set -ex
|
||||||
|
|
||||||
# Originally from https://github.com/llvm/llvm-project/releases/download/llvmorg-15.0.6/clang+llvm-15.0.6-x86_64-linux-gnu-ubuntu-18.04.tar.xz
|
# Originally from https://github.com/llvm/llvm-project/releases/download/llvmorg-16.0.4/clang+llvm-16.0.4-x86_64-linux-gnu-ubuntu-22.04.tar.xz
|
||||||
curl https://ci-mirrors.rust-lang.org/rustc/2022-12-06-clang%2Bllvm-15.0.6-x86_64-linux-gnu-ubuntu-18.04.tar.xz | \
|
curl https://ci-mirrors.rust-lang.org/rustc/2023-05-17-clang%2Bllvm-16.0.4-x86_64-linux-gnu-ubuntu-22.04.tar.xz | \
|
||||||
tar xJf -
|
tar xJf -
|
||||||
bin="$PWD/clang+llvm-15.0.6-x86_64-linux-gnu-ubuntu-18.04/bin"
|
bin="$PWD/clang+llvm-16.0.4-x86_64-linux-gnu-ubuntu-22.04/bin"
|
||||||
|
|
||||||
git clone https://github.com/WebAssembly/wasi-libc
|
git clone https://github.com/WebAssembly/wasi-libc
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
- [\*-unknown-netbsd\*](platform-support/netbsd.md)
|
- [\*-unknown-netbsd\*](platform-support/netbsd.md)
|
||||||
- [*-unknown-openbsd](platform-support/openbsd.md)
|
- [*-unknown-openbsd](platform-support/openbsd.md)
|
||||||
- [\*-unknown-uefi](platform-support/unknown-uefi.md)
|
- [\*-unknown-uefi](platform-support/unknown-uefi.md)
|
||||||
|
- [wasm32-wasi-preview1-threads](platform-support/wasm32-wasi-preview1-threads.md)
|
||||||
- [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md)
|
- [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md)
|
||||||
- [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md)
|
- [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md)
|
||||||
- [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)
|
- [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)
|
||||||
|
@ -318,6 +318,7 @@ target | std | host | notes
|
|||||||
`thumbv7a-pc-windows-msvc` | ? | |
|
`thumbv7a-pc-windows-msvc` | ? | |
|
||||||
`thumbv7a-uwp-windows-msvc` | ✓ | |
|
`thumbv7a-uwp-windows-msvc` | ✓ | |
|
||||||
`thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode ARMv7-A Linux with NEON, MUSL
|
`thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode ARMv7-A Linux with NEON, MUSL
|
||||||
|
[`wasm32-wasi-preview1-threads`](platform-support/wasm32-wasi-preview1-threads.md) | ✓ | WebAssembly with WASI Preview 1 and threads
|
||||||
[`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly
|
[`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly
|
||||||
`x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64
|
`x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64
|
||||||
[`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ? | | x86 64-bit tvOS
|
[`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ? | | x86 64-bit tvOS
|
||||||
|
@ -0,0 +1,139 @@
|
|||||||
|
# `wasm32-wasi-preview1-threads`
|
||||||
|
|
||||||
|
**Tier: 3**
|
||||||
|
|
||||||
|
The `wasm32-wasi-preview1-threads` target is a new and still (as of July 2023) an
|
||||||
|
experimental target. This target is an extension to `wasm32-wasi-preview1` target,
|
||||||
|
originally known as `wasm32-wasi`. It extends the original target with a
|
||||||
|
standardized set of syscalls that are intended to empower WebAssembly binaries with
|
||||||
|
native multi threading capabilities.
|
||||||
|
|
||||||
|
[wasi-threads]: https://github.com/WebAssembly/wasi-threads
|
||||||
|
[threads]: https://github.com/WebAssembly/threads
|
||||||
|
|
||||||
|
|
||||||
|
## Target maintainers
|
||||||
|
|
||||||
|
- Georgii Rylov, https://github.com/g0djan
|
||||||
|
- Alex Crichton, https://github.com/alexcrichton
|
||||||
|
- Andrew Brown, https://github.com/abrown
|
||||||
|
- Marcin Kolny, https://github.com/loganek
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
This target is cross-compiled. The target supports `std` fully.
|
||||||
|
|
||||||
|
The Rust target definition here is interesting in a few ways. We want to
|
||||||
|
serve two use cases here with this target:
|
||||||
|
* First, we want Rust usage of the target to be as hassle-free as possible,
|
||||||
|
ideally avoiding the need to configure and install a local wasm32-wasi-preview1-threads
|
||||||
|
toolchain.
|
||||||
|
* Second, one of the primary use cases of LLVM's new wasm backend and the
|
||||||
|
wasm support in LLD is that any compiled language can interoperate with
|
||||||
|
any other. The `wasm32-wasi-preview1-threads` target is the first with a viable C
|
||||||
|
standard library and sysroot common definition, so we want Rust and C/C++
|
||||||
|
code to interoperate when compiled to `wasm32-unknown-unknown`.
|
||||||
|
|
||||||
|
|
||||||
|
You'll note, however, that the two goals above are somewhat at odds with one
|
||||||
|
another. To attempt to solve both use cases in one go we define a target
|
||||||
|
that (ab)uses the `crt-static` target feature to indicate which one you're
|
||||||
|
in.
|
||||||
|
### No interop with C required
|
||||||
|
By default the `crt-static` target feature is enabled, and when enabled
|
||||||
|
this means that the bundled version of `libc.a` found in `liblibc.rlib`
|
||||||
|
is used. This isn't intended really for interoperation with a C because it
|
||||||
|
may be the case that Rust's bundled C library is incompatible with a
|
||||||
|
foreign-compiled C library. In this use case, though, we use `rust-lld` and
|
||||||
|
some copied crt startup object files to ensure that you can download the
|
||||||
|
wasi target for Rust and you're off to the races, no further configuration
|
||||||
|
necessary.
|
||||||
|
All in all, by default, no external dependencies are required. You can
|
||||||
|
compile `wasm32-wasi-preview1-threads` binaries straight out of the box. You can't, however,
|
||||||
|
reliably interoperate with C code in this mode (yet).
|
||||||
|
### Interop with C required
|
||||||
|
For the second goal we repurpose the `target-feature` flag, meaning that
|
||||||
|
you'll need to do a few things to have C/Rust code interoperate.
|
||||||
|
1. All Rust code needs to be compiled with `-C target-feature=-crt-static`,
|
||||||
|
indicating that the bundled C standard library in the Rust sysroot will
|
||||||
|
not be used.
|
||||||
|
2. If you're using rustc to build a linked artifact then you'll need to
|
||||||
|
specify `-C linker` to a `clang` binary that supports
|
||||||
|
`wasm32-wasi-preview1-threads` and is configured with the `wasm32-wasi-preview1-threads` sysroot. This
|
||||||
|
will cause Rust code to be linked against the libc.a that the specified
|
||||||
|
`clang` provides.
|
||||||
|
3. If you're building a staticlib and integrating Rust code elsewhere, then
|
||||||
|
compiling with `-C target-feature=-crt-static` is all you need to do.
|
||||||
|
|
||||||
|
All in all, by default, no external dependencies are required. You can
|
||||||
|
compile `wasm32-wasi-preview1-threads` binaries straight out of the box. You can't, however,
|
||||||
|
reliably interoperate with C code in this mode (yet).
|
||||||
|
|
||||||
|
|
||||||
|
This target is not a stable target. This means that there are not many engines
|
||||||
|
which implement the `wasi-threads` feature and if they do they're likely behind a
|
||||||
|
flag, for example:
|
||||||
|
|
||||||
|
* Wasmtime - `--wasm-features=threads --wasi-modules=experimental-wasi-threads`
|
||||||
|
|
||||||
|
Also note that at this time the `wasm32-wasi-preview1-threads` target assumes the
|
||||||
|
presence of other merged wasm proposals such as (with their LLVM feature flags):
|
||||||
|
|
||||||
|
* [Bulk memory] - `+bulk-memory`
|
||||||
|
* Mutable imported globals - `+mutable-globals`
|
||||||
|
* Atomics - `+atomics`
|
||||||
|
|
||||||
|
[Bulk memory]: https://github.com/WebAssembly/spec/blob/main/proposals/bulk-memory-operations/Overview.md
|
||||||
|
|
||||||
|
LLVM 16 is required for this target. The reason is related to linker flags: prior to LLVM 16, --import-memory and --export-memory were not allowed together. The reason both are needed is an artifact of how WASI currently does things; see https://github.com/WebAssembly/WASI/issues/502 for more details.
|
||||||
|
|
||||||
|
The target intends to match the corresponding Clang target for its `"C"` ABI.
|
||||||
|
|
||||||
|
> **Note**: due to the relatively early-days nature of this target when working
|
||||||
|
> with this target you may encounter LLVM bugs. If an assertion hit or a bug is
|
||||||
|
> found it's recommended to open an issue either with rust-lang/rust or ideally
|
||||||
|
> with LLVM itself.
|
||||||
|
|
||||||
|
## Building the target
|
||||||
|
|
||||||
|
Users need to install or built wasi-sdk since release 20.0
|
||||||
|
https://github.com/WebAssembly/wasi-sdk/releases/tag/wasi-sdk-20
|
||||||
|
and specify path to *wasi-root* `.cargo/config.toml`
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[target.wasm32-wasi-preview1-threads]
|
||||||
|
wasi-root = ".../wasi-libc/sysroot"
|
||||||
|
```
|
||||||
|
|
||||||
|
After that users can build this by adding it to the `target` list in
|
||||||
|
`config.toml`, or with `-Zbuild-std`.
|
||||||
|
|
||||||
|
## Building Rust programs
|
||||||
|
|
||||||
|
Since it is Tier 3, rust doesn't ship pre-compiled artifacts for this target.
|
||||||
|
|
||||||
|
Specify `wasi-root` as explained in the previous section and then use the `build-std`
|
||||||
|
nightly cargo feature to build the standard library:
|
||||||
|
```shell
|
||||||
|
cargo +nightly build --target=wasm32-wasi-preview1-threads -Zbuild-std
|
||||||
|
```
|
||||||
|
|
||||||
|
## Cross-compilation
|
||||||
|
|
||||||
|
This target can be cross-compiled from any hosts.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Currently testing is not well supported for `wasm32-wasi-preview1-threads` and the
|
||||||
|
Rust project doesn't run any tests for this target. However the UI testsuite can be run
|
||||||
|
manually following this instructions:
|
||||||
|
|
||||||
|
0. Ensure [wamr](https://github.com/bytecodealliance/wasm-micro-runtime), [wasmtime](https://github.com/bytecodealliance/wasmtime)
|
||||||
|
or another engine that supports `wasi-threads` is installed and can be found in the `$PATH` env variable.
|
||||||
|
1. Clone master branch.
|
||||||
|
2. Apply such [a change](https://github.com/g0djan/rust/compare/godjan/wasi-threads...g0djan:rust:godjan/wasi-run-ui-tests?expand=1) with an engine from the step 1.
|
||||||
|
3. Run `./x.py test --target wasm32-wasi-preview1-threads tests/ui` and save the list of failed tests.
|
||||||
|
4. Checkout branch with your changes.
|
||||||
|
5. Apply such [a change](https://github.com/g0djan/rust/compare/godjan/wasi-threads...g0djan:rust:godjan/wasi-run-ui-tests?expand=1) with an engine from the step 1.
|
||||||
|
6. Run `./x.py test --target wasm32-wasi-preview1-threads tests/ui` and save the list of failed tests.
|
||||||
|
7. For both lists of failed tests run `cat list | sort > sorted_list` and compare it with `diff sorted_list1 sorted_list2`.
|
@ -139,6 +139,7 @@
|
|||||||
"wasm32-unknown-emscripten",
|
"wasm32-unknown-emscripten",
|
||||||
"wasm32-unknown-unknown",
|
"wasm32-unknown-unknown",
|
||||||
"wasm32-wasi",
|
"wasm32-wasi",
|
||||||
|
"wasm32-wasi-preview1-threads",
|
||||||
"x86_64-apple-darwin",
|
"x86_64-apple-darwin",
|
||||||
"x86_64-apple-ios",
|
"x86_64-apple-ios",
|
||||||
"x86_64-fortanix-unknown-sgx",
|
"x86_64-fortanix-unknown-sgx",
|
||||||
|
@ -152,28 +152,30 @@
|
|||||||
// [r72] needs-llvm-components: webassembly
|
// [r72] needs-llvm-components: webassembly
|
||||||
// [r73] compile-flags:--target wasm32-wasi
|
// [r73] compile-flags:--target wasm32-wasi
|
||||||
// [r73] needs-llvm-components: webassembly
|
// [r73] needs-llvm-components: webassembly
|
||||||
// [r74] compile-flags:--target x86_64-apple-ios
|
// [r74] compile-flags:--target wasm32-wasi-preview1-threads
|
||||||
// [r74] needs-llvm-components: x86
|
// [r74] needs-llvm-components: webassembly
|
||||||
// [r75] compile-flags:--target x86_64-fortanix-unknown-sgx
|
// [r75] compile-flags:--target x86_64-apple-ios
|
||||||
// [r75] needs-llvm-components: x86
|
// [r75] needs-llvm-components: x86
|
||||||
// [r76] compile-flags:--target x86_64-unknown-fuchsia
|
// [r76] compile-flags:--target x86_64-fortanix-unknown-sgx
|
||||||
// [r76] needs-llvm-components: x86
|
// [r76] needs-llvm-components: x86
|
||||||
// [r77] compile-flags:--target x86_64-linux-android
|
// [r77] compile-flags:--target x86_64-unknown-fuchsia
|
||||||
// [r77] needs-llvm-components: x86
|
// [r77] needs-llvm-components: x86
|
||||||
// [r78] compile-flags:--target x86_64-sun-solaris
|
// [r78] compile-flags:--target x86_64-linux-android
|
||||||
// [r78] needs-llvm-components: x86
|
// [r78] needs-llvm-components: x86
|
||||||
// [r79] compile-flags:--target x86_64-unknown-freebsd
|
// [r79] compile-flags:--target x86_64-sun-solaris
|
||||||
// [r79] needs-llvm-components: x86
|
// [r79] needs-llvm-components: x86
|
||||||
// [r80] compile-flags:--target x86_64-unknown-illumos
|
// [r80] compile-flags:--target x86_64-unknown-freebsd
|
||||||
// [r80] needs-llvm-components: x86
|
// [r80] needs-llvm-components: x86
|
||||||
// [r81] compile-flags:--target x86_64-unknown-linux-gnux32
|
// [r81] compile-flags:--target x86_64-unknown-illumos
|
||||||
// [r81] needs-llvm-components: x86
|
// [r81] needs-llvm-components: x86
|
||||||
// [r82] compile-flags:--target x86_64-unknown-linux-musl
|
// [r82] compile-flags:--target x86_64-unknown-linux-gnux32
|
||||||
// [r82] needs-llvm-components: x86
|
// [r82] needs-llvm-components: x86
|
||||||
// [r83] compile-flags:--target x86_64-unknown-netbsd
|
// [r83] compile-flags:--target x86_64-unknown-linux-musl
|
||||||
// [r83] needs-llvm-components: x86
|
// [r83] needs-llvm-components: x86
|
||||||
// [r84] compile-flags: --target x86_64-unknown-redox
|
// [r84] compile-flags:--target x86_64-unknown-netbsd
|
||||||
// [r84] needs-llvm-components: x86
|
// [r84] needs-llvm-components: x86
|
||||||
|
// [r85] compile-flags: --target x86_64-unknown-redox
|
||||||
|
// [r85] needs-llvm-components: x86
|
||||||
// compile-flags: -Z stack-protector=all
|
// compile-flags: -Z stack-protector=all
|
||||||
// compile-flags: -C opt-level=2
|
// compile-flags: -C opt-level=2
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user