How to include library headers in CMakeLists - c++

I'm having trouble getting CMake and Make to find external header files I need to compile my code.
My code has is trying to use a header provided by the external aruco library
#include <aruco.h>
And when I try to compile I get
/home/ncr/ncr_ws/src/aruco_ros/src/aruco_ros_node.cpp:21:19: fatal error: aruco.h: No such file or directory
#include <aruco.h>
^
compilation terminated.
My CMakeLists.txt has:
cmake_minimum_required(VERSION 2.8.3)
project(aruco_ros)
set(CMAKE_MODULE_PATH /usr/local/lib/cmake)
message( STATUS "CMAKE_MODULE_PATH: " ${CMAKE_MODULE_PATH})
find_package(OpenCV REQUIRED)
find_package(aruco REQUIRED)
...
include_directories(
${OpenCV_INCLUDE_DIRS}
${aruco_INCLUDE_DIRS}
)
message(STATUS "OpenCV_INCLUDE_DIRS: " ${OpenCV_INCLUDE_DIRS})
message(STATUS "aruco_INCLUDE_DIRS: " ${aruco_INCLUDE_DIRS})
The Findaruco.cmake file is in /usr/local/lib/cmake/Findaruco.cmake
The Findaruco.cmake file sets the aruco_INCLUDE_DIRS variable as /usr/local/include and the include file aruco.h is in /usr/local/include/aruco. Does make not search subdirectories? Most of the opencv headers are in /usr/local/include/opencv2 but the OpenCV_INCLUDE_DIRS only declares /usr/local/include and yet all opencv the headers are found without any problem.

As James Adkison said, I needed to properly reference the header files. Looking at the other opencv include files, I start them all off with #include <opencv2/[blah]>, which explains why those work as well.

Related

Cmake C++ Project With Eigen Headers in src [duplicate]

