I'm trying to learn how to compile CPP into WASM and I can't seem get it to work properly.
I have a simple CPP code that implements a squarer function which squares a given integer:
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
int EMSCRIPTEN_KEEPALIVE squarer(int num) {return num * num;}
I can compile this into WASM but when I try to load it in JS it says there are no exported functions. Looking at the WAT version (by running wasm2wat from wabt) it is clear that the problem is that the squarer function is not being exported.
(module
(type $t0 (func (param i32) (result i32)))
(import "env" "__linear_memory" (memory $env.__linear_memory 0))
(import "env" "__indirect_function_table" (table $env.__indirect_function_table 0 funcref))
(func $_Z7squareri (type $t0) (param $p0 i32) (result i32)
(i32.mul
(local.get $p0)
(local.get $p0))))
So I tried to compile again with the EXPORTED_FUNCTIONS flag (see the following line), but I get the following warning and the squarer function is still not being exported.
$ emcc squarer.cc -o squarer.wasm -c -O1 -s EXPORTED_FUNCTIONS="_Z7squareri","squarer"
emcc: warning: linker setting ignored during compilation: 'EXPORTED_FUNCTIONS' [-Wunused-command-line-argument]
When I edited the WAT to include an export (by changing func $_Z7squareri
to func (export "squarer")
) and compiled it back to WASM the JS successfully loaded the function, so it seems that the missing export really is the problem.
I tested it on two linux machines (one running ubuntu 20.04 and the other 18.04, both with the latest version of emsdk downloaded from their github as per the instructions in the MDN website). I also tried using all of the other emcc flags with "EXPORT" in them but they all got the same warning.
This is my first time building a WASM module, and I learned everything from the internet so I might have missed some crucial step. Am I doing it wrong?
Am I using outdated tools?
Is there a better / newer CPP to WASM compiler I should be using?
Thanks! Ittai
The
-c
command line option produces a wasm object file which is not designed to be executed directly. You need to then link that object file usingemcc
(without-c
) to get the final binary.You can do both compiling and linking in single command by simply removing the
-c
from the example command line you give above.If you use EMSCRIPTEN_KEEPALIVE you don't need EXPORTED_FUNCTIONS on the command line as they serve the same purpose.