CMake not linking SDL library? [duplicate] - c++

I'm looking for the simplest way to compile a c++ program using SDL2 and SDL_image with cmake.
Here is my best attempt, after hours of searching:
CMakeLists.txt
project(shooter-cmake2)
cmake_minimum_required(VERSION 2.8)
set(SOURCES
shooter.cpp
classes.cpp
utils.cpp
)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
add_executable(${PROJECT_NAME} ${SOURCES})
INCLUDE(FindPkgConfig)
PKG_SEARCH_MODULE(SDL2 REQUIRED sdl2)
PKG_SEARCH_MODULE(SDL2_image REQUIRED sdl2_image)
INCLUDE_DIRECTORIES(${SDL2_INCLUDE_DIRS} ${SDL2IMAGE_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${SDL2_LIBRARIES} ${SDL2IMAGE_LIBRARY})
I get these errors:
In function `loadTexture(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, SDL_Renderer*)':
undefined reference to `IMG_LoadTexture'
collect2: ld returned 1 exit status
Here is the function call:
#include "SDL.h"
#include "SDL_image.h"
SDL_Texture* loadTexture(const std::string &file, SDL_Renderer *ren){
SDL_Texture *texture = IMG_LoadTexture(ren, file.c_str());
texture != nullptr or die("LoadTexture");
return texture;
}

I think that the following will work, as it finds the libraries on my ubuntu system and the example function you provided can link:
project(shooter-cmake2)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
add_executable(${PROJECT_NAME} src/test.cpp)
INCLUDE(FindPkgConfig)
PKG_SEARCH_MODULE(SDL2 REQUIRED sdl2)
PKG_SEARCH_MODULE(SDL2IMAGE REQUIRED SDL2_image>=2.0.0)
INCLUDE_DIRECTORIES(${SDL2_INCLUDE_DIRS} ${SDL2IMAGE_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${SDL2_LIBRARIES} ${SDL2IMAGE_LIBRARIES})
If cmake is executed with --debug-output it outputs:
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.26")
Called from: [2] /usr/share/cmake-2.8/Modules/FindPkgConfig.cmake
[1] $USER/stack-overflow/cmake-sdl2-image/CMakeLists.txt
-- checking for one of the modules 'sdl2'
Called from: [1] $USER/stack-overflow/cmake-sdl2-image/CMakeLists.txt
-- checking for one of the modules 'SDL2_image>=2.0.0'
Called from: [1] $USER/stack-overflow/cmake-sdl2-image/CMakeLists.txt
This made me check the contents of
/usr/lib/x86_64-linux-gnu/pkgconfig/sdl2.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/SDL2_image.pc
I noticed that SDL2_image.pc contains
Name: SDL2_image
which I assumed should match the third parameter to PKG_SEARCH_MODULE for this library.

There are two blog posts about this here:
Using SDL2 with CMake
Using SDL2_image with CMake
Basically you need a FindSDL2.cmake and FindSDL2_image.cmake module. They can be based of the ones that work for SDL 1.2 which are included in CMake already. Using these Find modules will also work on Windows.
If you are on Linux and only need SDL2 you don't even need the FindSDL2.cmake as the following already works:
cmake_minimum_required(VERSION 3.7)
project(SDL2Test)
find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS})
add_executable(SDL2Test Main.cpp)
target_link_libraries(SDL2Test ${SDL2_LIBRARIES})

I was having trouble with these answers, I think cmake changed the way to import targets. Following #trenki blog post I needed to change my CMakeLists.txt to:
project(SDL2Test)
find_package(SDL2 REQUIRED COMPONENTS SDL2::SDL2)
add_executable(SDL2Test main.cpp)
target_link_libraries(SDL2Test SDL2::SDL2)
Currently this works out of the box on Arch Linux.

