Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I compile a C++ file to WebAssembly?

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.

like image 745
sdgfsdh Avatar asked Jul 17 '17 13:07

sdgfsdh


People also ask

Can C be compiled to WebAssembly?

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.

What can compile to WebAssembly?

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.

Can you compile go to Wasm?

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.

Can you compile C++ to Wasm?

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.


3 Answers

I found this gist to be very helpful.

Basically, this are the steps:

  1. (build llvm and clang 5.0.0 or above with -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly)
  2. Compile the .cpp soure to llvm bitcode with clang:

    clang -emit-llvm --target=wasm32 -Oz math.cpp -c -o math.bc

  3. Compile the bitcode to s-assembly:

    llc -asm-verbose=false -o math.s math.bc

  4. Use binaryen's s2wasm tool to create a .wast file

    s2wasm math.s > math.wast

  5. 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
like image 70
MB-F Avatar answered Oct 21 '22 10:10

MB-F


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

like image 13
Clint Avatar answered Oct 21 '22 11:10

Clint


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

like image 7
Petter Avatar answered Oct 21 '22 10:10

Petter