From 1e896871f60255dbbe8925485b733acf3b45111b Mon Sep 17 00:00:00 2001 From: Nis Meinert Date: Wed, 21 Jan 2026 23:45:18 +0100 Subject: [PATCH 1/5] doc: add cargo to list of requirements (#586) During the build step, cargo is needed but this was not listed under requirements. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 932437e..014016d 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ The Wasm-sdk's build process needs some packages : * `clang` * `ninja` * `python3` +* `cargo` Please refer to your OS documentation to install those packages. From 3d4ea12dbee832e92a4734c938fa980395f59da3 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 29 Jan 2026 16:47:40 -0500 Subject: [PATCH 2/5] Update wasi-libc (#584) Removes the `_start` export for the `wasm32-wasip2` target, purging the use of the adapter. --- cmake/wasi-sdk-sysroot.cmake | 1 - src/wasi-libc | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/cmake/wasi-sdk-sysroot.cmake b/cmake/wasi-sdk-sysroot.cmake index 5bd04bb..72088d9 100644 --- a/cmake/wasi-sdk-sysroot.cmake +++ b/cmake/wasi-sdk-sysroot.cmake @@ -173,7 +173,6 @@ function(define_wasi_libc_sub target target_suffix lto) -DCMAKE_C_FLAGS=${extra_cflags} -DBUILTINS_LIB=${libcompiler_rt_a} -DUSE_WASM_COMPONENT_LD=OFF - -DBINDINGS_TARGET=OFF -DWASI_SDK_VERSION=${wasi_sdk_version} DEPENDS compiler-rt EXCLUDE_FROM_ALL ON diff --git a/src/wasi-libc b/src/wasi-libc index 6036a9f..ec0effd 160000 --- a/src/wasi-libc +++ b/src/wasi-libc @@ -1 +1 @@ -Subproject commit 6036a9f3e349315faba2732a32508d5dc9d6d928 +Subproject commit ec0effd769df5f05b647216578bcf5d3b5449725 From 372ba0d2222bcc7fb5e8f032afa36ad896c9d94f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 12 Feb 2026 14:45:31 -0600 Subject: [PATCH 3/5] Add experimental support for C++ exceptions (#590) > **Note**: this PR is me weaving together the work of many others. For example @yerzham's and @cpetig's work on #565 pretty much shaped this PR. Thank you! This commit adds initial configuration support for building wasi-sdk with support for C++ exceptions in WebAssembly. A small test is included which is exercised in CI at this time, but otherwise this does not update CI to actually ship sdk builds with C++ exceptions enabled. Instead the intention here is to make it easier to test builds with support for C++ exceptions and centralize planning/development around this. The goal here is to get things compiling to the point that applications can be compiled. I haven't thoroughly tested C++ exceptions and as evident in this PR it still requires changes in LLVM. Some small logic is added here to apply a `*.patch` file to LLVM to avoid needing a new submodule fork or waiting for upstream changes. The intention is that this `*.patch` is short-lived once the changes are officially merged into LLVM itself. The `*.patch` included here contains llvm/llvm-project#168449 as well as another minor edit I found was necessary to get things compiling locally. Given the discussion on that PR it looks like once LLVM is updated with that merged the extra part of the `*.patch` won't be necessary. This PR notably does not enable shared libraries when exceptions are enabled. I don't know enough about how things are supposed to work to be able to fully diagnose the compilation errors I'm seeing if shared libraries are enabled. This is something I'd hope would be fixed before actually shipping exceptions support. This PR then additionally folds in [this gist][gist] for various bits of build logic to this repository itself. Finally, this PR includes some documentation about the current status of exceptions and links to various tracking issues too. [gist]: https://gist.github.com/yerzham/302efcec6a2e82c1e8de4aed576ea29d --- .github/actions/install-deps/action.yml | 2 +- .github/workflows/main.yml | 11 ++++- CppExceptions.md | 60 +++++++++++++++++++++++++ README.md | 4 ++ cmake/wasi-sdk-sysroot.cmake | 29 ++++++++++-- src/llvm-pr-168449.patch | 28 ++++++++++++ tests/CMakeLists.txt | 18 +++++++- tests/general/exceptions.cc | 17 +++++++ tests/testcase.sh | 2 +- 9 files changed, 162 insertions(+), 9 deletions(-) create mode 100644 CppExceptions.md create mode 100644 src/llvm-pr-168449.patch create mode 100644 tests/general/exceptions.cc diff --git a/.github/actions/install-deps/action.yml b/.github/actions/install-deps/action.yml index 2e4967a..e3d00f8 100644 --- a/.github/actions/install-deps/action.yml +++ b/.github/actions/install-deps/action.yml @@ -7,7 +7,7 @@ runs: - name: Setup `wasmtime` for tests uses: bytecodealliance/actions/wasmtime/setup@v1 with: - version: "29.0.1" + version: "41.0.3" - name: Install ccache, ninja (macOS) run: brew install ccache ninja if: runner.os == 'macOS' diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0e2df4b..8811575 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -155,8 +155,14 @@ jobs: key: 0-cache-${{ matrix.artifact }}-${{ github.run_id }} build-only-sysroot: - name: Build only sysroot + name: Build only sysroot - ${{ matrix.name }} runs-on: ubuntu-24.04 + strategy: + matrix: + include: + - name: default + - name: exceptions + defines: -DWASI_SDK_EXCEPTIONS=ON steps: - uses: actions/checkout@v4 with: @@ -172,7 +178,8 @@ jobs: -DWASI_SDK_INCLUDE_TESTS=ON \ -DWASI_SDK_CPU_CFLAGS="" \ -DCMAKE_C_LINKER_DEPFILE_SUPPORTED=OFF \ - -DCMAKE_CXX_LINKER_DEPFILE_SUPPORTED=OFF + -DCMAKE_CXX_LINKER_DEPFILE_SUPPORTED=OFF \ + ${{ matrix.defines }} - run: ninja -C build - run: ctest --output-on-failure --parallel 10 --test-dir build/tests diff --git a/CppExceptions.md b/CppExceptions.md new file mode 100644 index 0000000..7ea1e2d --- /dev/null +++ b/CppExceptions.md @@ -0,0 +1,60 @@ +# Support for C++ Exceptions + +The released artifacts for wasi-sdk at this time do not support C++ exceptions. +LLVM and Clang, however, have support for C++ exceptions in WebAssembly and this +is intended to serve as documentation of the current state of affairs of using +C++ exceptions. It should be noted though that the current status of C++ +exceptions support is not intended to be the final state of support, and this is +all continuing to be iterated on over time. + +## Building wasi-sdk with exceptions + +When building the sysroot with wasi-sdk you can pass `-DWASI_SDK_EXCEPTIONS=ON` +to enable support for C++ exceptions. For example: + +```shell script +$ cmake -G Ninja -B build/sysroot -S . \ + -DCMAKE_TOOLCHAIN_FILE=$path/to/wasi-sdk-p1.cmake \ + -DWASI_SDK_EXCEPTIONS=ON +``` + +The C++ standard library will be compiled with support for exceptions for the +desired targets and the resulting sysroot supports using exceptions. + +## Compiling code with C++ exceptions + +Currently extra compilation flags are required to fully support C++ exceptions. +Without these flags programs using C++ exceptions will not work correctly: + +* `-fwasm-exceptions` - needed to enable the WebAssembly exception-handling + proposal. +* `-mllvm -wasm-use-legacy-eh=false` - indicates that the standard WebAssembly + exception-handling instructions should be used. +* `-lunwind` - links in support for unwinding which C++ exceptions requires. + +This can be specified for example with: + +```shell script +$ export CFLAGS="-fwasm-exceptions -mllvm -wasm-use-legacy-eh=false" +$ export LDFLAGS="-lunwind" +``` + +## Limitations + +Currently C++ exceptions support in wasi-sdk does not support shared libraries. +Fixing this will require resolving some miscellaneous build issues in this +repository itself. + +## Future Plans + +There are a few tracking issues with historical discussion about C++ exceptions +support in wasi-sdk such as [#334](https://github.com/WebAssembly/wasi-sdk/issues/334) +and [#565](https://github.com/WebAssembly/wasi-sdk/issues/565). The major +remaining items are: + +* Figure out support for shared libraries. +* Determine how to ship a sysroot that supports both with-and-without + exceptions. +* Figure out how to avoid the need for extra compiler flags when using + exceptions. +* Figure out if a new wasm target is warranted. diff --git a/README.md b/README.md index 014016d..97bb4f5 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,10 @@ in compiling WebAssembly code. Supported CMake flags are: * `-DWASI_SDK_INCLUDE_TESTS=ON` - used for building tests. * `-DWASI_SDK_CPU_CFLAGS=..` - used to specify CFLAGS to tweak wasm features to enable/disable. The default is `-mcpu=lime1`. +* `-DWASI_SDK_LTO=ON` - whether to enable/disable builds of LTO-capable + libraries as part of the build. +* `-DWASI_SDK_EXCEPTIONS=ON` - whether to enable/disable support for C++ + exceptions, see [CppExceptions.md](./CppExceptions.md) for more information. * `-DWASI_SDK_TEST_HOST_TOOLCHAIN=ON` - test the host toolchain's wasi-libc and sysroot libraries, don't build or use fresh libraries for tests. * `-DWASI_SDK_TARGETS=..` - a list of targets to build, by default all WASI diff --git a/cmake/wasi-sdk-sysroot.cmake b/cmake/wasi-sdk-sysroot.cmake index 72088d9..7be2a18 100644 --- a/cmake/wasi-sdk-sysroot.cmake +++ b/cmake/wasi-sdk-sysroot.cmake @@ -24,6 +24,7 @@ option(WASI_SDK_DEBUG_PREFIX_MAP "Pass `-fdebug-prefix-map` for built artifacts" option(WASI_SDK_INCLUDE_TESTS "Whether or not to build tests by default" OFF) option(WASI_SDK_INSTALL_TO_CLANG_RESOURCE_DIR "Whether or not to modify the compiler's resource directory" OFF) option(WASI_SDK_LTO "Whether or not to build LTO assets" ON) +option(WASI_SDK_EXCEPTIONS "Whether or not C++ exceptions are enabled" OFF) set(WASI_SDK_CPU_CFLAGS "-mcpu=lime1" CACHE STRING "CFLAGS to specify wasm features to enable") set(wasi_tmp_install ${CMAKE_CURRENT_BINARY_DIR}/install) @@ -89,6 +90,8 @@ function(define_compiler_rt target) -DCOMPILER_RT_BUILD_GWP_ASAN=OFF -DCMAKE_C_COMPILER_TARGET=${target} -DCMAKE_C_FLAGS=${WASI_SDK_CPU_CFLAGS} + -DCMAKE_CXX_FLAGS=${WASI_SDK_CPU_CFLAGS} + -DCMAKE_ASM_FLAGS=${WASI_SDK_CPU_CFLAGS} -DCMAKE_INSTALL_PREFIX=${wasi_resource_dir} EXCLUDE_FROM_ALL ON USES_TERMINAL_CONFIGURE ON @@ -231,6 +234,17 @@ function(define_libcxx_sub target target_suffix extra_target_flags extra_libdir_ --sysroot ${wasi_sysroot} -resource-dir ${wasi_resource_dir}) + if (WASI_SDK_EXCEPTIONS) + # TODO: lots of builds fail with shared libraries and `-fPIC`. Looks like + # things are maybe changing in llvm/llvm-project#159143 but otherwise I'm at + # least not really sure what the state of shared libraries and exceptions + # are. For now shared libraries are disabled and supporting them is left for + # a future endeavor. + set(pic OFF) + set(runtimes "libunwind;${runtimes}") + list(APPEND extra_flags -fwasm-exceptions -mllvm -wasm-use-legacy-eh=false) + endif() + set(extra_cflags_list ${CMAKE_C_FLAGS} ${extra_flags}) list(JOIN extra_cflags_list " " extra_cflags) set(extra_cxxflags_list ${CMAKE_CXX_FLAGS} ${extra_flags}) @@ -254,14 +268,14 @@ function(define_libcxx_sub target target_suffix extra_target_flags extra_libdir_ -DLLVM_COMPILER_CHECKED=ON -DLIBCXX_ENABLE_SHARED:BOOL=${pic} -DLIBCXX_ENABLE_EXPERIMENTAL_LIBRARY:BOOL=OFF - -DLIBCXX_ENABLE_EXCEPTIONS:BOOL=OFF + -DLIBCXX_ENABLE_EXCEPTIONS:BOOL=${WASI_SDK_EXCEPTIONS} -DLIBCXX_ENABLE_FILESYSTEM:BOOL=ON -DLIBCXX_ENABLE_ABI_LINKER_SCRIPT:BOOL=OFF -DLIBCXX_CXX_ABI=libcxxabi -DLIBCXX_CXX_ABI_INCLUDE_PATHS=${llvm_proj_dir}/libcxxabi/include -DLIBCXX_HAS_MUSL_LIBC:BOOL=ON -DLIBCXX_ABI_VERSION=2 - -DLIBCXXABI_ENABLE_EXCEPTIONS:BOOL=OFF + -DLIBCXXABI_ENABLE_EXCEPTIONS:BOOL=${WASI_SDK_EXCEPTIONS} -DLIBCXXABI_ENABLE_SHARED:BOOL=${pic} -DLIBCXXABI_SILENT_TERMINATE:BOOL=ON -DLIBCXXABI_ENABLE_THREADS:BOOL=ON @@ -270,12 +284,18 @@ function(define_libcxx_sub target target_suffix extra_target_flags extra_libdir_ -DLIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY:BOOL=OFF -DLIBCXXABI_HAS_WIN32_THREAD_API:BOOL=OFF -DLIBCXXABI_ENABLE_PIC:BOOL=${pic} - -DLIBCXXABI_USE_LLVM_UNWINDER:BOOL=OFF + -DLIBCXXABI_USE_LLVM_UNWINDER:BOOL=${WASI_SDK_EXCEPTIONS} + -DLIBUNWIND_ENABLE_SHARED:BOOL=${pic} + -DLIBUNWIND_ENABLE_THREADS:BOOL=ON + -DLIBUNWIND_USE_COMPILER_RT:BOOL=ON + -DLIBUNWIND_INCLUDE_TESTS:BOOL=OFF -DUNIX:BOOL=ON -DCMAKE_C_FLAGS=${extra_cflags} + -DCMAKE_ASM_FLAGS=${extra_cflags} -DCMAKE_CXX_FLAGS=${extra_cxxflags} -DLIBCXX_LIBDIR_SUFFIX=/${target}${extra_libdir_suffix} -DLIBCXXABI_LIBDIR_SUFFIX=/${target}${extra_libdir_suffix} + -DLIBUNWIND_LIBDIR_SUFFIX=/${target}${extra_libdir_suffix} -DLIBCXX_INCLUDE_TESTS=OFF -DLIBCXX_INCLUDE_BENCHMARKS=OFF @@ -290,6 +310,9 @@ function(define_libcxx_sub target target_suffix extra_target_flags extra_libdir_ USES_TERMINAL_CONFIGURE ON USES_TERMINAL_BUILD ON USES_TERMINAL_INSTALL ON + PATCH_COMMAND + ${CMAKE_COMMAND} -E chdir .. bash -c + "git apply ${CMAKE_SOURCE_DIR}/src/llvm-pr-168449.patch || git apply ${CMAKE_SOURCE_DIR}/src/llvm-pr-168449.patch -R --check" ) endfunction() diff --git a/src/llvm-pr-168449.patch b/src/llvm-pr-168449.patch new file mode 100644 index 0000000..a0da1d8 --- /dev/null +++ b/src/llvm-pr-168449.patch @@ -0,0 +1,28 @@ +diff --git a/libunwind/src/assembly.h b/libunwind/src/assembly.h +index f8e83e138eff..c5097d25b0c6 100644 +--- a/libunwind/src/assembly.h ++++ b/libunwind/src/assembly.h +@@ -249,6 +249,9 @@ aliasname: \ + #define WEAK_ALIAS(name, aliasname) + #define NO_EXEC_STACK_DIRECTIVE + ++#elif defined(__wasm__) ++#define NO_EXEC_STACK_DIRECTIVE ++ + // clang-format on + #else + +diff --git a/libunwind/src/config.h b/libunwind/src/config.h +index deb5a4d4d73d..23c9f012cbcf 100644 +--- a/libunwind/src/config.h ++++ b/libunwind/src/config.h +@@ -66,7 +66,8 @@ + #define _LIBUNWIND_EXPORT + #define _LIBUNWIND_HIDDEN + #else +- #if !defined(__ELF__) && !defined(__MACH__) && !defined(_AIX) ++ #if !defined(__ELF__) && !defined(__MACH__) && !defined(_AIX) && \ ++ !defined(__wasm__) + #define _LIBUNWIND_EXPORT __declspec(dllexport) + #define _LIBUNWIND_HIDDEN + #else diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index edbb129..a213392 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -67,7 +67,12 @@ function(add_testcase runwasi test) # Apply language-specific options and dependencies. if(test MATCHES "cc$") - target_compile_options(${target_name} PRIVATE -fno-exceptions) + if(WASI_SDK_EXCEPTIONS) + target_compile_options(${target_name} PRIVATE -fwasm-exceptions -mllvm -wasm-use-legacy-eh=false) + target_link_options(${target_name} PRIVATE -lunwind) + else() + target_compile_options(${target_name} PRIVATE -fno-exceptions) + endif() if(NOT WASI_SDK_TEST_HOST_TOOLCHAIN) add_dependencies(${target_name} libcxx-${target}) endif() @@ -84,11 +89,20 @@ function(add_testcase runwasi test) endif() if(runwasi) + set(runner ${runwasi}) + if(${runner} MATCHES wasmtime) + if(target MATCHES threads) + set(runner "${runner} -Wshared-memory") + endif() + if(WASI_SDK_EXCEPTIONS) + set(runner "${runner} -Wexceptions") + endif() + endif() add_test( NAME test-${target_name} COMMAND bash ../testcase.sh - "${runwasi}" + ${runner} ${test} $ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/tests/general/exceptions.cc b/tests/general/exceptions.cc new file mode 100644 index 0000000..3daed98 --- /dev/null +++ b/tests/general/exceptions.cc @@ -0,0 +1,17 @@ +#include +#include + +int main() { +#ifdef __wasm_exception_handling__ + try { + throw std::runtime_error("An error occurred"); + abort(); + } catch (const std::runtime_error& e) { + // .. + return 0; + } + abort(); +#else + return 0; +#endif +} diff --git a/tests/testcase.sh b/tests/testcase.sh index 551eec3..d2c5a8c 100755 --- a/tests/testcase.sh +++ b/tests/testcase.sh @@ -46,7 +46,7 @@ fi # Run the test, capturing stdout, stderr, and the exit status. exit_status=0 -"$runwasi" $env $dir "$wasm" $dirarg \ +$runwasi $env $dir "$wasm" $dirarg \ < "$stdin" \ > "$stdout_observed" \ 2> "$stderr_observed" \ From 1033443e5c3696389c66157877d0e1a491bd43fc Mon Sep 17 00:00:00 2001 From: Roman Volosatovs Date: Fri, 13 Feb 2026 16:11:24 +0100 Subject: [PATCH 4/5] Update `wasm-component-ld` in CI (#592) Use latest `wasm-component-ld` in CI Signed-off-by: Roman Volosatovs --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8811575..f420121 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -169,7 +169,7 @@ jobs: fetch-depth: 0 - uses: ./.github/actions/checkout - uses: ./.github/actions/install-deps - - run: cargo install wasm-component-ld@0.5.12 + - run: cargo install wasm-component-ld@0.5.20 - run: sudo apt-get update -y && sudo apt-get install -y clang-20 lld-20 - run: | cmake -G Ninja -B build -S . \ From a64d51d14378e306add001fad180d5733df1491c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 23 Feb 2026 12:11:22 -0600 Subject: [PATCH 5/5] Update wasm-component-ld (#594) Keeping it up-to-date --- .github/workflows/main.yml | 2 +- cmake/wasi-sdk-toolchain.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f420121..9b39e65 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -169,7 +169,7 @@ jobs: fetch-depth: 0 - uses: ./.github/actions/checkout - uses: ./.github/actions/install-deps - - run: cargo install wasm-component-ld@0.5.20 + - run: cargo install wasm-component-ld@0.5.21 - run: sudo apt-get update -y && sudo apt-get install -y clang-20 lld-20 - run: | cmake -G Ninja -B build -S . \ diff --git a/cmake/wasi-sdk-toolchain.cmake b/cmake/wasi-sdk-toolchain.cmake index fa972b9..c02560d 100644 --- a/cmake/wasi-sdk-toolchain.cmake +++ b/cmake/wasi-sdk-toolchain.cmake @@ -119,7 +119,7 @@ install(DIRECTORY ${wasi_tmp_install}/bin ${wasi_tmp_install}/lib ${wasi_tmp_ins # Build logic for `wasm-component-ld` installed from Rust code. set(wasm_component_ld_root ${CMAKE_CURRENT_BINARY_DIR}/wasm-component-ld) set(wasm_component_ld ${wasm_component_ld_root}/bin/wasm-component-ld${CMAKE_EXECUTABLE_SUFFIX}) -set(wasm_component_ld_version 0.5.20) +set(wasm_component_ld_version 0.5.21) if(RUST_TARGET) set(rust_target_flag --target=${RUST_TARGET}) endif()