Skip to content

Commit 8ecda18

Browse files
committed
Support building for Wasm/WASI
This commit changes the `build.rs` and `makefile.cargo` files to support compiling mozjs for `wasm32-wasip1` and `wasm32-wasip2`. SpiderMonkey itself has long supported targeting WASI, but the build system requires some finagling to line everything up just right for these targets. It also frobs things a little bit to make tests pass (disabling the one test that uses threads and thus isn't supported at all on wasm32-wasi right now.) Signed-off-by: Till Schneidereit <[email protected]>
1 parent f5d9a37 commit 8ecda18

File tree

5 files changed

+84
-6
lines changed

5 files changed

+84
-6
lines changed

mozjs-sys/build.rs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ const SM_TARGET_ENV_VARS: &'static [&'static str] = &[
4545
"CXXFLAGS",
4646
"READELF",
4747
"OBJCOPY",
48+
"WASI_SDK_PATH",
4849
];
4950

5051
const EXTRA_FILES: &'static [&'static str] = &["makefile.cargo"];
@@ -60,6 +61,12 @@ fn main() {
6061
// https://github.com/servo/servo/issues/14759
6162
env::set_var("MOZ_NO_DEBUG_RTL", "1");
6263

64+
if let Some(path) = wasi_sdk() {
65+
env::set_var("WASI_SYSROOT", PathBuf::from(&path).join("share").join("wasi-sysroot"));
66+
env::set_var("TARGET_CC", PathBuf::from(&path).join("bin").join("clang"));
67+
env::set_var("TARGET_CXX", PathBuf::from(&path).join("bin").join("clang++"));
68+
}
69+
6370
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
6471
let build_dir = out_dir.join("build");
6572

@@ -338,6 +345,12 @@ fn build_bindings(build_dir: &Path, target: BuildTarget) {
338345
.formatter(Formatter::Rustfmt)
339346
.clang_args(cc_flags(true));
340347

348+
if env::var("TARGET").unwrap().contains("wasi") {
349+
builder = builder
350+
.clang_arg("--sysroot")
351+
.clang_arg(env::var("WASI_SYSROOT").unwrap().to_string());
352+
}
353+
341354
if target == BuildTarget::JSGlue {
342355
builder = builder
343356
.parse_callbacks(Box::new(JSGlueCargoCallbacks::default()))
@@ -433,9 +446,15 @@ fn link_static_lib_binaries(build_dir: &Path) {
433446
println!("cargo:rustc-link-lib=c++");
434447
} else if target.contains("windows") && target.contains("gnu") {
435448
println!("cargo:rustc-link-lib=stdc++");
436-
} else if !target.contains("windows") {
449+
} else if !target.contains("windows") && !target.contains("wasi") {
450+
// The build works without this for WASI, and specifying it means
451+
// needing to use the WASI-SDK's clang for linking, which is annoying.
437452
println!("cargo:rustc-link-lib=stdc++")
438453
}
454+
455+
if target.contains("wasi") {
456+
println!("cargo:rustc-link-lib=wasi-emulated-getpid");
457+
}
439458
}
440459

441460
fn link_bindgen_static_lib_binaries(build_dir: &Path) {
@@ -511,6 +530,13 @@ fn cc_flags(bindgen: bool) -> Vec<&'static str> {
511530
if env::var_os("CARGO_FEATURE_PROFILEMOZJS").is_some() {
512531
flags.push("-fno-omit-frame-pointer");
513532
}
533+
534+
if target.contains("wasi") {
535+
// Unconditionally target p1 for now. Even if the application
536+
// targets p2, an adapter will take care of it.
537+
flags.push("--target=wasm32-wasip1");
538+
flags.push("-fvisibility=default");
539+
}
514540
}
515541

516542
flags.extend(&["-DSTATIC_JS_API", "-DRUST_BINDGEN"]);
@@ -534,6 +560,10 @@ fn cc_flags(bindgen: bool) -> Vec<&'static str> {
534560
flags.push("-stdlib=libc++");
535561
}
536562

563+
if target.contains("wasi") {
564+
flags.push("-D_WASI_EMULATED_GETPID");
565+
}
566+
537567
flags
538568
}
539569

@@ -554,6 +584,14 @@ fn js_config_path(build_dir: &Path) -> String {
554584
.to_string()
555585
}
556586

