From 3916aba709b7eab8af027ff59e294b9cf5cded94 Mon Sep 17 00:00:00 2001 From: Till Schneidereit Date: Tue, 29 Jul 2025 16:38:59 +0200 Subject: [PATCH 01/12] Update to SpiderMonkey 140 --- CMakeLists.txt | 1 - builtins/web/base64.cpp | 2 +- builtins/web/console.cpp | 4 ++-- builtins/web/crypto/uuid.cpp | 2 -- builtins/web/event/event-target.cpp | 2 +- builtins/web/fetch/fetch-utils.cpp | 2 +- builtins/web/fetch/fetch_event.cpp | 2 +- builtins/web/fetch/request-response.cpp | 2 +- builtins/web/form-data/form-data-encoder.cpp | 2 +- cmake/builtins.cmake | 5 ++--- cmake/compile-flags.cmake | 2 +- cmake/fmt.cmake | 3 --- cmake/spidermonkey.cmake | 5 ++++- cmake/wasi-sdk.cmake | 4 ++-- cmake/wasm-tools.cmake | 4 ++-- cmake/wizer.cmake | 2 +- host-apis/wasi-0.2.0/host_api.cpp | 4 ++-- runtime/debugger.cpp | 2 +- runtime/engine.cpp | 3 ++- runtime/js.cpp | 8 -------- 20 files changed, 25 insertions(+), 36 deletions(-) delete mode 100644 cmake/fmt.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 5696c4ec..200a9953 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,7 +33,6 @@ include("wizer") include("weval") include("wasmtime") -include("fmt") include("spidermonkey") include("openssl") include("${HOST_API}/host_api.cmake") diff --git a/builtins/web/base64.cpp b/builtins/web/base64.cpp index 76106543..fee32521 100644 --- a/builtins/web/base64.cpp +++ b/builtins/web/base64.cpp @@ -212,7 +212,7 @@ JS::Result forgivingBase64Decode(std::string_view data, auto hasWhitespace = std::find_if(data.begin(), data.end(), &isAsciiWhitespace); std::string dataWithoutAsciiWhitespace; - if (hasWhitespace) { + if (*hasWhitespace) { dataWithoutAsciiWhitespace = data; dataWithoutAsciiWhitespace.erase(std::remove_if(dataWithoutAsciiWhitespace.begin() + std::distance(data.begin(), hasWhitespace), diff --git a/builtins/web/console.cpp b/builtins/web/console.cpp index afc2d680..19086865 100644 --- a/builtins/web/console.cpp +++ b/builtins/web/console.cpp @@ -468,7 +468,7 @@ static bool console_out(JSContext *cx, unsigned argc, JS::Value *vp) { // https://console.spec.whatwg.org/#assert // assert(condition, ...data) -static bool assert(JSContext *cx, unsigned argc, JS::Value *vp) { +static bool assert_(JSContext *cx, unsigned argc, JS::Value *vp) { JS::CallArgs args = CallArgsFromVp(argc, vp); args.rval().setUndefined(); auto condition = args.get(0).toBoolean(); @@ -811,7 +811,7 @@ static bool trace(JSContext *cx, unsigned argc, JS::Value *vp) { } const JSFunctionSpec Console::methods[] = { - JS_FN("assert", assert, 0, JSPROP_ENUMERATE), + JS_FN("assert", assert_, 0, JSPROP_ENUMERATE), JS_FN("clear", no_op, 0, JSPROP_ENUMERATE), JS_FN("count", count, 0, JSPROP_ENUMERATE), JS_FN("countReset", countReset, 0, JSPROP_ENUMERATE), diff --git a/builtins/web/crypto/uuid.cpp b/builtins/web/crypto/uuid.cpp index f6c211c7..771b0596 100644 --- a/builtins/web/crypto/uuid.cpp +++ b/builtins/web/crypto/uuid.cpp @@ -1,8 +1,6 @@ #include "uuid.h" #include "host_api.h" -#include - namespace builtins { namespace web { namespace crypto { diff --git a/builtins/web/event/event-target.cpp b/builtins/web/event/event-target.cpp index 9a24b2d4..4df3c164 100644 --- a/builtins/web/event/event-target.cpp +++ b/builtins/web/event/event-target.cpp @@ -102,7 +102,7 @@ bool default_passive_value() { namespace JS { -template struct JS::GCPolicy> { +template struct GCPolicy> { static void trace(JSTracer *trc, RefPtr *tp, const char *name) { if (T *target = tp->get()) { GCPolicy::trace(trc, target, name); diff --git a/builtins/web/fetch/fetch-utils.cpp b/builtins/web/fetch/fetch-utils.cpp index 913a1346..3b18718e 100644 --- a/builtins/web/fetch/fetch-utils.cpp +++ b/builtins/web/fetch/fetch-utils.cpp @@ -160,7 +160,7 @@ std::optional> extract_range(std::string_view range_q auto to_size = [](std::string_view s) -> std::optional { size_t v; - auto [ptr, ec] = std::from_chars(s.begin(), s.end(), v); + auto [ptr, ec] = std::from_chars(&*s.begin(), &*s.end(), v); return ec == std::errc() ? std::optional(v) : std::nullopt; }; diff --git a/builtins/web/fetch/fetch_event.cpp b/builtins/web/fetch/fetch_event.cpp index f9f30a18..0a886912 100644 --- a/builtins/web/fetch/fetch_event.cpp +++ b/builtins/web/fetch/fetch_event.cpp @@ -132,7 +132,7 @@ bool FetchEvent::init_incoming_request(JSContext *cx, JS::HandleObject self, bool is_head = !is_get && method_str == "HEAD"; if (!is_get) { - JS::RootedString method(cx, JS_NewStringCopyN(cx, method_str.cbegin(), method_str.length())); + JS::RootedString method(cx, JS_NewStringCopyN(cx, &*method_str.cbegin(), method_str.length())); if (!method) { return false; } diff --git a/builtins/web/fetch/request-response.cpp b/builtins/web/fetch/request-response.cpp index b50ee223..eeb53a04 100644 --- a/builtins/web/fetch/request-response.cpp +++ b/builtins/web/fetch/request-response.cpp @@ -88,7 +88,7 @@ class BodyFutureTask final : public api::AsyncTask { auto body = RequestOrResponse::incoming_body_handle(owner); auto read_res = body->read(HANDLE_READ_CHUNK_SIZE); - if (auto *err = read_res.to_err()) { + if (read_res.to_err()) { auto receiver = Request::is_instance(owner) ? "request" : "response"; api::throw_error(cx, FetchErrors::IncomingBodyStreamError, receiver); return error_stream_controller_with_pending_exception(cx, stream); diff --git a/builtins/web/form-data/form-data-encoder.cpp b/builtins/web/form-data/form-data-encoder.cpp index 013626d7..1aa3775c 100644 --- a/builtins/web/form-data/form-data-encoder.cpp +++ b/builtins/web/form-data/form-data-encoder.cpp @@ -658,7 +658,7 @@ JSObject *MultipartFormData::create(JSContext *cx, HandleObject form_data) { } auto res = host_api::Random::get_bytes(12); - if (auto *err = res.to_err()) { + if (res.to_err()) { return nullptr; } diff --git a/cmake/builtins.cmake b/cmake/builtins.cmake index effcea27..a5192fb4 100644 --- a/cmake/builtins.cmake +++ b/cmake/builtins.cmake @@ -36,7 +36,7 @@ add_builtin( builtins/web/form-data/form-data-parser.cpp DEPENDENCIES multipart - fmt) +) add_builtin( builtins::web::dom_exception @@ -96,7 +96,7 @@ add_builtin( builtins/web/fetch/headers.cpp builtins/web/fetch/request-response.cpp DEPENDENCIES - fmt) +) add_builtin( builtins::web::fetch::fetch_event @@ -118,6 +118,5 @@ add_builtin( builtins/web/crypto/uuid.cpp DEPENDENCIES OpenSSL::Crypto - fmt INCLUDE_DIRS runtime) diff --git a/cmake/compile-flags.cmake b/cmake/compile-flags.cmake index ca4660c2..219b2f05 100644 --- a/cmake/compile-flags.cmake +++ b/cmake/compile-flags.cmake @@ -12,7 +12,7 @@ list(APPEND CMAKE_EXE_LINKER_FLAGS list(JOIN CMAKE_EXE_LINKER_FLAGS " " CMAKE_EXE_LINKER_FLAGS) list(APPEND CMAKE_CXX_FLAGS - -std=gnu++20 -Wall -Werror -Qunused-arguments -Wimplicit-fallthrough + -std=gnu++20 -Wall -Werror -Qunused-arguments -Wimplicit-fallthrough -Wno-unknown-warning-option -fno-sized-deallocation -fno-aligned-new -mthread-model single -fPIC -fno-rtti -fno-exceptions -fno-math-errno -pipe -fno-omit-frame-pointer -funwind-tables -m32 diff --git a/cmake/fmt.cmake b/cmake/fmt.cmake deleted file mode 100644 index a160d910..00000000 --- a/cmake/fmt.cmake +++ /dev/null @@ -1,3 +0,0 @@ -set(FMT_OS OFF) -set(FMT_INSTALL OFF) -CPMAddPackage(NAME fmt URL https://github.com/fmtlib/fmt/releases/download/10.1.1/fmt-10.1.1.zip) diff --git a/cmake/spidermonkey.cmake b/cmake/spidermonkey.cmake index b496692f..0e267627 100644 --- a/cmake/spidermonkey.cmake +++ b/cmake/spidermonkey.cmake @@ -41,4 +41,7 @@ target_sources(spidermonkey PRIVATE ${SM_OBJS} ${CMAKE_CURRENT_BINARY_DIR}/null. target_include_directories(spidermonkey PUBLIC ${SM_INCLUDE_DIR}) target_link_libraries(spidermonkey PUBLIC ${SM_SOURCE_DIR}/lib/libjs_static.a) -add_compile_definitions("MOZ_JS_STREAMS") +# SpiderMonkey's builds include a header that defines some configuration options that need to be set +# to ensure e.g. object layout is identical to the one used in the build. +# We include this header in all compilations. +add_compile_options(-include ${SM_INCLUDE_DIR}/js-confdefs.h) diff --git a/cmake/wasi-sdk.cmake b/cmake/wasi-sdk.cmake index e25595f1..5ee67d66 100644 --- a/cmake/wasi-sdk.cmake +++ b/cmake/wasi-sdk.cmake @@ -1,6 +1,6 @@ -set(WASI_SDK_VERSION 20 CACHE STRING "Version of wasi-sdk to use") +set(WASI_SDK_VERSION 25 CACHE STRING "Version of wasi-sdk to use") -set(WASI_SDK_URL "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VERSION}/wasi-sdk-${WASI_SDK_VERSION}.0-${HOST_OS}.tar.gz") +set(WASI_SDK_URL "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VERSION}/wasi-sdk-${WASI_SDK_VERSION}.0-${HOST_CPU}-${HOST_OS}.tar.gz") CPMAddPackage(NAME wasi-sdk URL ${WASI_SDK_URL}) set(WASI_SDK_PREFIX ${CPM_PACKAGE_wasi-sdk_SOURCE_DIR}) set(CMAKE_TOOLCHAIN_FILE ${CPM_PACKAGE_wasi-sdk_SOURCE_DIR}/share/cmake/wasi-sdk.cmake) diff --git a/cmake/wasm-tools.cmake b/cmake/wasm-tools.cmake index a8e03b9f..40f8dd73 100644 --- a/cmake/wasm-tools.cmake +++ b/cmake/wasm-tools.cmake @@ -1,6 +1,6 @@ -set(WASM_TOOLS_VERSION 1.0.54) +set(WASM_TOOLS_VERSION 1.235.0) -set(WASM_TOOLS_URL https://github.com/bytecodealliance/wasm-tools/releases/download/wasm-tools-${WASM_TOOLS_VERSION}/wasm-tools-${WASM_TOOLS_VERSION}-${HOST_ARCH}-${HOST_OS}.tar.gz) +set(WASM_TOOLS_URL https://github.com/bytecodealliance/wasm-tools/releases/download/v${WASM_TOOLS_VERSION}/wasm-tools-${WASM_TOOLS_VERSION}-${HOST_ARCH}-${HOST_OS}.tar.gz) CPMAddPackage(NAME wasm-tools URL ${WASM_TOOLS_URL} DOWNLOAD_ONLY TRUE) set(WASM_TOOLS_DIR ${CPM_PACKAGE_wasm-tools_SOURCE_DIR}) set(WASM_TOOLS_BIN ${WASM_TOOLS_DIR}/wasm-tools CACHE FILEPATH "Path to wasm-tools binary") diff --git a/cmake/wizer.cmake b/cmake/wizer.cmake index f429e8a2..142cd68f 100644 --- a/cmake/wizer.cmake +++ b/cmake/wizer.cmake @@ -1,4 +1,4 @@ -set(WIZER_VERSION v3.0.1 CACHE STRING "Version of wizer to use") +set(WIZER_VERSION v9.0.0 CACHE STRING "Version of wizer to use") set(WIZER_URL https://github.com/bytecodealliance/wizer/releases/download/${WIZER_VERSION}/wizer-${WIZER_VERSION}-${HOST_ARCH}-${HOST_OS}.tar.xz) CPMAddPackage(NAME wizer URL ${WIZER_URL} DOWNLOAD_ONLY TRUE) diff --git a/host-apis/wasi-0.2.0/host_api.cpp b/host-apis/wasi-0.2.0/host_api.cpp index e33ec366..3060acad 100644 --- a/host-apis/wasi-0.2.0/host_api.cpp +++ b/host-apis/wasi-0.2.0/host_api.cpp @@ -643,12 +643,12 @@ wasi_http_types_method_t http_method_to_host(string_view method_str) { auto method = method_str.begin(); for (uint8_t i = 0; i < WASI_HTTP_TYPES_METHOD_OTHER; i++) { auto name = http_method_names[i]; - if (strcasecmp(method, name) == 0) { + if (strcasecmp(&*method, name) == 0) { return wasi_http_types_method_t{i}; } } - auto val = bindings_string_t{reinterpret_cast(const_cast(method)), + auto val = bindings_string_t{reinterpret_cast(const_cast(&*method)), method_str.length()}; return wasi_http_types_method_t{WASI_HTTP_TYPES_METHOD_OTHER, {val}}; } diff --git a/runtime/debugger.cpp b/runtime/debugger.cpp index bc14aa56..0fa98718 100644 --- a/runtime/debugger.cpp +++ b/runtime/debugger.cpp @@ -37,7 +37,7 @@ bool print_location(JSContext *cx, FILE *fp = stdout) { JS::AutoFilename filename; uint32_t lineno; JS::ColumnNumberOneOrigin column; - if (!DescribeScriptedCaller(cx, &filename, &lineno, &column)) { + if (!DescribeScriptedCaller(&filename, cx, &lineno, &column)) { return false; } fprintf(fp, "%s@%u:%u: ", filename.get(), lineno, column.oneOriginValue()); diff --git a/runtime/engine.cpp b/runtime/engine.cpp index bf8fd455..65f7b700 100644 --- a/runtime/engine.cpp +++ b/runtime/engine.cpp @@ -256,7 +256,8 @@ bool create_content_global(JSContext * cx) { JS::RealmOptions options; options.creationOptions().setStreamsEnabled(true); - JS::DisableIncrementalGC(cx); + // TODO: restore + // JS::DisableIncrementalGC(cx); // JS_SetGCParameter(cx, JSGC_MAX_EMPTY_CHUNK_COUNT, 1); RootedObject global( diff --git a/runtime/js.cpp b/runtime/js.cpp index deeb6f72..a5cf05c7 100644 --- a/runtime/js.cpp +++ b/runtime/js.cpp @@ -12,8 +12,6 @@ #include #endif -extern "C" void __wasm_call_ctors(); - api::Engine *engine; api::Engine* initialize(std::vector args) { @@ -77,8 +75,6 @@ void wizen() { WIZER_INIT(wizen); -extern "C" void __wasm_call_ctors(); - /** * The main entry function for the runtime. * @@ -89,8 +85,6 @@ extern "C" void __wasm_call_ctors(); * load the file `./index.js` and run it as the top-level module script. */ extern "C" bool exports_wasi_cli_run_run() { - __wasm_call_ctors(); - auto arg_strings = host_api::environment_get_arguments(); std::vector args; for (auto& arg : arg_strings) args.push_back(arg); @@ -109,8 +103,6 @@ extern "C" bool exports_wasi_cli_run_run() { * command line. */ extern "C" bool init_from_environment() { - __wasm_call_ctors(); - auto config_parser = starling::ConfigParser(); config_parser.apply_env(); ENGINE = new api::Engine(config_parser.take()); From 62a3f19521dea90d82126e24a2005f9098c78582 Mon Sep 17 00:00:00 2001 From: Till Schneidereit Date: Thu, 31 Jul 2025 18:51:21 +0200 Subject: [PATCH 02/12] Integrate SpiderMonkey build Instead of relying on the external [spidermonkey-wasi-embedding](https://github.com/bytecodealliance/spidermonkey-wasi-embedding) repo doing debug/release builds of SpiderMonkey as a static library, and StarlingMonkey just pulling those in, with this commit the build is integrated into StarlingMonkey's CMake setup. The build system is still prepared to make use of pre-generated binaries, but right now nothing produces and publishes those. I'll follow this up with more commits adding both caching for CI and publishing of the binaries. Once that's done, hopefully the setup introduced here will just work with them. If not, I'll tweak things accordingly. --- CMakeLists.txt | 1 + cmake/cbindgen.cmake | 16 ++++ cmake/init-corrosion.cmake | 2 +- cmake/spidermonkey.cmake | 180 +++++++++++++++++++++++++++++++++---- cmake/wasi-sdk.cmake | 4 +- rust-toolchain.toml | 2 +- 6 files changed, 185 insertions(+), 20 deletions(-) create mode 100644 cmake/cbindgen.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 200a9953..fab42bc8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,7 @@ include("binaryen") include("wizer") include("weval") include("wasmtime") +include("cbindgen") include("spidermonkey") include("openssl") diff --git a/cmake/cbindgen.cmake b/cmake/cbindgen.cmake new file mode 100644 index 00000000..a5ef3a84 --- /dev/null +++ b/cmake/cbindgen.cmake @@ -0,0 +1,16 @@ +set(CBINDGEN_VERSION 0.29.0) + +# cbindgen doesn't have pre-built binaries for all platforms, so we install it via cargo-binstall. Which we install first, too. +find_program(CBINDGEN_EXECUTABLE cbindgen) +if(NOT CBINDGEN_EXECUTABLE) + find_program(CARGO_BINSTALL_EXECUTABLE cargo-binstall) + if(NOT CARGO_BINSTALL_EXECUTABLE) + execute_process( + COMMAND curl -L --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh + COMMAND bash + ) + endif() + execute_process( + COMMAND cargo binstall -y cbindgen + ) +endif() diff --git a/cmake/init-corrosion.cmake b/cmake/init-corrosion.cmake index dfaa07a8..a98a25fa 100644 --- a/cmake/init-corrosion.cmake +++ b/cmake/init-corrosion.cmake @@ -9,7 +9,7 @@ set(Rust_CARGO_TARGET_LINK_NATIVE_LIBS "") file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/rust-toolchain.toml" Rust_TOOLCHAIN REGEX "^channel ?=") string(REGEX MATCH "[0-9.]+" Rust_TOOLCHAIN "${Rust_TOOLCHAIN}") execute_process(COMMAND rustup toolchain install ${Rust_TOOLCHAIN}) -execute_process(COMMAND rustup target add --toolchain ${Rust_TOOLCHAIN} wasm32-wasi) +execute_process(COMMAND rustup target add --toolchain ${Rust_TOOLCHAIN} wasm32-wasip1) CPMAddPackage("gh:corrosion-rs/corrosion@0.5.1") string(TOLOWER ${Rust_CARGO_HOST_ARCH} HOST_ARCH) diff --git a/cmake/spidermonkey.cmake b/cmake/spidermonkey.cmake index 0e267627..4226bc55 100644 --- a/cmake/spidermonkey.cmake +++ b/cmake/spidermonkey.cmake @@ -1,16 +1,14 @@ -set(SM_REV b02d76023a15a3fa8c8f54bff5dac91099669003) +set(SM_TAG FIREFOX_140_0_4_RELEASE_STARLING) if (CMAKE_BUILD_TYPE STREQUAL "Debug") set(SM_BUILD_TYPE debug) else() set(SM_BUILD_TYPE release) endif() -set(SM_BUILD_TYPE_DASH ${SM_BUILD_TYPE}) option(WEVAL "Build with a SpiderMonkey variant that supports weval-based AOT compilation" OFF) if (WEVAL) - set(SM_BUILD_TYPE_DASH "${SM_BUILD_TYPE}-weval") set(SM_BUILD_TYPE "${SM_BUILD_TYPE}_weval") endif() @@ -21,27 +19,177 @@ endif() # This can be set, for example, to the output directly (`release/` or `debug/`) # under a local clone of the `spidermonkey-wasi-embedding` repo. if (DEFINED ENV{SPIDERMONKEY_BINARIES}) - set(SM_SOURCE_DIR $ENV{SPIDERMONKEY_BINARIES}) + set(SM_LIB_DIR $ENV{SPIDERMONKEY_BINARIES}) + message(STATUS "Using pre-built SpiderMonkey artifacts from local directory ${SM_LIB_DIR}") else() - CPMAddPackage(NAME spidermonkey-${SM_BUILD_TYPE} - URL https://github.com/bytecodealliance/spidermonkey-wasi-embedding/releases/download/rev_${SM_REV}/spidermonkey-wasm-static-lib_${SM_BUILD_TYPE}.tar.gz - DOWNLOAD_ONLY YES + set(SM_URL https://github.com/bytecodealliance/starlingmonkey/releases/download/libspidermonkey_${SM_TAG}/spidermonkey-static-${SM_BUILD_TYPE}.tar.gz) + execute_process( + COMMAND curl -s -o /dev/null -w "%{http_code}" ${SM_URL} + RESULT_VARIABLE CURL_RESULT + OUTPUT_VARIABLE HTTP_STATUS ) - set(SM_SOURCE_DIR ${CPM_PACKAGE_spidermonkey-${SM_BUILD_TYPE}_SOURCE_DIR} CACHE STRING "Path to spidermonkey ${SM_BUILD_TYPE} build" FORCE) + if (CURL_RESULT EQUAL 0 AND HTTP_STATUS STREQUAL "200") + message(STATUS "Using pre-built SpiderMonkey artifacts from ${SM_URL}") + CPMAddPackage(NAME spidermonkey-${SM_BUILD_TYPE} + URL ${SM_URL} + DOWNLOAD_ONLY YES + ) + set(SM_LIB_DIR ${CPM_PACKAGE_spidermonkey-${SM_BUILD_TYPE}_SOURCE_DIR} CACHE STRING "Path to spidermonkey ${SM_BUILD_TYPE} build" FORCE) + else() + message(STATUS "No pre-built ${SM_BUILD_TYPE} SpiderMonkey artifacts available for tag ${SM_TAG}. Building from source.") + endif() endif() -set(SM_INCLUDE_DIR ${SM_SOURCE_DIR}/include) - file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/null.cpp "") -file(GLOB SM_OBJS ${SM_SOURCE_DIR}/lib/*.o) -add_library(spidermonkey STATIC) -target_sources(spidermonkey PRIVATE ${SM_OBJS} ${CMAKE_CURRENT_BINARY_DIR}/null.cpp) -target_include_directories(spidermonkey PUBLIC ${SM_INCLUDE_DIR}) -target_link_libraries(spidermonkey PUBLIC ${SM_SOURCE_DIR}/lib/libjs_static.a) +if (DEFINED SM_LIB_DIR) + set(SM_INCLUDE_DIR ${SM_LIB_DIR}/include) + + add_library(spidermonkey INTERFACE) + target_include_directories(spidermonkey INTERFACE ${SM_INCLUDE_DIR}) + target_link_libraries(spidermonkey INTERFACE ${SM_LIB_DIR}/libspidermonkey.a) +else() + CPMAddPackage(NAME gecko-source + GIT_REPOSITORY "https://github.com/bytecodealliance/firefox.git" + GIT_TAG "${SM_TAG}" + DOWNLOAD_ONLY YES + ) + set(SM_SOURCE_DIR ${CPM_PACKAGE_gecko-source_SOURCE_DIR}) + set(SM_OBJ_DIR ${CMAKE_CURRENT_BINARY_DIR}/spidermonkey) + set(SM_LIB_DIR "${SM_OBJ_DIR}/dist") + set(SM_INCLUDE_DIR "${SM_LIB_DIR}/include") + + # Additional obj files needed, but not part of libjs_static.a + set(SM_OBJ_FILES + memory/build/Unified_cpp_memory_build0.o + memory/mozalloc/Unified_cpp_memory_mozalloc0.o + mfbt/Unified_cpp_mfbt0.o + mfbt/Unified_cpp_mfbt1.o + mozglue/misc/AutoProfilerLabel.o + mozglue/misc/ConditionVariable_noop.o + mozglue/misc/Debug.o + mozglue/misc/Decimal.o + mozglue/misc/MmapFaultHandler.o + mozglue/misc/Mutex_noop.o + mozglue/misc/Now.o + mozglue/misc/Printf.o + mozglue/misc/SIMD.o + mozglue/misc/StackWalk.o + mozglue/misc/TimeStamp.o + mozglue/misc/TimeStamp_posix.o + mozglue/misc/Uptime.o + mozglue/static/lz4.o + mozglue/static/lz4frame.o + mozglue/static/lz4hc.o + mozglue/static/xxhash.o + third_party/fmt/Unified_cpp_third_party_fmt0.o + ) + set(SM_OBJS) + foreach(obj_file ${SM_OBJ_FILES}) + list(APPEND SM_OBJS ${SM_OBJ_DIR}/${obj_file}) + endforeach() + + # Set up compiler environment + find_program(SM_HOST_CC clang c REQUIRED DOCS "C compiler for building SpiderMonkey") + find_program(SM_HOST_CXX clang++ c++ REQUIRED DOCS "C++ compiler for building") + + set(MOZCONFIG "${CMAKE_CURRENT_BINARY_DIR}/mozconfig-${SM_BUILD_TYPE}") + set(MOZCONFIG_CONTENT "ac_add_options --enable-project=js +ac_add_options --disable-js-shell +ac_add_options --target=wasm32-unknown-wasi +ac_add_options --without-system-zlib +ac_add_options --without-intl-api +ac_add_options --disable-jit +ac_add_options --disable-shared-js +ac_add_options --disable-shared-memory +ac_add_options --disable-tests +ac_add_options --disable-clang-plugin +ac_add_options --enable-jitspew +ac_add_options --enable-optimize=-O3 +ac_add_options --enable-js-streams +ac_add_options --enable-portable-baseline-interp +ac_add_options --prefix=${SM_OBJ_DIR}/dist +mk_add_options MOZ_OBJDIR=${SM_OBJ_DIR} +mk_add_options AUTOCLOBBER=1 +") + + # Add WASI sysroot if available + if(DEFINED ENV{WASI_SYSROOT}) + string(APPEND MOZCONFIG_CONTENT "ac_add_options --with-sysroot=\"$ENV{WASI_SYSROOT}\"\n") + endif() + + # Platform-specific configuration + if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") + string(APPEND MOZCONFIG_CONTENT "ac_add_options --disable-stdcxx-compat\n") + elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") + string(APPEND MOZCONFIG_CONTENT "ac_add_options --host=aarch64-apple-darwin\n") + else() + message(FATAL_ERROR "Unsupported build platform: ${CMAKE_HOST_SYSTEM_NAME}") + endif() + + # Mode-specific configuration + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + string(APPEND MOZCONFIG_CONTENT "ac_add_options --enable-debug\n") + else() + string(APPEND MOZCONFIG_CONTENT "ac_add_options --disable-debug\n") + string(APPEND MOZCONFIG_CONTENT "ac_add_options --enable-lto=thin\n") + endif() + + # Weval-specific configuration + if(WEVAL) + string(APPEND MOZCONFIG_CONTENT "ac_add_options --enable-portable-baseline-interp-force\n") + string(APPEND MOZCONFIG_CONTENT "ac_add_options --enable-aot-ics\n") + string(APPEND MOZCONFIG_CONTENT "ac_add_options --enable-aot-ics-force\n") + string(APPEND MOZCONFIG_CONTENT "ac_add_options --enable-pbl-weval\n") + endif() + + file(GENERATE OUTPUT ${MOZCONFIG} CONTENT "${MOZCONFIG_CONTENT}") + + add_custom_command( + OUTPUT ${SM_OBJS} ${SM_LIB_DIR}/libjs_static.a + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env + CC=${CMAKE_C_COMPILER} + CXX=${CMAKE_CXX_COMPILER} + AR=${CMAKE_AR} + HOST_CC=${SM_HOST_CC} + HOST_CXX=${SM_HOST_CXX} + MOZCONFIG=${MOZCONFIG} + SM_SOURCE_DIR=${SM_SOURCE_DIR} + SM_OBJ_DIR=${SM_OBJ_DIR} + python3 ${SM_SOURCE_DIR}/mach --no-interactive build + COMMAND ${CMAKE_COMMAND} -E rm -f ${SM_INCLUDE_DIR}/js-confdefs.h + COMMAND ${CMAKE_COMMAND} -E create_symlink ${SM_OBJ_DIR}/js/src/js-confdefs.h ${SM_INCLUDE_DIR}/js-confdefs.h + COMMAND ${CMAKE_COMMAND} -E create_symlink ${SM_OBJ_DIR}/js/src/build/libjs_static.a ${SM_LIB_DIR}/libjs_static.a + DEPENDS ${MOZCONFIG} + COMMENT "Building SpiderMonkey for WASI" + VERBATIM + ) + + # Create combined static library including everything needed for embedding SpiderMonkey. + set(LIB_SM ${SM_LIB_DIR}/libspidermonkey.a) + add_custom_command( + OUTPUT ${LIB_SM} + COMMAND ${CMAKE_COMMAND} -E copy ${SM_LIB_DIR}/libjs_static.a ${LIB_SM} + COMMAND ${CMAKE_AR} -q ${LIB_SM} ${SM_OBJS} + DEPENDS ${SM_OBJS} ${SM_LIB_DIR}/libjs_static.a + COMMENT "Creating combined SpiderMonkey library" + VERBATIM + ) + add_custom_target(spidermonkey_build DEPENDS ${LIB_SM}) + + add_library(spidermonkey INTERFACE) + add_dependencies(spidermonkey spidermonkey_build) + target_include_directories(spidermonkey INTERFACE ${SM_INCLUDE_DIR}) + target_link_libraries(spidermonkey INTERFACE ${LIB_SM}) +endif() # SpiderMonkey's builds include a header that defines some configuration options that need to be set # to ensure e.g. object layout is identical to the one used in the build. # We include this header in all compilations. -add_compile_options(-include ${SM_INCLUDE_DIR}/js-confdefs.h) +## (And because that file doesn't exist until the SpiderMonkey build is complete, we create a placeholder for now.) +if (NOT EXISTS ${SM_INCLUDE_DIR}/js-confdefs.h) + file(WRITE ${SM_INCLUDE_DIR}/js-confdefs.h "// Placeholder\n") +endif() +target_compile_options(spidermonkey INTERFACE -include ${SM_INCLUDE_DIR}/js-confdefs.h) diff --git a/cmake/wasi-sdk.cmake b/cmake/wasi-sdk.cmake index 5ee67d66..ba5f79c6 100644 --- a/cmake/wasi-sdk.cmake +++ b/cmake/wasi-sdk.cmake @@ -1,6 +1,6 @@ -set(WASI_SDK_VERSION 25 CACHE STRING "Version of wasi-sdk to use") +set(WASI_SDK_VERSION 25 CACHE STRING "Version of wasi-sdk to use" FORCE) set(WASI_SDK_URL "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VERSION}/wasi-sdk-${WASI_SDK_VERSION}.0-${HOST_CPU}-${HOST_OS}.tar.gz") CPMAddPackage(NAME wasi-sdk URL ${WASI_SDK_URL}) set(WASI_SDK_PREFIX ${CPM_PACKAGE_wasi-sdk_SOURCE_DIR}) -set(CMAKE_TOOLCHAIN_FILE ${CPM_PACKAGE_wasi-sdk_SOURCE_DIR}/share/cmake/wasi-sdk.cmake) +set(CMAKE_TOOLCHAIN_FILE ${WASI_SDK_PREFIX}/share/cmake/wasi-sdk.cmake) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 4c21f8c7..e7a439c8 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "1.80.0" +channel = "1.88.0" targets = [ "wasm32-wasip1" ] profile = "minimal" From a27bd909c9d3eb09730c993505840c421c0a210c Mon Sep 17 00:00:00 2001 From: Till Schneidereit Date: Thu, 31 Jul 2025 19:19:17 +0200 Subject: [PATCH 03/12] ci: Update GH Actions testing workflow This includes a few changes: - Disable weval in CI, since we unfortunately don't have weval support anymore for the time being - Cache SpiderMonkey builds in CI - Upload SpiderMonkey build artifacts in CI --- .github/workflows/main.yml | 40 ++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index df9e956d..7d7c77ab 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -24,16 +24,30 @@ jobs: strategy: fail-fast: false matrix: - build: [release, debug, weval] + build: [release, debug] os: [ubuntu-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 - - name: Install Rust 1.80.0 + - name: Install Rust 1.88.0 run: | - rustup toolchain install 1.80.0 - rustup target add wasm32-wasip1 --toolchain 1.80.0 + rustup toolchain install 1.88.0 + rustup target add wasm32-wasip1 --toolchain 1.88.0 + + - name: Cache SpiderMonkey tarball + uses: actions/cache@v4 + id: sm-cache + with: + path: | + spidermonkey-dist + key: spidermonkey-cache-${{ matrix.build }}-${{ hashFiles('cmake/spidermonkey.cmake') }} + + - name: Set env var to use cached SpiderMonkey tarball + if: steps.sm-cache.outputs.cache-hit == 'true' + run: | + tree spidermonkey-dist + echo "SPIDERMONKEY_BINARIES=$(pwd)/spidermonkey-dist" >> $GITHUB_ENV - uses: actions/setup-node@v2 with: @@ -64,3 +78,21 @@ jobs: - name: StarlingMonkey E2E, Integration, and WPT Tests run: | CTEST_OUTPUT_ON_FAILURE=1 ctest --test-dir cmake-build-${{ matrix.build }} -j$(nproc) --verbose + + - name: Set up cacheable SpiderMonkey artifacts + if: steps.sm-cache.outputs.cache-hit != 'true' + run: | + mkdir -p spidermonkey-dist + cp -a cmake-build-${{ matrix.build }}/spidermonkey-obj/dist/libspidermonkey.a spidermonkey-dist/ + cp -aL cmake-build-${{ matrix.build }}/spidermonkey-obj/dist/include spidermonkey-dist/ + tree spidermonkey-dist + + # Upload tarball as an artifact of the github action run, so the output + # can be inspected for pull requests. + - name: Upload SpiderMonkey tarball + uses: actions/upload-artifact@v4 + if: (github.event_name != 'push' || (github.ref != 'refs/heads/main' && !startsWith(github.ref, 'refs/tags/v'))) + && steps.sm-cache.outputs.cache-hit != 'true' + with: + name: spidermonkey-${{ matrix.build }} + path: spidermonkey-dist/* From 132dd25acca3367790927eb96c32ca01469c1db3 Mon Sep 17 00:00:00 2001 From: Till Schneidereit Date: Sat, 2 Aug 2025 14:38:57 +0200 Subject: [PATCH 04/12] Don't use CPM to clone SpiderMonkey source MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CPM, via CMake's `ExternalProject`, [doesn't actually do shallow clones of git repositories](https://gitlab.kitware.com/cmake/cmake/-/issues/17770). Instead, it forces fetching all branches, not even just the default branch. That makes cloning the firefox repo take a very very long time :( So instead, we spend 90 lines of lovely CMake script handling the cloning process ourselves ❤️ Signed-off-by: Till Schneidereit --- .gitignore | 2 + cmake/spidermonkey.cmake | 99 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 94 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index a01f0f57..577821a8 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,5 @@ /tests/e2e/*/*.log /tests/integration/*/*.wasm /tests/integration/*/*.log +/deps/.spidermonkey-clone.lock +/deps/spidermonkey-source diff --git a/cmake/spidermonkey.cmake b/cmake/spidermonkey.cmake index 4226bc55..7b656301 100644 --- a/cmake/spidermonkey.cmake +++ b/cmake/spidermonkey.cmake @@ -50,13 +50,98 @@ if (DEFINED SM_LIB_DIR) target_include_directories(spidermonkey INTERFACE ${SM_INCLUDE_DIR}) target_link_libraries(spidermonkey INTERFACE ${SM_LIB_DIR}/libspidermonkey.a) else() - CPMAddPackage(NAME gecko-source - GIT_REPOSITORY "https://github.com/bytecodealliance/firefox.git" - GIT_TAG "${SM_TAG}" - DOWNLOAD_ONLY YES - ) - set(SM_SOURCE_DIR ${CPM_PACKAGE_gecko-source_SOURCE_DIR}) - set(SM_OBJ_DIR ${CMAKE_CURRENT_BINARY_DIR}/spidermonkey) + # Clone SpiderMonkey source using git directly for shallow clone + # Use deps folder in project root for shared access across build directories + set(SM_SOURCE_DIR ${CMAKE_SOURCE_DIR}/deps/spidermonkey-source) + set(SM_LOCK_FILE ${CMAKE_SOURCE_DIR}/deps/.spidermonkey-clone.lock) + + # Use file locking to prevent concurrent clone operations + file(LOCK ${SM_LOCK_FILE}) + + # Check if source directory already exists and has the correct tag + set(NEED_CLONE TRUE) + set(NEED_CHECKOUT FALSE) + + if(EXISTS ${SM_SOURCE_DIR}/.git) + # Check current tag + execute_process( + COMMAND git -C ${SM_SOURCE_DIR} describe --tags --exact-match HEAD + OUTPUT_VARIABLE CURRENT_TAG + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + RESULT_VARIABLE TAG_CHECK_RESULT + ) + + if(TAG_CHECK_RESULT EQUAL 0 AND CURRENT_TAG STREQUAL ${SM_TAG}) + set(NEED_CLONE FALSE) + message(STATUS "SpiderMonkey source already at correct tag ${SM_TAG}") + else() + # Repository exists but wrong tag - fetch and checkout instead of re-cloning + set(NEED_CLONE FALSE) + set(NEED_CHECKOUT TRUE) + message(STATUS "SpiderMonkey source not at correct tag, checking out ${SM_TAG}") + endif() + endif() + + if(NEED_CLONE) + message(STATUS "Cloning SpiderMonkey source at tag ${SM_TAG}") + # Remove existing directory if it exists but isn't a git repo + if(EXISTS ${SM_SOURCE_DIR}) + file(REMOVE_RECURSE ${SM_SOURCE_DIR}) + endif() + + # Perform shallow clone of specific tag + execute_process( + COMMAND git clone --depth 1 --branch ${SM_TAG} + https://github.com/bytecodealliance/firefox.git + ${SM_SOURCE_DIR} + RESULT_VARIABLE CLONE_RESULT + ERROR_VARIABLE CLONE_ERROR + ) + + if(NOT CLONE_RESULT EQUAL 0) + message(FATAL_ERROR "Failed to clone SpiderMonkey source: ${CLONE_ERROR}") + endif() + elseif(NEED_CHECKOUT) + # Check if the tag already exists locally + execute_process( + COMMAND git -C ${SM_SOURCE_DIR} rev-parse --verify "refs/tags/${SM_TAG}" + OUTPUT_QUIET + ERROR_QUIET + RESULT_VARIABLE TAG_EXISTS_RESULT + ) + + if(NOT TAG_EXISTS_RESULT EQUAL 0) + # Tag doesn't exist locally, fetch it + message(STATUS "Fetching tag ${SM_TAG}") + execute_process( + COMMAND git -C ${SM_SOURCE_DIR} fetch --depth 1 origin tag ${SM_TAG} + RESULT_VARIABLE FETCH_RESULT + ERROR_VARIABLE FETCH_ERROR + ) + + if(NOT FETCH_RESULT EQUAL 0) + message(FATAL_ERROR "Failed to fetch tag ${SM_TAG}: ${FETCH_ERROR}") + endif() + endif() + + # Checkout the tag (whether it was already local or just fetched) + execute_process( + COMMAND git -C ${SM_SOURCE_DIR} checkout ${SM_TAG} + RESULT_VARIABLE CHECKOUT_RESULT + ERROR_VARIABLE CHECKOUT_ERROR + ) + + if(NOT CHECKOUT_RESULT EQUAL 0) + message(FATAL_ERROR "Failed to checkout tag ${SM_TAG}: ${CHECKOUT_ERROR}") + endif() + endif() + + # Release the lock + file(LOCK ${SM_LOCK_FILE} RELEASE) + + # Each build configuration gets its own object directory + set(SM_OBJ_DIR ${CMAKE_CURRENT_BINARY_DIR}/spidermonkey-obj) set(SM_LIB_DIR "${SM_OBJ_DIR}/dist") set(SM_INCLUDE_DIR "${SM_LIB_DIR}/include") From 53525d991b8bfd50d6d8986af913d962ab951cee Mon Sep 17 00:00:00 2001 From: Till Schneidereit Date: Sat, 2 Aug 2025 20:57:26 +0200 Subject: [PATCH 05/12] Optimize cloning of WPT repository Same as the Firefox one, this is a very large repo, which takes a long time to clone when done CPM way. This commit generalizes the repo handling used for the SpiderMonkey sources, and applies it to WPT, too. Signed-off-by: Till Schneidereit --- .gitignore | 4 +- cmake/manage-git-source.cmake | 98 +++++++++++++++++++++++++++++++++++ cmake/spidermonkey.cmake | 93 +++------------------------------ tests/wpt-harness/wpt.cmake | 17 +++--- 4 files changed, 119 insertions(+), 93 deletions(-) create mode 100644 cmake/manage-git-source.cmake diff --git a/.gitignore b/.gitignore index 577821a8..827ef5dd 100644 --- a/.gitignore +++ b/.gitignore @@ -28,5 +28,5 @@ /tests/e2e/*/*.log /tests/integration/*/*.wasm /tests/integration/*/*.log -/deps/.spidermonkey-clone.lock -/deps/spidermonkey-source +/deps/*.lock +/deps/*-source diff --git a/cmake/manage-git-source.cmake b/cmake/manage-git-source.cmake new file mode 100644 index 00000000..50cef2c9 --- /dev/null +++ b/cmake/manage-git-source.cmake @@ -0,0 +1,98 @@ +# Function to manage git-based source dependencies with shallow cloning and tag management +function(manage_git_source) + cmake_parse_arguments( + GIT_SRC + "" + "NAME;REPO_URL;TAG;SOURCE_DIR" + "" + ${ARGN} + ) + + if(NOT DEFINED GIT_SRC_NAME OR NOT DEFINED GIT_SRC_REPO_URL OR NOT DEFINED GIT_SRC_TAG OR NOT DEFINED GIT_SRC_SOURCE_DIR) + message(FATAL_ERROR "manage_git_source requires NAME, REPO_URL, TAG, and SOURCE_DIR arguments") + endif() + + set(LOCK_FILE ${CMAKE_SOURCE_DIR}/deps/.${GIT_SRC_NAME}-clone.lock) + + # Use file locking to prevent concurrent clone operations + file(LOCK ${LOCK_FILE} GUARD FUNCTION) + + # Check if source directory already exists and has the correct tag + set(NEED_CLONE TRUE) + set(NEED_CHECKOUT FALSE) + + if(EXISTS ${GIT_SRC_SOURCE_DIR}/.git) + # Check current tag + execute_process( + COMMAND git -C ${GIT_SRC_SOURCE_DIR} describe --tags --exact-match HEAD + OUTPUT_VARIABLE CURRENT_TAG + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + RESULT_VARIABLE TAG_CHECK_RESULT + ) + + if(TAG_CHECK_RESULT EQUAL 0 AND CURRENT_TAG STREQUAL ${GIT_SRC_TAG}) + set(NEED_CLONE FALSE) + message(STATUS "${GIT_SRC_NAME} source already at correct tag ${GIT_SRC_TAG}") + else() + # Repository exists but wrong tag - fetch and checkout instead of re-cloning + set(NEED_CLONE FALSE) + set(NEED_CHECKOUT TRUE) + message(STATUS "${GIT_SRC_NAME} source not at correct tag, checking out ${GIT_SRC_TAG}") + endif() + endif() + + if(NEED_CLONE) + message(STATUS "Cloning ${GIT_SRC_NAME} source at tag ${GIT_SRC_TAG}") + # Remove existing directory if it exists but isn't a git repo + if(EXISTS ${GIT_SRC_SOURCE_DIR}) + file(REMOVE_RECURSE ${GIT_SRC_SOURCE_DIR}) + endif() + + # Perform shallow clone of specific tag + execute_process( + COMMAND git clone --depth 1 --branch ${GIT_SRC_TAG} + ${GIT_SRC_REPO_URL} + ${GIT_SRC_SOURCE_DIR} + RESULT_VARIABLE CLONE_RESULT + ERROR_VARIABLE CLONE_ERROR + ) + + if(NOT CLONE_RESULT EQUAL 0) + message(FATAL_ERROR "Failed to clone ${GIT_SRC_NAME} source: ${CLONE_ERROR}") + endif() + elseif(NEED_CHECKOUT) + # Check if the tag already exists locally + execute_process( + COMMAND git -C ${GIT_SRC_SOURCE_DIR} rev-parse --verify "refs/tags/${GIT_SRC_TAG}" + OUTPUT_QUIET + ERROR_QUIET + RESULT_VARIABLE TAG_EXISTS_RESULT + ) + + if(NOT TAG_EXISTS_RESULT EQUAL 0) + # Tag doesn't exist locally, fetch it + message(STATUS "Fetching tag ${GIT_SRC_TAG}") + execute_process( + COMMAND git -C ${GIT_SRC_SOURCE_DIR} fetch --depth 1 origin tag ${GIT_SRC_TAG} + RESULT_VARIABLE FETCH_RESULT + ERROR_VARIABLE FETCH_ERROR + ) + + if(NOT FETCH_RESULT EQUAL 0) + message(FATAL_ERROR "Failed to fetch tag ${GIT_SRC_TAG}: ${FETCH_ERROR}") + endif() + endif() + + # Checkout the tag (whether it was already local or just fetched) + execute_process( + COMMAND git -C ${GIT_SRC_SOURCE_DIR} checkout ${GIT_SRC_TAG} + RESULT_VARIABLE CHECKOUT_RESULT + ERROR_VARIABLE CHECKOUT_ERROR + ) + + if(NOT CHECKOUT_RESULT EQUAL 0) + message(FATAL_ERROR "Failed to checkout tag ${GIT_SRC_TAG}: ${CHECKOUT_ERROR}") + endif() + endif() +endfunction() diff --git a/cmake/spidermonkey.cmake b/cmake/spidermonkey.cmake index 7b656301..6ee28d68 100644 --- a/cmake/spidermonkey.cmake +++ b/cmake/spidermonkey.cmake @@ -1,5 +1,7 @@ set(SM_TAG FIREFOX_140_0_4_RELEASE_STARLING) +include("manage-git-source") + if (CMAKE_BUILD_TYPE STREQUAL "Debug") set(SM_BUILD_TYPE debug) else() @@ -53,92 +55,13 @@ else() # Clone SpiderMonkey source using git directly for shallow clone # Use deps folder in project root for shared access across build directories set(SM_SOURCE_DIR ${CMAKE_SOURCE_DIR}/deps/spidermonkey-source) - set(SM_LOCK_FILE ${CMAKE_SOURCE_DIR}/deps/.spidermonkey-clone.lock) - - # Use file locking to prevent concurrent clone operations - file(LOCK ${SM_LOCK_FILE}) - - # Check if source directory already exists and has the correct tag - set(NEED_CLONE TRUE) - set(NEED_CHECKOUT FALSE) - - if(EXISTS ${SM_SOURCE_DIR}/.git) - # Check current tag - execute_process( - COMMAND git -C ${SM_SOURCE_DIR} describe --tags --exact-match HEAD - OUTPUT_VARIABLE CURRENT_TAG - OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_QUIET - RESULT_VARIABLE TAG_CHECK_RESULT - ) - - if(TAG_CHECK_RESULT EQUAL 0 AND CURRENT_TAG STREQUAL ${SM_TAG}) - set(NEED_CLONE FALSE) - message(STATUS "SpiderMonkey source already at correct tag ${SM_TAG}") - else() - # Repository exists but wrong tag - fetch and checkout instead of re-cloning - set(NEED_CLONE FALSE) - set(NEED_CHECKOUT TRUE) - message(STATUS "SpiderMonkey source not at correct tag, checking out ${SM_TAG}") - endif() - endif() - - if(NEED_CLONE) - message(STATUS "Cloning SpiderMonkey source at tag ${SM_TAG}") - # Remove existing directory if it exists but isn't a git repo - if(EXISTS ${SM_SOURCE_DIR}) - file(REMOVE_RECURSE ${SM_SOURCE_DIR}) - endif() - - # Perform shallow clone of specific tag - execute_process( - COMMAND git clone --depth 1 --branch ${SM_TAG} - https://github.com/bytecodealliance/firefox.git - ${SM_SOURCE_DIR} - RESULT_VARIABLE CLONE_RESULT - ERROR_VARIABLE CLONE_ERROR - ) - if(NOT CLONE_RESULT EQUAL 0) - message(FATAL_ERROR "Failed to clone SpiderMonkey source: ${CLONE_ERROR}") - endif() - elseif(NEED_CHECKOUT) - # Check if the tag already exists locally - execute_process( - COMMAND git -C ${SM_SOURCE_DIR} rev-parse --verify "refs/tags/${SM_TAG}" - OUTPUT_QUIET - ERROR_QUIET - RESULT_VARIABLE TAG_EXISTS_RESULT - ) - - if(NOT TAG_EXISTS_RESULT EQUAL 0) - # Tag doesn't exist locally, fetch it - message(STATUS "Fetching tag ${SM_TAG}") - execute_process( - COMMAND git -C ${SM_SOURCE_DIR} fetch --depth 1 origin tag ${SM_TAG} - RESULT_VARIABLE FETCH_RESULT - ERROR_VARIABLE FETCH_ERROR - ) - - if(NOT FETCH_RESULT EQUAL 0) - message(FATAL_ERROR "Failed to fetch tag ${SM_TAG}: ${FETCH_ERROR}") - endif() - endif() - - # Checkout the tag (whether it was already local or just fetched) - execute_process( - COMMAND git -C ${SM_SOURCE_DIR} checkout ${SM_TAG} - RESULT_VARIABLE CHECKOUT_RESULT - ERROR_VARIABLE CHECKOUT_ERROR - ) - - if(NOT CHECKOUT_RESULT EQUAL 0) - message(FATAL_ERROR "Failed to checkout tag ${SM_TAG}: ${CHECKOUT_ERROR}") - endif() - endif() - - # Release the lock - file(LOCK ${SM_LOCK_FILE} RELEASE) + manage_git_source( + NAME spidermonkey + REPO_URL https://github.com/bytecodealliance/firefox.git + TAG ${SM_TAG} + SOURCE_DIR ${SM_SOURCE_DIR} + ) # Each build configuration gets its own object directory set(SM_OBJ_DIR ${CMAKE_CURRENT_BINARY_DIR}/spidermonkey-obj) diff --git a/tests/wpt-harness/wpt.cmake b/tests/wpt-harness/wpt.cmake index b5361597..58b67fe5 100644 --- a/tests/wpt-harness/wpt.cmake +++ b/tests/wpt-harness/wpt.cmake @@ -1,7 +1,10 @@ +set(WPT_TAG "epochs/daily/2024-10-02_01H") + enable_testing() include("wasmtime") include("weval") +include("manage-git-source") if(WEVAL) set(COMPONENTIZE_FLAGS "--aot") @@ -12,13 +15,15 @@ endif() if(DEFINED ENV{WPT_ROOT}) set(WPT_ROOT $ENV{WPT_ROOT}) else() - CPMAddPackage( - NAME wpt-suite - GITHUB_REPOSITORY web-platform-tests/wpt - GIT_TAG 04d2e6c42ddce90925d73a076f6cfdd5786e8e54 - DOWNLOAD_ONLY TRUE + # Use deps folder in project root for shared access across build directories + set(WPT_ROOT ${CMAKE_SOURCE_DIR}/deps/wpt-source) + + manage_git_source( + NAME wpt + REPO_URL https://github.com/web-platform-tests/wpt.git + TAG ${WPT_TAG} + SOURCE_DIR ${WPT_ROOT} ) - set(WPT_ROOT ${CPM_PACKAGE_wpt-suite_SOURCE_DIR}) endif() add_builtin(wpt_support From c5dbe0e88322b72f7da2ba07d31fab4bd6339dff Mon Sep 17 00:00:00 2001 From: Till Schneidereit Date: Sat, 2 Aug 2025 10:27:34 +0200 Subject: [PATCH 06/12] Expand the README to explain using starling.wasm and starling-raw.wasm --- README.md | 51 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 87f0676b..3502118f 100644 --- a/README.md +++ b/README.md @@ -71,43 +71,60 @@ cmake -S . -B cmake-build-debug -DCMAKE_BUILD_TYPE=Debug 3. Build the runtime -Building the runtime is done in two phases: first, cmake is used to build a raw version as a -WebAssembly core module. Then, that module is turned into a [WebAssembly Component][wasm-component] -using the `componentize.sh` script generated by the build. +The build system provides two targets for the runtime: `starling-raw.wasm` and `starling.wasm`. The former is a raw WebAssembly core module that can be used to build a WebAssembly Component, while the latter is the final componentized runtime that can be used directly with a WebAssembly Component-aware runtime like [wasmtime](https://wasmtime.dev/). -The following command will build the `starling-raw.wasm` runtime module in the `cmake-build-release` +A key difference is that `starling.wasm` can only be used for runtime-evaluation of JavaScript code, +while `starling-raw.wasm` can be used to build a WebAssembly Component that is specialized for a specific +JavaScript application, and as a result has much faster startup times. + +## Using StarlingMonkey with dynamically loaded JS code + +The following command will build the `starling.wasm` runtime module in the `cmake-build-release` directory: ```console # Use cmake-build-debug for the debug build -# Change the value for `--parallel` to match the number of CPU cores in your system -cmake --build cmake-build-release --parallel 8 +cmake --build cmake-build-release -t starling --parallel $(nproc) ``` -Then, the `starling-raw.wasm` module can be turned into a component with the following command: +The resulting runtime can be used to load and evaluate JS code dynamically: ```console -cd cmake-build-release -./componentize.sh -o starling.wasm +wasmtime -S http cmake-build-release/starling.wasm -e "console.log('hello world')" +# or, to load a file: +wasmtime -S http --dir . starling.wasm index.js ``` -The resulting runtime can be used to load and evaluate JS code dynamically: + +## Creating a specialized runtime for your JS code + +To create a specialized version of the runtime, first build a raw, unspecialized core wasm version of StarlingMonkey: ```console -wasmtime -S http starling.wasm -e "console.log('hello world')" -# or, to load a file: -wasmtime -S http --dir . starling.wasm index.js +# Use cmake-build-debug for the debug build +cmake --build cmake-build-release -t starling-raw.wasm --parallel $(nproc) ``` -Alternatively, a JS file can be provided during componentization: +Then, the `starling-raw.wasm` module can be turned into a component specialized for your code with the following command: ```console cd cmake-build-release -./componentize.sh index.js -o starling.wasm +./componentize.sh index.js -o index.wasm ``` -This way, the JS file will be loaded during componentization, and the top-level code will be -executed, and can e.g. register a handler for the `fetch` event to serve HTTP requests. +This mode currently only supports the creation of HTTP server components, which means that the `index.js` file must register a `fetch` event handler. For example, your `index.js` could contain the following code: + +```javascript +addEventListener('fetch', event => { + event.respondWith(new Response('Hello, world!')); +}); +``` + +Componentizing this code like above allows running it like this: + +```console +wasmtime serve -S cli --dir . index.wasm +``` [cmake]: https://cmake.org/ [gh-pages]: https://bytecodealliance.github.io/StarlingMonkey/ From 13054ac54f8dce7570f94f021cc50163fdfc5adf Mon Sep 17 00:00:00 2001 From: Till Schneidereit Date: Sat, 2 Aug 2025 14:32:48 +0200 Subject: [PATCH 07/12] Update CPM to 0.42.0 Signed-off-by: Till Schneidereit --- CMakeLists.txt | 4 ++++ cmake/CPM.cmake | 25 ++++++++++--------------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fab42bc8..33d7b7dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,10 @@ else() endif() message(STATUS "Using host API: ${HOST_API}") +# Ensure that the CPM cache is created outside the build dir, even if no location is specified by the developer. +if(NOT DEFINED ENV{CPM_SOURCE_CACHE} AND NOT DEFINED CPM_SOURCE_CACHE) + set(CPM_SOURCE_CACHE ${CMAKE_CURRENT_SOURCE_DIR}/deps/cpm_cache) +endif() include("CPM") include("toolchain") diff --git a/cmake/CPM.cmake b/cmake/CPM.cmake index 157aa974..d61eaeea 100644 --- a/cmake/CPM.cmake +++ b/cmake/CPM.cmake @@ -2,28 +2,23 @@ # # SPDX-FileCopyrightText: Copyright (c) 2019-2023 Lars Melchior and contributors -set(CPM_DOWNLOAD_VERSION 0.40.5) -set(CPM_HASH_SUM "c46b876ae3b9f994b4f05a4c15553e0485636862064f1fcc9d8b4f832086bc5d") +set(CPM_DOWNLOAD_VERSION 0.42.0) +set(CPM_HASH_SUM "2020b4fc42dba44817983e06342e682ecfc3d2f484a581f11cc5731fbe4dce8a") -# Ensure that the CPM_SOURCE_CACHE is defined and in sync with ENV{CPM_SOURCE_CACHE} -if (NOT DEFINED CPM_SOURCE_CACHE) - if(DEFINED ENV{CPM_SOURCE_CACHE}) - set(CPM_SOURCE_CACHE $ENV{CPM_SOURCE_CACHE}) - else() - set(CPM_SOURCE_CACHE ${CMAKE_CURRENT_SOURCE_DIR}/deps/cpm_cache) - endif() +if(CPM_SOURCE_CACHE) + set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +elseif(DEFINED ENV{CPM_SOURCE_CACHE}) + set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +else() + set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake") endif() -set(ENV{CPM_SOURCE_CACHE} ${CPM_SOURCE_CACHE}) - -set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") -set(CPM_USE_NAMED_CACHE_DIRECTORIES ON) # Expand relative path. This is important if the provided path contains a tilde (~) get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE) file(DOWNLOAD - https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake - ${CPM_DOWNLOAD_LOCATION} EXPECTED_HASH SHA256=${CPM_HASH_SUM} + https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake + ${CPM_DOWNLOAD_LOCATION} EXPECTED_HASH SHA256=${CPM_HASH_SUM} ) include(${CPM_DOWNLOAD_LOCATION}) From 59df7d3dd77ae775a0c814d153fea20aeb7d30f0 Mon Sep 17 00:00:00 2001 From: Till Schneidereit Date: Sat, 2 Aug 2025 22:48:49 +0200 Subject: [PATCH 08/12] Update OpenSSL to 3.0.17 Good to do, but here mainly done to trigger a re-run of CI. Signed-off-by: Till Schneidereit --- cmake/openssl.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/openssl.cmake b/cmake/openssl.cmake index f69cabb3..23153bec 100644 --- a/cmake/openssl.cmake +++ b/cmake/openssl.cmake @@ -1,6 +1,6 @@ # Based on https://stackoverflow.com/a/72187533 -set(OPENSSL_VERSION 3.0.16) -set(OPENSSL_HASH "SHA256=57e03c50feab5d31b152af2b764f10379aecd8ee92f16c985983ce4a99f7ef86") +set(OPENSSL_VERSION 3.0.17) +set(OPENSSL_HASH "SHA256=dfdd77e4ea1b57ff3a6dbde6b0bdc3f31db5ac99e7fdd4eaf9e1fbb6ec2db8ce") set(OPENSSL_INSTALL_DIR ${CMAKE_BINARY_DIR}/deps/OpenSSL) set(OPENSSL_INCLUDE_DIR ${OPENSSL_INSTALL_DIR}/include) include(ExternalProject) From a2fe8446f6890aa94d77e8d6100a40bc7b295184 Mon Sep 17 00:00:00 2001 From: Till Schneidereit Date: Sat, 2 Aug 2025 19:05:06 +0200 Subject: [PATCH 09/12] Update Binaryen to version 123 Mainly to trigger another build and hopefully see the cached SpiderMonkey build working. Signed-off-by: Till Schneidereit --- cmake/binaryen.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/binaryen.cmake b/cmake/binaryen.cmake index 23c8f07f..dbd20dd1 100644 --- a/cmake/binaryen.cmake +++ b/cmake/binaryen.cmake @@ -1,4 +1,4 @@ -set(BINARYEN_VERSION 117) +set(BINARYEN_VERSION 123) set(BINARYEN_ARCH ${HOST_ARCH}) if(HOST_OS STREQUAL "macos" AND HOST_ARCH STREQUAL "aarch64") From fddc853ff48ab234627bbc8f3be38c3c4d948d67 Mon Sep 17 00:00:00 2001 From: Till Schneidereit Date: Tue, 29 Jul 2025 16:39:26 +0200 Subject: [PATCH 10/12] Ensure that the integration-test-server is rebuilt whenever any of its inputs change --- tests/tests.cmake | 49 +++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/tests/tests.cmake b/tests/tests.cmake index 5416374e..f4f11876 100644 --- a/tests/tests.cmake +++ b/tests/tests.cmake @@ -12,22 +12,35 @@ function(test_e2e TEST_NAME) set_tests_properties(e2e-${TEST_NAME} PROPERTIES TIMEOUT 120) endfunction() -add_custom_target(integration-test-server DEPENDS test-server.wasm) - function(test_integration TEST_NAME) get_target_property(RUNTIME_DIR starling-raw.wasm BINARY_DIR) + add_test(integration-${TEST_NAME} ${BASH_PROGRAM} ${CMAKE_SOURCE_DIR}/tests/test.sh ${RUNTIME_DIR} ${CMAKE_SOURCE_DIR}/tests/integration/${TEST_NAME} test-server.wasm ${TEST_NAME}) + set_property(TEST integration-${TEST_NAME} PROPERTY ENVIRONMENT "WASMTIME=${WASMTIME};WIZER=${WIZER_DIR}/wizer;WASM_TOOLS=${WASM_TOOLS_DIR}/wasm-tools;") + set_tests_properties(integration-${TEST_NAME} PROPERTIES TIMEOUT 120) +endfunction() + +function(integration_tests) + get_target_property(RUNTIME_DIR starling-raw.wasm BINARY_DIR) + set(TESTS_DIR ${CMAKE_SOURCE_DIR}/tests/integration) + set(DEPS ${RUNTIME_DIR}/componentize.sh starling-raw.wasm ${TESTS_DIR}/test-server.js ${TESTS_DIR}/handlers.js + ) + foreach(TEST_NAME ${ARGV}) + list(APPEND DEPS ${TESTS_DIR}/${TEST_NAME}/${TEST_NAME}.js) + endforeach() + add_custom_command( - OUTPUT test-server.wasm - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E env "WASM_TOOLS=${WASM_TOOLS_DIR}/wasm-tools" env "WIZER=${WIZER_DIR}/wizer" env "PREOPEN_DIR=${CMAKE_SOURCE_DIR}/tests" ${RUNTIME_DIR}/componentize.sh ${CMAKE_SOURCE_DIR}/tests/integration/test-server.js test-server.wasm - DEPENDS ${ARG_SOURCES} ${RUNTIME_DIR}/componentize.sh starling-raw.wasm - VERBATIM + OUTPUT test-server.wasm + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E env "WASM_TOOLS=${WASM_TOOLS_DIR}/wasm-tools" env "WIZER=${WIZER_DIR}/wizer" env "PREOPEN_DIR=${CMAKE_SOURCE_DIR}/tests" ${RUNTIME_DIR}/componentize.sh ${TESTS_DIR}/test-server.js test-server.wasm + DEPENDS ${DEPS} + VERBATIM ) + add_custom_target(integration-test-server DEPENDS test-server.wasm) - add_test(integration-${TEST_NAME} ${BASH_PROGRAM} ${CMAKE_SOURCE_DIR}/tests/test.sh ${RUNTIME_DIR} ${CMAKE_SOURCE_DIR}/tests/integration/${TEST_NAME} ${RUNTIME_DIR}/test-server.wasm ${TEST_NAME}) - set_property(TEST integration-${TEST_NAME} PROPERTY ENVIRONMENT "WASMTIME=${WASMTIME};WIZER=${WIZER_DIR}/wizer;WASM_TOOLS=${WASM_TOOLS_DIR}/wasm-tools;") - set_tests_properties(integration-${TEST_NAME} PROPERTIES TIMEOUT 120) + foreach(TEST_NAME ${ARGV}) + test_integration(${TEST_NAME}) + endforeach() endfunction() test_e2e(blob) @@ -44,10 +57,12 @@ test_e2e(multi-stream-forwarding) test_e2e(teed-stream-as-outgoing-body) test_e2e(init-script) -test_integration(blob) -test_integration(btoa) -test_integration(crypto) -test_integration(event) -test_integration(fetch) -test_integration(performance) -test_integration(timers) +integration_tests( + blob + btoa + crypto + event + fetch + performance + timers +) From 30cc3de90510cf3976e35b83ec68302852973618 Mon Sep 17 00:00:00 2001 From: Till Schneidereit Date: Mon, 4 Aug 2025 13:03:53 +0200 Subject: [PATCH 11/12] Release SpiderMonkey build artifacts when landing PRs updating SpiderMonkey This is a lot of yaml code to automate releasing of pre-built SpiderMonkey libraries for all build configs whenever the version of SpiderMonkey used is changed. These releases are done on merge to `main`, and will be picked up automatically by StarlingMonkey's build system. --- .github/workflows/main.yml | 86 +++++++++++++++++++++++++++++++------- cmake/spidermonkey.cmake | 3 +- 2 files changed, 74 insertions(+), 15 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7d7c77ab..d251ec64 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -26,28 +26,44 @@ jobs: matrix: build: [release, debug] os: [ubuntu-latest] + outputs: + SM_TAG_EXISTS: ${{ steps.check-sm-release.outputs.SM_TAG_EXISTS }} + SM_TAG: ${{ steps.check-sm-release.outputs.SM_TAG }} + SM_CACHE_KEY_debug: ${{ steps.check-sm-release.outputs.SM_CACHE_KEY_debug }} + SM_CACHE_KEY_release: ${{ steps.check-sm-release.outputs.SM_CACHE_KEY_release }} runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 - - name: Install Rust 1.88.0 + - name: Check if SpiderMonkey Release Exists + id: check-sm-release run: | - rustup toolchain install 1.88.0 - rustup target add wasm32-wasip1 --toolchain 1.88.0 + SM_TAG="libspidermonkey_$(awk '/^set\(SM_TAG/ {gsub(/set\(SM_TAG |\)/, ""); print}' cmake/spidermonkey.cmake)" + echo "SM_TAG=${SM_TAG}" >> "$GITHUB_OUTPUT" + if gh release view "${SM_TAG}" >/dev/null 2>&1; then + echo "Found existing SpiderMonkey release tag: ${SM_TAG}" + echo "SM_TAG_EXISTS=true" >> "$GITHUB_OUTPUT" + else + echo "SM_TAG_EXISTS=false" >> "$GITHUB_OUTPUT" + echo "SM_CACHE_KEY_${{ matrix.build }}=spidermonkey-cache-${{ matrix.build }}-${{ hashFiles('cmake/spidermonkey.cmake') }}" >> "$GITHUB_OUTPUT" + fi + env: + GH_TOKEN: ${{ github.token }} - name: Cache SpiderMonkey tarball + if: steps.check-sm-release.outputs.SM_TAG_EXISTS == 'false' uses: actions/cache@v4 id: sm-cache with: path: | - spidermonkey-dist + spidermonkey-dist-${{ matrix.build }} key: spidermonkey-cache-${{ matrix.build }}-${{ hashFiles('cmake/spidermonkey.cmake') }} - name: Set env var to use cached SpiderMonkey tarball - if: steps.sm-cache.outputs.cache-hit == 'true' + if: steps.check-sm-release.outputs.SM_TAG_EXISTS == 'false' && steps.sm-cache.outputs.cache-hit == 'true' run: | - tree spidermonkey-dist - echo "SPIDERMONKEY_BINARIES=$(pwd)/spidermonkey-dist" >> $GITHUB_ENV + tree spidermonkey-dist-${{ matrix.build }} + echo "SPIDERMONKEY_BINARIES=$(pwd)/spidermonkey-dist-${{ matrix.build }}" >> $GITHUB_ENV - uses: actions/setup-node@v2 with: @@ -80,19 +96,61 @@ jobs: CTEST_OUTPUT_ON_FAILURE=1 ctest --test-dir cmake-build-${{ matrix.build }} -j$(nproc) --verbose - name: Set up cacheable SpiderMonkey artifacts - if: steps.sm-cache.outputs.cache-hit != 'true' + if: steps.check-sm-release.outputs.SM_TAG_EXISTS == 'false' && steps.sm-cache.outputs.cache-hit != 'true' run: | - mkdir -p spidermonkey-dist - cp -a cmake-build-${{ matrix.build }}/spidermonkey-obj/dist/libspidermonkey.a spidermonkey-dist/ - cp -aL cmake-build-${{ matrix.build }}/spidermonkey-obj/dist/include spidermonkey-dist/ - tree spidermonkey-dist + mkdir -p spidermonkey-dist-${{ matrix.build }} + cp -a cmake-build-${{ matrix.build }}/spidermonkey-obj/dist/libspidermonkey.a spidermonkey-dist-${{ matrix.build }}/ + cp -aL cmake-build-${{ matrix.build }}/spidermonkey-obj/dist/include spidermonkey-dist-${{ matrix.build }}/ + tree spidermonkey-dist-${{ matrix.build }} # Upload tarball as an artifact of the github action run, so the output # can be inspected for pull requests. - name: Upload SpiderMonkey tarball uses: actions/upload-artifact@v4 if: (github.event_name != 'push' || (github.ref != 'refs/heads/main' && !startsWith(github.ref, 'refs/tags/v'))) - && steps.sm-cache.outputs.cache-hit != 'true' + && steps.check-sm-release.outputs.SM_TAG_EXISTS == 'false' && steps.sm-cache.outputs.cache-hit != 'true' with: name: spidermonkey-${{ matrix.build }} - path: spidermonkey-dist/* + path: spidermonkey-dist-${{ matrix.build }}/* + + release-spidermonkey: + needs: test + if: needs.test.outputs.SM_TAG_EXISTS == 'false' && (github.event_name == 'push' && + (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))) + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Restore SpiderMonkey Debug Cache + uses: actions/cache/restore@v4 + id: sm-cache-debug + with: + path: | + spidermonkey-dist-debug + key: ${{ needs.test.outputs.SM_CACHE_KEY_debug }} + fail-on-cache-miss: true + - name: Restore SpiderMonkey Release Cache + uses: actions/cache/restore@v4 + id: sm-cache-release + with: + path: | + spidermonkey-dist-release + key: ${{ needs.test.outputs.SM_CACHE_KEY_release }} + fail-on-cache-miss: true + + - name: Create SpiderMonkey Tar Balls + run: | + mkdir -p release-artifacts + tar -a -cf release-artifacts/spidermonkey-static-debug.tar.gz spidermonkey-dist-debug/* + tar -a -cf release-artifacts/spidermonkey-static-release.tar.gz spidermonkey-dist-release/* + tree release-artifacts + + - name: Do the Release + uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8 #2.3.2 + with: + body: | + This release contains pre-built SpiderMonkey artifacts to be used by the StarlingMonkey + build system. It's not meant for general public consumption and doesn't come with any + stability or availability guarantees. + tag_name: ${{ needs.test.outputs.SM_TAG }} + files: release-artifacts/* diff --git a/cmake/spidermonkey.cmake b/cmake/spidermonkey.cmake index 6ee28d68..838b76f4 100644 --- a/cmake/spidermonkey.cmake +++ b/cmake/spidermonkey.cmake @@ -25,8 +25,9 @@ if (DEFINED ENV{SPIDERMONKEY_BINARIES}) message(STATUS "Using pre-built SpiderMonkey artifacts from local directory ${SM_LIB_DIR}") else() set(SM_URL https://github.com/bytecodealliance/starlingmonkey/releases/download/libspidermonkey_${SM_TAG}/spidermonkey-static-${SM_BUILD_TYPE}.tar.gz) + message(STATUS "Checking for pre-built SpiderMonkey artifacts at ${SM_URL}") execute_process( - COMMAND curl -s -o /dev/null -w "%{http_code}" ${SM_URL} + COMMAND curl -sIL -o /dev/null -w "%{http_code}" ${SM_URL} RESULT_VARIABLE CURL_RESULT OUTPUT_VARIABLE HTTP_STATUS ) From 4f87a57bb4d59873604dd4c1924870137469d320 Mon Sep 17 00:00:00 2001 From: Till Schneidereit Date: Mon, 4 Aug 2025 18:23:15 +0200 Subject: [PATCH 12/12] Fix setting default CPM source cache directory CPM kept overriding this with the helpful value `"OFF"`. No more, CPM, no more. Signed-off-by: Till Schneidereit --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 33d7b7dd..2f24aa77 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,8 +21,8 @@ endif() message(STATUS "Using host API: ${HOST_API}") # Ensure that the CPM cache is created outside the build dir, even if no location is specified by the developer. -if(NOT DEFINED ENV{CPM_SOURCE_CACHE} AND NOT DEFINED CPM_SOURCE_CACHE) - set(CPM_SOURCE_CACHE ${CMAKE_CURRENT_SOURCE_DIR}/deps/cpm_cache) +if(NOT DEFINED ENV{CPM_SOURCE_CACHE}) + set(ENV{CPM_SOURCE_CACHE} ${CMAKE_CURRENT_SOURCE_DIR}/deps/cpm_cache) endif() include("CPM") include("toolchain")