I introduced a modern and portable approach for linking to the SDL2, SDL2_image. These SDL2 CMake modules let you build an SDL2 & SDL2_image project as follows :
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/sdl2)
find_package(SDL2 REQUIRED)
find_package(SDL2_image REQUIRED)
target_link_libraries(${PROJECT_NAME} SDL2::Main SDL2::Image)
You should just clone the repo in your project:
git clone https://github.com/aminosbh/sdl2-cmake-modules cmake/sdl2
Note: If CMake didn't find the SDL2/SDL2_image libraries (in Windows), we can specify the CMake options SDL2_PATH and SDL2_IMAGE_PATH as follows:
cmake .. -DSDL2_PATH="/path/to/sdl2" -DSDL2_IMAGE_PATH="/path/to/sdl2-image"
It supports also other related libraries : SDL2_ttf, SDL2_net, SDL2_mixer and SDL2_gfx. For more details, please read the README.md file.
You can find a list of examples/samples and projects that uses these modules here : https://github.com/aminosbh/sdl-samples-and-projects

Since 2.6 version, SDL2_image installation is shipped with CMake config script SDL2_imageConfig.cmake/SDL2_image-config.cmake.
So find_package(SDL2_image) works without any additional FindSDL2_image.cmake module, and creates IMPORTED target SDL2_image::SDL2_image:
find_package(SDL2_image REQUIRED)
target_link_libraries(<executable-target> SDL2_image::SDL2_image)
Note, that variables like SDL2_IMAGE_LIBRARIES or SDL2_IMAGE_INCLUDE_DIRS are NOT set in this case, so using them is meaningless.

The following commands works fine for me:
set(SDL_INCLUDE_DIR "/usr/include/SDL2")
set(SDL_LIBRARY "SDL2")
include(FindSDL)
if(SDL_FOUND)
message(STATUS "SDL FOUND")
endif()

Related

Symbol not found error for matplotlibcpp, building with CMake

I am trying to use CMake for including Matplotlibcpp in my C++ project (I am new to both CMake and C++). I am following https://github.com/lava/matplotlib-cpp/issues/236#issuecomment-716510547 for setting up a CMake file. The project builds fine, but when I try to run the executable, here is the error I get:
dyld[73245]: symbol not found in flat namespace
'_PyCapsule_GetPointer'
zsh: abort ./data_measure_img_seq
I'm not sure how to resolve this. Any suggestions? For reference, I am putting my CMakeLists file below:
# set the minimum version
cmake_minimum_required(VERSION "3.13")
# set project
project(image-data-cv)
set(OpenCV_DIR /Users/anshgodha/Developer/opencv/install/lib/cmake/opencv4)
set(CMAKE_CXX_STANDARD 14)
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
# for matplotlibcpp
find_package(Python3 COMPONENTS Interpreter Development NumPy REQUIRED)
find_package(PythonLibs 3.0 REQUIRED)
include_directories(${PYTHON3_INCLUDE_DIRS} ${NumPy_INCLUDE_DIRS})
include(FetchContent)
FetchContent_Declare(
matplotlib
GIT_REPOSITORY https://github.com/lava/matplotlib-cpp.git
GIT_TAG f23347fca25219d1c42cbb91608b5556814bf572
)
FetchContent_GetProperties(matplotlib)
if(NOT matplotlib_POPULATED)
FetchContent_Populate(matplotlib)
endif()
include_directories(SYSTEM ${matplotlib_SOURCE_DIR})
set(PROJECTS basic_data_measures;data_measure_img_seq)
foreach(PROJECT ${PROJECTS})
add_executable(${PROJECT} ${PROJECT}/main.cpp)
target_link_libraries(${PROJECT} PUBLIC ${OpenCV_LIBS})
set_target_properties(${PROJECT} PROPERTIES OUTPUT_NAME "${PROJECT}")
endforeach(PROJECT ${PROJECTS})
# link python and numpy
target_link_libraries(data_measure_img_seq
PRIVATE
${PYTHON_LIBRARIES}
Python3::NumPy
)
I was having the same issue compiling using cmake. Perhaps the included cmake doesn't link everything properly. I got around it using e.g.
g++ fill.cpp -o fill -std=c++11 -I/usr/include/python2.7 -lpython2.7

LibTorch with OpenCV: version GOMP_5.0 not found

