Reputation: 2216
In this tutorial it shows the following example for exporting C functions
./emcc tests/hello_function.cpp -o function.html -s EXPORTED_FUNCTIONS='["_int_sqrt"]' -s EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]'
I would like to do the same except that I use CMake like this
cd bin
emcmake cmake ../src
emmake make
What is the canonical way of specifying -s
in emmake? Should I add it to CMakeLists.txt
like
set(EXPORTED_FUNCTIONS '["_int_sqrt"]')
or do something similar?
Upvotes: 5
Views: 4342
Reputation: 1172
extern "C"
as the docs says:main.cpp
extern "C"
{
void sayHello()
{
std::cout << "hello" << std::endl;
}
}
If you don't add this, it will be an error: em++: error: undefined exported symbol: "_sayHello"
CMakeLists.txt
file:target_link_options(${EXECUTABLE_NAME} PRIVATE
-sEXPORTED_RUNTIME_METHODS=["cwrap"])
target_link_options(${EXECUTABLE_NAME} PRIVATE
-sEXPORTED_FUNCTIONS=["_sayHello"])
Module["onRuntimeInitialized"] = function() {
const sayHello = Module.cwrap("sayHello", null, []);
sayHello();
};
Upvotes: 0
Reputation: 1520
I just ran into exactly the same issue and even started one on the Emscripten github page (see here).
What worked for me was to put all the Emscripten specific flags into one long string which I then added with target_compile_options and target_link_options.
set(EMS
"SHELL:-s EXPORTED_FUNCTIONS=['_main','_malloc','_int_sqrt'] -s EXTRA_EXPORTED_RUNTIME_METHODS=['ccall','cwrap']"
)
target_compile_options(EmscriptenExample PRIVATE ${EMS})
target_link_options(EmscriptenExample PRIVATE ${EMS})
It's important to drop both, double quotes and whitespaces from the list of functions otherwise it won't work. At least with CMake 3.17.3 escaping the double quotes did not work for me.
/edit For the sake of completeness: Emscripten now allows to remove the whitespace between the -s prefix and the actual flag. This makes it possible to actually use CMake's own target_*_options functions, e.g.:
target_link_options(target PRIVATE -sEXPORTED_FUNCTIONS=['_main','_foo','_bar'])
Upvotes: 0
Reputation: 2020
This is the simplest/cleanest way now:
target_link_options(target PRIVATE
-sEXPORTED_FUNCTIONS=['_main','_foo','_bar'])
And if you have more -s settings (and you probably will) you can add them within this function call, or you can call target_link_options multiple times, both work. It seems quite accommodating, I haven't needed to escape anything.
Upvotes: 4
Reputation: 2216
What I figured out so far is that it can be achieved CMake with the following settings
# Here you can add -s flag during compiling object files
add_definitions("-s EXPORTED_RUNTIME_METHODS='[\"ccall\",\"cwrap\"]'")
add_definitions("-s EXTRA_EXPORTED_RUNTIME_METHODS='[\"ccall\",\"cwrap\"]'")
add_definitions("-s EXPORTED_FUNCTIONS='[\"_testInt\"]'")
# Here you can add -s flag during linking
set_target_properties(web_mealy_compiler PROPERTIES LINK_FLAGS "-s EXTRA_EXPORTED_RUNTIME_METHODS=['ccall','cwrap']")
# Set this if you want to to generate sample html file
set(CMAKE_EXECUTABLE_SUFFIX ".html")
Then you should be able to call C functions from javascript as follows:
<script type="text/javascript">
Module['onRuntimeInitialized'] = function() {
console.log("wasm loaded ");
console.log(Module.ccall); // make sure it's not undefined
console.log(Module._testInt); // make sure it's not undefined
console.log(Module._testInt()); // this should work
console.log( Module.ccall('testInt', // name of C function
'number', // return type
[], // argument types
[]) // argument values
);
}
</script>
And this is my definition of C function:
#include <emscripten.h>
EMSCRIPTEN_KEEPALIVE
int testInt(){
return 69420;
}
Upvotes: 4