emscripten-core / emscripten

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

problem with build cairo using emscripten(works fine if I just use cmake) #13284

Open lwyj123 opened 3 years ago

lwyj123 commented 3 years ago

I built a simple demo for rendering a simple arch in window using SDL2 + cairo. But I get some error when I try to do it with emscripten and get the error like error: undefined symbol: cairo_set_line_width (referenced by top-level compiled C/C++ code).

Here is the CMakeLists.txt

cmake_minimum_required(VERSION 3.10)

project(Karaoke)

# cmake
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)

# Source files
set(SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/source")
set(EXTERNAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external")
set(SOURCES "${SRC_DIR}/main.cpp")

file(GLOB SRC
    CONFIGURE_DEPENDS
    "include/*.h"
    "source/*.cpp"
)
add_executable(main ${SRC})
target_include_directories(main PRIVATE "include")

target_compile_features(main PUBLIC cxx_std_17)
set_target_properties(main PROPERTIES CXX_EXTENSIONS OFF)

# # OpenGL
# find_package(OpenGL REQUIRED)
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")

# Cairo
if (${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten")
else ()
find_package(Cairo)
if(CAIRO_FOUND)
  message("Cairo found")
else()
  message(FATAL_ERROR "Cairo not found")
endif()
endif()

target_include_directories(main PRIVATE ${CAIRO_INCLUDE_DIRS})
target_link_libraries(main ${CAIRO_LIBRARIES})

message(${CAIRO_INCLUDE_DIRS} ${CAIRO_LIBRARIES})

# SDL 2

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCMAKE_EXPORT_COMPILE_COMMANDS=1")

if (${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s USE_SDL=2 -s USE_SDL_IMAGE=2")
  set(SDL2_LIBRARIES "-s USE_SDL=2")
  set(SDL2_IMAGE_LIBRARIES "-s USE_SDL_IMAGE=2")
  set(SDL2_TTF_LIBRARIES "-s USE_SDL_TTF=2")
else ()
  include(FindPkgConfig)
  find_package(SDL2 REQUIRED)
  find_package(SDL2_Image REQUIRED)
  find_package(SDL2_ttf REQUIRED)
  pkg_search_module(SDL2 REQUIRED sdl2)
  pkg_search_module(SDL2IMAGE REQUIRED SDL2_image>=2.0.0)
  pkg_search_module(SDL2TTF REQUIRED SDL2_ttf>=2.0.0)

  include_directories(${SDL2_INCLUDE_DIRS} ${SDL2IMAGE_INCLUDE_DIRS} ${SDL2TFF_INCLUDE_DIRS})
  target_link_libraries(main ${SDL2_LIBRARIES} ${SDL2_IMAGE_LIBRARIES} ${SDL2_TTF_LIBRARIES})
endif ()

## end part
cmake_policy (SET CMP0072 NEW)

# Assets
file(COPY assets DESTINATION ${CMAKE_BINARY_DIR})

And below is the shell script I used for dev.

#!/bin/bash
emcmake cmake -S . -B build -D CAIRO_LIBRARIES=/usr/local/Cellar/cairo/1.16.0_4/lib/libcairo.dylib -D CAIRO_INCLUDE_DIRS=/usr/local/Cellar/cairo/1.16.0_4/include/cairo
cd build
emmake make

But after I run the command cmmake make, I get the error log:

Scanning dependencies of target main
[ 33%] Building CXX object CMakeFiles/main.dir/source/MainWindow.cpp.o
[ 66%] Building CXX object CMakeFiles/main.dir/source/main.cpp.o
[100%] Linking CXX executable main.js
error: undefined symbol: cairo_arc (referenced by top-level compiled C/C++ code)
warning: Link with `-s LLD_REPORT_UNDEFINED` to get more information on undefined symbols
warning: To disable errors for undefined symbols use `-s ERROR_ON_UNDEFINED_SYMBOLS=0`
warning: _cairo_arc may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
error: undefined symbol: cairo_create (referenced by top-level compiled C/C++ code)
warning: _cairo_create may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
error: undefined symbol: cairo_fill (referenced by top-level compiled C/C++ code)
warning: _cairo_fill may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
error: undefined symbol: cairo_image_surface_create_for_data (referenced by top-level compiled C/C++ code)
warning: _cairo_image_surface_create_for_data may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
error: undefined symbol: cairo_rectangle (referenced by top-level compiled C/C++ code)
warning: _cairo_rectangle may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
error: undefined symbol: cairo_set_line_width (referenced by top-level compiled C/C++ code)
warning: _cairo_set_line_width may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
error: undefined symbol: cairo_set_source_rgba (referenced by top-level compiled C/C++ code)
warning: _cairo_set_source_rgba may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
error: undefined symbol: cairo_stroke (referenced by top-level compiled C/C++ code)
warning: _cairo_stroke may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
error: undefined symbol: cairo_surface_set_device_scale (referenced by top-level compiled C/C++ code)
warning: _cairo_surface_set_device_scale may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
Error: Aborting compilation due to previous errors
em++: error: '/Users/someone/lab/emsdk/node/12.18.1_64bit/bin/node /Users/someone/lab/emsdk/upstream/emscripten/src/compiler.js /var/folders/gm/1xp7t1wj1lx_8298gt0xxf2h0000gp/T/tmp3k7i7vdm.txt' failed (1)
make[2]: *** [main.js] Error 1
make[1]: *** [CMakeFiles/main.dir/all] Error 2
make: *** [all] Error 2

but if I run the native cmake like below

#!/bin/bash
cmake -S . -B build
cmake --build build -j
./build/main

It just works fine. image

Noxdor commented 3 years ago

@lwyj123 getting the same error with SDL2. CMakeLists.txt (top level)

cmake_minimum_required(VERSION 3.13)
project(MRT1-C-Praktikum)
enable_language(C)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s USE_SDL=2")

# Unterverzeichnisse
add_subdirectory(mrt_lib)

# Ausführbares Programm
add_executable(fraktal_sets main.c)
target_link_libraries(fraktal_sets PUBLIC mrt_lib)

CMakeLists.txt (sub-level, inside a library)

add_library(mrt_lib src/fraktal.c src/graphic.c src/dialog.c)
target_include_directories(mrt_lib PUBLIC include)

running emcmake cmake .. and then emmake make produces the following errors:

make: make
[ 66%] Built target mrt_lib
[ 83%] Linking C executable fraktal_sets.js
error: undefined symbol: SDL_CreateRenderer (referenced by top-level compiled C/C++ code)
warning: Link with `-s LLD_REPORT_UNDEFINED` to get more information on undefined symbols
warning: To disable errors for undefined symbols use `-s ERROR_ON_UNDEFINED_SYMBOLS=0`
warning: _SDL_CreateRenderer may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
error: undefined symbol: SDL_CreateTexture (referenced by top-level compiled C/C++ code)
warning: _SDL_CreateTexture may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
error: undefined symbol: SDL_CreateWindow (referenced by top-level compiled C/C++ code)
warning: _SDL_CreateWindow may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
error: undefined symbol: SDL_DestroyTexture (referenced by top-level compiled C/C++ code)
warning: _SDL_DestroyTexture may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
error: undefined symbol: SDL_RenderClear (referenced by top-level compiled C/C++ code)
warning: _SDL_RenderClear may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
error: undefined symbol: SDL_RenderCopy (referenced by top-level compiled C/C++ code)
warning: _SDL_RenderCopy may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
error: undefined symbol: SDL_RenderDrawPoint (referenced by top-level compiled C/C++ code)
warning: _SDL_RenderDrawPoint may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
error: undefined symbol: SDL_RenderPresent (referenced by top-level compiled C/C++ code)
warning: _SDL_RenderPresent may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
error: undefined symbol: SDL_RenderSetLogicalSize (referenced by top-level compiled C/C++ code)
warning: _SDL_RenderSetLogicalSize may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
error: undefined symbol: SDL_SetHint (referenced by top-level compiled C/C++ code)
warning: _SDL_SetHint may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
error: undefined symbol: SDL_SetRenderDrawColor (referenced by top-level compiled C/C++ code)
warning: _SDL_SetRenderDrawColor may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
error: undefined symbol: SDL_SetRenderTarget (referenced by top-level compiled C/C++ code)
warning: _SDL_SetRenderTarget may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
Error: Aborting compilation due to previous errors
emcc: error: '/home/lennart/tools/emsdk/node/12.18.1_64bit/bin/node /home/lennart/tools/emsdk/upstream/emscripten/src/compiler.js /tmp/tmp9pqun6ca.txt' failed (1)
make[2]: *** [CMakeFiles/fraktal_sets.dir/build.make:88: fraktal_sets.js] Error 1
make[1]: *** [CMakeFiles/Makefile2:96: CMakeFiles/fraktal_sets.dir/all] Error 2
make: *** [Makefile:84: all] Error 2

My main problem with the build process with emscripten (+ cmake) is, that I still don't fully understand, where and how I have to add the SDL Library. I understand it, if I only have one source file and how to add it there with emcc. But with a larger projekt, it becomes a bit confusing and unfortunately after hours of searching I can't find information about it, neither on emscripten.org.

The project compiled just fine of course, when only using CMake (the CMakeLists.txt files I changed since then), the errors are appearing only now, since I'm trying to bring the program into the web.

pinguin999 commented 3 years ago

@Noxdor add to your target_link_libraries the SDL2 lib like here:

target_link_libraries(jngl PUBLIC ${FREETYPE_LIBRARIES} ${OPENAL_LIBRARY} SDL2 freetype ogg vorbis)
Noxdor commented 3 years ago

@pinguin999 Thanks, actually I figured it out already quit a while back, but yeah, that solved the problem. Quit an amazing technology WASM. Just takes some time to get used to the new toolchain and the few but important changes in the code.

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because there has been no activity in the past year. It will be closed automatically if no further activity occurs in the next 30 days. Feel free to re-open at any time if this issue is still relevant.