587+
fn wasi_sdk() -> Option<OsString> {
588+
if env::var("TARGET").unwrap().contains("wasi") {
589+
get_cc_rs_env_os("WASI_SDK_PATH")
590+
} else {
591+
None
592+
}
593+
}
594+
557595
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
558596
enum BuildTarget {
559597
JSApi,

mozjs-sys/makefile.cargo

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@ ifneq (,$(CARGO_FEATURE_JITSPEW))
1616
endif
1717

1818
ifneq (,$(CARGO_FEATURE_DEBUGMOZJS))
19-
CONFIGURE_FLAGS += --enable-debug --disable-optimize --enable-gczeal
19+
CONFIGURE_FLAGS += --enable-debug --enable-gczeal
20+
ifneq (,$(findstring -wasi,$(TARGET)))
21+
# wasm-opt chokes on -O0 builds.
22+
CONFIGURE_FLAGS += --enable-optimize=-O1
23+
else
24+
CONFIGURE_FLAGS += --disable-optimize
25+
endif
2026
endif
2127

2228
ifneq (,$(CARGO_FEATURE_PROFILEMOZJS))
@@ -25,6 +31,11 @@ endif
2531

2632
ifneq (,$(CARGO_FEATURE_LIBZ_RS))
2733
CONFIGURE_FLAGS += --enable-libz-rs
34+
else ifneq (,$(findstring wasi,$(TARGET)))
35+
# system libz is not available on wasi
36+
CONFIGURE_FLAGS += --enable-libz-rs
37+
else
38+
CONFIGURE_FLAGS += --enable-libz
2839
endif
2940

3041
ifneq (,$(CCACHE))
@@ -72,6 +83,27 @@ ifneq ($(HOST),$(TARGET))
7283
TARGET = aarch64-linux-gnu
7384
endif
7485

86+
ifneq (,$(findstring -wasi,$(TARGET)))
87+
ifeq (,$(WASI_SDK_PATH))
88+
$(error WASI_SDK_PATH environment variable must be set when building for wasm32)
89+
endif
90+
WASI_SYSROOT = $(WASI_SDK_PATH)/share/wasi-sysroot
91+
CC = $(WASI_SDK_PATH)/bin/clang
92+
CPP = $(WASI_SDK_PATH)/bin/clang -E
93+
CXX = $(WASI_SDK_PATH)/bin/clang++
94+
AR = $(WASI_SDK_PATH)/bin/ar
95+
HOST_CC = clang
96+
HOST_CXX = clang++
97+
CONFIGURE_FLAGS += \
98+
--enable-portable-baseline-interp \
99+
--disable-clang-plugin \
100+
--disable-jit \
101+
--disable-shared-memory \
102+
--lto=thin \
103+
--with-sysroot=$(WASI_SDK_PATH)/share/wasi-sysroot \
104+
$(NULL)
105+
endif
106+
75107
ifeq (android,$(findstring android,$(TARGET)))
76108
# Force use of lld on android. Mozilla build system tries to use
77109
# gold or bfd linker on Android to support their 'elfhack'functionality in
@@ -150,7 +182,7 @@ all: maybe-configure
150182
JSSRC := '$(SRC_DIR)'/js/src
151183
# Keep track of all input variables to configure, so we don't skip reconfigure
152184
# when we do need to reconfigure
153-
CONFIGURE_INPUTS := "$(CC)$(CFLAGS)$(CPP)$(CPPFLAGS)$(CXX)$(CXXFLAGS)$(AS)$(AR)$(CONFIGURE_FLAGS)"
185+
CONFIGURE_INPUTS := "$(CC)$(CFLAGS)$(CPP)$(CPPFLAGS)$(CXX)$(CXXFLAGS)$(AS)$(AR)$(HOST_CC)$(HOST_CXX)$(WASI_SYSROOT)$(CONFIGURE_FLAGS)"
154186
LAST_CONFIGURE_INPUTS := "$(shell cat reconfigure.inputs)"
155187
maybe-configure:
156188
[[ $(JSSRC)/configure -ot $(JSSRC)/configure.in ]] && touch $(JSSRC)/configure || true
@@ -161,6 +193,9 @@ maybe-configure:
161193
CC="$(CC)" CFLAGS="$(CFLAGS)" \
162194
CPP="$(CPP)" CPPFLAGS="$(CPPFLAGS)" \
163195
CXX="$(CXX)" CXXFLAGS="$(CXXFLAGS)" \
196+
HOST_CC="$(HOST_CC)" \
197+
HOST_CXX="$(HOST_CXX)" \
198+
WASI_SYSROOT="$(WASI_SYSROOT)" \
164199
AS="$(AS)" AR="$(AR)" \
165200
$(JSSRC)/configure $(strip $(CONFIGURE_FLAGS)) || (cat config.log && exit 1) ; \
166201
fi

mozjs-sys/src/jsglue.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,7 @@ bool AppendToRootedObjectVector(JS::PersistentRootedObjectVector* v,
883883

884884
void DeleteRootedObjectVector(JS::PersistentRootedObjectVector* v) { delete v; }
885885

886-
#if defined(__linux__)
886+
#if defined(__linux__) || defined(__wasi__)
887887
# include <malloc.h>
888888
#elif defined(__APPLE__)
889889
# include <malloc/malloc.h>
@@ -897,7 +897,7 @@ void DeleteRootedObjectVector(JS::PersistentRootedObjectVector* v) { delete v; }
897897

898898
// SpiderMonkey-in-Rust currently uses system malloc, not jemalloc.
899899
static size_t MallocSizeOf(const void* aPtr) {
900-
#if defined(__linux__)
900+
#if defined(__linux__) || defined(__wasi__)
901901
return malloc_usable_size((void*)aPtr);
902902
#elif defined(__APPLE__)
903903
return malloc_size((void*)aPtr);

mozjs/Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ libc.workspace = true
2626
log = "0.4"
2727
mozjs_sys = { path = "../mozjs-sys" }
2828

29-
[dev-dependencies]
29+
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
30+
criterion = { version = "0.6", default-features = false, features = ["html_reports"] }
31+
32+
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
3033
criterion = "0.6"
3134

3235
[build-dependencies]

mozjs/tests/runtime.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
* License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

5+
#![cfg(not(target_arch = "wasm32"))]
6+
57
use std::ptr;
68
use std::sync::mpsc::channel;
79
use std::thread;

0 commit comments

Comments
 (0)