Skip to content

gl4es no longer works with Emscripten #15674

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
parasti opened this issue Nov 30, 2021 · 12 comments
Closed

gl4es no longer works with Emscripten #15674

parasti opened this issue Nov 30, 2021 · 12 comments

Comments

@parasti
Copy link
Contributor

parasti commented Nov 30, 2021

I've been maintaining a Neverball build here: https://neverball.github.io/

Hadn't compiled in a while. It worked great last I tried, which was around 2.0.16. Getting linker errors about missing eglGetProcAddress (via SDL2) and emscripten_GetProcAddress (via gl4es):

wasm-ld: error: C:\Development\emsdk\upstream\emscripten\cache\sysroot\lib\wasm32-emscripten\libSDL2.a(SDL_emscriptenopengles.c.o): undefined symbol: eglGetProcAddress
wasm-ld: error: ../gl4es/lib\libGL.a(loader.c.o): undefined symbol: emscripten_GetProcAddress

Seems to me that compilation with gl4es is broken since, presumably, #13524.

gl4es provides its own GL library, but requires emscripten_GetProcAddress to exist. Unless I'm misreading, emscripten_GetProcAddress is only included when linking with the default GL library.

If I am misreading, how do I compile with gl4es now? Or, I guess, what's the proper fix that should be implemented and to which part?

@sbc100
Copy link
Collaborator

sbc100 commented Nov 30, 2021

emscripten_GetProcAddress is defined in system/lib/gl/gl.c and eglGetProcAddress is defined in libprocaddr.c.

As you have noticed both of those files are part of libGL.a which is included via -lGL. Unless you opt out of it using -sNO_AUTO_NATIVE_LIBRARIES (or -sSTRICT) then I think that library should always get included.

Can you include the full emcc command that is failing along with the full wasm-ld command?

@sbc100
Copy link
Collaborator

sbc100 commented Nov 30, 2021

Oh I see you already tracked down the culprit PR: #13524.

I think I see what is happening.. you are putting gl4es/lib in the library path so that the version of libGL that lives there overrides the emscripten version of libGL.a in the system library path.

@kripken might have some ideas on how to fix this.

