|
| 1 | +# Compiling C/C++ to WebAssembly |
| 2 | + |
| 3 | +Many high level languages already support compilation to WebAssembly |
| 4 | +through the experimental LLVM backend. Unfortunately, it is a tedious |
| 5 | +and poorly documented process. This document aims to alleviate some |
| 6 | +of this tedium with a step-by-step tutorial to compile some basic C |
| 7 | +code to WAST format using LLVM, as well as provide instructions for building |
| 8 | +the toolchain. |
| 9 | + |
| 10 | +## Dependencies |
| 11 | + |
| 12 | +- LLVM + Clang: Must be built with the experimental WebAssebmly backend enabled |
| 13 | +- Binaryen: Needed to convert the `.s` output of LLVM's backend to WAST |
| 14 | + |
| 15 | +## Install LLVM and Clang with the WebAssembly backend |
| 16 | + |
| 17 | +### From the repo |
| 18 | + |
| 19 | +First, clone the needed repositories: |
| 20 | + |
| 21 | +`git clone http://llvm.org/git/llvm.git` |
| 22 | + |
| 23 | +`cd llvm/tools` |
| 24 | + |
| 25 | +`git clone http://llvm.org/git/clang.git` |
| 26 | + |
| 27 | +`cd ../projects` |
| 28 | + |
| 29 | +`git clone http://llvm.org/git/compiler-rt.git` |
| 30 | + |
| 31 | +Then initialize CMake: |
| 32 | + |
| 33 | +`mkdir ../build` |
| 34 | + |
| 35 | +`cd ../build` |
| 36 | + |
| 37 | +`cmake -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly -DLLVM_TARGETS_TO_BUILD= ..` |
| 38 | + |
| 39 | +Lastly, call `make` as usual: |
| 40 | + |
| 41 | +`make -j4 all` |
| 42 | + |
| 43 | +At the end of the (long) build the binaries will be in `bin`. Feel free to add that to your `PATH` for ease of use. |
| 44 | + |
| 45 | +## Install Binaryen |
| 46 | + |
| 47 | +This one is much easier. Simply: |
| 48 | + |
| 49 | +`git clone https://github.com/WebAssembly/binaryen.git` |
| 50 | + |
| 51 | +`cd binaryen` |
| 52 | + |
| 53 | +`mkdir build` |
| 54 | + |
| 55 | +`cd build` |
| 56 | + |
| 57 | +`cmake ..` |
| 58 | + |
| 59 | +`make -j4 all` |
| 60 | + |
| 61 | +CMake will also generate an `install` target if you want to actually install Binaryen on your system. |
| 62 | + |
| 63 | +## Compile C/C++ to WebAssembly |
| 64 | + |
| 65 | +First we must compile C to LLVM bitcode through the Clang frontend: |
| 66 | + |
| 67 | +`clang -emit-llvm --target=wasm32-unknown-unknown-elf -c -o source.bc source.c` |
| 68 | + |
| 69 | +Next we can generate linear WASM output from the bitcode: |
| 70 | + |
| 71 | +`llc -asm-verbose=false -o main.s main.bc` |
| 72 | + |
| 73 | +The backend output is in linear WASM format so we must convert this to WAST with binaryen's `s2wasm` tool: |
| 74 | + |
| 75 | +`s2wasm -o main.wast main.s` |
| 76 | + |
| 77 | +The code will now be in WAST format but must be cleaned up with `ewasm-cleanup` to be deployed as a contract. |
0 commit comments