Issues with linking GLFW to the executable with CMake - cmake

I am currently trying to link the GLFW library with my executable files in CLion. After hours of research and trial & error, I am stuck. I am using find_package() to locate my GLFW library. For some reason my FindGLFW.cmake file seems to correctly locate the library in /usr/local/lib/libglfw.a when using find_library(), but my CMakeLists.txt returns empty with find_package(). I don't really understand how that's possible. Could someone help me out?
CMakeLists.txt:
cmake_minimum_required(VERSION 3.15)
project(learnopengl)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMake)
find_package(glfw 3.3 REQUIRED)
message(STATUS "(CMakeLists.txt) GLFW: [${glfw}]")
if (NOT glfw)
message(SEND_ERROR "(CMakeLists) Did not find glfw_library")
endif()
add_executable(learnopengl src/main.cpp)
target_link_libraries(learnopengl glfw)
FindGLFW.cmake
find_library( GLFW_LIBRARY
NAMES
glfw3 glfw
PATHS
${GLFW_LOCATION}/lib
$ENV{GLFW_LOCATION}/lib
/usr/lib64
/usr/lib
/usr/local/lib64
/usr/local/lib
NO_DEFAULT_PATH
DOC "The GLFW library"
)
message(STATUS "(FindGLFW.cmake) GLFW_INCLUDE_DIR: [${GLFW_INCLUDE_DIR}]")
message(STATUS "(FindGLFW.cmake) GLFW_LIB: [${GLFW_LIBRARY}]")
if (NOT GLFW_LIBRARY)
message(SEND_ERROR "(FindGLFW.cmake) Did not find glfw_library")
Output when running cmake ..
-- (FindGLFW.cmake) GLFW_INCLUDE_DIR: [/usr/local/include]
-- (FindGLFW.cmake) GLFW_LIB: [/usr/local/lib/libglfw3.a]
-- (CMakeLists.txt) GLFW: []
CMake Error at CMakeLists.txt:12 (message):
(CMakeLists) Did not find glfw_library
When I tried to directly include find_library() in my CMakeLists.txt instead, it did locate the library, but when I tried to link it with my executable, I got a linker error saying it couldn't locate the library:
CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(learnopengl)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMake)
find_library( GLFW_LIBRARY
NAMES
glfw3 glfw
PATHS
${GLFW_LOCATION}/lib
$ENV{GLFW_LOCATION}/lib
/usr/lib64
/usr/lib
/usr/local/lib64
/usr/local/lib
NO_DEFAULT_PATH
DOC "The GLFW library"
)
message(STATUS "(FindGLFW.cmake) GLFW_LIB: [${GLFW_LIBRARY}]")
if (NOT GLFW_LIBRARY)
message(SEND_ERROR "(CMakeLists.txt) Did not find glfw_library")
endif()
add_executable(learnopengl src/main.cpp)
target_link_libraries(learnopengl GLFW_LIBRARY)
Output:
~/dev/projects/opengl/learnopengl/build  cmake ..
-- (CMakeLists.txt) GLFW_LIB: [/usr/local/lib/libglfw3.a]
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/Philipp/dev/projects/opengl/learnopengl/build
~/dev/projects/opengl/learnopengl/build  cmake --build .
[ 50%] Linking CXX executable learnopengl
ld: library not found for -lGLFW_LIBRARY
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [learnopengl] Error 1
make[1]: *** [CMakeFiles/learnopengl.dir/all] Error 2
make: *** [all] Error 2
I would really appreciate some hints as to what I am doing wrong. I can't see why it wouldn't locate/link the library correctly.
Thank you!

In cmake, arguments are case sensitive, so find_package should be
find_package(GLFW 3.3 REQUIRED)
Linker problem can be found easily in the logs. You are trying to link -lGLFW_LIBRARY, however what you want to link is GLFW_LIBRARY's value, /usr/local/lib/libglfw3.a .
target_link_libraries(learnopengl ${GLFW_LIBRARY})

Related

CMake having multiple executables throws me an error