I am having difficulty using a header-only library (Eigen) in my CMake project. When i take off all the portion related to Eigen library it compiles, but not sure how to build with (Eigen). Note that Eigen has a CmakeLists.txt in Eigen folder, and it has /src folder having (*.h and *.cpp) related to Matrix operation etc...
The structure of my program is as follow
Myproject (folder) is composed of :
CmakeLists.txt
/Build
/Source
The Source folder has bunch of my files (*.h and *.cpp) and the /Eigen (folder).
what i did is :
FIND_PACKAGE(PkgConfig REQUIRED)
PKG_CHECK_MODULES(GTK3 REQUIRED gtk+-3.0)
LIST(APPEND CMAKE_CXX_FLAGS
"-std=c++0x
-pthread
${CMAKE_CXX_FLAGS}
-g
-Wall -Wextra ")
ADD_LIBRARY(Eigen ${CMAKE_SOURCE_DIR}/Eigen)
TARGET_INCLUDE_DIRECTORIES(Eigen INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
$<INSTALL_INTERFACE:include/Eigen>
)
INCLUDE_DIRECTORIES(${GTK3_INCLUDE_DIRS})
ADD_DEFINITIONS(${GTK3_CFLAGS_OTHERS})
INCLUDE_DIRECTORIES(include)
ADD_LIBRARY(RTT
Def.cpp
Def.h
krnel.cpp
krnel.h
Mesh.cpp
Mesh.h
Mcom.cpp
Mcom.h
timer.h
Identifier.h)
ADD_EXECUTABLE(Rdrtst main.cpp)
TARGET_LINK_LIBRARIES(Rdrtst RTT ${GTK3_LIBRARIES} Eigen)
When i cd to /Build and type (Cmake ../Source )
I get the following :
[/../Build]$ cmake ../Source
-- Configuring done
CMake Error: Cannot determine link language for target "Eigen".
CMake Error: CMake can not determine linker language for target:Eigen
-- Generating done
-- Build files have been written to: /../../MyProject/Build
The eigen folder has the CMakeLists.txt with the following content :
include(RegexUtils)
test_escape_string_as_regex()
file(GLOB Eigen_directory_files "*")
escape_string_as_regex(ESCAPED_CMAKE_CURRENT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
foreach(f ${Eigen_directory_files})
if(NOT f MATCHES "\\.txt" AND NOT f MATCHES "${ESCAPED_CMAKE_CURRENT_SOURCE_DIR}/[.].+" AND NOT f MATCHES "${ESCAPED_CMAKE_CURRENT_SOURCE_DIR}/src")
list(APPEND Eigen_directory_files_to_install ${f})
endif()
endforeach(f ${Eigen_directory_files})
install(FILES
${Eigen_directory_files_to_install}
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen COMPONENT Devel
)
add_subdirectory(src)
You are trying to include Eigen as a compiled library. However, as you have stated, Eigen is really a header only library and does not need to be compiled, just included. There should be no .cpp files at all.
Remove the line
ADD_LIBRARY(Eigen ${CMAKE_SOURCE_DIR}/Eigen)
as that is meant for static or shared libraries. Now that you're not building Eigen, you can remove the line
TARGET_INCLUDE_DIRECTORIES(Eigen ...
The Eigen CMakeLists file really just copies the Eigen header files to an include directory and doesn't compile anything. See this link for an example of how to use Eigen with CMake.
You just need the correct path in INCLUDE_DIRECTORIES (also make sure to include the correct folder or subfolder, depending if in your c++ file you are using #include Eigen/something.h or #include something.h )
So, remove the lines ADD_LIBRARY(Eigen ... and TARGET_LINK_LIBRARIES Eigen.
For troubleshooting, you can also include the absolute path of the Eigen folder , and then when you get it working, transform it in a relative path
This is a late answer, but it might help someone else. These are the precise steps I took in order to include the Eigen lib into my project with CMake files.
First, assuming your project already include the Eigen sub-directory, e.g., at src/third_party/eigen, copy-paste FindEigen3.cmake file into src/cmake.
Second, you might want to edit the FindEigen3.cmake to include your own location hints that you will provide from you CMake file. For example:
find_path( EIGEN3_INCLUDE_DIR NAMES signature_of_eigen3_matrix_library
HINTS "${EIGEN3_ROOT}" "$ENV{EIGEN3_ROOT_DIR}" "${EIGEN3_INCLUDE_DIR_HINTS}"
# ... leave the rest as it is
)
Third, "include" the Eigen from your CMakeLists.txt by specifying the hint EIGEN3_ROOT and the location of the FindEigen3.cmake file:
message(STATUS "Trying to include Eigen library")
set(EIGEN3_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/third_party/eigen)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
find_package(Eigen3 3.2.0 REQUIRED)
include_directories(${EIGEN3_INCLUDE_DIR})
message(STATUS "EIGEN: " ${EIGEN3_VERSION} " (internal)")
Forth, start using Eigen from within your project:
#include <Eigen/Dense>
using Eigen::MatrixXd;
// ...
MatrixXd m(2,2);
m(0,0) = 3;
m(1,0) = 2.5;
m(0,1) = -1;
m(1,1) = m(1,0) + m(0,1);
std::cout << m << std::endl;

CMakeLists include Header File from subdirectories

I am trying to work with CMake for the first time and am struggling to link header files into my main. My cmake directory looks like this:
Project
| CmakeLists.txt
| src
|| CMakeLists.txt
|| Main.cpp
| Libs
|| CMakeLists.txt
|| headers
|||obstacle_detection.hpp
||source
|||obstacle_detection.cpp
|build
||"build files"
I would like to link the files in the headers folder to main, but what I currently have does not appear to work. The following runs the CMake command correctly but fails to compile with the make command, being unable to find the given header file. My CMakeLists files are as follows:
Project:
cmake_minimum_required(VERSION 3.17)
project(Sensivision)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
find_package(OpenCV REQUIRED)
find_package(realsense2 REQUIRED)
find_library(darknet REQUIRED)
add_subdirectory(libs)
add_subdirectory(src)
target_link_libraries(${PROJECT_NAME} obstacle_detection)
Libs:
add_library(
obstacle_detection
headers/obstacle_detection.hpp
sources/obstacle_detection.cpp
)
target_link_directories(obstacle_detection PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
src:
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS})
target_link_libraries(${PROJECT_NAME} ${realsense2_LIBRARY})
My include in main.cpp is
include <obstacle_detection.hpp>
I have also tried
include <headers/obstacle_detection.hpp>
and
include <obstacle_detection>
Each gives the error:
obstacle_detection.hpp: no such file or directory
What am I doing incorrectly to link the header to the main?
You haven't added any include directories to the obstacle_detection library. By listing the header file in the add_library call, this may allow the header to be displayed in an IDE, but it doesn't do anything for compilation. You should use target_include_directories to add the headers directory as an include directory for the obstacle_detection library. Otherwise, it, and other consuming targets, will have no knowledge of the headers in that directory.
add_library(
obstacle_detection
headers/obstacle_detection.hpp
sources/obstacle_detection.cpp
)
# Add this line.
target_include_directories(obstacle_detection PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/headers)
# Not sure this line is necessary, as it doesn't appear you actually link anything...
target_link_directories(obstacle_detection PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
You haven't shown the CMake code in the src directory, but be sure to link the obstacle_detection library target to the main target, e.g.:
target_link_libraries(MyExeTarget PRIVATE obstacle_detection)
In addition, because this header file is local, it is best if you use quotes to include the header:
#include "obstacle_detection.hpp"
You can use target_include_directories to add folder where your headers are located and #include <header.hpp> where needed.
Ex:
libs cmake:
add_library(
obstacle_detection
headers/obstacle_detection.hpp
sources/obstacle_detection.cpp
)
target_include_directories(obstacle_detection PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
cpp:
#include <headers/obstacle_detection.hpp>

CMake: Unable to include external library header files in my library's header files that are not included in any source files

I've tried looking for an answer to this question. There are similar questions but none that answer mine.
I am trying to create a library that depends on a couple other external libraries. I have the external libraries as git submodules and compile them myself in CMake using add_subdirectory followed by target_link_library.
After doing that, I am able to use the external libraries and include their header files in any source file in my library that I have added using target_sources and also in any header file that at least one of these source files include.
For example, I have an external library glm and call target_sources(myLib PRIVATE Application.cpp) in my library. The header files in my library are added to the project using target_include_directories.
Now, I can do #include <glm/glm.hpp> in the Application.cpp file with no problems.
I also have an Application.hpp file that is included in the Application.cpp file. Because it is included, that allows me to do #include <glm/glm.hpp> in the Application.hpp file as well.
However, now I also have a Core.hpp file without a corresponding Core.cpp file. Because the Core.hpp file is not included in any source files, doing #include <glm/glm.hpp> throws an error that the file cannot be found.
This is my root CMakeLists.txt:
cmake_minimum_required(VERSION 3.16)
project(Ivory)
set(CMAKE_CXX_STANDARD 20)
add_library(${PROJECT_NAME} SHARED)
# Determine compiler platform (x32 or x64)
math(EXPR PLATFORM_BITS "8*${CMAKE_SIZEOF_VOID_P}")
set(PLATFORM "x${PLATFORM_BITS}")
# Determine target build platform
target_compile_definitions(${PROJECT_NAME}
PUBLIC
IVORY_WINDOWS
PRIVATE
IVORY_BUILD_DLL
)
# Set output directory
set(OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/${CMAKE_SYSTEM_NAME}-${CMAKE_BUILD_TYPE}-${PLATFORM})
# Subdirectories
add_subdirectory(src)
add_subdirectory(tests)
add_subdirectory(executables)
target_include_directories(${PROJECT_NAME} PUBLIC include)
# External Libraries #
set(BUILD_SHARED_LIBS OFF)
# GLM
add_subdirectory(lib/glm)
target_link_libraries(${PROJECT_NAME} PRIVATE glm)
# GLEW
add_subdirectory(lib/glew)
target_link_libraries(${PROJECT_NAME} PRIVATE libglew_static)
# SFML
add_subdirectory(lib/SFML)
target_link_libraries(${PROJECT_NAME} PRIVATE sfml-window sfml-audio)
# SPDLOG
add_subdirectory(lib/spdlog)
target_link_libraries(${PROJECT_NAME} PRIVATE spdlog)
# MinGW
target_link_libraries(${PROJECT_NAME} PRIVATE -static)
# Output Location
set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIRECTORY})
This is the src CMakeLists.txt:
target_sources(${PROJECT_NAME}
PRIVATE
Application.cpp
)
I am using CLion on Windows 10 with MinGW 7.3 compiler (64 bit).
What am I doing wrong?
If the Core.hpp header is meant to be included by clients and glm headers are called from this header the glm dependency in the target_link_libraries command must be PUBLIC not PRIVATE.
For the CMake documentation see here. For a more detailed explanation of the PUBLIC, PRIVATE, and INTERFACE keywords with examples see here.

Can't Include LibXML2 Files in a CMake C++ Project (using QtCreator IDE)

I'm working on a Cmake based C++ project in QtCreator. I am trying to use mlpack in my project, but as soon as I include the line #include <mlpack/core.hpp> to my only source file, I get an error pertaining to some libxml files that are included by mlpack/core.hpp:
In file included from /usr/local/include/mlpack/core/util/save_restore_utility.hpp:26:0,
from /usr/local/include/mlpack/core.hpp:171,
from /home/revinci/code/workspaces/qt_ws/Semantic_Perception/src/features_slic.cpp:18:
/usr/include/libxml2/libxml/parser.h:15:31: fatal error: libxml/xmlversion.h: No such file or directory
#include <libxml/xmlversion.h>
Now, I went into /usr/include/libxml2/libxml/ and found parser.h with the line #include <libxml/xmlversion.h> in it.
So, I saw that xmlversion.h and parser.h are in the same folder and tried a hack: I changed the #include <libxml/xmlversion.h> in parser.h to #include "xmlversion.h" only to get the following error:
In file included from /usr/include/libxml2/libxml/parser.h:15:0,
from /usr/local/include/mlpack/core/util/save_restore_utility.hpp:26,
from /usr/local/include/mlpack/core.hpp:171,
from /home/revinci/code/workspaces/qt_ws/Semantic_Perception/src/features_slic.cpp:18:
/usr/include/libxml2/libxml/xmlversion.h:13:31: fatal error: libxml/xmlexports.h: No such file or directory
#include <libxml/xmlexports.h>
Which is basically telling me that it can't find xmlexports.h (included by xmlversion.h). More importantly, xmlexports.h is in the same directory as xmlversion.h and parser.h!
I tried the solution mentioned here and installed libxml2-dev (again) and libxslt1-dev, but my problem wasn't solved.
I think this may have something to do with specifying my include paths correctly. I've tried to add /usr/include/libxml2 to the various path environment variables (PATH, INCLUDE_PATH and CPATH) that are present in my build environment in QtCreator, but to no avail. My CMakeLists.txt looks like this:
project(Semantic_Perception)
cmake_minimum_required(VERSION 2.8)
#Vigra Headers
include_directories(
include
)
file(GLOB_RECURSE VigraImpex include/impex/)
add_library(VigraImpex ${VigraImpex})
#LibXml2 Headers
find_package(LibXml2 REQUIRED)
#Armadillo Headedrs
find_package(Armadillo REQUIRED)
include_directories(${ARMADILLO_INCLUDE_DIRS})
#Boost Headers
find_package(Boost 1.54.0 REQUIRED)
add_executable(features_slic src/features_slic.cpp)
target_link_libraries(features_slic
VigraImpex
${ARMADILLO_LIBRARIES}
)
BTW: LibXml2, Armadillo and Boost are all dependencies of the library I am trying to use - mlpack. The command find_pakcage(mlpack) won't work because there is no Findmlpack.cmake file on my system anywhere, and I couldn't find one on the internet either.

Cmake file for C++/CUDA project

I'm having trouble compiling my application using cmake and make. The source files of the project are organized as follows:
SOURCE/
CMakeLists.txt
myApp.cc
include/
classA.hh
classB.hh
src/
classA.cc
classB.cc
classB.cu
My CMakeLists.txt file is as follows:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(myApp)
FIND_PACKAGE(VTK REQUIRED)
INCLUDE(${VTK_USE_FILE})
FIND_PACKAGE(GDCM REQUIRED)
IF(GDCM_FOUND)
INCLUDE(${GDCM_USE_FILE})
SET(GDCM_LIBRARIES gdcmCommon vtkgdcm)
ELSE(GDCM_FOUND)
MESSAGE(FATAL_ERROR "Cannot find GDCM, did you set GDCM_DIR?")
ENDIF(GDCM_FOUND)
SET(CUDA_TOOLKIT_ROOT_DIR="/Developer/NVIDIA/CUDA-7.5/")
FIND_PACKAGE(CUDA REQUIRED)
SET(CUDA_PROPAGATE_HOST_FLAGS ON)
SET(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -gencode arch=compute_30,code=sm_30)
SET(LIB_TYPE SHARED)
SET(CUDA_SEPARABLE_COMPILATION ON)
LINK_DIRECTORIES(/lib/FFTW/INSTALL/lib)
INCLUDE_DIRECTORIES(/lib/FFTW/INSTALL/include)
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include)
FILE(GLOB headers ${PROJECT_SOURCE_DIR}/include/*.hh)
FILE(GLOB sources ${PROJECT_SOURCE_DIR}/src/*.cc)
FILE(GLOB cudafile ${PROJECT_SOURCE_DIR}/src/*.cu)
CUDA_ADD_EXECUTABLE(myApp myApp ${headers} ${sources} ${cudafile})
TARGET_LINK_LIBRARIES(myApp ${VTK_LIBRARIES} ${GDCM_LIBRARIES} fftw3)
When I try to compile the project using make (after successfully running cmake) I get:
nvcc fatal : A single input file is required for a non-link phase when an outputfile is specified
CMake Error at myApp_generated_classB.cu.o.cmake:207 (message):
Error generating
../BUILD/CMakeFiles/myApp.dir/src/./myApp_generated_classB.cu.o
Is breaking up the source file of a class into .cc and .cu files problematic?
This is not a comprehensive explanation of what exactly causes the problem stated in the question; nevertheless it solves the problem in a fairly satisfactory way.
First, apparently there is a conflict between using FIND_PACKAGE(VTK) (and hence FIND_PACKAGE(GDCM) which seems to require VTK CMake files for vtkgdcm) and nvcc. This has been recently reported on Mantis. To avoid this conflict, I use:
LINK_DIRECTORIES( {VTK_Directory}/INSTALL/lib)
INCLUDE_DIRECTORIES({VTK_Directory}/INSTALL/include/vtk-6.2)
LINK_DIRECTORIES( {GDCM_Directory}/INSTALL/lib)
INCLUDE_DIRECTORIES({GDCM_Directory}/INSTALL/include/gdcm-2.4)
instead of,
FIND_PACKAGE(VTK REQUIRED)
FIND_PACKAGE(GDCM REQUIRED)
Second, as for the CUDA part of the project, I put everything into a .cu file and use CUDA_COMPILE(cuda_o myCUDAstudff.cu) to create an object file. Then I use the native C++ compiler to create an executable as usual using ADD_EXECUTABLE( ... ${cuda_o}). Since I am using the native C++ compiler as opposed to nvcc, I need to include the following header files in my kernel (myCUDAstudff.cu) file:
#include <cuda.h>
#include <cuda_runtime.h>
and also link to libcudart in TARGET_LINK_LIBRARIES(), for which I used the shared library. I couldn't figure out a way to do the same with libcudart_static.a though.
Alternatively, one can use CUDA_ADD_EXECUTABLE(... myCUDAstudff.cu) instead of all the above steps (i.e., CUDA_COMPILE(), ADD_EXECUTABLE(),...).