Cmake link library target link error - c++

Hi I have problem with linkg Glfw and other libraries using cmake.
From command line i compile like this
g++ main.cpp -lGL -lGLU -lGLEW -lglfw
But I wanted to use cmake for compiling. I tried to use target_linkg_libraries but this produce error
CMake Error at CMakeLists.txt:18 (target_link_libraries): Cannot
specify link libraries for target "GL" which is not built by this
project.
I tried do this using add definitions. I dont see error but this don't link libraries.
cmake_minimum_required (VERSION 2.6)
project (test)
find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
ADD_DEFINITIONS(
-lGL
-lGLU
-lGLEW
-lglfw
)
add_executable(test.out
main.cpp
)
target_link_libraries(GL GLU GLEW glfw)

The syntax for target_link_libraries is:
target_link_libraries(your_executable_name libraries_list)
And you don't have to add add_definition statements (target_link_libraries adds this options)
There are also some useful variables provided by OpenGL and GLEW packages.
Your CMakeLists.txt should be like:
cmake_minimum_required (VERSION 2.6)
project (test)
find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR} ${GLEW_INCLUDE_DIRS})
add_executable(test
main.cpp
)
target_link_libraries(test ${OPENGL_LIBRARIES} ${GLEW_LIBRARIES})
One important detail to keep in mind is to place the target_link_libraries after the add_executable (or add_library) line.

Related

Project compiling with raylib static library

I am trying to create a game with the Raylib library. I just was until now just trying around inside the main.cpp and always compiled my code with this line inside the terminal.
clang -std=c++11 -framework CoreVideo -framework IOKit -framework Cocoa -framework GLUT -framework OpenGL libraylib.a main.cpp -o my_app
Now I want to recreate the Snake game just for fun. I thought I would be wise the spilt the main.cpp into multiple src files but I actually don't know how I should compile all of this. I tried to create a CMakeList.txt like this:
cmake_minimum_required (VERSION 3.0)
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -framework CoreVideo")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -framework IOKit")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -framework Cocoa")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -framework GLUT")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -framework OpenGL")
project(Snake)
add_executable(
Snake
main.cpp
Snake.cpp
)
target_link_libraries(main ${CMAKE_SOURCE_DIR}/librarylib.a)
but this doesn't work. This is the Error message.
CMake Error at CMakeLists.txt:18 (target_link_libraries):
Cannot specify link libraries for target "main" which is not built by this
project.
-- Configuring incomplete, errors occurred!
Are there better ways to compile this project and can anyone explain to me what the -framework flag actually does? I still want to use VSCode because I want to learn how to use the terminal a bit better.
Edit: Information form brew ls --verbose raylib:
/usr/local/Cellar/raylib/2.5.0/LICENSE.md
/usr/local/Cellar/raylib/2.5.0/INSTALL_RECEIPT.json
/usr/local/Cellar/raylib/2.5.0/.brew/raylib.rb
/usr/local/Cellar/raylib/2.5.0/CHANGELOG
/usr/local/Cellar/raylib/2.5.0/include/raylib.h
/usr/local/Cellar/raylib/2.5.0/HISTORY.md
/usr/local/Cellar/raylib/2.5.0/README.md
/usr/local/Cellar/raylib/2.5.0/lib/pkgconfig/raylib.pc
/usr/local/Cellar/raylib/2.5.0/lib/cmake/raylib/raylib-config-version.cmake
/usr/local/Cellar/raylib/2.5.0/lib/cmake/raylib/raylib-config.cmake
/usr/local/Cellar/raylib/2.5.0/lib/libraylib.2.5.0.dylib
/usr/local/Cellar/raylib/2.5.0/lib/libraylib.2.dylib
/usr/local/Cellar/raylib/2.5.0/lib/libraylib.a
/usr/local/Cellar/raylib/2.5.0/lib/libraylib.dylib
Solved it by setting my CMakeLists.txt up like this:
cmake_minimum_required(VERSION 3.0)
project(Snake)
set (CMAKE_CXX_STANDARD 11)
# Executable & linking
add_executable(${PROJECT_NAME} main.cpp snake.cpp)
if (NOT TARGET raylib)
find_package(raylib 2.5.0 REQUIRED)
endif()
target_link_libraries(${PROJECT_NAME} raylib)
You want to link your executable to librarylib.a. The target name of your executable is Snake.
If we look at the error:
Cannot specify link libraries for target "main" which is not built by this project.
Indeed, you never added a library or an executable called main.
This is what should be in your target_link_libraries call should look like:
target_link_libraries(Snake PUBLIC "${CMAKE_SOURCE_DIR}/librarylib.a")

