emscripten-core / emscripten

Emscripten: An LLVM-to-WebAssembly Compiler
Other
25.63k stars 3.28k forks source link

[question] Mixing C and C++ code if -fwasm-exceptions enabled #18500

Open harsszegi opened 1 year ago

harsszegi commented 1 year ago

Hi,

most probably it is related to https://github.com/emscripten-core/emscripten/issues/11219, but I'd like to have a confirmation. I am building C++ code into a library with "-fwasm-exceptions", which means that "libc++-except.a" is being pulled in during linking. However I need to create a C library (which by default pulls in "libc++-noexcept.a") - as I have different CFLAGS and CXXFLAGS, I am adding "-fwasm-exceptions" only to the CXXFLAGS. And finally I need to link them together. Currently it fails with duplicate symbols as lot of __cxa stuff is being pulled in duplicated from "libc++-except.a" and "libc++-noexcept.a".

I have sorted the issue out via adding "-fwasm-exceptions" to CFLAGS as well, which sounds kinda counterintuitive.

Is it the appropriate way to sort this issue out? Thanks,

sbc100 commented 1 year ago

When you say "C library" do you mean an ar archive file (.a file)? If so then it won't include any reference to libc++-except.a or to libc++-noexcept.a.

When you link the two libraries together to form the final binary just make sure you pass -fwasm-exceptions at link time it it should pull in the correct libc++-except.a library.

sbc100 commented 1 year ago

Also, if you were to link a pure C program (with emcc and not em++) then it should not include any version libc++.. since that is a C++-only library.

harsszegi commented 1 year ago

Yeah, I am producing .a files. Btw from which emcc version (I'm using 3.1.3 currently) is the "should not include libc++" feature available? I jusst tried with a "hello world" application, e.g. something like this:

add_library(foo foo.cpp bar.c) add_executable(baz baz.cpp) target_link_libraries(baz foo)

And CMake compiler detection picks up this:

set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/work/.emscripten_cache/sysroot/include/SDL;/work/.emscripten_cache/sysroot/include/compat;/opt/emsdk-main/upstream/lib/clang/14.0.0/include;/work/.emscripten_cache/sysroot/include") set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "GL;al;html5;stubs-debug;noexit;c-debug;dlmalloc;compiler_rt;c++-noexcept;c++abi-noexcept;sockets") set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/work/.emscripten_cache/sysroot/lib/wasm32-emscripten") set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "")

set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/work/.emscripten_cache/sysroot/include/SDL;/work/.emscripten_cache/sysroot/include/compat;/work/.emscripten_cache/sysroot/include/c++/v1;/opt/emsdk-main/upstream/lib/clang/14.0.0/include;/work/.emscripten_cache/sysroot/include") set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "GL;al;html5;stubs-debug;noexit;c-debug;dlmalloc;compiler_rt;c++-except;c++abi-except;unwind-except;sockets") set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/work/.emscripten_cache/sysroot/lib/wasm32-emscripten") set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "")

My settings:

CC=emcc CXX=em++ CFLAGS=-Wno-format-security -Werror=return-type CXXFLAGS=-Wno-format-security -Werror=return-type -fwasm-exceptions -std=c++17

sbc100 commented 1 year ago

Right, but you are only linking a single executable there.. so it should only use the C++ link settings, no? The combined program in a C++ program.

BTW where are you getting things like CMAKE_CXX_IMPLICIT_LINK_LIBRARIES from? Where are those setting specified?

Are you sure that add_library(foo foo.cpp bar.c) is building a static library? Can you show the full link command that cmake ends up using? You can show this with ninja -v or make VERBOSE=1 if you use make.

harsszegi commented 1 year ago

