wasixcc is a clang wrapper designed to simplify compilation for the WASIX platform.
It provides a convenient interface to configure and invoke the LLVM toolchain with appropriate
flags for the WASIX platform.
- Easy configuration of WASIX compilation parameters
- Automatic sysroot management
- Support for both C and C++ compilation
- Flexible flag management for compiler and linker
- Integration with wasm-opt for optimization
- Support for various module types
- Static, dynamic, shared libraries
- Exception handling, asyncify
curl -fsSL https://wasix.cc | shThe installer will install wasixcc and its dependencies to ~/.wasixcc
Other installation options
If you don't use the installer (or the github action)
-
From crates.io (macOS, Linux)
cargo install wasixcc # Install executables sudo wasixccenv install-executables /usr/local/bin # Download the latest LLVM toolchain, WASIX sysroot, and wasm-opt wasixccenv download-all
-
cargo binstall wasixcc # Install executables sudo wasixccenv install-executables /usr/local/bin # Download the latest LLVM toolchain, WASIX sysroot, and wasm-opt wasixccenv download-all
-
Directly from the git repo
git clone https://github.com/wasix-org/wasixcc cd wasixcc cargo build -r # Install executables sudo ./target/release/wasixccenv install-executables /usr/local/bin # Download the latest LLVM toolchain, WASIX sysroot, and wasm-opt wasixccenv download-all
To use wasixcc in your GitHub Action use the following snippet
- name: Install wasixcc
uses: wasix-org/wasixcc@mainThis will setup wasixcc and all dependencies in less than 10 seconds.
Environment management commands are available from the wasixccenv binary.
Run wasixccenv --help for comprehensive usage instructions.
To use the compiler toolchain, first run wasixccenv install-executables and
then run the correct tool (wasixcc, wasixar, etc.).
| Option | Description |
|---|---|
-h, --help |
Print help message |
-v, --version |
Print version information |
install-executables <PATH> |
Install executables to specified path |
download-sysroot <TAG> |
Download and install WASIX libc sysroot ('latest' or specific tag) |
download-llvm <TAG> |
Download and install LLVM toolchain ('latest' or specific tag) |
download-all |
Download and install the latest sysroot and LLVM toolchain |
print-sysroot |
Print current sysroot location |
-s[CONFIG]=[VALUE] |
Set configuration values (see below) |
Configuration can be set via command line (-s flag) or environment variables (WASIXCC_ prefix).
You can run wasixccenv help-config to see detailed explanation of each flag and what it does. A
summary is provided here for reference:
| Option | Description |
|---|---|
SYSROOT |
Set the sysroot location - not recommended, use SYSROOT_PREFIX instead where possible |
SYSROOT_PREFIX |
Set the sysroot prefix directory |
LLVM_LOCATION |
Set location of LLVM binaries |
BINARYEN_LOCATION |
Set location of wasm-opt |
COMPILER_FLAGS |
Extra compiler flags (colon-separated) |
COMPILER_POST_FLAGS |
Extra compiler flags (after command line args) |
COMPILER_FLAGS_C |
C-specific compiler flags |
COMPILER_POST_FLAGS_C |
C-specific post compiler flags |
COMPILER_FLAGS_CXX |
C++-specific compiler flags |
COMPILER_POST_FLAGS_CXX |
C++-specific post compiler flags |
LINKER_FLAGS |
Extra linker flags |
INCLUDE_CPP_SYMBOLS |
Whether to also link libc++, libc++abi and libunwind into C binaries |
RUN_WASM_OPT |
Whether to run wasm-opt |
WASM_OPT_FLAGS |
Extra wasm-opt flags |
WASM_OPT_SUPPRESS_DEFAULT |
Suppress default wasm-opt flags |
WASM_OPT_PRESERVE_UNOPTIMIZED |
Whether to preserve the unoptimized binary in a temp directory |
MODULE_KIND |
Module type (static-main, dynamic-main, shared-library, object-file) |
WASM_EXCEPTIONS |
Enable WASM exception handling. (yes, no, legacy, exnref) |
PIC |
Enable position-independent code |
LINK_SYMBOLIC |
Enable -Bsymbolic linking (enabled by default) |
GENERATE_SHELL_SCRIPT |
Generate a shell script for running the resulting WASM binary as if it was a native executable |
SHELL_SCRIPT_WASMER_ARGS |
Specify wasmer args for running the WASM binary in the shell script |
DISCARD_UNSUPPORTED_FLAGS |
Some flags that you would use with native tools don't work when targeting WASIX. Discard them. |
AUTOCONF_WORKAROUNDS |
Attempt to detect autoconf tests and make them work as intended. |
All configuration options can be set via environment variables by prefixing them with WASIXCC_:
export WASIXCC_SYSROOT=/custom/sysroot
export WASIXCC_COMPILER_FLAGS="-O2"
wasixcc program.c -o program.wasmThis is useful when wasixcc is integrated into build systems where you don't control the CLI invocation
directly, such as when running through CMake.
-
Compile a simple C program:
wasixcc hello.c -o hello.wasm
-
Compile a simple C++ program:
wasix++ hello.cpp -o program.wasm
-
Compile with custom sysroot:
wasixcc -sSYSROOT=/path/to/sysroot program.c -o program.wasm
-
Compile with custom flags:
export WASIXCC_COMPILER_FLAGS="-O3" # ... a lot of other code ... wasixcc app.c -o app.wasm
wasixcc supports 3 primary build configurations. The configurations are mainly
differentiated based on where they can run and what language features they support,
and how setjmp/longjmp is handled.
-
The default configuration; this configuration can run anywhere, but relies on
asyncifyforsetjmp/longjmpsupport.asyncifyhas considerable performance implications, and should be avoided where possible. Support for C++ exceptions in this configuration has not been tested, and it is likely to be broken. -
The EH configuration uses the WASM Exception Handling Proposal to support
setjmp/longjmp. This configuration can only run on EH-enabled WASM runtimes, including Wasmer's LLVM backend and browsers. However, it is considerably faster than the default configuration due to avoidingasyncify. C++ exceptions are also fully supported in this mode.To enable this mode, run
wasixccwith-sWASM_EXCEPTIIONS=yes. -
The EH+PIC configuration uses the EH proposal similarly to the EH configuration, but also enables Position-Independent Code. In the WASM world, PIC is only useful for dynamic linking scenarios, so you should avoid this configuration unless you require support for
dlopen/dlsym.To enable this mode, run
wasixccwith-sWASM_EXCEPTIONS=yes -sPIC=yes.
If you need support for dynamic linking, you need to use the EH+PIC configuration
for the main module and all side modules. The usual clang flags work here; just
passing -shared will give you a DL side module, a.k.a. a
dynamically-linked library.
However, there is one caveat: native binaries generally link against libc
dynamically at runtime, with libc being provided by the OS. Since there is
no concept of an OS in wasm, the approach is slightly different; the main
module is expected to embed all libc/libc++ symbols and make them available
to side modules.
To enable this behavior in wasixcc, you may need to explicitly set the module
kind to dynamic-main by passing -sMODULE_KIND=dynamic-main.
wasixcc can be integrated into different build systems to adapt existing
software to the WASIX platform.
To use wasixcc with Autotools, simply replace the default LLVM tools with the
wasixcc equivalent.
wasixcc runs wasm-opt to generate working output modules by default, but this
can break compilation tests, so it is recommended to disable wasm-opt during
configuration:
# Set up wasixcc's settings
export WASIXCC_XXX=YYY
# Replace default tools with wasixcc equivalents
export \
CC=wasixcc \
CXX=wasix++ \
LD=wasixld \
AR=wasixar \
NM=wasixnm \
RANLIB=wasixranlib \
# The way configure detects functions is not compatible with wasm.
# Enable detection and automatic workarounds for that.
WASIXCC_AUTOCONF_WORKAROUNDS=yes ./configure ...
make ...To use wasixcc with CMake, you can use the
toolchain file in this repository:
# First, set up wasixcc settings for the build. This is important
# because the build settings influence the sysroot location.
export WASIXCC_XXX=YYY
# wasix-toolchain.cmake references this variable
export WASIX_SYSROOT=$(wasixccenv print-sysroot)
# Disable wasm-opt during configuration...
WASIXCC_RUN_WASM_OPT=no \
cmake ... -DCMAKE_TOOLCHAIN_FILE=wasix-toolchain.cmake
# ... but make sure to enable it again during the build
cmake --build ...Contributions are welcome! Please feel free to open a PR if there's something you feel can be improved.
make build # cargo build --release --locked
make test # cargo test --locked
make fmt # cargo fmt --checkwasixcc is also published to the Wasmer registry as wasmer/wasixcc, a
wasm32-wasmer-wasi module that runs inside Wasmer alongside wasmer/clang.
That build resolves its dependencies through the WASIX overlay registry, which
serves X.Y.Z+wasix.N forks of the crates that need patching to link for
WASIX:
make wasix # build the module (needs cargo-wasix)
make wasix-test # run the test suite as a WASIX module (needs wasmer)
make wasix-update # re-resolve and refresh Cargo.wasix.lock
make wasix-package # build and stage the module for `wasmer publish`The overlay config lives in wasix/registry.toml and is passed explicitly with
cargo --config. Never place it at .cargo/config.toml, and never commit
such a file. Cargo auto-discovers that path for every invocation, so the
overlay would apply to native builds too, and source replacement records the
replaced source id — leaving Cargo.lock pinning +wasix.N versions that
claim to come from crates.io and don't exist there. That breaks
cargo install --locked wasixcc and cargo vendor for everyone downstream
(see issue #72). Cargo.lock is the crates.io resolution; the WASIX build
keeps its own in Cargo.wasix.lock, and make wasix swaps between them.
The download stack (wasixccenv download-* / aio-install) sits behind the
default-on download feature. The WASIX build turns it off — inside the
Wasmer package, clang and the sysroot come from wasmer/clang, so there is
nothing to download and no reason to link a TLS stack.