Using CMAKE find_package with SDL2 - c++

I've got a project that uses CMAKE, and needs to link SDL2. I'm trying to understand how find_package works. At one point in the past, I was able to get find_package to work by supplying my own FindSDL2.cmake, but after some new linker errors, I decided to try a different apporoach. The reading I'm doing seems to imply that, after I've installed the libsdl2-dev package, I should be able to just use find_package(SDL2 REQUIRED) and then target_link_libraries(Suqua PRIVATE SDL2::SDL2), but cmake throws a package not found error. Do I need to provide a custom FindSDL2.cmake?
CMakeLists.txt
cmake_minimum_required (VERSION 3.8)
set(CMAKE_CXX_STANDARD 17)
find_package(SDL2 CONFIG REQUIRED)
file(GLOB source_files
"src/*.cpp"
"header/*.h"
)
add_library(Suqua ${source_files} "src/glad.c" )
target_include_directories(Suqua PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/header)
target_include_directories(Suqua PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include)
target_link_libraries(Suqua PRIVATE SDL2::SDL2 enet)
if(UNIX)
target_link_libraries(Suqua PRIVATE stdc++fs)
endif()
Error
CMake Error at Suqua/CMakeLists.txt:13 (add_library):
Target "Suqua" links to target "SDL2::SDL2" but the target was not found.
Perhaps a find_package() call is missing for an IMPORTED target, or an
ALIAS target is missing?
Thank you, and if you have any other critiques of my CMakeLists, they'd be greatly appreciated!

Answer supplied by Tsyvarev
When using an installed library (not built from source), use the SD2_LIBRARIES variable.
On another note, I actually fixed this earlier, but assumed I was doing something wrong when I got a linker error relating to linking CMAKE_DL_LIBS, which I'd removed because I assumed it didn't do anything :/
Definitely gonna read through that CMake book. Thanks all!

Related

CMake is not using correct paths when looking for lib files

I recently installed vcpkg on my windows system and the cmake (and cmake tools) extension for vscode, because I wanted to use a json file for my c++ project. I had put vcpkg in a random location just to mess around with it and learn how it works. However, when I moved it to another location as its final spot, CMake got confused and couldn't find lib files for jsoncpp.
Here's the error:
Unable to open 'json_value.cpp': Unable to read file 'c:\path\to\old\location\vcpkg\buildtrees\jsoncpp\src\3918c327b1-034a82149a.clean\src\lib_json\json_value.cpp' (Error: Unable to resolve non-existing file 'c:\path\to\old\location\vcpkg\buildtrees\jsoncpp\src\3918c327b1-034a82149a.clean\src\lib_json\json_value.cpp').
I had moved vcpkg from C:\path\to\old\location\vcpkg to C:\vcpkg
And here's my CMakeLists.txt file:
cmake_minimum_required(VERSION 3.0.0)
project(myProgram VERSION 0.1.0)
include(CTest)
enable_testing()
add_executable(myProgram main.cpp)
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
# set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR})
set(CMAKE_BUILD_TYPE debug)
# set_target_properties(${PROJECT_NAME}
# PROPERTIES
# RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_SOURCE_DIR})
include(CPack)
include_directories(C:/vcpkg/installed/x64-windows/include)
link_directories(C:/vcpkg/installed/x64-windows/lib)
find_package(jsoncpp CONFIG REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE jsoncpp_lib jsoncpp_object)
I have already tried updating the CMAKE_TOOLCHAIN_FILE property in settings.json, deleting cmake's cache, resetting the extension, and reinstalling jsoncpp, vcpkg and the cmake extensions fresh (I had made sure that their files were deleted).
I had to take out the find package function. The find package function made cmake expect the source code to be in the buildtrees folder, which in this case isn't (I think it was at some point, but I don't know why it wont come back). Just by using target_link_libraries(${PROJECT_NAME} jsoncpp), as well as the include/link directories statements gave cmake everything it needed to include the library. One thing I still don't understand however is why cmake was looking in the old location for that bit of source code.

CMake not finding GL/glew.h

