Skip to content

Commit e572044

Browse files
committed
Add WASI platform
Introduces the WASI (WebAssembly System Interface) platform allowing AtomVM to run as a pure WebAssembly module under runtimes such as wasmtime, WasmEdge, and wasmer. Three target triples are supported: - wasm32-wasip1: no SMP, no networking - wasm32-wasip1-threads: SMP via wasi-threads, no networking - wasm32-wasip2: networking via wasi:sockets@0.2.x, no SMP Signed-off-by: Paul Guyot <pguyot@kallisys.net>
1 parent 84129c5 commit e572044

29 files changed

Lines changed: 2519 additions & 46 deletions

.github/workflows/build-and-test-on-freebsd.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ jobs:
9393
shell: freebsd {0}
9494
run: |
9595
cd $GITHUB_WORKSPACE;
96-
sed -i '' 's/test_http_server/%test_http_server/g' tests/libs/eavmlib/tests.erl
96+
sed -i '' 's/test_http_server, //g' tests/libs/eavmlib/tests.erl
9797
9898
- name: "Build: create build dir"
9999
shell: freebsd {0}

.github/workflows/wasi-build.yaml

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
#
2+
# Copyright 2026 Paul Guyot <pguyot@kallisys.net>
3+
#
4+
# SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
5+
#
6+
7+
name: WASI Build
8+
9+
on:
10+
push:
11+
paths:
12+
- '.github/workflows/wasi-build.yaml'
13+
- 'CMakeLists.txt'
14+
- 'CMakeModules/**'
15+
- 'libs/**'
16+
- 'src/platforms/wasi/**'
17+
- 'src/libAtomVM/**'
18+
pull_request:
19+
paths:
20+
- '.github/workflows/wasi-build.yaml'
21+
- 'CMakeLists.txt'
22+
- 'CMakeModules/**'
23+
- 'libs/**'
24+
- 'src/platforms/wasi/**'
25+
- 'src/libAtomVM/**'
26+
27+
permissions:
28+
contents: write
29+
30+
concurrency:
31+
group: ${{ github.workflow }}-${{ github.ref != 'refs/heads/main' && github.ref || github.run_id }}
32+
cancel-in-progress: true
33+
34+
jobs:
35+
36+
compile_tests:
37+
38+
runs-on: ubuntu-24.04
39+
container: erlang:28
40+
permissions:
41+
actions: read
42+
contents: read
43+
security-events: write
44+
45+
strategy:
46+
fail-fast: false
47+
matrix:
48+
language: ["c-cpp"]
49+
50+
steps:
51+
- name: Checkout repo
52+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
53+
54+
- name: Install required packages
55+
run: apt update && apt install -y gperf zlib1g-dev cmake ninja-build
56+
57+
- name: "Git config safe.directory for codeql"
58+
run: git config --global --add safe.directory /__w/AtomVM/AtomVM
59+
60+
- name: "Initialize CodeQL"
61+
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
62+
with:
63+
languages: ${{matrix.language}}
64+
build-mode: manual
65+
queries: +./code-queries/term-to-non-term-func.ql,./code-queries/non-term-to-term-func.ql,./code-queries/mismatched-atom-string-length.ql,./code-queries/mismatched-free-type.ql,./code-queries/term-use-after-gc.ql,./code-queries/allocations-exceeding-ensure-free.ql,./code-queries/allocations-without-ensure-free.ql
66+
67+
- name: Compile AtomVM and test modules
68+
run: |
69+
set -e
70+
mkdir build
71+
cd build
72+
cmake .. -G Ninja -DAVM_WARNINGS_ARE_ERRORS=ON
73+
ninja AtomVM atomvmlib erlang_test_modules test_etest test_alisp test_estdlib test_eavmlib
74+
75+
- name: "Perform CodeQL Analysis"
76+
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
77+
78+
- name: Upload AtomVM and test modules
79+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
80+
with:
81+
name: atomvm-and-test-modules
82+
path: |
83+
build/**/*.avm
84+
build/**/*.beam
85+
build/src/AtomVM
86+
retention-days: 1
87+
88+
wasi_build_and_test:
89+
needs: compile_tests
90+
runs-on: ubuntu-24.04
91+
92+
strategy:
93+
fail-fast: false
94+
matrix:
95+
include:
96+
# No SMP, no networking - minimal stable target.
97+
- target: wasm32-wasip1
98+
disable_smp: ON
99+
wasmtime_flags: ""
100+
# SMP via wasi-threads, no networking. Needs shared-memory in wasmtime.
101+
- target: wasm32-wasip1-threads
102+
disable_smp: OFF
103+
wasmtime_flags: "-W threads -W shared-memory -S threads"
104+
# No SMP, networking via wasi:sockets@0.2.x - exercises BSD sockets and SSL.
105+
- target: wasm32-wasip2
106+
disable_smp: ON
107+
wasmtime_flags: "-S inherit-network -S allow-ip-name-lookup"
108+
109+
steps:
110+
- name: Checkout repo
111+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
112+
113+
- name: Install required packages
114+
run: sudo apt-get update -y && sudo apt-get install -y cmake ninja-build gperf
115+
116+
- name: Install WASI SDK
117+
run: |
118+
set -euo pipefail
119+
WASI_SDK_VERSION=33
120+
wget -q "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VERSION}/wasi-sdk-${WASI_SDK_VERSION}.0-x86_64-linux.tar.gz"
121+
sudo mkdir -p /opt/wasi-sdk
122+
sudo tar xzf "wasi-sdk-${WASI_SDK_VERSION}.0-x86_64-linux.tar.gz" --strip-components=1 -C /opt/wasi-sdk
123+
124+
- name: Install wasmtime
125+
run: |
126+
set -euo pipefail
127+
WASMTIME_VERSION=44.0.1
128+
WASMTIME_TARBALL="wasmtime-v${WASMTIME_VERSION}-x86_64-linux.tar.xz"
129+
WASMTIME_SHA256="afd58715f105e3a7f454169daed22168c5736ec5f225fb04c4ac62c54c9508a3"
130+
wget -q "https://github.com/bytecodealliance/wasmtime/releases/download/v${WASMTIME_VERSION}/${WASMTIME_TARBALL}"
131+
echo "${WASMTIME_SHA256} ${WASMTIME_TARBALL}" | sha256sum -c -
132+
sudo mkdir -p /opt/wasmtime
133+
sudo tar xf "${WASMTIME_TARBALL}" --strip-components=1 -C /opt/wasmtime
134+
echo "/opt/wasmtime" >> $GITHUB_PATH
135+
136+
- name: Build (${{ matrix.target }})
137+
working-directory: ./src/platforms/wasi/
138+
run: |
139+
set -euo pipefail
140+
mkdir build
141+
cd build
142+
cmake -G Ninja \
143+
-DCMAKE_TOOLCHAIN_FILE=../wasi-sdk.cmake \
144+
-DAVM_DISABLE_JIT=ON \
145+
-DAVM_DISABLE_SMP=${{ matrix.disable_smp }} \
146+
-DWASI_TARGET=${{ matrix.target }} \
147+
..
148+
ninja
149+
150+
- name: Download AtomVM and test modules
151+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
152+
with:
153+
name: atomvm-and-test-modules
154+
path: build
155+
156+
- name: Test (${{ matrix.target }})
157+
working-directory: ./build
158+
run: |
159+
set -euxo pipefail
160+
WASM=../src/platforms/wasi/build/src/AtomVM.wasm
161+
FLAGS="${{ matrix.wasmtime_flags }}"
162+
wasmtime run ${FLAGS} --dir=. ${WASM} tests/libs/alisp/test_alisp.avm
163+
wasmtime run ${FLAGS} --dir=. ${WASM} tests/libs/estdlib/test_estdlib.avm
164+
wasmtime run ${FLAGS} --dir=. ${WASM} tests/libs/etest/test_etest.avm
165+
wasmtime run ${FLAGS} --dir=. ${WASM} tests/libs/eavmlib/test_eavmlib.avm
166+
167+
- name: "Rename and write sha256sum"
168+
if: startsWith(github.ref, 'refs/tags/')
169+
working-directory: src/platforms/wasi/build/src
170+
run: |
171+
ATOMVM_WASM=AtomVM-${{ matrix.target }}-${{ github.ref_name }}.wasm
172+
mv AtomVM.wasm "${ATOMVM_WASM}"
173+
sha256sum "${ATOMVM_WASM}" > "${ATOMVM_WASM}.sha256"
174+
175+
- name: "Release"
176+
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
177+
if: startsWith(github.ref, 'refs/tags/')
178+
with:
179+
draft: true
180+
fail_on_unmatched_files: true
181+
files: |
182+
src/platforms/wasi/build/src/AtomVM-${{ matrix.target }}-${{ github.ref_name }}.wasm
183+
src/platforms/wasi/build/src/AtomVM-${{ matrix.target }}-${{ github.ref_name }}.wasm.sha256

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1616
- Added I2C and SPI APIs to stm32 platform
1717
- Added `Transfer-Encoding: chunked` response support to `ahttp_client`, including HTTP trailers
1818
- Added `proc_lib:init_fail/2,3`
19+
- Added WASI platform, with `wasm32-wasip1` (no SMP, no networking),
20+
`wasm32-wasip1-threads` (SMP, no networking) and `wasm32-wasip2` (no SMP,
21+
networking via `wasi:sockets@0.2.x`) target triples
1922