I'm trying to use OpenCV and LibTorch in the same project. Libtorch is installed in /usr/include/libtorch, downloaded from the PyTorch website. I'm using the cxx11 ABI version for CUDA 11.3.
Here's my CMakeLists.txt file:
cmake_minimum_required(VERSION 3.23 FATAL_ERROR)
project(chess-rl VERSION 1.0)
find_package( OpenCV REQUIRED )
set(CMAKE_PREFIX_PATH /usr/include/libtorch/share/cmake/)
find_package(Torch REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
include_directories(${OpenCV_LIBS})
include_directories(${TORCH_INCLUDE_DIRS})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}")
file (GLOB SOURCE_FILES
${PROJECT_SOURCE_DIR}/src/*.cc
${PROJECT_SOURCE_DIR}/src/chess/*.cc
)
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS} "${TORCH_LIBRARIES}" )
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20)
The program has a #include <opencv2/opencv.hpp> line at the top.
Compilation works fine, but running the executable gives me this error:
/usr/include/libtorch/lib/libgomp-52f2fd74.so.1: version `GOMP_5.0' not found (required by /usr/lib/libvtkCommonCore.so.1)
I believe libtorch is trying to use a library that is incompatible with OpenCV.
If I run the program with LD_PRELOAD=/usr/lib/libgomp.so ./build/my-program, it runs fine.
How can I fix this error without having to use that environment variable? Is there a way to link that particular library in CMake?
I faced the same problem, and your thread contributed to one solution.
You need to add a shared library in your CMakelists.txt file.
add_library(libName SHARED IMPORTED)
set_property(TARGET libName PROPERTY IMPORTED_LOCATION "/usr/lib/libgomp.so")
target_link_libraries(PROJECT_NAME
libName)
I hope I could help you
With kind regards

Installing libzippp library with cmake not working

Trying to install libzippp library in this project is not working for some reason, here is my project's CMakeLists.txt:
CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(startProject)
set(Leptonica_DIR /Users/alejandrocamba/Documents/leptonica/build)
find_package(OpenCV REQUIRED)
find_package(Leptonica REQUIRED)
find_package(Tesseract REQUIRED)
find_package(libzippp 3.0 REQUIRED)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
include_directories(${OpenCV_INCLUDE_DIRS})
include_directories(${Leptonica_INCLUDE_DIRS})
include_directories(${Tesseract_INCLUDE_DIRS})
add_executable(startProject main.cpp)
target_link_libraries(startProject libzipp::libzipp)
target_link_libraries(startProject ${OpenCV_LIBS})
target_link_libraries(startProject ${Tesseract_LIBRARIES})
I'm getting the error:
ld: library not found for -llibzipp::libzipp
I have followed the instructions and i cloned the repository and successfully installed it, so if i do make install i get:
But i can't seem to find a way to use it on my project, i need help to make get it working on my project!
Need more p: the proper target name for link with is libzippp::libzippp.
The project's README wrongly suggests to use libzipp::libzipp.

Compiling with CMake and Boost unit tests

I'm relatively new to C++, and I'm trying to compile a project using CMake with the following #include:
#include <boost/test/unit_test.hpp>
I get the following error
undefined symbols for architecture x86_64:
"boost::unit_test::unit_test_log_t::instance()", referenced from:
___cxx_global_var_init in functions1.cpp.o
___cxx_global_var_init in functions2.cpp.o
___cxx_global_var_init in main.cpp.o
ld: symbol(s) not found for architecture x86_64
I'm pretty sure this is something to do with my CMakeLists.txt, so here it is:
cmake_minimum_required(VERSION 3.13)
project(MyProject)
set(CMAKE_CXX_STANDARD 14)
include_directories(.)
include_directories(/usr/local/include/)
add_executable(MyProject
functions1.cpp
functions1.h
functions2.cpp
functions2.h
main.cpp
main.h
utillity.cpp
utillity.h)
set(BOOST_ROOT "/usr/local/Cellar/boost/1.69.0_2")
find_package(Boost COMPONENTS filesystem system unit_test_framework REQUIRED)
#find_package(Boost 1.69.0)
if(NOT Boost_FOUND)
message(FATAL_ERROR "Could not find boost!")
endif()
include_directories (${Boost_INCLUDE_DIRS})
I'm on OSX Mojave, and installing with brew install boost. I'm aware there are several posts out there that report very similar issues, but none of the solutions seem to work for me.
Edit:
Have adjusted my CMakeLists to the following based on Guillaume's suggestion below.
make_minimum_required(VERSION 3.13)
project(MyProject)
set(CMAKE_CXX_STANDARD 14)
add_executable(MyProject
functions1.cpp
functions1.h
functions2.cpp
functions2.h
main.cpp
main.h
utillity.cpp
utillity.h)
set(BOOST_ROOT "/usr/local/Cellar/boost/1.69.0_2")
find_package(Boost COMPONENTS filesystem system test REQUIRED)
target_include_directories(MyProject PUBLIC ".")
target_link_libraries(MyProject PUBLIC
Boost::filesystem Boost::system Boost::test)
I understand that this is, in principle, better, but it's giving me:
Unable to find the requested Boost libraries.
Boost version: 1.69.0
Boost include path: /usr/local/Cellar/boost/1.69.0_2/include
Could not find the following Boost libraries:
boost_test
Some (but not all) of the required Boost libraries were found. You may need to install these additional Boost libraries. Alternatively, set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.
Edit 2:
Have tried edits and upgrading to boost 1.7, but still have:
Could not find a package configuration file provided by "boost_test"
(requested version 1.70.0) with any of the following names:
boost_testConfig.cmake
boost_test-config.cmake
Add the installation prefix of "boost_test" to CMAKE_PREFIX_PATH or set
"boost_test_DIR" to a directory containing one of the above files. If
"boost_test" provides a separate development package or SDK, be sure it
has been installed.
You have to link properly to boost instead of adding include directory flags.
Linking libraries in cmake will apply all required property to use boost onto your targets.
First off, don't do that:
include_directories(.)
include_directories(/usr/local/include/)
This is asking for link error. It will enable you to use headers of libraries you don't link properly to. This will cause linking errors, even within your own project.
cmake_minimum_required(VERSION 3.13)
project(MyProject)
set(CMAKE_CXX_STANDARD 14)
add_executable(MyProject
functions1.cpp
functions1.h
functions2.cpp
functions2.h
main.cpp
main.h
utillity.cpp
utillity.h)
list(APPEND CMAKE_PREFIX_PATH "/usr/local/Cellar/boost/1.69.0_2")
set(Boost_ADDITIONAL_VERSIONS "1.69.0" "1.69")
find_package(Boost COMPONENTS filesystem system test REQUIRED)
# Not needed
#if(NOT Boost_FOUND)
# message(FATAL_ERROR "Could not find boost!")
#endif()
# include_directories (${Boost_INCLUDE_DIRS})
target_include_directories(MyProject PUBLIC ".")
# adds include directories, definitions and link libraries
target_link_libraries(MyProject PUBLIC
Boost::filesystem Boost::system Boost::test
)

How to use SDL2 and SDL_image with cmake

I'm looking for the simplest way to compile a c++ program using SDL2 and SDL_image with cmake.
Here is my best attempt, after hours of searching:
CMakeLists.txt
project(shooter-cmake2)
cmake_minimum_required(VERSION 2.8)
set(SOURCES
shooter.cpp
classes.cpp
utils.cpp
)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
add_executable(${PROJECT_NAME} ${SOURCES})
INCLUDE(FindPkgConfig)
PKG_SEARCH_MODULE(SDL2 REQUIRED sdl2)
PKG_SEARCH_MODULE(SDL2_image REQUIRED sdl2_image)
INCLUDE_DIRECTORIES(${SDL2_INCLUDE_DIRS} ${SDL2IMAGE_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${SDL2_LIBRARIES} ${SDL2IMAGE_LIBRARY})
I get these errors:
In function `loadTexture(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, SDL_Renderer*)':
undefined reference to `IMG_LoadTexture'
collect2: ld returned 1 exit status
Here is the function call:
#include "SDL.h"
#include "SDL_image.h"
SDL_Texture* loadTexture(const std::string &file, SDL_Renderer *ren){
SDL_Texture *texture = IMG_LoadTexture(ren, file.c_str());
texture != nullptr or die("LoadTexture");
return texture;
}
I think that the following will work, as it finds the libraries on my ubuntu system and the example function you provided can link:
project(shooter-cmake2)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
add_executable(${PROJECT_NAME} src/test.cpp)
INCLUDE(FindPkgConfig)
PKG_SEARCH_MODULE(SDL2 REQUIRED sdl2)
PKG_SEARCH_MODULE(SDL2IMAGE REQUIRED SDL2_image>=2.0.0)
INCLUDE_DIRECTORIES(${SDL2_INCLUDE_DIRS} ${SDL2IMAGE_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${SDL2_LIBRARIES} ${SDL2IMAGE_LIBRARIES})
If cmake is executed with --debug-output it outputs:
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.26")
Called from: [2] /usr/share/cmake-2.8/Modules/FindPkgConfig.cmake
[1] $USER/stack-overflow/cmake-sdl2-image/CMakeLists.txt
-- checking for one of the modules 'sdl2'
Called from: [1] $USER/stack-overflow/cmake-sdl2-image/CMakeLists.txt
-- checking for one of the modules 'SDL2_image>=2.0.0'
Called from: [1] $USER/stack-overflow/cmake-sdl2-image/CMakeLists.txt
This made me check the contents of
/usr/lib/x86_64-linux-gnu/pkgconfig/sdl2.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/SDL2_image.pc
I noticed that SDL2_image.pc contains
Name: SDL2_image
which I assumed should match the third parameter to PKG_SEARCH_MODULE for this library.
There are two blog posts about this here:
Using SDL2 with CMake
Using SDL2_image with CMake
Basically you need a FindSDL2.cmake and FindSDL2_image.cmake module. They can be based of the ones that work for SDL 1.2 which are included in CMake already. Using these Find modules will also work on Windows.
If you are on Linux and only need SDL2 you don't even need the FindSDL2.cmake as the following already works:
cmake_minimum_required(VERSION 3.7)
project(SDL2Test)
find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS})
add_executable(SDL2Test Main.cpp)
target_link_libraries(SDL2Test ${SDL2_LIBRARIES})
I was having trouble with these answers, I think cmake changed the way to import targets. Following #trenki blog post I needed to change my CMakeLists.txt to:
project(SDL2Test)
find_package(SDL2 REQUIRED COMPONENTS SDL2::SDL2)
add_executable(SDL2Test main.cpp)
target_link_libraries(SDL2Test SDL2::SDL2)
Currently this works out of the box on Arch Linux.
I introduced a modern and portable approach for linking to the SDL2, SDL2_image. These SDL2 CMake modules let you build an SDL2 & SDL2_image project as follows :
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/sdl2)
find_package(SDL2 REQUIRED)
find_package(SDL2_image REQUIRED)
target_link_libraries(${PROJECT_NAME} SDL2::Main SDL2::Image)
You should just clone the repo in your project:
git clone https://github.com/aminosbh/sdl2-cmake-modules cmake/sdl2
Note: If CMake didn't find the SDL2/SDL2_image libraries (in Windows), we can specify the CMake options SDL2_PATH and SDL2_IMAGE_PATH as follows:
cmake .. -DSDL2_PATH="/path/to/sdl2" -DSDL2_IMAGE_PATH="/path/to/sdl2-image"
It supports also other related libraries : SDL2_ttf, SDL2_net, SDL2_mixer and SDL2_gfx. For more details, please read the README.md file.
You can find a list of examples/samples and projects that uses these modules here : https://github.com/aminosbh/sdl-samples-and-projects
Since 2.6 version, SDL2_image installation is shipped with CMake config script SDL2_imageConfig.cmake/SDL2_image-config.cmake.
So find_package(SDL2_image) works without any additional FindSDL2_image.cmake module, and creates IMPORTED target SDL2_image::SDL2_image:
find_package(SDL2_image REQUIRED)
target_link_libraries(<executable-target> SDL2_image::SDL2_image)
Note, that variables like SDL2_IMAGE_LIBRARIES or SDL2_IMAGE_INCLUDE_DIRS are NOT set in this case, so using them is meaningless.
The following commands works fine for me:
set(SDL_INCLUDE_DIR "/usr/include/SDL2")
set(SDL_LIBRARY "SDL2")
include(FindSDL)
if(SDL_FOUND)
message(STATUS "SDL FOUND")
endif()