cmake link subdirectories together - c++

I have the following folder hieararchy in my QT project and I need to use some classes of the Utility folder in the classes of the ImageProcessing folder.
CMAKE file of Utilities:
file(GLOB Utilities_Files *.cpp *.h *.hpp)
# add component
add_library(Utilities ${Utilities_Files})
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(Utilities ${OpenCV_LIBRARIES})
CMAKE file of ImageProcessing:
file(GLOB ImageProcessing_FILES *.cpp *.h *.hpp)
# add component
add_library(ImageProcessing ${ImageProcessing_FILES})
include_directories(../Utilities)
target_link_libraries(ImageProcessing Utilities)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(ImageProcessing ${OpenCV_LIBRARIES})
when I try to include classes from Utilities in classes of ImageProcessing:
#include "Utilities/className.h"
The compiler always fails.. Not sure why? It seems there is something missed or misunderstood.
Thanks.

Your line include_directories(../Utilities) adds the path ../Utilities to include directories. However, you include Utilities/className.h in the source file which makes the compiler search for files ./Utilities/className.h and ../Utilities/Utilities/className.h.
Remove one of the Utilities in either include_directories or #include.
include_directories(..)
or
#include "className.h"

Related

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 - Include directories outside project

So I want to include a global header file that is in a different folder. The code for the CMakeList.txt is below. In my .cpp when I include something from the local include folder it works, but not for the something that is in a different folder.
cmake_minimum_required(VERSION 2.8)
#Project name
project(Server-Client)
#Add all cpp files as source files
file(GLOB_RECURSE SOURCES "src/*.cpp")
#Build executable 'Server' with all files in SOURCES
add_executable(Server ${SOURCES})
#Include all files in include directory
include_directories("include")
target_include_directories(Server PUBLIC "../../GlobalFiles/include")
find_package(Threads REQUIRED)
#Build executable 'localization' with all files in SOURCES
target_link_libraries(Server ${CMAKE_THREAD_LIBS_INIT})
Don't use a relative paths, instead use CMAKE_CURRENT_SOURCE_DIR variable like this:
target_include_directories(Server PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../../GlobalFiles/include")
Other than that, it might be a good idea to use a Macro to find the global header you are looking for.

CMake + Qt Creator: Add header files to project files

If I have .h and .cpp files in the directory src, where the .cpp files include the .h files, using these commands in CMake:
aux_source_directory(src SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})
And opening that CMake file in Qt Creator, gets all the files (sources + headers) in the list of project files (the file tree on the left by default).
Now, on the other hand, if I put all the .h files in a directory include, and use this:
include_directories(include)
aux_source_directory(src SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})
The header files disappear from the project files!
How can I keep the header files in that directory, and still have them listed in Qt Creator's project files?
You shouldn't use aux_source_directory() for your task. That command is for something different. Just list the source files (or put them in a variable).
You shouldn't use include_directory() for defining include directories any more. This command will just populate the -I flag of the compiler. Define a variable with the header files and add that to the executable.
In case you don't want to list every file manually, use file(GLOB ...). But be aware of the caveats mentioned frequently all over the web with using that command.
Afterwards, tell CMake to populate the -I flag only for that executable with the include directory. That way, other targets don't get polluted by includes, they shouldn't use.
set(SOURCES
src/main.cpp
src/whatever.cpp)
set(HEADERS
include/whatever.h)
add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS})
target_include_directories(${PROJECT_NAME} PUBLIC include)
I add my header files always explicit to avoid any surprise.
But on MacOS using QtCreator 4.2.0 and cmake 3.7.1 I can't reproduce your issue.
However I recommend to use following structure to know which files are within project and to trigger update of cmake's data during update of CMakeLists.txt.
In project/CMakeLists.txt:
add_subdirectory(src)
include_directory(include)
add_executable(foo ${SRC_LIST})
In project/src/CMakeLists.txt:
set(SRC_LIST
${SRC_LIST}
${CMAKE_CURRENT_SOURCE_DIR}/a.cpp
${CMAKE_CURRENT_SOURCE_DIR}/b.cpp
PARENT_SCOPE
)

How to properly use file GLOB?

