Skip to content

Commit 95e90d3

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 644e97b commit 95e90d3

File tree

5 files changed

+82
-6
lines changed

5 files changed

+82
-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

@@ -342,6 +349,12 @@ fn build_bindings(build_dir: &Path, target: BuildTarget) {
342349
.formatter(Formatter::Rustfmt)
343350
.clang_args(cc_flags(true));
344351

352+
if env::var("TARGET").unwrap().contains("wasi") {
353+
builder = builder
354+
.clang_arg("--sysroot")
355+
.clang_arg(env::var("WASI_SYSROOT").unwrap().to_string());
356+
}
357+
345358
if target == BuildTarget::JSGlue {
346359
builder = builder
347360
.parse_callbacks(Box::new(JSGlueCargoCallbacks::default()))
@@ -437,9 +450,15 @@ fn link_static_lib_binaries(build_dir: &Path) {
437450
println!("cargo:rustc-link-lib=c++");
438451
} else if target.contains("windows") && target.contains("gnu") {
439452
println!("cargo:rustc-link-lib=stdc++");
440-
} else if !target.contains("windows") {
453+
} else if !target.contains("windows") && !target.contains("wasi") {
454+
// The build works without this for WASI, and specifying it means
455+
// needing to use the WASI-SDK's clang for linking, which is annoying.
441456
println!("cargo:rustc-link-lib=stdc++")
442457
}
458+
459+
if target.contains("wasi") {
460+
println!("cargo:rustc-link-lib=wasi-emulated-getpid");
461+
}
443462
}
444463

445464
fn link_bindgen_static_lib_binaries(build_dir: &Path) {
@@ -518,6 +537,13 @@ fn cc_flags(bindgen: bool) -> Vec<&'static str> {
518537
if env::var_os("CARGO_FEATURE_PROFILEMOZJS").is_some() {
519538
flags.push("-fno-omit-frame-pointer");
520539
}
540+
541+
if target.contains("wasi") {
542+
// Unconditionally target p1 for now. Even if the application
543+
// targets p2, an adapter will take care of it.
544+
flags.push("--target=wasm32-wasip1");
545+
flags.push("-fvisibility=default");
546+
}
521547
}
522548

523549
flags.extend(&["-DSTATIC_JS_API", "-DRUST_BINDGEN"]);
@@ -541,6 +567,10 @@ fn cc_flags(bindgen: bool) -> Vec<&'static str> {
541567
flags.push("-stdlib=libc++");
542568
}
543569

570+
if target.contains("wasi") {
571+
flags.push("-D_WASI_EMULATED_GETPID");
572+
}
573+
544574
flags
545575
}
546576

@@ -561,6 +591,14 @@ fn js_config_path(build_dir: &Path) -> String {
561591
.to_string()
562592
}
563593

594+
fn wasi_sdk() -> Option<OsString> {
595+
if env::var("TARGET").unwrap().contains("wasi") {
596+
get_cc_rs_env_os("WASI_SDK_PATH")
597+
} else {
598+
None
599+
}
600+
}
601+
564602
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
565603
enum BuildTarget {
566604
JSApi,

mozjs-sys/makefile.cargo

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,13 @@ ifeq (,$(CARGO_FEATURE_INTL))
2020
endif
2121

2222
ifneq (,$(CARGO_FEATURE_DEBUGMOZJS))
23-
CONFIGURE_FLAGS += --enable-debug --disable-optimize --enable-gczeal
23+
CONFIGURE_FLAGS += --enable-debug --enable-gczeal
24+
ifneq (,$(findstring -wasi,$(TARGET)))
25+
# wasm-opt chokes on -O0 builds.
26+
CONFIGURE_FLAGS += --enable-optimize=-O1
27+
else
28+
CONFIGURE_FLAGS += --disable-optimize
29+
endif
2430
endif
2531

2632
ifneq (,$(CARGO_FEATURE_PROFILEMOZJS))
@@ -29,6 +35,9 @@ endif
2935

3036
ifneq (,$(CARGO_FEATURE_LIBZ_RS))
3137
CONFIGURE_FLAGS += --enable-libz-rs
38+
else ifneq (,$(findstring wasi,$(TARGET)))
39+
# system libz is not available on wasi
40+
CONFIGURE_FLAGS += --enable-libz-rs
3241
endif
3342

3443
ifneq (,$(CCACHE))
@@ -76,6 +85,27 @@ ifneq ($(HOST),$(TARGET))
7685
TARGET = aarch64-linux-gnu
7786
endif
7887

88+
ifneq (,$(findstring -wasi,$(TARGET)))
89+
ifeq (,$(WASI_SDK_PATH))
90+
$(error WASI_SDK_PATH environment variable must be set when building for wasm32)
91+
endif
92+
WASI_SYSROOT = $(WASI_SDK_PATH)/share/wasi-sysroot
93+
CC = $(WASI_SDK_PATH)/bin/clang
94+
CPP = $(WASI_SDK_PATH)/bin/clang -E
95+
CXX = $(WASI_SDK_PATH)/bin/clang++
96+
AR = $(WASI_SDK_PATH)/bin/ar
97+
HOST_CC = clang
98+
HOST_CXX = clang++
99+
CONFIGURE_FLAGS += \
100+
--enable-portable-baseline-interp \
101+
--disable-clang-plugin \
102+
--disable-jit \
103+
--disable-shared-memory \
104+
--lto=thin \
105+
--with-sysroot=$(WASI_SDK_PATH)/share/wasi-sysroot \
106+
$(NULL)
107+
endif
108+
79109
ifeq (android,$(findstring android,$(TARGET)))
80110
# Force use of lld on android. Mozilla build system tries to use
81111
# gold or bfd linker on Android to support their 'elfhack'functionality in
@@ -154,7 +184,7 @@ all: maybe-configure
154184
JSSRC := '$(SRC_DIR)'/js/src
155185
# Keep track of all input variables to configure, so we don't skip reconfigure
156186
# when we do need to reconfigure
157-
CONFIGURE_INPUTS := "$(CC)$(CFLAGS)$(CPP)$(CPPFLAGS)$(CXX)$(CXXFLAGS)$(AS)$(AR)$(CONFIGURE_FLAGS)"
187+
CONFIGURE_INPUTS := "$(CC)$(CFLAGS)$(CPP)$(CPPFLAGS)$(CXX)$(CXXFLAGS)$(AS)$(AR)$(HOST_CC)$(HOST_CXX)$(WASI_SYSROOT)$(CONFIGURE_FLAGS)"
158188
LAST_CONFIGURE_INPUTS := "$(shell cat reconfigure.inputs)"
159189
maybe-configure:
160190
[[ $(JSSRC)/configure -ot $(JSSRC)/configure.in ]] && touch $(JSSRC)/configure || true
@@ -165,6 +195,9 @@ maybe-configure:
165195
CC="$(CC)" CFLAGS="$(CFLAGS)" \
166196
CPP="$(CPP)" CPPFLAGS="$(CPPFLAGS)" \
167197
CXX="$(CXX)" CXXFLAGS="$(CXXFLAGS)" \
198+
HOST_CC="$(HOST_CC)" \
199+
HOST_CXX="$(HOST_CXX)" \
200+
WASI_SYSROOT="$(WASI_SYSROOT)" \
168201
AS="$(AS)" AR="$(AR)" \
169202
$(JSSRC)/configure $(strip $(CONFIGURE_FLAGS)) || (cat config.log && exit 1) ; \
170203
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
@@ -27,7 +27,10 @@ libc.workspace = true
2727
log = "0.4"
2828
mozjs_sys = { path = "../mozjs-sys" }
2929

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

3336
[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)