Link properly a library using cmake - c++

I try to learn how to use cmake, and so I created a little project but when I try to compile I get this error : /usr/bin/ld : CMakeFiles/test.dir/main.cpp.o : dans la fonction « main » : main.cpp:(.text+0x2d) : référence indéfinie vers « la::Matrice<int>::Matrice(unsigned int, unsigned int) »
.
├── build
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   ├── cmake_install.cmake
│   ├── LinearAlgebra
│   └── Makefile
├── CMakeLists.txt
├── LinearAlgebra
│   ├── CMakeLists.txt
│   ├── Matrice.cpp
│   └── Matrice.hpp
└── main.cpp
./CmakeLists.txt :
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED true)
project(test_project)
add_subdirectory(LinearAlgebra)
add_executable(test main.cpp)
link_libraries(test linear_algebra)
LinearAlgebra/CMakeLists.txt :
cmake_minimum_required(VERSION 3.10)
project(linear_algebra)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
set(SOURCES
Matrice.cpp
)
set(HEADERS
Matrice.hpp
)
add_library(linear_algebra ${HEADERS} ${SOURCES})
Do someone know where the problem is ?

With link_libraries you define which libraries will be linked for targets that are defined after this command and within the current directory.
You probably meant to use target_link_libraries which defines libraries to link to the given target.
The documentation suggests to use this over link_libraries whenever possible. It is explicit and better scoped.
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED true)
project(test_project)
add_subdirectory(LinearAlgebra)
add_executable(test main.cpp)
target_link_libraries(test linear_algebra)

Related

How to make my project find header file from my own separate library imported with FetchContent?