CMakeTextFile.txt For Librealsense (legacy) and GLFW3

I want to make a small application for an r200 camera. It uses C++ and it needs to use the librealsense library as well as the glfw3 library.
Previously I was trying to compile this program through the command line using something like:
g++ -std=c++11 pointcloud.cpp `pkg-config --cflags glfw3` -lrealsense -lopencv_core -lopencv_imgproc -lopencv_highgui -o ir `pkg-config --static --libs glfw3` && ./ir
However, I had the misfortune of having this not work (it still failed as it couldn't find the glfw3 methods). And if I removed the --static tag I received this error:
/usr/bin/x86_64-linux-gnu-ld:
/usr/local/lib/libglfw3.a(posix_thread.c.o): undefined reference to
symbol 'pthread_key_delete##GLIBC_2.2.5'
//lib/x86_64-linux-gnu/libpthread.so.0: error adding symbols: DSO
missing from command line collect2: error: ld returned 1 exit status
However, none of the suggested methods seemed to work for me.
So I have decided to try and make a CMakeLists.txt file to tackle this. What I currently have is:
cmake_minimum_required(VERSION 3.10)
project(main)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "-pthread")
find_package(OpenGL REQUIRED)
find_package(OpenCV REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR})
include_directories(${OpenCV_INCLUDE_DIRS})
add_subdirectory(librealsense)
add_executable(main pointcloud.cpp librealsense/examples/example.hpp)
target_link_libraries(main ${OpenCV_LIBS})
target_link_libraries(main ${OPENGL_gl_LIBRARY})
target_link_libraries(main realsense2)
However this doesn't work and unfortunately it takes about half an hour to make since its building the librealsense module. What I was hoping for was that there'd be something like this:
cmake_minimum_required(VERSION 3.10)
project(main)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS " -pthread ")
find_package(OpenGL REQUIRED)
find_package(OpenCV REQUIRED)
find_package(librealsense REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR})
include_directories(${OpenCV_INCLUDE_DIRS})
include_directories(${librealsense_INCLUDE_DIRS})
add_executable(main pointcloud.cpp librealsense/examples/example.hpp)
target_link_libraries(main ${OpenCV_LIBS})
target_link_libraries(main ${OPENGL_gl_LIBRARY})
target_link_libraries(main ${librealsense_LIBRARY})
However I can't find anything and this doesn't work since I don't know where to get the correct library names from. I managed to snag the OPENGL names from here.
But I don't know where to find the librealsense ones. If it matters I'm using a legacy branch as well as the r200 is no longer supported.
If anyone could help me with either the Makefile or the command line, that would be great as I'm having a tough time figuring this all out.

Build project with "experimental/filesystem" using cmake

