After merging rust-lang/compiler-team#574 I got side-tracked on other work, but here is a description of how I configured my rustc
environment in order to start adding and testing the new wasm32-wasi-threads
target. Don't be surprised if I forgot a step or left some TODOs in place — there was some trial-and-error involved in getting to this point!
-
First, in order to get things working locally, I build a local copy of a WASI sysroot from wasi-libc:
make && make THREAD_MODEL=posix
(sysroot/share
should now contain files for both targets--wasm32-wasi
andwasm32-wasi-threads
) -
Then, in my rust project, I point my
config.toml
to look at the local WASI sysroot I just built; I do this for both targets (the existing one and the one we're about to add):[target.wasm32-wasi] wasi-root = ".../wasi-libc/sysroot" [target.wasm32-wasi-threads] wasi-root = ".../wasi-libc/sysroot"
-
Add
compiler/rustc_target/src/spec/wasm32_wasi_threads.rs
: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::Yes), &["--target=wasm32-wasi-threads"]); // TODO is this right? we do pass this target to clang... 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(); // TODO options.singlethread = false; Target { llvm_target: "wasm32-wasi".into(), // TODO: is this right? LLVM doesn't know this target... 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, } }
-
Make some minor changes to get
rustc
to recognize the newwasm32-wasi-threads
target and find the correct sysroot:diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 0d86a3032a6..5823ba6d9c6 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1175,6 +1175,7 @@ fn $module() { ("wasm32-unknown-emscripten", wasm32_unknown_emscripten), ("wasm32-unknown-unknown", wasm32_unknown_unknown), ("wasm32-wasi", wasm32_wasi), + ("wasm32-wasi-threads", wasm32_wasi_threads), ("wasm64-unknown-unknown", wasm64_unknown_unknown), ("thumbv6m-none-eabi", thumbv6m_none_eabi), diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 598a4bf9282..16d3d242c4c 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -48,6 +48,9 @@ hermit-abi = { version = "0.3.0", features = ['rustc-dep-of-std'] } [target.wasm32-wasi.dependencies] wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false } +[target.wasm32-wasi-threads.dependencies] +wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false } + [features] backtrace = [ "gimli-symbolize", diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 8b80dfc0f9b..cadff3c5730 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -278,13 +278,14 @@ fn copy_self_contained_objects( let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained); target_deps.push((libunwind_path, DependencyType::TargetSelfContained)); } - } else if target.ends_with("-wasi") { + } else if target.contains("-wasi") { let srcdir = builder .wasi_root(target) .unwrap_or_else(|| { panic!("Target {:?} does not have a \"wasi-root\" key", target.triple) }) - .join("lib/wasm32-wasi"); + .join("lib") + .join(target.to_string()); for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] { copy_and_stamp( builder, diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index f4abdf1cc57..8765e971317 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -126,7 +126,7 @@ pub unsafe fn setup(_build: &mut crate::Build) {} (Some(Mode::Std), "backtrace_in_libstd", None), /* Extra values not defined in the built-in targets yet, but used in std */ (Some(Mode::Std), "target_env", Some(&["libnx"])), - // (Some(Mode::Std), "target_os", Some(&[])), + (Some(Mode::Std), "target_os", Some(&["wasm32-wasi-threads"])), (Some(Mode::Std), "target_arch", Some(&["asmjs", "spirv", "nvptx", "xtensa"])), /* Extra names used by dependencies */ // FIXME: Used by serde_json, but we should not be triggering on external dependencies.
-
Build the stage 1
rustc
compiler:./x.py build --stage 1 --target wasm32-wasi-threads
-
Create a
/tmp/threads.rs
test file:fn main() { let mut join = vec![]; for i in 0..10 { join.push(std::thread::spawn(move || { println!("thread {}", i); })); } for j in join { j.join().unwrap(); } }
-
Try (and surely fail) to build this file with the new target:
rustc +stage1 -v --target=wasm32-wasi-threads threads.rs
-
This is the point that I stopped at:
std::thread::spawn
still needs to be implemented and I believe the place to start at is inlibrary/std/src/sys/wasi/thread.rs