I'm trying to use my own library in a different project using CMake and FetchContent. My library is a static one that's built with CMake in a separate git repo, and it works fine when built with a demo in the same repo. When I use FetchContent to use it in a separate project it can't find the header files and I don't know how to include them.
dynamic-shadow-lib tree:
.
├── CMakeLists.txt
├── demo
│   ├── CMakeLists.txt
│   └── main.cpp
├── include
│   ├── line2D.hpp
│   ├── math.hpp
│   ├── mathplotUtil.hpp
│   ├── shape2D.hpp
│   ├── square2D.hpp
│   ├── triangle2D.hpp
│   └── vec2f.hpp
├── LICENSE
├── README.md
├── src
│   ├── line2D.cpp
│   ├── math.cpp
│   ├── square2D.cpp
│   ├── triangle2D.cpp
│   └── vec2f.cpp
└── tests
├── CMakeLists.txt
├── unit_tests
│   ├── CMakeLists.txt
│   ├── line2DTests.cpp
│   ├── main.cpp
│   ├── mathTests.cpp
│   ├── square2DTests.cpp
│   └── vec2fTests.cpp
└── visual_tests
├── CMakeLists.txt
├── main.cpp
└── visualTests.hpp
dynamic-shadow-lib root CmakeLists.txt:
cmake_minimum_required(VERSION 3.16)
project(
dynamic-shadows
VERSION 1.0
LANGUAGES CXX
)
# Build config variables
set(BUILD_DEMO FALSE)
set(BUILD_TESTS FALSE)
# Set C++ to version 14
set(CMAKE_CXX_STANDARD 14)
# Set binary destinations
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# Set header dir
set(HEADERS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
include_directories(${HEADERS_DIR})
# Set source dir
set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
# Set a name for the target
set(TARGET_LIB ${CMAKE_PROJECT_NAME}-lib)
# Make library ${TARGET_LIB}
add_library(
${TARGET_LIB} STATIC
${SOURCE_DIR}/math.cpp
${SOURCE_DIR}/vec2f.cpp
${SOURCE_DIR}/line2D.cpp
${SOURCE_DIR}/square2D.cpp
${SOURCE_DIR}/triangle2D.cpp
)
if (${BUILD_TESTS})
# Enable testing (GoogleTests)
include(CTest)
enable_testing()
add_subdirectory(tests)
endif()
if (${BUILD_DEMO})
# Demo
add_subdirectory(demo)
endif()
Project that I'm trying to include my lib in (tree):
.
├── CMakeLists.txt
├── include
│   ├── Game.hpp
│   └── Primitive.hpp
├── LICENSE
├── README.md
├── src
│   ├── Game.cpp
│   └── main.cpp
└── tests
├── CMakeLists.txt
└── main.cpp
Projects root CMakeLists.txt:
cmake_minimum_required(VERSION 3.16)
project(realtime-light-shadow-2D
LANGUAGES CXX
VERSION 1.0
)
# Set extra compiler flags
set(CMAKE_CXX_FLAGS "-W -Wall -std=c++14 -fopenmp")
# Set binary destinations
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# Dependencies
include(FetchContent)
set (FETCHCONTENT_QUIET FALSE)
# SFML
message (STATUS "Adding SFML..")
FetchContent_Declare(
sfml
GIT_REPOSITORY "https://github.com/SFML/SFML"
GIT_TAG 218154cf0098de3f495e31ced489da24b7318638 # Latest
GIT_PROGRESS TRUE
)
# No need to build audio and network modules
set(SFML_BUILD_AUDIO FALSE)
set(SFML_BUILD_NETWORK FALSE)
FetchContent_MakeAvailable(sfml)
# ImGui
message (STATUS "Adding ImGui")
FetchContent_Declare(
imgui
GIT_REPOSITORY https://github.com/ocornut/imgui
GIT_TAG 5c8f8d031166765d2f1e2ac2de27df6d3691c05a # Latest
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(imgui)
# ImGui-SFML
message (STATUS "Adding ImGui-SFML")
FetchContent_Declare(
imgui-sfml
GIT_REPOSITORY https://github.com/eliasdaler/imgui-sfml
GIT_TAG 4129d276d45845581b6ba99ede50db6f761e5089 # Latest
GIT_PROGRESS TRUE
)
set(IMGUI_DIR ${imgui_SOURCE_DIR})
set(IMGUI_SFML_FIND_SFML OFF)
set(IMGUI_SFML_IMGUI_DEMO ON)
FetchContent_MakeAvailable(imgui-sfml)
# dynamic-shadows-lib
message( STATUS "Adding dynamic-shadow-lib")
FetchContent_Declare(
dynamic-shadows-lib
GIT_REPOSITORY https://github.com/JesperGlas/dynamic-shadows-lib/
GIT_TAG 59c7884caac7cc98f902fd880ccb1c9b0f50cca0 # Latest
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(dynamic-shadows-lib)
# Set header dir
set(HEADERS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
include_directories(${HEADERS_DIR})
# Set source dir
set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
set(TARGET_BIN ${CMAKE_PROJECT_NAME})
add_executable(
${TARGET_BIN}
${SOURCE_DIR}/main.cpp
${SOURCE_DIR}/Game.cpp
)
target_link_libraries(
${TARGET_BIN}
PUBLIC
sfml-system
sfml-graphics
ImGui-SFML::ImGui-SFML
dynamic-shadows-lib
)
When I try to build the project (sfml-dynamic-light-demo) I get the following error:
[build] /home/jesper/dev/cpp/sfml-dynamic-light-demo/include/Primitive.hpp:4:10: fatal error: vec2f.hpp: No such file or directory
[build] 4 | #include "vec2f.hpp"
Which tells me that the libraries include folder might not be available to the project. I've tried to include it as an install(DIRECTORY ${HEADER_DIR}) in the libs root CMakeLists, but it has no effect. I suspect I'm using it wrong since when I build the project I still get "No install step for 'dynamic-shadows-lib-populate'".
What am I doing wrong? If it's a concept that I'm missing, what should I read up on to make it work?
Thanks to the comments I was able to solve this. In my library (Built with CMake) I used the variable CMAKE_PROJECT_NAME when creating my library (CMAKE_PROJECT_NAME-lib). This variable references the top root CMakeLists.txt which resultet in my library getting the wrong name when I used it in another project. By changing all of those variables to PROJECT_NAME, and other similar ones, everything worked as it should.
TLDR: Make sure to use local variables when you want to use a CMake project as a subproject. (In this case PROJECT_NAME, instead of CMAKE_PROJECT_NAME etc...).

Importing header files and linking .a file in CMake

Trying to put Skia in my CMake project. How do I tell CMake to link my executable against libskia.a and use the header files inside ext/skia so that I can include them like so?
#include <skia/subdirectory/headerfile.h>
My project structure is currently the following:
.
├── CMakeLists.txt
├── CMakeLists.txt.user
├── ext
│   ├── libskia.a
│   └── skia
│   └── <subdirectories>
│      └── <header files>.h
└── src
└── main.cpp
and my CMakeLists.txt:
cmake_minimum_required(VERSION 3.5)
project(project LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
add_executable(project src/main.cpp)
In your primary CMakeLists.txt file you would simply add the following:
target_link_libraries(project skia)
If CMake cannot find the library, you can either do:
target_link_libraries(project /full/path/to/libskia.a)
or:
link_directories(/path/to/libraries)
target_link_libraries(project skia)

CMake Qt5 specify output directory of header ui files

I have re-organized a CMake Qt5 project in multiple subdirectory, the final folder structure looks like this:
├── CMakeLists.txt
├── headers
│   ├── a.h
│   ├── b.h
├── LICENSE
├── README.md
├── resources
│   ├── images
│   │   ├── img.png
│   └── res.qrc
├── sources
│   ├── main.cpp
│   ├── a.cpp
│   ├── b.cpp
└── ui
├── a.ui
└── b.ui
The problems comes when i try to compile the whole project: in fact the compiler say that it cannot find headers ui files(e.g. ui_main.h and ui_sub.h), this is the error:
In file included from /home/vbm/test/headers/a.h:13,
from /home/vbm/test/headers/b.h:14,
from /home/vbm/test/sources/main.cpp:6:
/home/vbm/test/headers/a.h:12:10: fatal error: ui_a.h: No such file or directory
#include "ui_a.h"
^~~~~~~~
This is my CMakeLists.txt file:
cmake_minimum_required(VERSION 3.9)
project(test VERSION 0.1)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
find_package(Qt5Widgets REQUIRED)
find_package(Qt5Core REQUIRED)
# Declaring files
set( SOURCES
sources/main.cpp
source/a.cpp
source/b.cpp
)
set( HEADERS
headers/a.h
headers/b.h
)
set( UIS
ui/a.ui
ui/b.ui
)
set( RES
resources/res.qrc
)
add_executable(test ${SOURCES} ${HEADERS} ${UIS} ${RES})
target_link_libraries(test Qt5::Widgets Qt5::Core)
How can i specify the output directory of those header UI files?
--EDIT--
I have already added the CMAKE_AUTOUIC_SEARCH_PATHS property without any success, the compiler still gave me the same error.
This is what i've added to the CMakeLists.txt:
set(CMAKE_AUTOUIC_SEARCH_PATHS "${PROJECT_SOURCE_DIR}/ui")

C++ Armadillo library gives undefined reference to `arma::arma_rng_cxx11_instance'

I used CMake to build my project and Catch2 to do the testing. The following is my project structure
├── build
├── CMakeLists.txt
├── compile_commands.json
├── include
│   ├── node.h
│   ├── rrt.h
│   └── tree.h
├── Makefile
├── package.xml
├── scripts
├── src
│   ├── main.cpp
│   ├── node.cpp
│   ├── rrt.cpp
│   └── tree.cpp
├── test
│   ├── CMakeLists.txt
│   └── test.cpp
└── third_party
└── catch.hpp
In ./CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.3)
project(rrt_ros)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/include/rrt.h
${CMAKE_CURRENT_SOURCE_DIR}/include/tree.h
${CMAKE_CURRENT_SOURCE_DIR}/include/node.h
${CMAKE_CURRENT_SOURCE_DIR}/src/rrt.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/tree.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/node.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp
)
find_package(catkin REQUIRED COMPONENTS roscpp std_msgs)
find_package(Armadillo REQUIRED)
FIND_PACKAGE(Eigen3 REQUIRED)
add_executable(
rrt
${SOURCES}
)
target_include_directories(
rrt
PUBLIC
${catkin_INCLUDE_DIRS}
${EIGEN3_INCLUDE_DIR}
${ARMADILLO_INCLUDE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
)
target_link_libraries(rrt ${catkin_LIBRARIES} ${ARMADILLO_LIBRARIES})
add_subdirectory(test)
In test/CMakeLists.txt, I have
project(rrt_ros)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
find_package(catkin REQUIRED COMPONENTS roscpp std_msgs)
find_package(Armadillo REQUIRED)
FIND_PACKAGE(Eigen3 REQUIRED)
message("TESTING......" ${CMAKE_CURRENT_SOURCE_DIR}/../include/rrt.h)
add_executable(rrt_test test.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../include/rrt.h
${CMAKE_CURRENT_SOURCE_DIR}/../include/tree.h
${CMAKE_CURRENT_SOURCE_DIR}/../include/node.h
${CMAKE_CURRENT_SOURCE_DIR}/../src/rrt.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../src/tree.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../src/node.cpp
)
target_include_directories(
rrt_test
PUBLIC
${catkin_INCLUDE_DIRS}
${Armadillo_INCLUDE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/../third_party
${CMAKE_CURRENT_SOURCE_DIR}/../include
)
target_link_libraries(
rrt_test
${catkin_LIBRARIES}
${Aramdillo_LIBRARIES}
)
In rrt.cpp, I have a function that calls armadillo's sampling function
arma::randi<arma::mat>(1, 2, arma::distr_params(1, 10))
When I compile the project, it gives me an undefined error:
rrt.cpp:(.text._ZTWN4arma23arma_rng_cxx11_instanceE[_ZTWN4arma23arma_rng_cxx11_instanceE]+0x15): undefined reference to 'arma::arma_rng_cxx11_instance'
collect2: error: ld returned 1 exit status
However, when I comment out ${CMAKE_CURRENT_SOURCE_DIR}/../src/rrt.cpp in ./test/CMakeLists.txt, it compiles fine.
I went through the same problem recently.
In your test/CmakeLists.txt, ${ARMADILLO_LIBRARIES} should be used instead of ${Aramdillo_LIBRARIES} (spelling mistake and upper case problem).

Error while including Caffe in C++ Project using cmake

I want to include caffe in my project. This is the folder structure of the project:
.
├── AUTHORS
├── ChangeLog
├── cmake
│   ├── FindCaffe.cmake
│   └── FindCUDA.cmake
├── CMakeLists.txt
├── CMakeLists.txt.user
├── data
│   └── info.plist
├── deep-app.pro.user
├── LICENSE.txt
├── README.md
├── [reference]
│   ├── deep-app.pro
│   ├── deep-app.pro.user
│   ├── deployment.pri
│   ├── main.cpp
│   ├── main.qml
│   ├── Page1Form.ui.qml
│   ├── Page1.qml
│   └── qml.qrc
└── src
├── CMakeLists.txt
├── code
│   └── main.cpp
├── icons.yml
└── res
├── assets
│   ├── assets.qrc
│   ├── book-open-page.svg
│   └── book-open.svg
├── icons
│   ├── action_home.svg
│   ├── action_list.svg
│   ├── action_search.svg
│   ├── action_settings.svg
│   ├── file_cloud_done.svg
│   ├── icons.qrc
│   ├── maps_place.svg
│   ├── navigation_check.svg
│   └── social_school.svg
└── qml
├── main.qml
├── Page1Form.ui.qml
├── Page1.qml
└── qml.qrc
Here is the root/CMakeLists.txt:
project(generic-object-detection)
cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR)
cmake_policy(VERSION 3.4.1)
ENABLE_LANGUAGE(C)
# Find includes in corresponding build directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Instruct CMake to run moc and rrc automatically when needed
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
# Apple-specific configuration
set(APPLE_SUPPRESS_X11_WARNING ON)
# Build flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -fvisibility-inlines-hidden -Werror -Wall -Wextra -Wno-unused-parameter -pedantic -std=c++11")
### Set libraries' locations
# Set Caffe
set(Caffe_DIR "/home/ubuntu/Libraries/caffe")
set(Caffe_INCLUDE_DIRS "/home/cortana/Libraries/caffe/include")
set(Caffe_LIBRARIES "/usr/lib/x86_64-linux-gnu/libcaffe.so")
# Disable debug output for release builds
if(CMAKE_BUILD_TYPE MATCHES "^[Rr]elease$")
add_definitions(-DQT_NO_DEBUG_OUTPUT)
endif()
# Minimum version requirements
set(QT_MIN_VERSION "5.4.0")
# Find Qt5
find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
Core
Qml
Quick
Concurrent)
# Find OpenCV 3.1
find_package(OpenCV 3.1.0 REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
# Find Boost
FIND_PACKAGE(Boost COMPONENTS program_options REQUIRED)
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR})
# Find CUDA
FIND_PACKAGE(CUDA REQUIRED)
# Find Caffe
FIND_PACKAGE(Caffe REQUIRED)
if(UNIX)
if(APPLE)
set(MACOSX_BUNDLE_INFO_STRING "generic-object-detection")
set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.mybitchinapp.generic-object-detection")
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_NAME}-${PROJECT_VERSION}")
set(MACOSX_BUNDLE_BUNDLE_NAME "generic-object-detection")
set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION})
set(MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION})
else()
# Assume linux
# TODO: Install desktop and appdata files
endif()
elseif(WIN32)
# Nothing to do here
endif()
add_subdirectory(src)
The file root/src/CMakeLists.txt:
file(GLOB_RECURSE SOURCES
*.cpp *.h
code/*.cpp code/*.h)
set(SOURCES ${SOURCES}
res/assets/assets.qrc
res/icons/icons.qrc
res/qml/qml.qrc)
add_executable(deep-app ${SOURCES})
target_link_libraries(deep-app
Qt5::Core
Qt5::Qml
Qt5::Quick
Qt5::Concurrent
${OpenCV_LIBS}
${Boost_LIBRARIES}
${CUDA_LIBRARIES})
set_target_properties(deep-app PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/data/Info.plist)
install(TARGETS deep-app
RUNTIME DESTINATION bin
DESTINATION ${CMAKE_INSTALL_BINDIR})
The error is:
CMake Error at CMakeLists.txt:55 (FIND_PACKAGE):
By not providing "FindCaffe.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "Caffe", but
CMake did not find one.
Could not find a package configuration file provided by "Caffe" with any of
the following names:
CaffeConfig.cmake
caffe-config.cmake
Add the installation prefix of "Caffe" to CMAKE_PREFIX_PATH or set
"Caffe_DIR" to a directory containing one of the above files. If "Caffe"
provides a separate development package or SDK, be sure it has been
installed.
-- Configuring incomplete, errors occurred!
I have setup Caffe_DIR and other required variables. But it still gives the same errors. I removed the previous [cmake] cache so thats not the problem. I cant figure out how to resolve this problem and I need to use Caffe in the project. Please help.
You want to set your CMAKE_MODULE_PATH to location where cmake module files are located for Caffe project, which would be directory pointed to below:
.
├── AUTHORS
├── ChangeLog
├── cmake <---------Set Caffe_DIR it to this directory
│ ├── FindCaffe.cmake
│ └── FindCUDA.cmake
If that doesn't work then you should set your Caffe_DIR to the above directory and make sure your rename the files under that directory to one of the names mentioned in the following error:
Could not find a package configuration file provided by "Caffe" with any of
the following names:
CaffeConfig.cmake
caffe-config.cmake