I need to add a "experimental/filesystem" header to my project
#include <experimental/filesystem>
int main() {
auto path = std::experimental::filesystem::current_path();
return 0;
}
So I used -lstdc++fs flag and linked with libstdc++fs.a
cmake_minimum_required(VERSION 3.7)
project(testcpp)
set(CMAKE_CXX_FLAGS "-std=c++14 -lstdc++fs" )
set(SOURCE_FILES main.cpp)
target_link_libraries(${PROJECT_NAME} /usr/lib/gcc/x86_64-linux-gnu/7/libstdc++fs.a)
add_executable(testcpp ${SOURCE_FILES})
However, I have next error:
CMake Error at CMakeLists.txt:9 (target_link_libraries): Cannot
specify link libraries for target "testcpp" which is not built by
this project.
But if I compile directly, it`s OK:
g++-7 -std=c++14 -lstdc++fs -c main.cpp -o main.o
g++-7 -o main main.o /usr/lib/gcc/x86_64-linux-gnu/7/libstdc++fs.a
Where is my mistake?
It's just that the target_link_libraries() call has to come after the add_executable() call. Otherwise the testcpp target is not known yet. CMake parses everything sequential.
So just for completeness, here is a working version of your example I've tested:
cmake_minimum_required(VERSION 3.7)
project(testcpp)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# NOTE: The following would add library with absolute path
# Which is bad for your projects cross-platform capabilities
# Just let the linker search for it
#add_library(stdc++fs UNKNOWN IMPORTED)
#set_property(TARGET stdc++fs PROPERTY IMPORTED_LOCATION "/usr/lib/gcc/x86_64-linux-gnu/7/libstdc++fs.a")
set(SOURCE_FILES main.cpp)
add_executable(testcpp ${SOURCE_FILES})
target_link_libraries(${PROJECT_NAME} stdc++fs)

How to use FFTW library in cmake?

I have C++ code which uses FFTW 3.3.4. Ubuntu 16.04, cmake version 3.7.2
$ locate *fftw*.so
/usr/lib/libsfftw.so
/usr/lib/libsfftw_mpi.so
/usr/lib/libsfftw_threads.so
/usr/lib/libsrfftw.so
/usr/lib/libsrfftw_mpi.so
/usr/lib/libsrfftw_threads.so
/usr/lib/x86_64-linux-gnu/libfftw3.so
/usr/lib/x86_64-linux-gnu/libfftw3_mpi.so
/usr/lib/x86_64-linux-gnu/libfftw3_omp.so
/usr/lib/x86_64-linux-gnu/libfftw3_threads.so
/usr/lib/x86_64-linux-gnu/libfftw3f.so
/usr/lib/x86_64-linux-gnu/libfftw3f_mpi.so
/usr/lib/x86_64-linux-gnu/libfftw3f_omp.so
/usr/lib/x86_64-linux-gnu/libfftw3f_threads.so
/usr/lib/x86_64-linux-gnu/libfftw3l.so
/usr/lib/x86_64-linux-gnu/libfftw3l_mpi.so
/usr/lib/x86_64-linux-gnu/libfftw3l_omp.so
/usr/lib/x86_64-linux-gnu/libfftw3l_threads.so
/usr/lib/x86_64-linux-gnu/libfftw3q.so
/usr/lib/x86_64-linux-gnu/libfftw3q_omp.so
/usr/lib/x86_64-linux-gnu/libfftw3q_threads.so
$ locate fftw3.h
/usr/include/fftw3.h
I can compile it in this way:
g++ main.cpp -o main -lfftw3
but I have a problem with cmake.
This is my CMakeLists.txt:
cmake_minimum_required(VERSION 3.5.1)
project (main)
SET(CMAKE_C_COMPILER gcc)
SET(CMAKE_CXX_COMPILER g++)
file(GLOB SOURCES "*.cpp")
SET(CMAKE_CXX_FLAGS "-lm -lfftw3")
SET(CMAKE_C_FLAGS "-lm -lfftw3")
INCLUDE_DIRECTORIES(/usr/include)
LINK_DIRECTORIES(/usr/lib/x86_64-linux-gnu)
add_library(fftw3 STATIC IMPORTED)
set(CMAKE_C_OUTPUT_EXTENSION_REPLACE 1)
set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1)
add_executable(main ${SOURCES})
cmake . && make
gives
undefined reference to `fftw_malloc'
and the same for the other fftw functions.
The command add_library will create a library in your project (CMake -
add_library). I assume that is not what you want.
The command: g++ main.cpp -o main -lfftw3 will link the executable to the fftw library. In CMake you can reproduce the linking with:
add_executable(main ${SOURCES})
target_link_libraries(main fftw3)
Docu: CMake - target_link_libraries
Notice: It is important that the add_executable command comes before the linking.
Have fun with FFTW :)
We delegate this to pkg-config:
find_package(PkgConfig REQUIRED)
pkg_search_module(FFTW REQUIRED fftw3 IMPORTED_TARGET)
include_directories(PkgConfig::FFTW)
link_libraries (PkgConfig::FFTW)
This works with cmake 3.11 (at least, it may work with earlier versions too).
NOTE: This doesn't work with fftw3_thread component because they don't have a separate .pc file. (see https://github.com/FFTW/fftw3/issues/180).
This may work to add the component (not tested, doesn't work in Macs --see comments--):
link_libraries (PkgConfig::FFTW -lfftw3_thread)
NOTE 2: I am pasting here #OlafWilkocx solution to get the thread component as well
cmake_minimum_required(VERSION 3.20)
...
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -fno-math-errno -ffinite-math-only") # clang
find_package(OpenMP REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(FFTW IMPORTED_TARGET REQUIRED fftw3)
if( NOT FFTW_ROOT AND DEFINED ENV{FFTWDIR} )
set( FFTW_ROOT $ENV{FFTWDIR} )
endif()
find_library(
FFTW_DOUBLE_THREADS_LIB
NAMES "fftw3_threads"
PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR}
)
if (FFTW_DOUBLE_THREADS_LIB)
set(FFTW_DOUBLE_THREADS_LIB_FOUND TRUE)
set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_DOUBLE_THREADS_LIB})
add_library(FFTW::DoubleThreads INTERFACE IMPORTED)
set_target_properties(FFTW::DoubleThreads
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}"
INTERFACE_LINK_LIBRARIES "${FFTW_DOUBLE_THREADS_LIB}"
)
else()
set(FFTW_DOUBLE_THREADS_LIB_FOUND FALSE)
endif()
include_directories(PkgConfig::FFTW)
add_executable(solver_step src/solver_step.cc)
target_link_libraries(solver_step PRIVATE OpenMP::OpenMP_CXX ${VTK_LIBRARIES} PkgConfig::FFTW ${FFTW_DOUBLE_THREADS_LIB})
NOTE 3
I am told that the line include_directories(PkgConfig::FFTW) is always incorrect and suggested to either only use link_libraries(PkgConfig::FFTW) or target_link_libraries(target_name PRIVATE PkgConfig::FFTW).
see here: Avoid bad include paths in CMake's pkg-config fallback

FreeType not linking with CMake after explicit path to library given.

I have an issue with linking FreeType with my project. I have my libs in a separate folder, {PROJECT}/lib, where libfreetype.a is located. My compiler is MinGW-64 4.8.3 x86_64-posix-seh-rev2, and I built libfreetype.a from source using this compiler. My cmake file looks like the following:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/Build/Debug")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -lmingw32")
set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++")
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
include_directories(${PROJECT_SOURCE_DIR}/include)
link_directories(${PROJECT_SOURCE_DIR}/lib)
set(FREETYPE_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/include/)
set(FREETYPE_LIBRARY ${PROJECT_SOURCE_DIR}/lib/libfreetype.a)
find_package(Freetype REQUIRED)
set(SOURCE_FILES main.cpp ...)
add_executable(Wahoo ${SOURCE_FILES})
target_link_libraries(Test freetype)
Running this will cause the linker to fail with undefined references to '__imp_FT_Init_FreeType'. Removing the the libfreeType.a causes CMAKE say that it cannot find -lfreeType (as expected), but including libfreetype.a will cause the linker errors.
I have to change my answer, because I tried it on my own and it was bullshit.
I think, you have to change only your last line into
target_link_libraries(Test ${FREETYPE_LIBRARY})