2023
### Changed
2124
- Updated network type db() to dbm() to reflect the actual representation of the type

README.Md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Supported Platforms
2020
* STM32 MCUs (with official ST HAL/LL SDK, see [stm32](https://doc.atomvm.org/main/getting-started-guide.html#getting-started-on-the-stm32-platform))
2121
* Raspberry Pi Pico and Pico 2 (see [rp2](https://doc.atomvm.org/main/getting-started-guide.html#getting-started-on-the-raspberry-pi-pico-platform))
2222
* Browsers and NodeJS with WebAssembly (see [emscripten](https://doc.atomvm.org/main/getting-started-guide.html#getting-started-with-atomvm-webassembly))
23+
* Standalone WebAssembly runtimes such as wasmtime (see [wasi](https://doc.atomvm.org/main/build-instructions.html#building-for-wasi))
2324

2425
AtomVM aims to be easily portable to new platforms with a minimum effort, so additional platforms
2526
might be supported in a near future.
@@ -72,8 +73,9 @@ available in the documentation for
7273
[ESP32](https://doc.atomvm.org/main/build-instructions.html#building-for-esp32),
7374
[STM32](https://doc.atomvm.org/main/build-instructions.html#building-for-stm32),
7475
[Raspberry Pi Pico and Pico 2](https://doc.atomvm.org/main/build-instructions.html#building-for-raspberry-pi-pico)
75-
(rp2), and
76-
[WASM](https://doc.atomvm.org/main/build-instructions.html#building-for-nodejs-web) (NodeJS/Web).
76+
(rp2),
77+
[WASM](https://doc.atomvm.org/main/build-instructions.html#building-for-nodejs-web) (NodeJS/Web), and
78+
[WASI](https://doc.atomvm.org/main/build-instructions.html#building-for-wasi) (standalone WebAssembly).
7779

7880
Project Status
7981
==============

doc/src/build-instructions.md

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ The native C parts of AtomVM compile to machine code on MacOS, Linux, and FreeBS
2020

2121
The Erlang and Elixir parts are compiled to BEAM byte-code using the Erlang (`erlc`) and Elixir compilers. For information about specific versions of required software, see the [Release Notes](./release-notes.md).
2222

23-
This guide provides information about how to build AtomVM for the various supported platforms (Generic UNIX, ESP32, and STM32).
23+
This guide provides information about how to build AtomVM for the various supported platforms (Generic UNIX, ESP32, STM32, RP2, Emscripten WASM, and WASI).
2424

2525
```{attention}
2626
In order to build AtomVM AVM files for ESP32 and STM32 platforms, you will also need to build
@@ -92,6 +92,7 @@ It is possible to use a local copy of `uf2tool` source code by setting `UF2TOOL_
9292
* [STM32](#building-for-stm32)
9393
* [RP2](#building-for-rp2) (including Pico boards)
9494
* [WASM](#building-for-emscripten) (NodeJS or web)
95+
* [WASI](#building-for-wasi) (WebAssembly System Interface, wasmtime/wasmer)
9596

9697
## Building for Generic UNIX
9798

@@ -1218,3 +1219,103 @@ $ cd src/platforms/emscripten/tests/
12181219
$ npm install cypress
12191220
$ npx cypress open
12201221
```
1222+
1223+
## Building for WASI
1224+
1225+
WASI (WebAssembly System Interface) allows AtomVM to run as a pure WebAssembly module without JavaScript dependencies. Unlike the Emscripten build, WASI targets standalone runtimes such as wasmtime, WasmEdge, and wasmer.
1226+
1227+
### WASI Prerequisites
1228+
1229+
* [WASI SDK](https://github.com/WebAssembly/wasi-sdk/releases) at version 33 or
1230+
newer recommended
1231+
* A WASI runtime, such as [wasmtime](https://wasmtime.dev) (recommended)
1232+
* `cmake` 3.13 or later
1233+
* Erlang/OTP
1234+
1235+
### WASI Target Modes
1236+
1237+
The build supports three target triples, picked automatically from `AVM_DISABLE_SMP`. SMP and networking sit on different targets and are currently mutually exclusive:
1238+
1239+
| Target triple | SMP | Networking | Selection |
1240+
| ------------------------- | --- | ---------------------------------- | ------------------------------------------------------ |
1241+
| `wasm32-wasip1-threads` | yes | no | default (`-DAVM_DISABLE_SMP=OFF`) |
1242+
| `wasm32-wasip2` | no | yes (`wasi:sockets@0.2.x`) | `-DAVM_DISABLE_SMP=ON` |
1243+
| `wasm32-wasip1` | no | no | `-DAVM_DISABLE_SMP=ON -DWASI_TARGET=wasm32-wasip1` |
1244+
1245+
`erlang:system_info(system_architecture)` reports the active triple (e.g. `wasm32-wasip2`).
1246+
1247+
### WASI Build Instructions
1248+
1249+
Default (SMP, no networking):
1250+
1251+
```shell
1252+
$ cd src/platforms/wasi/
1253+
$ mkdir build
1254+
$ cd build
1255+
$ cmake -G Ninja \
1256+
-DCMAKE_TOOLCHAIN_FILE=../wasi-sdk.cmake \
1257+
-DAVM_DISABLE_JIT=ON \
1258+
..
1259+
$ ninja
1260+
```
1261+
1262+
For networking (single-threaded `wasm32-wasip2`):
1263+
1264+
```shell
1265+
$ cmake -G Ninja \
1266+
-DCMAKE_TOOLCHAIN_FILE=../wasi-sdk.cmake \
1267+
-DAVM_DISABLE_JIT=ON \
1268+
-DAVM_DISABLE_SMP=ON \
1269+
..
1270+
```
1271+
1272+
The WASI SDK location is detected automatically from the `WASI_SDK_PATH` environment variable, `/opt/local/libexec/wasi-sdk` (MacPorts), or `/opt/wasi-sdk`.
1273+
1274+
### Running AtomVM on WASI
1275+
1276+
WASI uses capability-based security. Grant directory access with `--dir` when running:
1277+
1278+
```shell
1279+
$ wasmtime run --dir=. build/src/AtomVM.wasm myapp.avm
1280+
```
1281+
1282+
For SMP (`wasm32-wasip1-threads`) wasmtime needs the threads proposal:
1283+
1284+
```shell
1285+
$ wasmtime run -W threads -W shared-memory --dir=. build/src/AtomVM.wasm myapp.avm
1286+
```
1287+
1288+
For networking (`wasm32-wasip2`) grant socket and DNS capabilities:
1289+
1290+
```shell
1291+
$ wasmtime run -S inherit-network -S allow-ip-name-lookup --dir=. \
1292+
build/src/AtomVM.wasm myapp.avm
1293+
```
1294+
1295+
You can load multiple AVM or BEAM files by listing them as additional arguments:
1296+
1297+
```shell
1298+
$ wasmtime run --dir=. build/src/AtomVM.wasm myapp.avm libs/atomvmlib.avm
1299+
```
1300+
1301+
### Running tests with WASI
1302+
1303+
Build the test modules first using the Generic UNIX build (see above). Then run:
1304+
1305+
```shell
1306+
$ cd build
1307+
$ wasmtime run --dir=. ../src/platforms/wasi/build/src/AtomVM.wasm \
1308+
tests/libs/alisp/test_alisp.avm
1309+
$ wasmtime run --dir=. ../src/platforms/wasi/build/src/AtomVM.wasm \
1310+
tests/libs/estdlib/test_estdlib.avm
1311+
$ wasmtime run --dir=. ../src/platforms/wasi/build/src/AtomVM.wasm \
1312+
tests/libs/etest/test_etest.avm
1313+
```
1314+
1315+
### WASI Platform Limitations
1316+
1317+
* JIT compilation is not supported; the WebAssembly sandbox prohibits executable memory.
1318+
* Networking requires the `wasm32-wasip2` target; the WASI Preview 1 targets (`wasm32-wasip1` and `wasm32-wasip1-threads`) have no sockets.
1319+
* SMP requires the `wasm32-wasip1-threads` target; `wasm32-wasip2` does not provide threads.
1320+
* Process creation (fork/exec) is not supported on any WASI target.
1321+
* Directory access requires explicit capability grants via `--dir`.

doc/src/welcome-to-atomvm.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ AtomVM is licensed under the terms of the [Apache2](https://www.apache.org/licen
5555

5656
## Source Code
5757

58-
The [AtomVM Github Repository](https://github.com/atomvm/AtomVM) contains the AtomVM source code, including the AtomVM virtual machine and core libraries. The AtomVM [Build Instructions](./build-instructions.md) contains instructions for building AtomVM for Generic UNIX, ESP32, and STM32 platforms.
58+
The [AtomVM Github Repository](https://github.com/atomvm/AtomVM) contains the AtomVM source code, including the AtomVM virtual machine and core libraries. The AtomVM [Build Instructions](./build-instructions.md) contains instructions for building AtomVM for Generic UNIX, ESP32, STM32, RP2, Emscripten, and WASI platforms.
5959

6060
## Contributing
6161

src/platforms/wasi/.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Copyright 2026 Paul Guyot <pguyot@kallisys.net>
2+
#
3+
# SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
4+
5+
build/
6+
build.*

0 commit comments

Comments
 (0)