Search code examples
c++cmakecompiler-errorsmingwsfml

Error when I try to compile project using CMake with SFML library by mingw


When I want to compile project using CMake with SFML library by mingw (last verison), I catch a lot of strange errors (c++).

CMake code:

cmake_minimum_required(VERSION 3.0)

project(MLproject)

SET(CMAKE_SYSTEM_NAME    Windows)
SET(CMAKE_SYSTEM_VERSION 1)
SET(CMAKE_C_COMPILER     "i686-w64-mingw32-gcc")
SET(CMAKE_CXX_COMPILER   "i686-w64-mingw32-g++")
SET(CMAKE_RC_COMPILER    "i686-w64-mingw32-windres")
SET(CMAKE_RANLIB         "i686-w64-mingw32-ranlib")
set(CMAKE_CXX_STANDARD 17)

SET(CMAKE_FIND_ROOT_PATH "/usr/i686-w64-mingw32")
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

set(SOURCE_EXE src/main.cpp)

set(SOURCE_GAME
  src/Boss/Boss.cpp
  *...*
  src/Game/Game.cpp)

set(SOURCE_UI
  src/UI/ScrollBar/ScrollBar.cpp)

add_library(UI SHARED ${SOURCE_UI})
add_library(Game SHARED ${SOURCE_GAME})

add_executable(main ${SOURCE_EXE})

target_link_libraries(main Game UI
  sfml-graphics sfml-system sfml-windos sfml-audio)

Error:

CMakeFiles/UI.dir/src/UI/ScrollBar/ScrollBar.cpp.o:ScrollBar.cpp:(.text+0x6d): undefined reference to `_imp___ZN2sf14RectangleShapeC1ERKNS_7Vector2IfEE'
CMakeFiles/UI.dir/src/UI/ScrollBar/ScrollBar.cpp.o:ScrollBar.cpp:(.text+0x399): undefined reference to `_imp___ZN2sf12RenderStates7DefaultE.....

How can I fix it? Does I catch error because have too old C++ version? (Everything is successfully compiled for Linux, but I wanted to make cross-platform)


Solution

  • The error:

    CMakeFiles/UI.dir/src/UI/ScrollBar/ScrollBar.cpp.o:ScrollBar.cpp:(.text+0x6d): undefined reference to `_imp___ZN2sf14RectangleShapeC1ERKNS_7Vector2IfEE'
    

    indicates that the UI library uses some SFML components. However, you only link the SFML libraries to the main executable, so the library doesn't know where these SFML references are defined. So, you must link any relevant SFML libraries to the UI target:

    target_link_libraries(UI PUBLIC sfml-graphics sfml-system sfml-windos sfml-audio)
    

    Use PUBLIC here to propagate the SFML libraries to consumers of the UI target, such as your main executable. This removes the need to explicitly link them to main. Here is your full CMake with these changes:

    cmake_minimum_required(VERSION 3.0)
    
    project(MLproject)
    
    # As commented, consider moving these calls to your toolchain file.
    SET(CMAKE_SYSTEM_NAME    Windows)
    SET(CMAKE_SYSTEM_VERSION 1)
    SET(CMAKE_C_COMPILER     "i686-w64-mingw32-gcc")
    SET(CMAKE_CXX_COMPILER   "i686-w64-mingw32-g++")
    SET(CMAKE_RC_COMPILER    "i686-w64-mingw32-windres")
    SET(CMAKE_RANLIB         "i686-w64-mingw32-ranlib")
    
    SET(CMAKE_FIND_ROOT_PATH "/usr/i686-w64-mingw32")
    SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
    SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
    SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
    
    set(CMAKE_CXX_STANDARD 17)
    
    set(SOURCE_EXE src/main.cpp)
    
    set(SOURCE_GAME
      src/Boss/Boss.cpp
      *...*
      src/Game/Game.cpp)
    
    set(SOURCE_UI
      src/UI/ScrollBar/ScrollBar.cpp)
    
    add_library(UI SHARED ${SOURCE_UI})
    # Link SFML libraries to UI.
    target_link_libraries(UI PUBLIC sfml-graphics sfml-system sfml-windos sfml-audio)
    
    add_library(Game SHARED ${SOURCE_GAME})
    
    add_executable(main ${SOURCE_EXE})
    
    # Link Game and UI to the executable, which propagates the SFML libraries from UI also.
    target_link_libraries(main PRIVATE Game UI)
    

    Note, many of the calls at the top of your CMake belong in a toolchain file (as commented), often for cross-compiling. I encourage you to read through the documentation to determine your need for it, and understand how to set it up.