emscripten-core / emscripten

Emscripten: An LLVM-to-WebAssembly Compiler
Other
25.72k stars 3.3k forks source link

Can't export gl functions in main module for dynamic linking #19357

Closed junyuecao closed 1 year ago

junyuecao commented 1 year ago
 emcc -sUSE_SDL=2 -g0 -O0 -o mandelbrot.html mandelbrot.cc -sALLOW_MEMORY_GROWTH -sWASM_BIGINT -sFULL_ES2=1 -sFULL_ES3=1 -sMAIN_MODULE=2 -sEXPORTED_FUNCTIONS="[\"_main\", \"_glGenBuffers\"]"

error code is : emcc: error: undefined exported symbol: "_glGenBuffers" [-Wundefined] [-Werror]

sbc100 commented 1 year ago

IIUC this is because _glGenBuffers is a JS library functions and (for reasons that I assume are mostly historical) JS library functions cannot be exported via EXPORTED_FUNCTIONS unless there are otherwise referenced. This is true even without dynamic linking:

$ ./emcc test/hello_world.c -sEXPORTED_FUNCTIONS=_main,_glGenBuffers
emcc: error: undefined exported symbol: "_glGenBuffers" [-Wundefined] [-Werror]

This is true for all JS library symbols, not just GL:

$ ./emcc test/hello_world.c -sEXPORTED_FUNCTIONS=_main,_emscripten_resize_heap
emcc: error: undefined exported symbol: "_emscripten_resize_heap" [-Wundefined] [-Werror]

Its somewhat unfortunate, but that way to work around this is to add -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE=glGenBuffers (not that we don't use the underscore mangling scheme in this list, also for mostly historical reasons):

$ ./emcc test/hello_world.c -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE=glGenBuffers -sEXPORTED_FUNCTIONS=_glGenBuffers,_main

Having said that, if your side module uses glGenBuffers, the best way to include it would be to simply pass the side module on the command line when linking the main module. That way the dependencies will be automatic and precise.

junyuecao commented 1 year ago

@sbc100 That's a clear explanation.

For for part of passing side module on the cmd line when linking, I also want to make sure if I want to use dlopen to load side module, should I pass the side module on the cmd-line? Since the doc told me if specified the side module it will be loaded automatically on load-time. image

sbc100 commented 1 year ago

yes, by default any side module you specify on the command line will be loaded on startup. If you want to delay loading until dlopen time you can use -sAUTOLOAD_DYLIBS=0