Search code examples
linkerwebassemblyemscripten

Can Emscripten link libraries (static ".a" archive files) built for MacOS?


I am trying to link some libraries for my WebAssembly project.

I am using a CMakeLists.txt file rather than directly in the command line.

I have read that it is possible to link static libraries in Emscripten, using archive files (.a) which I conveniently already have built and tested or the MacOS version of the project.

Can I use the same .a files for Emscripten?


I have added the include directory in CMakeLists.txt like so:

include_directories(
    ...
    "${CMAKE_SOURCE_DIR}/../External/macports/ffmpeg_5.1.2_6/include/"
)

And I have added the link directory like so:

link_directories(
    ...
    "${PROJECT_SOURCE_DIR}/../External/macports/ffmpeg_5.1.2_6/lib/"
)

The next line is for the executable, which I understand goes before the library files (below):

add_executable(${PROJECT_NAME} ${SOURCE_FILES})

And finally I am adding the library files like so:

link_libraries(
    "${PROJECT_SOURCE_DIR}/../External/macports/ffmpeg_5.1.2_6/lib/libavcodec.a"
    "${PROJECT_SOURCE_DIR}/../External/macports/ffmpeg_5.1.2_6/lib/libavdevice.a"
    "${PROJECT_SOURCE_DIR}/../External/macports/ffmpeg_5.1.2_6/lib/libavfilter.a"
    "${PROJECT_SOURCE_DIR}/../External/macports/ffmpeg_5.1.2_6/lib/libavformat.a"
    "${PROJECT_SOURCE_DIR}/../External/macports/ffmpeg_5.1.2_6/lib/libavutil.a"
    "${PROJECT_SOURCE_DIR}/../External/macports/ffmpeg_5.1.2_6/lib/libswresample.a"
    "${PROJECT_SOURCE_DIR}/../External/macports/ffmpeg_5.1.2_6/lib/libswscale.a"
)

The program builds (reaches 100%) but fails at linking with the following errors:

Linking CXX executable Build\project_wasm.html
wasm-ld: error: CMakeFiles/project_wasm.dir/C_/Users/.../VideoPlayer.cpp.o: undefined symbol: av_frame_unref
wasm-ld: error: CMakeFiles/project_wasm.dir/C_/Users/.../VideoPlayer.cpp.o: undefined symbol: av_packet_unref
wasm-ld: error: CMakeFiles/project_wasm.dir/C_/Users/.../VideoPlayer.cpp.o: undefined symbol: avcodec_close
wasm-ld: error: CMakeFiles/project_wasm.dir/C_/Users/.../VideoPlayer.cpp.o: undefined symbol: avcodec_close
wasm-ld: error: CMakeFiles/project_wasm.dir/C_/Users/.../VideoPlayer.cpp.o: undefined symbol: av_frame_unref
wasm-ld: error: CMakeFiles/project_wasm.dir/C_/Users/.../VideoPlayer.cpp.o: undefined symbol: av_packet_unref
wasm-ld: error: CMakeFiles/project_wasm.dir/C_/Users/.../VideoPlayer.cpp.o: undefined symbol: avcodec_close
wasm-ld: error: CMakeFiles/project_wasm.dir/C_/Users/.../VideoPlayer.cpp.o: undefined symbol: avcodec_close
wasm-ld: error: CMakeFiles/project_wasm.dir/C_/Users/.../VideoPlayer.cpp.o: undefined symbol: av_malloc
wasm-ld: error: CMakeFiles/project_wasm.dir/C_/Users/.../VideoPlayer.cpp.o: undefined symbol: av_packet_alloc
wasm-ld: error: CMakeFiles/project_wasm.dir/C_/Users/.../VideoPlayer.cpp.o: undefined symbol: av_frame_alloc
wasm-ld: error: CMakeFiles/project_wasm.dir/C_/Users/.../VideoPlayer.cpp.o: undefined symbol: avcodec_receive_frame
wasm-ld: error: CMakeFiles/project_wasm.dir/C_/Users/.../VideoPlayer.cpp.o: undefined symbol: avcodec_send_packet
wasm-ld: error: CMakeFiles/project_wasm.dir/C_/Users/.../VideoPlayer.cpp.o: undefined symbol: av_mallocz
wasm-ld: error: CMakeFiles/project_wasm.dir/C_/Users/.../VideoPlayer.cpp.o: undefined symbol: swr_alloc
wasm-ld: error: CMakeFiles/project_wasm.dir/C_/Users/.../VideoPlayer.cpp.o: undefined symbol: av_get_channel_layout_nb_channels
wasm-ld: error: CMakeFiles/project_wasm.dir/C_/Users/.../VideoPlayer.cpp.o: undefined symbol: av_get_default_channel_layout
wasm-ld: error: CMakeFiles/project_wasm.dir/C_/Users/.../VideoPlayer.cpp.o: undefined symbol: av_opt_set_int
wasm-ld: error: CMakeFiles/project_wasm.dir/C_/Users/.../VideoPlayer.cpp.o: undefined symbol: av_opt_set_int
wasm-ld: error: CMakeFiles/project_wasm.dir/C_/Users/.../VideoPlayer.cpp.o: undefined symbol: av_opt_set_sample_fmt

Solution

  • No, emscripten cannot use object files built for macOS, or any other operating system.

    Emscripten is a cross compiler and all objects and libraries that you pass to it must be built by emscripten itself (or rather, they must be object files built for the wasm32-unknown-emscripten llvm target).