I'm using CLion under pop_OS! 20.04 and am currently trying to get CMake to work with GLEW because I want to follow these tutorials to get started with OpenGL. I'm relatively new to C/C++ and completely new to CMake.
I installed the libgl1-mesa-dev,libglew-dev,libglfw3,libglfw3-dev packages with apt-get install and the glew.h is located alongside the other GL header files in /usr/include/GL.
When trying to compile a simple program:
#include <GL/glew.h>
int main() {
return 0;
}
cmake can't find the headerfile:
test/main.cpp:1:10: fatal error: GL/glew.h: No such file or directory
1 | #include <GL/glew.h>
| ^~~~~~~~~~~
Do I have to manually add these header files in CMakeLists.txt for cmake to find them? I tried like a dozen different suggestions but I didn't get it to work. For example, I tried
cmake_minimum_required(VERSION 3.17)
project(test)
set(CMAKE_CXX_STANDARD 14)
find_package(GLEW REQUIRED)
include_directories(${GLEW_INCLUDE_DIRS})
link_libraries(${GLEW_LIBRARIES})
target_link_libraries(test GLEW::GLEW)
but this results in
CMake Error at /app/extra/clion/bin/cmake/linux/share/cmake-3.17/Modules/FindPackageHandleStandardArgs.cmake:164 (message):
Could NOT find GLEW (missing: GLEW_INCLUDE_DIRS GLEW_LIBRARIES)
Is this somehow a problem with CLion and I need to include libraries into my project in a different manner? Or am I using cmake in a wrong way?
Your last try was nearly right.
Forget about include_directories and link_libraries commands. All it needs when doing modern CMake is an add_executable(test main.cpp) followed by a target_link_libraries(test PRIVATE GLEW::glew) command. The target GLEW::glew (case matters here) bundles all compile definitions, include directories, libraries, and further settings that are needed to compile and link your example.
Your CMakeLists.txt would now look like this:
cmake_minimum_required(VERSION 3.17)
project(test)
set(CMAKE_CXX_STANDARD 14)
find_package(GLEW REQUIRED)
add_executable(myTest main.cpp)
target_link_libraries(myTest PRIVATE GLEW::glew)
Edit: Just noticed, that GLEW::GLEW can also be used.
The answer by #vre is OK. I only add how to find it yourself.
First, run
cmake --help-module-list
and look for GLEW. Under Linux, you can simplify this step to
cmake --help-module-list | grep -i Glew
where -i stands for "case insesitive match", as we usually don't remember if it's GLEW or perhaps Glew. Once you know the module name, you can ask for the specific help related to just this module:
cmake --help-module FindGLEW
The answer is there. Read and enjoy!
PS. There's no need to memorize this answer. All can be reduced to cmake --help.

cmake find openssl libraries in non-standard paths