I'm having some trouble with cmake: I'm using cmake for my school project and there is a bonus part but we have to compile another executable for the bonus part, and I tried this:
cmake_minimum_required(VERSION 3.10)
project(philosophers)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_C_COMPILER /usr/bin/clang)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_FLAGS "-Wall -Wextra -Werror")
set(CMAKE_EXE_LINKER_FLAGS "-lpthread")
set(LIBFT ${CMAKE_CURRENT_SOURCE_DIR}/lib/libft42/libft.a)
add_custom_command(OUTPUT ${LIBFT}
COMMAND make
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib/libft42)
link_libraries(philo_bonus ${LIBFT})
link_libraries(philo ${LIBFT})
aux_source_directory(src SRC)
aux_source_directory(src_bonus SRC_BONUS)
add_executable(philo ${SRC} ${LIBFT})
add_executable(philo_bonus ${SRC_BONUS} ${LIBFT})
target_include_directories(philo
PUBLIC inc
PUBLIC lib/libft42/inc)
target_include_directories(philo_bonus
PUBLIC inc_bonus
PUBLIC lib/libft42/inc)
I removed include_directories and replaced it with target_include_directories because I want my two projects to have separate includes, but when I try to cmake -Bbuild -H., it says:
CMake Error at CMakeLists.txt:23 (add_executable):
Target "philo_bonus" links to itself.
CMake Error at CMakeLists.txt:22 (add_executable):
Target "philo" links to itself.
CMake Error: Cannot determine link language for target "philo_bonus".
CMake Error: CMake can not determine linker language for target: philo_bonus
-- Generating done
CMake Generate step failed. Build files cannot be regenerated correctly.
I don't understand what happened here, I changed nothing in add_executable and it worked fine before I added another.

Hot do I link MPFR in CMake?

I'm totally new to cmake, I'm on MacOs and I'm trying to build a c++ library and I need to link my executables to mpfr in order to make it work
This is my CMakeLists.txt file:
cmake_minimum_required(VERSION 3.19)
project(my_project)
set(CMAKE_CXX_STANDARD 14)
add_executable(my_project main.cpp)
find_package(GSL REQUIRED)
target_link_libraries(my_project GSL::gsl GSL::gslcblas)
find_package(Boost REQUIRED)
target_link_libraries(my_project Boost::boost)
find_package(MPFR REQUIRED) # <- It fails here!
target_link_libraries(my_project MPFR::mpfr)
When I try to build my project with CLion I get the following error:
CMake Error at CMakeLists.txt:13 (find_package):
By not providing "FindMPFR.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "MPFR", but
CMake did not find one.
Could not find a package configuration file provided by "MPFR" with any of
the following names:
MPFRConfig.cmake
mpfr-config.cmake
Add the installation prefix of "MPFR" to CMAKE_PREFIX_PATH or set
"MPFR_DIR" to a directory containing one of the above files. If "MPFR"
provides a separate development package or SDK, be sure it has been
installed.
After some research I found out that Cmake was linking correctly both GSL and Boost because there are both a /usr/local/share/cmake/Modules/FindGSL.cmake and a /usr/local/share/cmake/Modules/FindBoost.cmake file, So I looked online for a FindMPFR.cmake file to insert into the /usr/local/share/cmake/Modules/ directory, I tried with this one but the error remains the same. What am I doing wrong?
Edit:
Ok now my CMakeLists.txt file looks like this:
cmake_minimum_required(VERSION 3.19)
project(my_project)
set(CMAKE_CXX_STANDARD 14)
add_executable(my_project main.cpp )
# Append the cmake/ directory to the CMAKE_MODULE_PATH
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
find_package(GSL REQUIRED)
message(STATUS "GSL Found: ${GSL_FOUND}")
target_link_libraries(my_project GSL::gsl GSL::gslcblas)
find_package(Boost REQUIRED)
message(STATUS "Boost Found: ${Boost_FOUND}")
target_link_libraries(my_project Boost::boost)
find_package(MPFR REQUIRED)
message(STATUS "MPFR Found: ${MPFR_FOUND}")
target_link_libraries(my_project ${MPFR_LIBRARIES})
And it works fine :)

How to add Ziplib library in Clion on Ubuntu

