Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [SOLVED] Linker errors with CMake project  (Read 971 times)

0 Members and 1 Guest are viewing this topic.

ChocolatePinecone

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
[SOLVED] Linker errors with CMake project
« on: March 03, 2020, 05:05:58 pm »
Hey all,

I've googled my ass off and tried anything I found relevant both inside and outside this forum, but cannot seem to find a solution.

Some context:
I've converted the build setup of my big project to use CMake. This worked nicely with Visual Studio I'm using on Windows.
However, I'm exploring how to make a Linux build by trying to compile the project on Ubuntu. After ironing out some issues, I've been stuck for the past few hours trying to get my building to work.
I'm still pretty new with CMake and am probably missing something.

I'm using seperate downloaded SFML directories for the windows and linux builds.
Both directories are the already built versions of SFML, not the source code.

Currently the actual compiling is succeeding, but the linker is throwing errors:

Quote
[  1%] Linking CXX executable Rocket-Shipment
CMakeFiles/Rocket-Shipment.dir/src/engine/RocketEngine.cpp.o: In function `re::RocketEngine::setMainFont(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
RocketEngine.cpp:(.text+0x15f): undefined reference to `sf::Font::loadFromFile(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
CMakeFiles/Rocket-Shipment.dir/src/engine/RocketEngine.cpp.o: In function `re::RocketEngine::changeWindowResolution(sf::VideoMode, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool)':
RocketEngine.cpp:(.text+0x36a): undefined reference to `sf::String::String(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::locale const&)'
RocketEngine.cpp:(.text+0x42c): undefined reference to `sf::String::String(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::locale const&)'
CMakeFiles/Rocket-Shipment.dir/src/engine/audio/MusicManager.cpp.o: In function `re::MusicManager::playNextSong()':
MusicManager.cpp:(.text+0x1ca): undefined reference to `sf::Music::openFromFile(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
Etc, etc, etc.

My makefile:
Quote
cmake_minimum_required(VERSION 3.10)

# Set the project name and version
project(Rocket-Shipment)

# Specify the C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# Set project variables
set(VERSION_DESC \"ALPHA-DEMO\")
set(VERSION_MAJOR 0)
set(VERSION_MINOR 0)
set(VERSION_PATCH 1)
if(CMAKE_BUILD_TYPE MATCHES Debug)
   set(DEBUG_MODE true)
   message("Debug mode on")
else()
   set(DEBUG_MODE false)
   message("Debug mode off")
endif()

# Set OS specific variables
if(${CMAKE_SYSTEM_NAME} MATCHES Windows)
   set(SFML_DIR "SFML-2.5.0-win/lib/cmake/SFML")
   set(OPENBROWSERCMD \"start\")
   set(WINDOWS true)
   message("Set variables for Windows")
else()
   set(SFML_DIR "SFML-2.5.0-linux/lib/cmake/SFML")
   set(OPENBROWSERCMD \"xdg-open\")
   set(WINDOWS false)
   message("Set variables for Linux")
endif()

configure_file(
   "${PROJECT_SOURCE_DIR}/BuildConfig.h.in"
   "${PROJECT_BINARY_DIR}/BuildConfig.h"
)

# Find SFML
find_package(SFML 2.5 COMPONENTS audio graphics window system REQUIRED)
if(NOT SFML_FOUND)
  message(FATAL_ERROR "SFML couldn't be located!")
endif()

# Add the binary tree to the search path for include files
# so that we will find BuildConfig.h
include_directories("${PROJECT_BINARY_DIR}")

# Define sources and executable
set(EXECUTABLE_NAME "Rocket-Shipment")
FILE(GLOB_RECURSE SRCFILES src/*.cpp src/*.h)

# Copy OS specific data
if(${CMAKE_SYSTEM_NAME} MATCHES Windows)
   set(SFML_DLLS "SFML-2.5.0-win/bin")
   if(DEBUG_MODE)
      file(COPY ${SFML_DLLS}/sfml-audio-d-2.dll ${SFML_DLLS}/sfml-graphics-d-2.dll ${SFML_DLLS}/sfml-window-d-2.dll ${SFML_DLLS}/sfml-system-d-2.dll ${SFML_DLLS}/openal32.dll DESTINATION .)
      message("Added debug dlls to build directory")
   else()
      file(COPY ${SFML_DLLS}/sfml-audio-2.dll ${SFML_DLLS}/sfml-graphics-2.dll ${SFML_DLLS}/sfml-window-2.dll ${SFML_DLLS}/sfml-system-2.dll ${SFML_DLLS}/openal32.dll DESTINATION .)
      message("Added release dlls to build directory")
   endif()
endif()

# Copy game data folder
FILE(COPY data/ DESTINATION data/)

if(DEBUG_MODE OR NOT ${CMAKE_SYSTEM_NAME} MATCHES Windows)
   add_executable(${EXECUTABLE_NAME} Main.cpp ${SRCFILES})
   message("Create normal executable")
elseif(${CMAKE_SYSTEM_NAME} MATCHES Windows)
   add_executable(${EXECUTABLE_NAME} WIN32 Main.cpp ${SRCFILES})
   message("Create windows executable without console window")
endif()

# Add SFML
#include_directories(${SFML_INCLUDE_DIR})
target_link_libraries(${EXECUTABLE_NAME} sfml-audio sfml-graphics sfml-window sfml-system)
message("Added SFML")

Just to be clear, I'm running 'cmake ../' from the teminal to create the project and the 'make' command to compile.

I'm guessing I'm forgetting to link something or doing it wrong, but I can't seem to figure out how to solve this.
Here's to hoping you guys do!
« Last Edit: March 05, 2020, 08:42:48 am by ChocolatePinecone »

ChocolatePinecone

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
Re: Linker errors with CMake project
« Reply #1 on: March 05, 2020, 08:42:30 am »
After some experimenting with tutorials I solved the problem!

I was using the pre-built version 2.5.0 of SFML downloaded from the SFML downloads page.
I changed this by using 2.5.1 which I built myself using the latest version from the git repo.

I also changed my CMakeLists file to this:

Quote
cmake_minimum_required(VERSION 3.10)

# Set the project name and version
project(Rocket-Shipment)

# Specify the C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Set project variables
set(VERSION_DESC \"ALPHA-DEMO\")
set(VERSION_MAJOR 0)
set(VERSION_MINOR 0)
set(VERSION_PATCH 1)
if(CMAKE_BUILD_TYPE MATCHES Debug)
   set(DEBUG_MODE true)
   message(STATUS "Set debug mode on")
else()
   set(DEBUG_MODE false)
   message(STATUS "Set debug mode off")
endif()

# Set OS specific variables
if(${CMAKE_SYSTEM_NAME} MATCHES Windows)
   set(SFML_DIR "SFML-2.5.0-win/lib/cmake/SFML")
   set(OPENBROWSERCMD \"start\")
   set(WINDOWS true)
   message(STATUS "Set variables for Windows")
else()
   set(SFML_DIR "SFML-2.5.1-linux/lib/cmake/SFML")
   set(SFML_INCLUDE_DIR "SFML-2.5.1-linux/include")
   set(SFML_LIBRARY_DIR "SFML-2.5.1-linux/lib")
   link_directories(SFML_LIBRARY_DIR)
   include_directories(SFML_INCLUDE_DIR)
   set(OPENBROWSERCMD \"xdg-open\")
   set(WINDOWS false)
   message(STATUS "Set variables for Linux")
endif()

configure_file(
   "${PROJECT_SOURCE_DIR}/BuildConfig.h.in"
   "${PROJECT_BINARY_DIR}/BuildConfig.h"
)

# Find SFML
find_package(SFML 2.5 COMPONENTS audio graphics window system REQUIRED)
if(SFML_FOUND)
   message(STATUS "SFML_INCLUDE_DIR: ${SFML_INCLUDE_DIR}")
   message(STATUS "SFML_LIBRARIES: ${SFML_LIBRARIES}")
   message(STATUS "SFML_VERSION: ${SFML_VERSION}")
else()
   message(FATAL_ERROR "SFML couldn't be located!")
endif()

# Add the binary tree to the search path for include files
# so that we will find BuildConfig.h
include_directories("${PROJECT_BINARY_DIR}")

# Define sources and executable
set(EXECUTABLE_NAME "Rocket-Shipment")
FILE(GLOB_RECURSE SRCFILES src/*.cpp src/*.h)

# Copy OS specific data
if(${CMAKE_SYSTEM_NAME} MATCHES Windows)
   set(SFML_DLLS "SFML-2.5.0-win/bin")
   if(DEBUG_MODE)
      file(COPY ${SFML_DLLS}/sfml-audio-d-2.dll ${SFML_DLLS}/sfml-graphics-d-2.dll ${SFML_DLLS}/sfml-window-d-2.dll ${SFML_DLLS}/sfml-system-d-2.dll ${SFML_DLLS}/openal32.dll DESTINATION .)
      message(STATUS "Added debug dlls to build directory")
   else()
      file(COPY ${SFML_DLLS}/sfml-audio-2.dll ${SFML_DLLS}/sfml-graphics-2.dll ${SFML_DLLS}/sfml-window-2.dll ${SFML_DLLS}/sfml-system-2.dll ${SFML_DLLS}/openal32.dll DESTINATION .)
      message(STATUS "Added release dlls to build directory")
   endif()
endif()

# Copy game data folder
FILE(COPY data/ DESTINATION data/)

if(DEBUG_MODE OR NOT ${CMAKE_SYSTEM_NAME} MATCHES Windows)
   add_executable(${EXECUTABLE_NAME} Main.cpp ${SRCFILES})
   message(STATUS "Create normal executable")
elseif(${CMAKE_SYSTEM_NAME} MATCHES Windows)
   add_executable(${EXECUTABLE_NAME} WIN32 Main.cpp ${SRCFILES})
   message(STATUS "Create windows executable without console window")
endif()

# Add filesystem library
target_link_libraries(${EXECUTABLE_NAME} stdc++fs)

# Add SFML
target_link_libraries(${EXECUTABLE_NAME} sfml-audio sfml-graphics sfml-window sfml-system)
message(STATUS "Added SFML")

This solved the issue for me, including a linker issue with the filesystem of the std lib.