I am having trouble telling cmake to find openssl on my mac. Let me say, I am an amateur at using cmake, as my acquaintance with it, is very recent and occasional. That said, I can do simple things in cmake such as create small projects build them and run them. Some commands (find_library, find_package, ...) always perplex me.
I downloaded and installed openssl (./configure, make and make install) and it has put the files in /opt/openssl
I was googling around to see help for a simple inclusion openssl in my program.
One search result points to a command FindOpenSSL here (https://cmake.org/cmake/help/v3.6/module/FindOpenSSL.html). When i used FindOpenSSL, cmake emitted error saying FindOpenSSL is not a command.
I also tried find_library and find_package commands.
But if I check the variable OPENSSL_FOUND, it is still undefined.
It looks like I have to hardcode (or pass through -D options to cmake) the variables for openssl. What is the best practice here? The reference manual of cmake seems to be like piece of puzzle, as I don't understand the true difference between find_library and find_package, or when to use in preference of the other.
Am I the only one facing this, or more souls around here that are confused and struggling?
Thanks to anyone pointing me the right direction and helping me out of this confusion.
My current CMakeLists.txt looks like below:
ravindranaths-MacBook-Pro:crypt_handlers ravindranath$ cat CMakeLists.txt
cmake_minimum_required (VERSION 3.5.1)
# search for CPP_HOME. If found use this as the install_root dir.
# else, use /usr/local
message (STATUS "Searching for environment var CPP_HOME ...")
if (DEFINED ENV{CPP_HOME})
message (STATUS "Found CPP_HOME: " $ENV{CPP_HOME})
set (CPP_HOME $ENV{CPP_HOME})
else()
message (STATUS "Could not find. Treating /usr/local as CPP_HOME...")
set (CPP_HOME /usr/local)
endif()
set(Boost_USE_STATIC_LIBS ON)
###########################################################
set(CMAKE_INCLUDE_PATH /usr/local/ssl/include/openssl)
set(OPENSSL_USE_STATIC_LIBS ON)
############################################################
find_package(Boost 1.45.0 COMPONENTS system )
find_package (Threads)
set (CMAKE_CXX_STANDARD 11)
include_directories(../../include)
include_directories(../../include/ext)
include_directories(../../include/ext/spdlog)
include_directories(${CPP_HOME}/externals/plog/include)
add_executable(crypt app.cpp)
link_directories(../../build/src)
target_link_libraries (crypt ${CMAKE_THREAD_LIBS_INIT})
find_library(OpenSSL_LIB libcrypto.a libssl.a)
#find_package(OpenSSL)
if (OPENSSL_FOUND)
message (STATUS "OPENSSL found")
message (STATUS "OpenSSL INclude directories:" OPENSSL_INCLUDE_DIR)
else()
message (FATAL_ERROR "OpenSSL Not found.")
endif()
include_directories(${OPENSSL_INCLUDE_DIR})
target_link_libraries(crypt ${CMAKE_DL_LIBS})
TARGET_LINK_LIBRARIES(crypt ${OPENSSL_LIBRARIES} ${LIBYAML_LIBRARIES} pthread -ldl)
#target_link_libraries(crypt /usr/local/ssl/lib/libcrypto.a /usr/local/lib/libssl.a)
target_link_libraries(crypt /usr/local/lib/libcrypto.a /usr/local/lib/libssl.a)
if(Boost_FOUND)
include_directories(${include_directories} ${Boost_INCLUDE_DIRS})
target_link_libraries(crypt nettu ${Boost_LIBRARIES})
endif()
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/dist/bin)
UPDATE
now, I just use find_package(OpenSSL), instead of find_libraries(...). And, I am running cmake as below:
cmake -DCMAKE_BUILD_TYPE=Debug -DOPENSSL_ROOT_DIR=/opt/openssl/ -DOPENSSL_LIBRARIES=/opt/openssl/lib/ ..
cmake succeeds by writing the makefiles. However, I get a linker error when running make. The error points to missing libssl.a like below:
make[2]: *** No rule to make target `/usr/local/lib/libssl.a', needed by `examples/crypt_handlers/crypt'. Stop.
What I don't understand is that the make is still looking for libssl.a in "/usr/local/lib/.." instead of /opt/openssl/lib.
How to fix this?
You can change as follows
#find_library(OpenSSL_LIB libcrypto.a libssl.a)
find_package(OpenSSL)
And run
cmake -DOPENSSL_ROOT_DIR=/opt/openssl
Where OPENSSL_ROOT_DIR is hint for FindOpenSSL.cmake standard module where to find root for OpenSSL installation.

Use libbitcoin in CLion