I'm trying to add ZipLip into my project using Clion on ubuntu, but I have this output:
====================[ Build | TryZip | Debug ]==================================
/home/david/Snap/clion-2019.2.4/bin/cmake/linux/bin/cmake --build
/home/david/CLionProjects/TryZip/cmake-build-debug --target TryZip -- -j 2
[ 13%] Built target bzip2
[ 31%] Built target zlib
[ 83%] Built target lzma
[ 95%] Built target ZipLib
Scanning dependencies of target TryZip
[ 97%] Linking CXX executable ../bin/TryZip
/usr/bin/ld: cannot find -lExternalLibrary/ZipLib
collect2: error: ld returned 1 exit status
CMakeFiles/TryZip.dir/build.make:102: recipe for target '../bin/TryZip' failed
make[3]: *** [../bin/TryZip] Error 1
CMakeFiles/Makefile2:109: recipe for target 'CMakeFiles/TryZip.dir/all' failed
make[2]: *** [CMakeFiles/TryZip.dir/all] Error 2
CMakeFiles/Makefile2:116: recipe for target 'CMakeFiles/TryZip.dir/rule' failed
make[1]: *** [CMakeFiles/TryZip.dir/rule] Error 2
Makefile:131: recipe for target 'TryZip' failed
make: *** [TryZip] Error 2
This is my Cmakefile.txt
cmake_minimum_required(VERSION 3.15)
project(TryZip)
if(BOOST_FILESYSTEM)
include_directories(${BOOST_INCLUDE_DIR})
link_directories(${BOOST_LIB_DIR})
add_definitions(-DUSE_BOOST_FILESYSTEM)
else()
if(MSVC)
add_definitions(-DFILESYSTEM_EXPERIMENTAL)
endif()
endif()
if(BOOST_FILESYSTEM)
if(UNIX)
find_package(Boost COMPONENTS system filesystem REQUIRED)
target_link_libraries(${Boost_FILESYSTEM_LIBRARY}
${Boost_SYSTEM_LIBRARY})
endif()
endif()
add_subdirectory(ExternalLibrary/ZipLib)
link_libraries(ExternalLibrary/ZipLib)
include_directories(ExternalLibrary/ZipLib)
set(CMAKE_CXX_STANDARD 17)
add_executable(TryZip main.cpp ExternalLibrary/ZipLib/ZipFile.cpp)
target_link_libraries(TryZip ZipLib)
Can someone help me to solve this please?
My ZipLib folder is in the same folder as my cmakefile.txt file.
The call to link_libraries() appears to accept the wrong arguments in this case. The link_libraries() command takes arguments of existing CMake targets, or library names. It is also redundant with your target_link_libraries() call, as this already links ZipLib to TryZip.
Try removing the call to link_libraries(), as this CMake function is deprecated and its use is highly discouraged. The include_directories() call is similarly deprecated, in favor of the target-specific command, so consider using target_include_directories() instead.
Assuming your added sub-directory ExternalLibrary/ZipLib contains an additional CMakeLists.txt file for configuring the ZipLib target, you should not need to add the ZipFile.cpp file again. If this file is already compiled in the sub-directory into the target ZipLib, you do not need to compile it again into TryZip.
add_subdirectory(ExternalLibrary/ZipLib)
set(CMAKE_CXX_STANDARD 17)
add_executable(TryZip main.cpp)
target_include_directories(TryZip PRIVATE ExternalLibrary/ZipLib)
target_link_libraries(TryZip PRIVATE ZipLib)
EDIT: Based on your feedback, it appears ZipLib also depends on pthread but somehow it is not getting linked correctly. You might try to add the following to your ExternalLibrary/ZipLib/CMakeLists.txt file (if it doesn't already exist), to utilize CMake's FindThreads module:
find_package(Threads REQUIRED)
...
target_link_libraries(ZipLib PUBLIC Threads::Threads)

cmake on windows. Link libraries in folder

Disclaimer: I'm new to cmake so i have no idea what I'm doing.
All guides and tutorials i find seem to think I'm running a 20 man team that needs to work together.
All I'm trying to do is put all my libraries in an include folder and lib folder.
In visual studio and code::blocks i just set up the linker in the IDE, but cmake is a little hard for me to wrap my head around.
I've set include and link directories with
include_directories(${PROJECT_SOURCE_DIR}/include)
link_directories(${PROJECT_SOURCE_DIR}/lib)
Then i try to
target_link_libraries(${PROJECT_NAME} jsoncpp)
This however produces undefined references. Is there a simple way to add and link libraries without me having to google and add a cmake module for each one?
Edit:
attempts:
target_link_libraries(${PROJECT_NAME} libjsoncpp.a)
error: undefined reference
target_link_libraries(${PROJECT_NAME} libjsoncpp)
error: cannot find -llibjsoncpp
target_link_libraries(${PROJECT_NAME} jsoncpp)
error: undefined reference
target_link_libraries(${PROJECT_NAME} C:/Repos/prosjekt-bad-racoon/lib/libjsoncpp.a)
error: undefined reference
target_link_libraries(${PROJECT_NAME} ${PROJECT_SOURCE_DIR}/lib/libjsoncpp.a)
error: undefined reference
Edit:
Full cmake file
cmake_minimum_required(VERSION 3.8)
project(prosjekt_bad_racoon)
set(CMAKE_CXX_STANDARD 11)
include_directories(${PROJECT_SOURCE_DIR}/include)
link_directories(${PROJECT_SOURCE_DIR}/lib)
set(SOURCE_FILES main.cpp Core.cpp Core.h Collider.cpp Collider.h Player.cpp Player.h Texture.cpp Texture.h AudioController.cpp AudioController.h)
add_executable(prosjekt_bad_racoon ${SOURCE_FILES})
set(EXECUTABLE_NAME ${PROJECT_NAME})
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules" ${CMAKE_MODULE_PATH})
target_link_libraries(${PROJECT_NAME} libjsoncpp.a)
find_package(SFML 2 REQUIRED system window graphics network audio)
if(SFML_FOUND)
include_directories(${SFML_INCLUDE_DIR})
target_link_libraries(${EXECUTABLE_NAME} ${SFML_LIBRARIES})
link_directories("${PROJECT_SOURCE_DIR}")
endif()
"C:\Program Files\JetBrains\CLion 2017.2.2\bin\cmake\bin\cmake.exe" --build C:\Repos\prosjekt-bad-racoon\cmake-build-debug --target prosjekt_bad_racoon -- -j 2
[ 14%] Linking CXX executable prosjekt_bad_racoon.exe
CMakeFiles\prosjekt_bad_racoon.dir/objects.a(Core.cpp.obj): In function `ZN4CoreC2Ev':
C:/Repos/prosjekt-bad-racoon/Core.cpp:3: undefined reference to `Json::Value::Value(char const*)'
CMakeFiles\prosjekt_bad_racoon.dir/objects.a(Core.cpp.obj): In function `ZN4CoreD2Ev':
C:/Repos/prosjekt-bad-racoon/Core.cpp:8: undefined reference to `Json::Value::~Value()'
collect2.exe: error: ld returned 1 exit status
CMakeFiles\prosjekt_bad_racoon.dir\build.make:236: recipe for target 'prosjekt_bad_racoon.exe' failed
mingw32-make.exe[3]: *** [prosjekt_bad_racoon.exe] Error 1
CMakeFiles\Makefile2:66: recipe for target 'CMakeFiles/prosjekt_bad_racoon.dir/all' failed
mingw32-make.exe[2]: *** [CMakeFiles/prosjekt_bad_racoon.dir/all] Error 2
CMakeFiles\Makefile2:78: recipe for target 'CMakeFiles/prosjekt_bad_racoon.dir/rule' failed
mingw32-make.exe[1]: *** [CMakeFiles/prosjekt_bad_racoon.dir/rule] Error 2
Makefile:117: recipe for target 'prosjekt_bad_racoon' failed
mingw32-make.exe: *** [prosjekt_bad_racoon] Error 2

CMake, shared library linking fail

I'm currently getting used to cmake and I'm trying to compile a small project with a .so library linking.
My project is the following.
/
CMakeLists.txt
inc/
Als.h
src/
main.c
CMakeLists.txt
lib/
libals.so
build/
I'm compiling from the build directory with:
$ cmake ..
-- DIR:
-- Configuring done
-- Generating done
-- Build files have been written to: /home/julien/tmp/cmakeTest/build
And then:
$ make
Linking C executable cmakeTest
/usr/bin/ld: ne peut trouver -lals
collect2: error: ld returned 1 exit status
src/CMakeFiles/cmakeTest.dir/build.make:85: recipe for target 'src/cmakeTest' failed
make[2]: *** [src/cmakeTest] Error 1
CMakeFiles/Makefile2:75: recipe for target 'src/CMakeFiles/cmakeTest.dir/all' failed
make[1]: *** [src/CMakeFiles/cmakeTest.dir/all] Error 2
Makefile:76: recipe for target 'all' failed
make: *** [all] Error 2
The linker seems to be unable to find the libals.so file.
Here is the file /CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
PROJECT(cmaketest)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
INCLUDE_DIRECTORIES(
inc
)
ADD_SUBDIRECTORY(src)
get_directory_property(OUT_VAR LINK_DIRECTORIES)
message(STATUS "DIR: ${OUT_VAR}")
And here is the file /src/CMakeLists.txt:
PROJECT(cmakeTest)
FILE(
GLOB
${PROJECT_NAME}_Sources
*.c
)
INCLUDE_DIRECTORIES(
inc
inc
)
ADD_EXECUTABLE(
${PROJECT_NAME}
${${PROJECT_NAME}_Sources}
)
LINK_DIRECTORIES(
/home/julien/tmp/cmakeTest/lib/
)
TARGET_LINK_LIBRARIES(
${PROJECT_NAME}
als
pthread
)
Maybe I missed something but if I change the /src/CMakeLists.txt to:
PROJECT(cmakeTest)
FILE(
GLOB
${PROJECT_NAME}_Sources
*.c
)
INCLUDE_DIRECTORIES(
inc
inc
)
ADD_EXECUTABLE(
${PROJECT_NAME}
${${PROJECT_NAME}_Sources}
)
TARGET_LINK_LIBRARIES(
${PROJECT_NAME}
/home/julien/tmp/cmakeTest/lib/libals.so
pthread
)
The compilation is ok. Does someone know why the linker is unable to find libals.so when I'm giving him the good directory path to look in?
The LINK_DIRECTORIES functions seems not to be working.
Besides the solution you already have, and my solution in a comment, the problem you have with the CMake file shown is the order in which you invoke the CMake commands.
From the link_directories command reference:
The command will apply only to targets created after it is called.
[Emphasis mine]
You simply need to call link_directories before you call add_executable.