Skip to content

Commit 9eb3ed6

Browse files
authored
Update documents about building wasm app with wasi-sdk (#955)
Checked with grammarly
1 parent 6917137 commit 9eb3ed6

File tree

1 file changed

+62
-25
lines changed

1 file changed

+62
-25
lines changed

doc/build_wasm_app.md

Lines changed: 62 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,38 @@
22

33
# Prepare WASM building environments
44

5-
For C and C++, WASI-SDK version 12.0+ is the major tool supported by WAMR to build WASM applications. Also we can use [Emscripten SDK (EMSDK)](https://github.com/emscripten-core/emsdk), but it is not recommended. And there are some other compilers such as the standard clang compiler, which might also work [here](./other_wasm_compilers.md).
5+
For C and C++, WASI-SDK version 12.0+ is the major tool supported by WAMR to build WASM applications. Also, we can use [Emscripten SDK (EMSDK)](https://github.com/emscripten-core/emsdk), but it is not recommended. And there are some other compilers such as the standard clang compiler, which might also work [here](./other_wasm_compilers.md).
66

77
To install WASI SDK, please download the [wasi-sdk release](https://github.com/CraneStation/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk`.
88

9-
The offical *wasi-sdk release* doesn't fully support *latest 128-bit SIMD spec* yet. WARM provides a script in [build-wasi-sdk](../test-tools/build-wasi-sdk/) to generate
10-
another wasi-sdk with *llvm-13* from source code and installs it at *../test-tools/wasi-sdk*. If you plan to build WASM applications with *latest 128-bit SIMD*, please use it instead of the offical release.
9+
The official *wasi-sdk release* doesn't fully support *latest 128-bit SIMD spec* yet. WARM provides a script in [build-wasi-sdk](../test-tools/build-wasi-sdk/) to generate
10+
another wasi-sdk with *llvm-13* from source code and installs it at *../test-tools/wasi-sdk*. If you plan to build WASM applications with *latest 128-bit SIMD*, please use it instead of the official release.
1111

1212
And [sample workloads](../samples/workload) are using the self-compiled wasi-sdk.
1313

1414
For [AssemblyScript](https://github.com/AssemblyScript/assemblyscript), please refer to [AssemblyScript quick start](https://www.assemblyscript.org/quick-start.html) and [AssemblyScript compiler](https://www.assemblyscript.org/compiler.html#command-line-options) for how to install `asc` compiler and build WASM applications.
1515

16-
For Rust, please firstly ref to [Install Rust and Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html) to install cargo, rustc and rustup, by default they are installed under ~/.cargo/bin, and then run `rustup target add wasm32-wasi` to install wasm32-wasi target for Rust toolchain. To build WASM applications, we can run `cargo build --target wasm32-wasi`, the output files are under `target/wasm32-wasi`.
16+
For Rust, please refer to [Install Rust and Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html) to install *cargo*, *rustc* and *rustup*. By default they are under ~/.cargo/bin.
17+
18+
And then run such a command to install `wasm32-wasi` target.
19+
20+
``` bash
21+
$ rustup target add wasm32-wasi
22+
```
23+
24+
To build WASM applications, run
25+
26+
``` bash
27+
$ cargo build --target wasm32-wasi
28+
```
29+
30+
The output files are under `target/wasm32-wasi`.
31+
32+
To build a release version
33+
34+
``` bash
35+
$ cargo build --release --target wasm32-wasi
36+
```
1737

1838

1939
Build WASM applications with wasi-sdk
@@ -55,9 +75,9 @@ To build the source file to WASM bytecode, we can input the following command:
5575

5676
## 1. wasi-sdk options
5777

58-
There are some useful options which can be specified to build the source code (for more link options, please run `/opt/wasi-sdk/bin/wasm-ld --help`):
78+
There are some useful options that are used to compile C/C++ to Wasm (for a full introduction, please refer to [clang command line argument reference](https://clang.llvm.org/docs/ClangCommandLineReference.html) and [wasm-ld command line argument manual](https://lld.llvm.org/WebAssembly.html)):
5979

60-
- **-nostdlib** Do not use the standard system startup files or libraries when linking. In this mode, the **libc-builtin** library of WAMR must be built to run the wasm app, otherwise, the **libc-wasi** library must be built. You can specify **-DWAMR_BUILD_LIBC_BUILTIN=1** or **-DWAMR_BUILD_LIBC_WASI=1** for cmake to build WAMR with libc-builtin support or libc-wasi support.
80+
- **-nostdlib** Do not use the standard system startup files or libraries when linking. In this mode, the **libc-builtin** library of WAMR must be built to run the wasm app, otherwise, the **libc-wasi** library must be built. You can specify **-DWAMR_BUILD_LIBC_BUILTIN=1** or **-DWAMR_BUILD_LIBC_WASI=1** for CMake to build WAMR with libc-builtin support or libc-wasi support.
6181

6282
- **-Wl,--no-entry** Do not output any entry point
6383

@@ -69,7 +89,7 @@ There are some useful options which can be specified to build the source code (f
6989

7090
- **-Wl,--max-memory=\<value\>** Maximum size of the linear memory, which must be a multiple of 65536
7191

72-
- **-z stack-size=\<vlaue\>** The auxiliary stack size, which is an area of linear memory, and must be smaller than initial memory size.
92+
- **-z stack-size=\<vlaue\>** The auxiliary stack size, which is an area of linear memory, must be smaller than the initial memory size.
7393

7494
- **-Wl,--strip-all** Strip all symbols
7595

@@ -81,7 +101,7 @@ There are some useful options which can be specified to build the source code (f
81101

82102
- **-pthread** Support POSIX threads in generated code
83103

84-
For example, we can build the wasm app with command:
104+
For example, we can build the wasm app with the command:
85105

86106
``` Bash
87107
/opt/wasi-sdk/bin/clang -O3 -nostdlib \
@@ -91,9 +111,9 @@ For example, we can build the wasm app with command:
91111
-Wl,--export=__heap_base -Wl,--export=__data_end \
92112
-Wl,--no-entry -Wl,--strip-all -Wl,--allow-undefined
93113
```
94-
to generate a wasm binary with nostdlib mode, auxiliary stack size is 8192 bytes, initial memory size is 64 KB, main function, heap base global and data end global are exported, no entry function is generated (no _start function is exported), and all symbols are stripped. Note that it is nostdlib mode, so libc-builtin should be enabled by runtime embedder or iwasm (with cmake -DWAMR_BUILD_LIBC_BUILT=1, enabled by iwasm in Linux by default).
114+
to generate a wasm binary with nostdlib mode, the auxiliary stack size is 8192 bytes, initial memory size is 64 KB, main function, heap base global and data end global are exported, no entry function is generated (no _start function is exported), and all symbols are stripped. Note that it is nostdlib mode, so libc-builtin should be enabled by runtime embedder or iwasm (with `cmake -DWAMR_BUILD_LIBC_BUILT=1`, enabled by iwasm in Linux by default).
95115

96-
If we want to build the wasm app with wasi mode, we may build the wasm app with command:
116+
If we want to build the wasm app with wasi mode, we may build the wasm app with the command:
97117

98118
```bash
99119
/opt/wasi-sdk/bin/clang -O3 \
@@ -103,7 +123,7 @@ If we want to build the wasm app with wasi mode, we may build the wasm app with
103123
-Wl,--strip-all
104124
```
105125

106-
to generate a wasm binary with wasi mode, auxiliary stack size is 8192 bytes, initial memory size is 64 KB, heap base global and data end global are exported, wasi entry function exported (_start function), and all symbols are stripped. Note that it is wasi mode, so libc-wasi should be enabled by runtime embedder or iwasm (with cmake -DWAMR_BUILD_LIBC_WASI=1, enabled by iwasm in Linux by default), and normally no need to export main function, by default _start function is executed by iwasm.
126+
to generate a wasm binary with wasi mode, the auxiliary stack size is 8192 bytes, initial memory size is 64 KB, heap base global and data end global are exported, wasi entry function exported (_start function), and all symbols are stripped. Note that it is wasi mode, so libc-wasi should be enabled by runtime embedder or iwasm (with `cmake -DWAMR_BUILD_LIBC_WASI=1`, enabled by iwasm in Linux by default), and normally no need to export main function, by default _start function is executed by iwasm.
107127

108128
## 2. How to reduce the footprint?
109129

@@ -119,7 +139,7 @@ Firstly if libc-builtin (-nostdlib) mode meets the requirements, e.g. there are
119139

120140
- reduce auxiliary stack size
121141

122-
The auxiliary stack is an area of linear memory, normally the size is 64 KB by default which might be a little large for embedded devices and actually partly used, we can use `-z stack-size=n` to set its size.
142+
The auxiliary stack is an area of linear memory, normally the size is 64 KB by default which might be a little large for embedded devices and partly used, we can use `-z stack-size=n` to set its size.
123143

124144
- use -O3 and -Wl,--strip-all
125145

@@ -133,7 +153,7 @@ Firstly if libc-builtin (-nostdlib) mode meets the requirements, e.g. there are
133153

134154
- decrease block_addr_cache size for classic interpreter
135155

136-
The block_addr_cache is an hash cache to store the else/end addresses for WebAssembly blocks (BLOCK/IF/LOOP) to speed up address lookup. This is only available in classic interpreter. We can set it by define macro `-DBLOCK_ADDR_CACHE_SIZE=n`, e.g. add `add_defintion (-DBLOCK_ADDR_CACHE_SIZE=n)` in CMakeLists.txt, by default it is 64, and total block_addr_cache size is 3072 bytes in 64-bit platform and 1536 bytes in 32-bit platform.
156+
The block_addr_cache is a hash cache to store the else/end addresses for WebAssembly blocks (BLOCK/IF/LOOP) to speed up address lookup. This is only available in the classic interpreter. We can set it by defineing macro `-DBLOCK_ADDR_CACHE_SIZE=n`, e.g. add `add_defintion (-DBLOCK_ADDR_CACHE_SIZE=n)` in CMakeLists.txt, by default it is 64, and the total block_addr_cache size is 3072 bytes in 64-bit platform and 1536 bytes in 32-bit platform.
137157

138158
### (2) Methods to reduce the libc-wasi (without -nostdlib) mode footprint
139159

@@ -178,7 +198,7 @@ EMCC_ONLY_FORCED_STDLIBS=1 emcc -O3 -s STANDALONE_WASM=1 \
178198

179199
There are some useful options:
180200

181-
- **EMCC_ONLY_FORCED_STDLIBS=1** whether to link libc library into the output binary or not, similar to `-nostdlib` option of wasi-sdk clang. If specified, then no libc library is linked and the **libc-builtin** library of WAMR must be built to run the wasm app, otherwise, the **libc-wasi** library must be built. You can specify **-DWAMR_BUILD_LIBC_BUILTIN=1** or **-DWAMR_BUILD_LIBC_WASI=1** for cmake to build WAMR with libc-builtin support or libc-wasi support.
201+
- **EMCC_ONLY_FORCED_STDLIBS=1** whether to link libc library into the output binary or not, similar to `-nostdlib` option of wasi-sdk clang. If specified, then no libc library is linked and the **libc-builtin** library of WAMR must be built to run the wasm app, otherwise, the **libc-wasi** library must be built. You can specify **-DWAMR_BUILD_LIBC_BUILTIN=1** or **-DWAMR_BUILD_LIBC_WASI=1** for CMake to build WAMR with libc-builtin support or libc-wasi support.
182202

183203
The emsdk's wasi implementation is incomplete, e.g. open a file might just return fail, so it is strongly not recommended to use this mode, especially when there are file io operations in wasm app, please use wasi-sdk instead.
184204

@@ -200,31 +220,48 @@ For more options, please ref to <EMSDK_DIR>/upstream/emscripten/src/settings.js,
200220

201221
# Build a project with cmake
202222

203-
If you have complex WASM application project which contains dozens of source files, you can consider using cmake for project building.
223+
If you have a complex WASM application project which contains dozens of source files, you can consider using cmake for project building.
204224

205225
You can cross compile your project by using the toolchain provided by WAMR.
206226

207-
We can generate a `CMakeLists.txt` file for `test.c`:
227+
Assume the original `CMakeLists.txt` for `test.c` likes below:
208228

209229
``` cmake
210230
cmake_minimum_required (VERSION 3.5)
211231
project(hello_world)
212-
213-
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS},--export=main")
214232
add_executable(hello_world test.c)
215233
```
216234

217-
It is simple to build this project by cmake:
235+
It is easy to use *wasi-sdk* in CMake by setting *CMAKE_TOOLCHAIN_FILE* without any modification on the original *CMakeLists.txt*.
218236

219-
``` Bash
220-
mkdir build && cd build
221-
cmake .. -DCMAKE_TOOLCHAIN_FILE=$WAMR_ROOT/wamr-sdk/app/wamr_toolchain.cmake
222-
make
237+
```
238+
$ cmake -DWASI_SDK_PREFIX=${WASI_SDK_INSTALLTION_DIR}
239+
-DCMAKE_TOOLCHAIN_FILE=${WASI_SDK_INSTALLTION_DIR}/share/cmake/wasi-sdk.cmake
240+
-DCMAKE_SYSROOT=<a sysroot directory>
241+
..
223242
```
224243

225-
You will get ```hello_world``` which is the WASM app binary.
244+
`WASI_SDK_INSTALLTION_DIR` is the directory in where you install the *wasi-sdk*. like */opt/wasi-sdk*
245+
246+
If you prefer WASI, set *CMAKE_SYSROOT* to *wasi-sysroot*
247+
248+
```
249+
$ cmake <same as above>
250+
-DCMAKE_SYSROOT=${WASI_SDK_INSTALLTION_DIR}/share/wasi-sysroot
251+
..
252+
```
226253

227-
> Note: If you have already built a SDK profile, then the **DCMAKE_TOOLCHAIN_FILE** should be changed into `$WAMR_ROOT/wamr-sdk/out/${PROFILE}/app-sdk/wamr_toolchain.cmake`
254+
If you prefer *WAMR builtin libc*, set *CMAKE_SYSROOT* to *libc-builtin-sysroot*
255+
256+
> Note: If you have already built a SDK profile
257+
258+
```
259+
$ cmake <same as above>
260+
-DCMAKE_SYSROOT=${WAMR_SOURCE_ROOT}/wamr-sdk/app/libc-builtin-sysroot
261+
..
262+
```
263+
264+
You will get ```hello_world``` which is the WASM app binary.
228265

229266

230267
# Compile WASM to AoT module

0 commit comments

Comments
 (0)