I'm trying to use GLOB_RECURSE to specify my sources and headers files. Currently, my CMakeLists.txt for a static library is:
project(LinearSystemLib)
file(GLOB_RECURSE ${PROJECT_NAME}_headers ${PROJECT_SOURCE_DIR}/*.h)
file(GLOB_RECURSE ${PROJECT_NAME}_sources ${PROJECT_SOURCE_DIR}/*.cpp)
add_library(
${PROJECT_NAME} STATIC ${${PROJECT_NAME}_headers}
${${PROJECT_NAME}_sources}
)
install(
TARGETS ${PROJECT_NAME}
LIBRARY DESTINATION libs
ARCHIVE DESTINATION archives
)
The library directory looks like this:
LinearSystemLib
CMakeLists.txt
source
LinearSystemLib.cpp
include
LinearSystemLib.h
When I run command cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug (in the build directory) everything goes ok. Yet, command make it displays the following:
/home/felipe/Documents/Dados/SINMEC/Eclipse/LinearSystemLib/source/LinearSystemLib.cpp:1:29: fatal error: LinearSystemLib.h: No such file or directory
Is my CMakeLists wrong? I don't want to set specify the sources and headers files by name. I'm not finding information about glob_recurse easily.
I can make it work by listing the sources and headers files by name. However, it MUST be done with the glob_recurse or with glob.
I solved my problem, here's what LinearSystemLib directory looks like:
LinearSystemLib
CMakeLists.txt
source
LinearSystemLib.cpp
include
LinearSystemLib.h
The CMakeLists.txt contains:
project(LinearSystemLib)
#INCLUDE DIRECTORIES
include_directories(${CMAKE_SOURCE_DIR}/${PROJECT_NAME}/include)
#SEARCH FOR .CPP AND .H FILES
file(GLOB ${PROJECT_NAME}_headers ${CMAKE_SOURCE_DIR}/${PROJECT_NAME}/include/*.h)
file(GLOB ${PROJECT_NAME}_sources ${CMAKE_SOURCE_DIR}/${PROJECT_NAME}/source/*.cpp)
#ADD LIBRARY
add_library(${PROJECT_NAME} STATIC ${${PROJECT_NAME}_sources})
#DEFINE OUTPUT LOCATION
install(
TARGETS ${PROJECT_NAME}
ARCHIVE DESTINATION static_libs
)
You don't actually NEED to add the .h/.hpp files using GLOB. I did it because otherwise, Visual Studio (or CodeBlocks) wouldn't create a "Header Files" folder on the project menu.
I wasn't properly specifying the path where GLOB would find the files.
${CMAKE_SOURCE_DIR}/${PROJECT_NAME}/source/
You need to add
target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR})
so the correct -I argument is added to your compilation step. Use make VERBOSE=1 to see exactly what commands make is executing.

My project can find one library header, but not another one

I have two C++ libraries, which I am using on Ubuntu. One of them, let's call it foo, I installed through apt-get, e.g. sudo apt-get install libfoo-dev. The other, let's call it bar, I installed by downloading the source files, and running make install. After these installations, I then have header files from foo in locations such as /usr/include/foo/foo.h, and header files from bar in locations such as /usr/local/include/bar/bar.h. From my knowledge, foo is a dependency of bar.
I then created my own C++ project, and included the line #include "bar/bar.h". But when compiling my project, I get an error saying error: foo.h: No such file or directory. If I click on the error in my debugger, it opens the file bar.h, and highlights the line #include <foo.h>. So, my project is able to find bar.h, but not foo.h. I do not mention either foo or bar in my CMakeLists.txt file.
So my questions are:
How does my project know how to find bar.h, when I have not told it where to find it in CMakeLists.txt?
What do I need to do to get my project to find foo.h and compile properly?
Thank you!
Edit: Here is my CMakeLists.txt file (the foo and bar libraries are none of the ones mentioned here):
cmake_minimum_required(VERSION 2.8.1)
set(CMAKE_CXX_FLAGS "-std=c++11 -O3")
project(Grasping_Simulator)
find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
find_package(GLUT REQUIRED)
find_package(Eigen3 REQUIRED)
find_package(Boost REQUIRED)
find_package(OpenCV REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR} ${GLEW_INCLUDE_DIR} ${GLUT_INCLUDE_DIR} ${EIGEN3_INCLUDE_DIR} ${BOOST_INCLUDE_DIRS} ${OPENCV_INCLUDE_DIRS})
file(GLOB SRCS *.cpp *.h)
add_executable(${PROJECT_NAME} ${SRCS})
target_link_libraries(${PROJECT_NAME} ${GLEW_LIBRARY} ${GLUT_LIBRARY} ${OpenCV_LIBS} pthread GL boost_system)
You need to add the option -I/usr/include/foo/ to your compilation command.
By default, locations such as /usr/include/ and /usr/local/include are already in the include search path. However, your library bar does something naughty by using #include <foo.h>. Really, it should be using things like #include <foo/foo.h> (by the way if you can make this change that would be cleaner). That would allow the compiler to search all its include paths, including the path /usr/include/, and try appending /foo/foo.h - which would succeed. As it stands, there is nothing in the default include path which would work merely by appending /foo.h, so it fails to find it.
EDIT: Given your CMake code above, most likely you need to append a variable that contains the value /usr/include/foo to the include_directories line to achieve the desired effect (this being the inclusion of -I/usr/include/foo/ on the compilation line).