Re CMAKE_CXX_IMPLICIT_LINK_LIBRARIES, I have zero idea where does CMake sets this from :( This is a CMake internal thing, I can't even change that. My bet that this is a compiler detection part of CMake, e.g. when it executes certain compiler tests to figure out the supported compiler features.

Re the link line. I need to simplify the situation my hello world setup to figure out what triggers the linker / CMake (god knows that) to add BOTH the except and noexception libraries on one link line. Currently I have this (this is the real world link command, not by "hello world" link - for some strange reason that setup doesn't produce the issue anymore).

em++: error: '/opt/emsdk-main/upstream/bin/wasm-ld -o cindertest.wasm CMakeFiles/cindertest.dir/test.cpp.o /home/cognoid/.conandata/cinderpackage/master+1-6cd9a68-dirty/cognex/master/package/5cdad9bcca112297413e7a06db2b66ad10f4a0e9/lib/libcinder.a /home/cognoid/.conandata/cinderpackage/master+1-6cd9a68-dirty/cognex/master/package/5cdad9bcca112297413e7a06db2b66ad10f4a0e9/lib/libcindergl.a /home/cognoid/.conandata/freetype/2.12.1+9-6e8ca24/cognex/master/package/f0acabdda8916b97b46e53472ab9354f9db0cfc7/lib/libfreetyped.a /home/cognoid/.conandata/libpng/1.6.37+24-fddfc75/cognex/master/package/5d5819f14062fd28b092e467ade4adfbdd0d9851/lib/libpng16d.a /home/cognoid/.conandata/zlib/1.2.12+33-6be05d7/cognex/master/package/c7ead44e92a4dbbf60eed72dc07233238dd48aaf/lib/libz.a /work/.emscripten_cache/sysroot/lib/wasm32-emscripten/libc++-noexcept.a /work/.emscripten_cache/sysroot/lib/wasm32-emscripten/libc++abi-noexcept.a -L/work/.emscripten_cache/sysroot/lib/wasm32-emscripten -lGL -lal -lhtml5 -lstubs-debug -lnoexit -lc-debug -ldlmalloc -lcompiler_rt -lc++-except -lc++abi-except -lunwind-except -lsockets -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr -mllvm -wasm-enable-eh -mllvm -exception-model=wasm --import-undefined --export-if-defined=main --export-if-defined=start_em_asm --export-if-defined=stop_em_asm --export-if-defined=__stdio_exit --export=emscripten_stack_get_end --export=emscripten_stack_get_free --export=emscripten_stack_init --export=stackSave --export=stackRestore --export=stackAlloc --export=wasm_call_ctors --export=errno_location --export=malloc --export=setThrew --export=free --export=saveSetjmp --export=memalign --export-table -z stack-size=5242880 --initial-memory=16777216 --no-entry --max-memory=16777216 --global-base=1024' failed (returned 1)

harsszegi commented 1 year ago

Ok, I'm a bit lost. I have checked the link.txt file in the build folder and it has this:

/opt/emsdk-main/upstream/emscripten/em++ -Wno-format-security -Werror=return-type -fwasm-exceptions -std=c++17 -g CMakeFiles/cindertest.dir/test.cpp.o -o cindertest /home/cognoid/.conandata/cinderpackage/master+1-6cd9a68-dirty/cognex/master/package/5cdad9bcca112297413e7a06db2b66ad10f4a0e9/lib/libcinder.a /home/cognoid/.conandata/cinderpackage/master+1-6cd9a68-dirty/cognex/master/package/5cdad9bcca112297413e7a06db2b66ad10f4a0e9/lib/libcindergl.a /home/cognoid/.conandata/freetype/2.12.1+9-6e8ca24/cognex/master/package/f0acabdda8916b97b46e53472ab9354f9db0cfc7/lib/libfreetyped.a /home/cognoid/.conandata/libpng/1.6.37+24-fddfc75/cognex/master/package/5d5819f14062fd28b092e467ade4adfbdd0d9851/lib/libpng16d.a /home/cognoid/.conandata/zlib/1.2.12+33-6be05d7/cognex/master/package/c7ead44e92a4dbbf60eed72dc07233238dd48aaf/lib/libz.a -lm -lc++-noexcept -lc++abi-noexcept

So it pulls in the "noexcept" libraries and it enables exceptions :(

sbc100 commented 1 year ago

Linking of all those system libraries (-lm -lc++-noexcept -lc++abi-noexcept) should be done implicitly by em++. They should not be being passed explicitly to em++ like that.

Can you figure out where those are coming from?

harsszegi commented 1 year ago

Aok, will try to figure it out who adds it