I am not a C++ programmer, only have made a course a while ago. Using homebrew I installed libbitcoin and was hoping that I can reference the library like I was able to reference the boost libraries. I also realized that there are no links in /usr/local/bin to the Cellar.
I think I could get it working by using the absolute paths but I am looking for the proper way of handling this constellation that I just mentioned.
Current CMake:
cmake_minimum_required(VERSION 2.8.4)
project(cplusplus)
message(STATUS "start running cmake...")
find_package(boost 1.65.1 COMPONENTS system filesystem REQUIRED)
find_package(libbitcoin 3.3.0 COMPONENTS system filesystem REQUIRED)
message("system: ${CMAKE_SYSTEM_PREFIX_PATH}")
find_library(LIB_BITCOIN libbitcoin)
message("bitcoin: ${LIB_BITCOIN}")
if(Boost_FOUND)
message(STATUS "Boost_INCLUDE_DIRS: ${Boost_INCLUDE_DIRS}")
message(STATUS "Boost_LIBRARIES: ${Boost_LIBRARIES}")
message(STATUS "Boost_VERSION: ${Boost_VERSION}")
include_directories(${Boost_INCLUDE_DIRS})
endif()
add_executable(cplusplus main.cpp)
if(Boost_FOUND)
target_link_libraries(cplusplus ${Boost_LIBRARIES})
endif()
Currently I get these errors:
/Applications/CLion.app/Contents/bin/cmake/bin/cmake -DCMAKE_BUILD_TYPE=Debug -G "CodeBlocks - Unix Makefiles" /Users/johndow/Documents/Workspace/bitcoin-code/cplusplus
-- start running cmake...
-- Boost version: 1.65.1
CMake Error at CMakeLists.txt:8 (find_package):
By not providing "Findlibbitcoin.cmake" in CMAKE_MODULE_PATH this project
has asked CMake to find a package configuration file provided by
"libbitcoin", but CMake did not find one.
Could not find a package configuration file provided by "libbitcoin"
(requested version 3.3.0) with any of the following names:
libbitcoinConfig.cmake
libbitcoin-config.cmake
Add the installation prefix of "libbitcoin" to CMAKE_PREFIX_PATH or set
"libbitcoin_DIR" to a directory containing one of the above files. If
"libbitcoin" provides a separate development package or SDK, be sure it has
been installed.
-- Configuring incomplete, errors occurred!
See also "/Users/johndoe/Documents/Workspace/bitcoin-code/cplusplus/cmake-build-debug/CMakeFiles/CMakeOutput.log".
[Finished]
You seem to have double lookup for libbitcoin library in your CMakeLists file. You are first looking for it by:
find_package(libbitcoin ...)
and then by
find_library(LIB_BITCOIN libbitcoin)
Cmake is not happy (as your error message says) with the find_package() clause as libbitcoin does not provide cmake configuration by itself. You have many ways how to fix it, just two of them:
remove find_package() and use only find_library(), I think this is the simpler way and your project should work this way
provide cmake configuration for libbitcoin by yourself. Good introduction how to do this is here (and good to read anyway):
https://cmake.org/Wiki/CMake:How_To_Find_Libraries
As far as I know, currently libbitcoin does not export any <libbitcoin>Config.cmake package.
But it does export a libbitcoin.pc file for generic use with pkg-config.
ie: /usr/local/lib/pkgconfig/libbitcoin.pc
If you get results from invoking pkg-config --cflags libbitcoin then it's there.
And then you can put something like this in your CMakeLists.txt:
#use this if libbitcoin is installed to some custom location
set(ENV{PKG_CONFIG_PATH} "/path/to/libbitcoin/pkgconfig/:$ENV{PKG_CONFIG_PATH}")
#then later..
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIB_BITCOIN REQUIRED libbitcoin)
#then later..
target_link_libraries(${PROJECT_NAME} PRIVATE ${LIB_BITCOIN_LIBRARIES})
target_include_directories(${PROJECT_NAME} PRIVATE ${LIB_BITCOIN_INCLUDE_DIRS})
That should pull in boost, make the libbitcoin includes visible and solve all manner of compiler and linker woes.
(Or if you are feeling mad, you could always make use of this gist).

CMake not wanting to link with libGL.so

I was coding in KDevelop, ant I set up my CMakeLists.txt to include and link against libGL and freeglut.
However, it gave me the following error:
make[2]: *** No rule to make target '/usr/lib/libGL.so', needed by 'opengl'. Stop.
Here is my CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
project(opengl)
add_executable(opengl main.cpp)
find_package(OpenGL REQUIRED)
find_package(GLUT REQUIRED)
include_directories( ${OPENGL_INCLUDE_DIRS} ${GLUT_INCLUDE_DIRS} )
target_link_libraries(opengl ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} )
First, what I am about to suggest might depend on CMake version, but I don't think (I'm using cmake version 3.1.0).
Looking at the installed FindOpenGL.cmake file, it looks like the variable you want in target_link_libraries is ${OPENGL_glu_LIBRARY}. Case does matter.
The best way to test an issue like this one is to use message("var: ${var}"), then you would be able to clearly see what your variable is set to during configuration.
Hope this helps!
FYI, I found the find module in the ${cmake_install_dir}/Modules/Find* where cmake_install_dir=/usr/share/cmake on my linux machine.
EDIT**
Sorry, was tired this morning and missed that you wanted GLUT, not GLU. There is a FindGLUT.cmake Module. You should call find_package(GLUT REQUIRED) and use ${GLUT_LIBRARIES} and ${GLUT_INCLUDE_DIR}. Sorry about the confusion!