One option would be to explictly includes gl4es/lib/libGL.a on the link line (but don't add gl4es/lib to the library path). That way both version of libGL will be linked in, but your one should take presences over the system one if/when it contains a given symbol.

@parasti
Copy link
Contributor Author

parasti commented Nov 30, 2021

I'll give it a try and report back, thanks.

@sbc100
Copy link
Collaborator

sbc100 commented Nov 30, 2021

Hmm.. I think maybe one solution is to split libprocaddr.c out into libEGL.a (which does not yet exist).

@kripken
Copy link
Member

kripken commented Nov 30, 2021

IIUC, the issue here is that this project does not link in libGL, but it does need emscripten_GetProcAddress which is defined there?

If so then I think -lGL should fix it. It should just link in that one object file if it doesn't need anything else.

I verified that that fixes this testcase with -s STRICT -lGL:

extern "C" int emscripten_GetProcAddress(const char *name);

int main() {
  return emscripten_GetProcAddress("foo");
}

@kripken
Copy link
Member

kripken commented Nov 30, 2021

Apologies for the breaking change here, btw. I'll add a changelog note for that release.

@sbc100
Copy link
Collaborator

sbc100 commented Nov 30, 2021

Its not clear if this issue is related to STRICT. @parasti are you using STRICT?

It could be that this issue is little more complicated. It could involve the presence of a custom libGL.a which takes the place of the system libGL.a.

Its not clear to how this ever worked though because wasn't emscripten_GetProcAddress always part of libGL.a? Maybe I'm misunderstanding the issue.

@kripken
Copy link
Member

kripken commented Nov 30, 2021

I think this used to work because that function was in a JS library. That meant it could always be linked in regardless of what libraries one specified at the commandline. (I guess we do conditionally include certain JS files, so maybe not always...)

That testcase (with STRICT) is fixed by adding -lGL. But another issue as you said in the PR is that aliasing the GL library might also be an issue here. In that case is there a link flag to say "link the system lib with this name"? (like "include_next" in header including, sort of) If not, a workaround could be to not create a user library that aliases a system library name, or we could split out that function into another library (but which, and when would it be linked in?)

@sbc100
Copy link
Collaborator

sbc100 commented Nov 30, 2021

But hasn't emscripten_GetProcAddress always been in native code and always been part of libGL?

(I looks like emscripten_GetProcAddress has been part of gl.c since 2014: 475548d)

@sbc100
Copy link
Collaborator

sbc100 commented Nov 30, 2021

Here is my theory. The issue is caused by -L/foo/bar path containing libGL.a which aliases the system library but in the past we didn't include system libraries via -lGL but via the pull path.. so aliasing in the past was not possible with emscirpten and both copies of libGL.a were being included in the link.

I seem to remember recently changing from /path/to/libGL.a to -lGL for system libraries...

@sbc100
Copy link
Collaborator

sbc100 commented Nov 30, 2021

I found the relevant changes, which were part of 2.0.24: #14342 and #14351

@parasti
Copy link
Contributor Author

parasti commented Dec 1, 2021

@sbc100 I think this is exactly what's happening. For the record, here is the full output of the link step.

$ make -f Makefile.emscripten
emcc -o js/neverball.js ball/demo.bc ball/demo_dir.bc ball/game_client.bc ball/game_common.bc ball/game_draw.bc ball/game_proxy.bc ball/game_server.bc ball/hud.bc ball/level.bc ball/main.bc ball/progress.bc ball/score.bc ball/set.bc ball/st_ball.bc ball/st_conf.bc ball/st_demo.bc ball/st_done.bc ball/st_fail.bc ball/st_goal.bc ball/st_help.bc ball/st_level.bc ball/st_name.bc ball/st_over.bc ball/st_pause.bc ball/st_play.bc ball/st_save.bc ball/st_set.bc ball/st_shared.bc ball/st_start.bc ball/st_title.bc ball/util.bc share/array.bc share/audio.bc share/ball.bc share/base_config.bc share/base_image.bc share/binary.bc share/cmd.bc share/common.bc share/config.bc share/dir.bc share/fetch_emscripten.bc share/font.bc share/fs_common.bc share/fs_jpg.bc share/fs_ov.bc share/fs_png.bc share/fs_stdio.bc share/miniz.bc share/geom.bc share/glext.bc share/gui.bc share/hmd_null.bc share/image.bc share/joy.bc share/lang.bc share/list.bc share/log.bc share/mtrl.bc share/package.bc share/part.bc share/queue.bc share/solid_all.bc share/solid_base.bc share/solid_draw.bc share/solid_sim_sol.bc share/solid_vary.bc share/st_common.bc share/state.bc share/text.bc share/theme.bc share/tilt_null.bc share/vec3.bc share/video.bc -O3 -std=gnu99 -Wall -Ishare -DNDEBUG -I../gl4es/include -s USE_SDL=2 -s USE_SDL_TTF=2 -s USE_VORBIS=1 -s USE_LIBPNG=1 -s USE_LIBJPEG=1 -L../gl4es/lib -lGL -s ALLOW_MEMORY_GROWTH=1 -s FULL_ES2=1 -s INVOKE_RUN=0 -s EXPORTED_RUNTIME_METHODS="['callMain']" -s HTML5_SUPPORT_DEFERRING_USER_SENSITIVE_REQUESTS=0 -s LLD_REPORT_UNDEFINED -s FETCH=1 -lidbfs.js --preload-file data-emscripten.zip@/data/base.zip --use-preload-cache
wasm-ld: error: C:\Development\emsdk\upstream\emscripten\cache\sysroot\lib\wasm32-emscripten\libSDL2.a(SDL_emscriptenopengles.c.o): undefined symbol: eglGetProcAddress
wasm-ld: error: ../gl4es/lib\libGL.a(loader.c.o): undefined symbol: emscripten_GetProcAddress
emcc: error: 'C:/Development/emsdk/upstream/bin\wasm-ld.exe -o js/neverball.wasm ball/demo.bc ball/demo_dir.bc ball/game_client.bc ball/game_common.bc ball/game_draw.bc ball/game_proxy.bc ball/game_server.bc ball/hud.bc ball/level.bc ball/main.bc ball/progress.bc ball/score.bc ball/set.bc ball/st_ball.bc ball/st_conf.bc ball/st_demo.bc ball/st_done.bc ball/st_fail.bc ball/st_goal.bc ball/st_help.bc ball/st_level.bc ball/st_name.bc ball/st_over.bc ball/st_pause.bc ball/st_play.bc ball/st_save.bc ball/st_set.bc ball/st_shared.bc ball/st_start.bc ball/st_title.bc ball/util.bc share/array.bc share/audio.bc share/ball.bc share/base_config.bc share/base_image.bc share/binary.bc share/cmd.bc share/common.bc share/config.bc share/dir.bc share/fetch_emscripten.bc share/font.bc share/fs_common.bc share/fs_jpg.bc share/fs_ov.bc share/fs_png.bc share/fs_stdio.bc share/miniz.bc share/geom.bc share/glext.bc share/gui.bc share/hmd_null.bc share/image.bc share/joy.bc share/lang.bc share/list.bc share/log.bc share/mtrl.bc share/package.bc share/part.bc share/queue.bc share/solid_all.bc share/solid_base.bc share/solid_draw.bc share/solid_sim_sol.bc share/solid_vary.bc share/st_common.bc share/state.bc share/text.bc share/theme.bc share/tilt_null.bc share/vec3.bc share/video.bc -L../gl4es/lib -LC:\Development\emsdk\upstream\emscripten\cache\sysroot\lib\wasm32-emscripten C:\Development\emsdk\upstream\emscripten\cache\sysroot\lib\wasm32-emscripten\libvorbis.a C:\Development\emsdk\upstream\emscripten\cache\sysroot\lib\wasm32-emscripten\libogg.a C:\Development\emsdk\upstream\emscripten\cache\sysroot\lib\wasm32-emscripten\libjpeg.a C:\Development\emsdk\upstream\emscripten\cache\sysroot\lib\wasm32-emscripten\libSDL2_ttf.a C:\Development\emsdk\upstream\emscripten\cache\sysroot\lib\wasm32-emscripten\libharfbuzz.a C:\Development\emsdk\upstream\emscripten\cache\sysroot\lib\wasm32-emscripten\libSDL2.a C:\Development\emsdk\upstream\emscripten\cache\sysroot\lib\wasm32-emscripten\libfreetype.a C:\Development\emsdk\upstream\emscripten\cache\sysroot\lib\wasm32-emscripten\libpng.a C:\Development\emsdk\upstream\emscripten\cache\sysroot\lib\wasm32-emscripten\libz.a --whole-archive -lfetch -lGL --no-whole-archive -lal -lhtml5 -lstubs -lc -lcompiler_rt -lc++-noexcept -lc++abi-noexcept -ldlmalloc -lc_rt -lsockets -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr --allow-undefined-file=C:\Users\parasti\AppData\Local\Temp\tmp90fjl84u.undefined --strip-debug --export-if-defined=main --export-if-defined=stackSave --export-if-defined=stackRestore --export-if-defined=stackAlloc --export-if-defined=__wasm_call_ctors --export-if-defined=__errno_location --export-if-defined=malloc --export-if-defined=free --export-if-defined=memcpy --export-if-defined=saveSetjmp --export-if-defined=setThrew --export-if-defined=_get_tzname --export-if-defined=_get_daylight --export-if-defined=_get_timezone --export-if-defined=memalign --export-if-defined=__dl_seterr --export-if-defined=__start_em_asm --export-if-defined=__stop_em_asm --export-table -z stack-size=5242880 --initial-memory=16777216 --entry=main --max-memory=2147483648 --global-base=1024' failed (returned 1)
make: *** [Makefile.emscripten:155: js/neverball.js] Error 1

I made the following change and the compilation succeeded.

-LDFLAGS := -L../gl4es/lib -lGL
+LDFLAGS := ../gl4es/lib/libGL.a

I can't really wrap my head around why I don't need the -lGL for the system library, but it must have been linked in automatically? Anyway, the resulting program runs fine, so I believe the fix is entirely sufficient. Thanks for the quick response!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants