Skip to content
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

Ports libpng and libfreetype uses emscripten_longjmp (-s SUPPORT_LONGJMP=wasm) #19001

Closed
codeart1st opened this issue Mar 18, 2023 · 5 comments · Fixed by #19004
Closed

Ports libpng and libfreetype uses emscripten_longjmp (-s SUPPORT_LONGJMP=wasm) #19001

codeart1st opened this issue Mar 18, 2023 · 5 comments · Fixed by #19004

Comments

@codeart1st
Copy link

Version of emscripten/emsdk:
emcc -v
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.34 (57b21b8)
clang version 17.0.0 (https://github.com/llvm/llvm-project a031f72187ce495b9faa4ccf99b1e901a3872f4b)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /emsdk/upstream/bin

Failing command line in full:

warning: undefined symbol: emscripten_longjmp (referenced by top-level compiled C/C++ code)
emcc: warning: warnings in JS library compilation [-Wjs-compiler]
Traceback (most recent call last):
  File "/emsdk/upstream/emscripten/emcc.py", line 4420, in <module>
    sys.exit(main(sys.argv))
  File "/usr/lib/python3.10/contextlib.py", line 79, in inner
    return func(*args, **kwds)
  File "/emsdk/upstream/emscripten/emcc.py", line 4413, in main
    ret = run(args)
  File "/emsdk/upstream/emscripten/emcc.py", line 1358, in run
    phase_post_link(options, state, wasm_target, wasm_target, target)
  File "/usr/lib/python3.10/contextlib.py", line 79, in inner
    return func(*args, **kwds)
  File "/emsdk/upstream/emscripten/emcc.py", line 3124, in phase_post_link
    phase_emscript(options, in_wasm, wasm_target, memfile)
  File "/usr/lib/python3.10/contextlib.py", line 79, in inner
    return func(*args, **kwds)
  File "/emsdk/upstream/emscripten/emcc.py", line 3151, in phase_emscript
    emscripten.run(in_wasm, wasm_target, final_js, memfile)
  File "/emsdk/upstream/emscripten/emscripten.py", line 945, in run
    emscript(in_wasm, out_wasm, outfile_js, memfile)
  File "/emsdk/upstream/emscripten/emscripten.py", line 433, in emscript
    module = create_module(receiving, metadata, forwarded_json['librarySymbols'])
  File "/emsdk/upstream/emscripten/emscripten.py", line 831, in create_module
    assert not metadata.invokeFuncs, "invoke_ functions exported but exceptions and longjmp are both disabled"
AssertionError: invoke_ functions exported but exceptions and longjmp are both disabled

Full link command and output with -v appended:

/emsdk/upstream/emscripten/emcc -O2 -fwasm-exceptions -s USE_ZLIB=1 -s USE_FREETYPE=1 -s USE_LIBPNG=1 -s USE_LIBJPEG=1 -s ENVIRONMENT='worker' -s MODULARIZE=1 -s ALLOW_MEMORY_GROWTH=1 -s 'EXPORTED_RUNTIME_METHODS=["cwrap", "FS"]' -s ERROR_ON_UNDEFINED_SYMBOLS=0 -lworkerfs.js [...]

The ports for libpng and libfreetype are use emscripten_longjmp. Is there a simple way to modify this behavior? Can i pass -s SUPPORT_LONGJMP=wasm to port build?

@codeart1st codeart1st changed the title Ports libpng and libfreetype uses emscripten_longjmp Ports libpng and libfreetype uses emscripten_longjmp (-s SUPPORT_LONGJMP=wasm) Mar 18, 2023
@DeusFacticius
Copy link

Probably obvious, but for the sake of others who follow the same path as myself and end up here -- this issue also arises even when libpng and / or libfreetype are only transitive dependencies, which is the case if using SDL2_Image with png support (-sUSE_SDL_IMAGE=2 -sSDL2_IMAGE_FORMATS='["png"]').

While I can confirm the SDL2_image+png case, the SDL2_ttf+libfreetype case is only assumed. I tried adding -sUSE_SDL_TTF=2 to my project to test it, and while it did download and build the libfreetype port, I did not have any linker errors -- but this may be due to the lack of any actual calls into SDL_ttf in the code, so the offending reference may have been elided out.

Removing png from the SDL2_IMAGE_FORMATS list resolves the issue, as it seems to remove the dependency on libpng by the time the linker runs. Unfortunately this isn't actually a viable workaround for me, as I need to load png images 😅

For additional context: the root of the issue is that the value of the SUPPORT_LONGJMP setting used when a library is built must match with the value used when building an executable that depends on the library. In this case, it looks like the libpng port builds by default with -sSUPPORT_LONGJMP=emscripten, thus if a downstream project uses -fwasm-exceptions (which implicitly configures -sSUPPORT_LONGJMP=wasm), the linker is unable to resolve a reference to the emscipten-flavored substitute for longjmp; and there isn't any obvious way to conditionally alter the build settings of an emscripten-ports provided library. Even if there is, my case is made slightly more complicated by the fact that libpng is a transitive rather than direct dependency.

Platform info:
OSX Catalina (10.15.7)

$ em++ -v
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.33 (c1927f22708aa9a26a5956bab61de083e8d3e463)
clang version 17.0.0 (https://github.com/llvm/llvm-project 671eeece457f6a5da7489f7b48f7afae55327b8b)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /Users/<redacted>/src/emsdk/upstream/bin

@sbc100
Copy link
Collaborator

sbc100 commented Mar 19, 2023

So one of these libraries uses setjmp/longjmp. Do you know which one it is? I wonder if we can build that library without the setjmp/longjmp usage?

Building a custom -wasm-exceptions variant of the library is possible, but would be better avoided if we can.

Can you confirm if freetype that is using setjmp/longjmp?

@codeart1st
Copy link
Author

codeart1st commented Mar 19, 2023

I used emnm [library_port_path] | grep emscripten_longjmp to find the cause of my problem after update the emsdk and fixed my own stuff. I digged into it, and found out that libfreetype and libpng contains emscripten_longjmp calls. So there sourcecode should use it.

*library_port_path is only a placeholder

The problem started for me with the change in 3.1.32.

SUPPORT_LONGJMP's default value now depends on the exception mode. If Wasm EH (-fwasm-exception) is used, it defaults to wasm, and if Emscripten EH (-sDISABLE_EXCEPTION_CATCHING=0) is used or no exception support is used, it defaults to emscripten. Previously it always defaulted to emscripten, so when a user specified -fwasm-exceptions, it resulted in Wasm EH + Emscripten SjLj, the combination we do not intend to support for the long term.

@DeusFacticius
Copy link

So one of these libraries uses setjmp/longjmp. Do you know which one it is? I wonder if we can build that library without the setjmp/longjmp usage?

Building a custom -wasm-exceptions variant of the library is possible, but would be better avoided if we can.

Can you confirm if freetype that is using setjmp/longjmp?

Also for reference Re: libpng:
#16572 (comment)

(@sbc100 is probably already aware of this though, as the comment in the link is in response to their own question in a similar thread 😉 )

@codeart1st
Copy link
Author

sbc100 added a commit that referenced this issue Mar 19, 2023
For libpng we simply avoid the use of setjmp/longjmp completely.

For libfreetype the use of setjmp/longjmp is not optional so we build a
variant of the library that uses wasm exceptions for setjmp/longjmp
support.

Fixes: #19001
sbc100 added a commit that referenced this issue Mar 20, 2023
For libpng we simply avoid the use of setjmp/longjmp completely.

For libfreetype the use of setjmp/longjmp is not optional so we build a
variant of the library that uses wasm exceptions for setjmp/longjmp
support.

Fixes: #19001
sbc100 added a commit that referenced this issue Mar 20, 2023
For libpng we simply avoid the use of setjmp/longjmp completely.

For libfreetype the use of setjmp/longjmp is not optional so we build a
variant of the library that uses wasm exceptions for setjmp/longjmp
support.

Fixes: #19001
sbc100 added a commit that referenced this issue Mar 20, 2023
For libpng we simply avoid the use of setjmp/longjmp completely.

For libfreetype the use of setjmp/longjmp is not optional so we build a
variant of the library that uses wasm exceptions for setjmp/longjmp
support.

Fixes: #19001
sbc100 added a commit that referenced this issue Mar 21, 2023
For libpng we simply avoid the use of setjmp/longjmp completely.

For libfreetype the use of setjmp/longjmp is not optional so we build a
variant of the library that uses wasm exceptions for setjmp/longjmp
support.

Fixes: #19001
sbc100 added a commit that referenced this issue Mar 21, 2023
For libpng we simply avoid the use of setjmp/longjmp completely.

For libfreetype the use of setjmp/longjmp is not optional so we build a
variant of the library that uses wasm exceptions for setjmp/longjmp
support.

Fixes: #19001
sbc100 added a commit that referenced this issue Mar 21, 2023
Sadly, even though libpng can be compiled with setjmp/longjmp support
some libraries such as openjpeg assume that setjmp support is included.

Fixes: #19001
sbc100 added a commit that referenced this issue Mar 21, 2023
Sadly, even though libpng can be compiled with setjmp/longjmp support
some libraries such as openjpeg assume that setjmp support is included.

Fixes: #19001
sbc100 added a commit that referenced this issue Mar 21, 2023
)

Sadly, even though libpng can be compiled with setjmp/longjmp support
some libraries such as openjpeg assume that setjmp support is included.

Fixes: #19001
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

Successfully merging a pull request may close this issue.

3 participants