Suppose I have a simple, self-contained C++ file (math.cpp
) like this:
int add(int x, int y) {
return x + y;
}
How would I compile it to WebAssembly (math.wasm
)?
Note: I am using the Clang tool-chain.
When you've written a new code module in a language like C/C++, you can compile it into WebAssembly using a tool like Emscripten.
Since it's a well-defined format, any language can have Wasm as a compilation target. Consequently, there are now around 40 high-level programming languages that support WebAssembly, including C and C++, Python, Go, Rust, Java, and PHP.
To be able to compile it to WASM you need to add GOOS=js GOARCH=wasm to the build command. This tells Go to compile to a . wasm file.
A program that can take our existing C++ code and compile it into a WebAssembly module. For this, we'll use Emscripten's emcc compiler, the most popular C++ to WebAssembly compiler of the bunch. To use the WebAssembly functionality from JavaScript, a binding is required.
I found this gist to be very helpful.
Basically, this are the steps:
-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly
)Compile the .cpp soure to llvm bitcode with clang:
clang -emit-llvm --target=wasm32 -Oz math.cpp -c -o math.bc
Compile the bitcode to s-assembly:
llc -asm-verbose=false -o math.s math.bc
Use binaryen's s2wasm tool to create a .wast file
s2wasm math.s > math.wast
Use WABT's wast2wasm tool to translate the textual .wast file into binary .wasm:
wast2wasm -o math.wasm math.wast
Some of the steps feel redundant but I have not yet found a tool that allows shortcuts. (It would be nice if llc could compile directly to .wasm, or if s2wasm actually created binary .wasm files as the name suggests.) Anyway, once you got the toolchain running it's relatively painless. Note, however, that there are no C or C++ standard libraries for web assembly yet.
Alternatively, if you need the .wasm file just for trying out stuff you can get away without all the toolchain trouble. Browse to https://mbebenita.github.io/WasmExplorer/, paste in your C/C++ code, and download the compiled .wasm file.
Thank you @noontz and @LB-- for pointing out that
Actually as the comments in the gist suggest you can skip binaryen and compile straight to wasm from Clang/LLVM. I'm currently using the following command line for C++ :
clang++ test.cpp -ObjC++ --compile --target=wasm32-unknown-unknown-wasm \ --optimize=3 --output test.wasm
Emscripten comes with everything you will need to compile a C++ file to wasm. Emscripten also has an SDK that makes life easy when it comes to installing all the necessary tools.
By default, however, Emscripten will add some framework code to your wasm file as well as generate some html and javascript.
It is possible to create a minimal wasm file with Emscripten that doesn't include any framework code, javascript, or html. Using options -s SIDE_MODULE=1 -Oz -s ONLY_MY_CODE=1
while compiling with emcc
or em++
will give you a minimal wasm file.
The following command would export a minimal wasm file using your examples and Emscripten:
em++ math.cpp -o math.wasm -Oz -s SIDE_MODULE=1 -s WASM=1 -s "EXPORTED_FUNCTIONS=['_add']" -s ONLY_MY_CODE=1
As of 2019, Clang (8) supports webassembly out of the box. Here is a repository that contains everything needed to compile, link and run a simple .wasm file.
https://github.com/PetterS/clang-wasm
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With