WASI SDK

repository·main·Indexed 23 days ago

https://github.com/webassembly/wasi-sdk

A pre-configured toolchain consisting of Clang, LLVM, and wasi-libc optimized for compiling C and C++ code to WebAssembly using the WebAssembly System Interface (WASI). It includes documentation on installation via binaries or Docker, building from source, CMake integration, and configuring advanced features such as C++ exceptions and setjmp/longjmp support.

Tokens
2.7K
Snippets
9
Records
13
Agent score
72%

What's inside wasi-sdk

  1. WASI SDK Limitations and Compatibility

    main

    When developing with WASI SDK, be aware of the following constraints:

    • C++ Exceptions: Disabled by default. Requires extra configuration.
    • setjmp/longjmp: Requires extra configuration.
    • Threading: Most targets do not support spawning threads. Experimental support is available via the wasm32-wasip1-threads target (using wasi-threads).
      • The pthread_* family and C++ primitives (<atomic>, <mutex>, <thread>) are available on all targets.
      • To catch errors when building for single-threaded targets, define the macro _WASI_STRICT_PTHREAD to make threading functions fail at compile time.
    • Dynamic Linking: Supported, but less mature than static linking; may contain obscure bugs.
    • Networking: WASIp1 targets do not support networking. WASIp2/WASIp3 support networking.
    • 64-bit Memory: wasm64 targets are not currently supported.
  2. Use WASI SDK via Docker

    main

    You can use the official WASI SDK Docker image to build projects without a local installation. The image includes Autotools, CMake, and Ninja, and sets standard environment variables for the SDK.

    To build a make-based project:

    docker run -v `pwd`:/src -w /src ghcr.io/webassembly/wasi-sdk make

    Note: Many projects may require disabling threads in their configure step to work with WASI SDK.

  3. Integrate WASI SDK with CMake

    main

    When using CMake, you can set up the WASI SDK platform by passing the CMAKE_TOOLCHAIN_FILE variable pointing to the appropriate .cmake file in the SDK's share/cmake/ directory.

    For the standard platform:

    cmake -DCMAKE_TOOLCHAIN_FILE=${WASI_SDK_PATH}/share/cmake/wasi-sdk.cmake ...

    For the platform with thread support (wasi-sdk-thread):

    cmake -DCMAKE_TOOLCHAIN_FILE=${WASI_SDK_PATH}/share/cmake/wasi-sdk-pthread.cmake ...
    $ cmake -DCMAKE_TOOLCHAIN_FILE=${WASI_SDK_PATH}/share/cmake/wasi-sdk.cmake ...
    
    $ cmake -DCMAKE_TOOLCHAIN_FILE=${WASI_SDK_PATH}/share/cmake/wasi-sdk-pthread.cmake ...
  4. Compile C++ code with exceptions enabled

    main

    Starting from wasi-sdk-33, the sysroot contains two copies of the C++ standard library: one with exceptions enabled and one with exceptions disabled. By default, exceptions are disabled. To enable C++ exceptions, you must provide specific compilation and linking flags to ensure the correct standard library is selected and WebAssembly exception-handling instructions are used.

    Required flags:

    • -fwasm-exceptions: Enables the WebAssembly exception-handling proposal and selects the correct C++ standard library during linking.
    • -mllvm -wasm-use-legacy-eh=false: Forces the use of standard WebAssembly exception-handling instructions instead of the legacy proposal.
    • -lunwind: Links the unwinding support required for C++ exceptions.
    $ export CFLAGS="-fwasm-exceptions -mllvm -wasm-use-legacy-eh=false"
    $ export LDFLAGS="-fwasm-exceptions -lunwind"
  5. Build WASI SDK from source

    main

    Building the SDK is a two-step process using CMake and Ninja.

    1. Build the toolchain

    First, build the Clang/LLVM toolchain components:

    cmake -G Ninja -B build/toolchain -S . -DWASI_SDK_BUILD_TOOLCHAIN=ON -DCMAKE_INSTALL_PREFIX=build/install
    cmake --build build/toolchain --target install

    2. Build the sysroot

    Next, build the sysroot using the toolchain just created:

    cmake -G Ninja -B build/sysroot -S . \
        -DCMAKE_INSTALL_PREFIX=build/install \
        -DCMAKE_TOOLCHAIN_FILE=build/install/share/cmake/wasi-sdk-p2.cmake \
        -DCMAKE_C_COMPILER_WORKS=ON \
        -DCMAKE_CXX_COMPILER_WORKS=ON
    cmake --build build/sysroot --target install
    # Build toolchain
    cmake -G Ninja -B build/toolchain -S . -DWASI_SDK_BUILD_TOOLCHAIN=ON -DCMAKE_INSTALL_PREFIX=build/install
    cmake --build build/toolchain --target install
    
    # Build sysroot
    cmake -G Ninja -B build/sysroot -S . \
        -DCMAKE_INSTALL_PREFIX=build/install \
        -DCMAKE_TOOLCHAIN_FILE=build/install/share/cmake/wasi-sdk-p2.cmake \
        -DCMAKE_C_COMPILER_WORKS=ON \
        -DCMAKE_CXX_COMPILER_WORKS=ON
    cmake --build build/sysroot --target install
  6. Build wasi-sdk sysroot with exception support

    main

    When building the wasi-sdk sysroot from source, you can enable support for C++ exceptions by passing the -DWASI_SDK_EXCEPTIONS=ON CMake flag. This compiles the C++ standard library with exception support for the target architectures.

    Requirement: Enabling C++ exceptions requires LLVM 22 or later.

    $ cmake -G Ninja -B build/sysroot -S . \
        -DCMAKE_TOOLCHAIN_FILE=$path/to/wasi-sdk-p1.cmake \
        -DWASI_SDK_EXCEPTIONS=ON
  7. Install WASI SDK from release binaries

    main

    To install the WASI SDK, download the appropriate tarball from the GitHub releases page based on your OS and architecture, then extract it.

    Example for Linux x86_64 (version 27):

    WASI_OS=linux
    WASI_ARCH=x86_64 # or 'arm64' if running on arm64 host
    WASI_VERSION=27
    WASI_VERSION_FULL=${WASI_VERSION}.0
    wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_VERSION}/wasi-sdk-${WASI_VERSION_FULL}-${WASI_ARCH}-${WASI_OS}.tar.gz
    tar xvf wasi-sdk-${WASI_VERSION_FULL}-${WASI_ARCH}-${WASI_OS}.tar.gz
  8. Enable C setjmp/longjmp support in WASI-SDK

    main

    To use setjmp and longjmp in your WebAssembly applications, you must provide specific compiler and linker flags. WASI-SDK implements this by using a compiler pass that replaces setjmp calls with a specialized implementation provided by wasi-libc via the -lsetjmp library.

    By default, the compiler emits legacy exception-handling instructions. To use the modern WebAssembly exception-handling specification (Phase 5), you must explicitly set -mllvm -wasm-use-legacy-eh=false.

  9. Known limitations of C++ exceptions in wasi-sdk

    main

    Users of C++ exceptions in wasi-sdk should be aware of the following current limitations:

    • No Shared Libraries: C++ exception support does not currently work with shared libraries.
    • Flag Requirements: -fwasm-exceptions is strictly required to enable exceptions; -fexceptions is not currently a supported substitute.
    • Unwinding Linkage: -lunwind must be explicitly passed during the linking stage.
    • LTO Conflict: There is a known issue where exceptions and Link Time Optimization (LTO) may not work together. See issue #629 for details.
  10. Compile setjmp/longjmp with LTO

    main

    When using Link Time Optimization (-flto=full), you must pass the -mllvm flags to both the compiler and the linker. This ensures the setjmp transformation and exception-handling instruction selection are correctly applied during the linking stage.

    clang -Os -flto=full -o test.wasm test.c \
        -mllvm -wasm-enable-sjlj -lsetjmp -mllvm -wasm-use-legacy-eh=false \
        -Wl,-mllvm,-wasm-enable-sjlj,-mllvm,-wasm-use-legacy-eh=false
  11. Compile C code using WASI SDK clang

    main

    To compile code, use the clang binary located in the bin directory of your WASI SDK installation. You must specify the --sysroot pointing to the share/wasi-sysroot directory within the SDK.

    Note: If the SDK is installed at /opt/wasi-sdk, the --sysroot flag is not required.

    WASI_SDK_PATH=`pwd`/wasi-sdk-${WASI_VERSION_FULL}-${WASI_ARCH}-${WASI_OS}
    CC="${WASI_SDK_PATH}/bin/clang --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot"
    $CC foo.c -o foo.wasm
  12. Configure WASI SDK build options

    main

    When building the WASI SDK from source, the following CMake flags are available:

    FlagDescription
    -DWASI_SDK_DEBUG_PREFIX_MAKESet to OFF to disable -fdebug-prefix-map (uses full host paths instead)
    -DWASI_SDK_INCLUDE_TESTSSet to ON to build tests
    -DWASI_SDK_CPU_CFLAGSSpecify CFLAGS to tweak WASM features (default: -mcpu=lime1)
    -DWASI_SDK_LTOEnable/disable builds of LTO-capable libraries
    -DWASI_SDK_BUILD_SHAREDSet to ON to build shared libraries (libc.so, libc++.so), or OFF for static-only
    -DWASI_SDK_EXCEPTIONSEnable/disable support for C++ exceptions
    -DWASI_SDK_TEST_HOST_TOOLCHAINTest host toolchain's libraries without building fresh ones
    -DWASI_SDK_TARGETSList of targets to build
    -DWASI_SDK_INSTALL_TO_CLANG_RESOURCE_DIRInstall compiler-rt to the compiler's resource directory
    -DLLVM_CMAKE_FLAGSExtra flags for building LLVM/Clang
    -DRUST_TARGETSpecific Rust target triple for wasm-component-ld