3

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?

Kevin
  • 16,549
  • 8
  • 60
  • 74
noble_gasses
  • 55
  • 1
  • 6

2 Answers2

2

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"
Kevin
  • 16,549
  • 8
  • 60
  • 74
  • Thank you this solved my issue. What is the difference between include and link in this context? – noble_gasses Sep 21 '20 at 12:57
  • 1
    @noble_gasses Header files are usually not *linked*; rather, they are used during the compilation process to provide definitions for your classes/variable/etc. You specify this with CMake using `target_include_directories`. After compilation, the resulting object files (and potentially other existing libraries) get **linked** to create a new library or executable during the link stage. You can specify other libraries to link with CMake using `target_link_libraries`. See the responses [here](https://stackoverflow.com/q/6264249/3987854) for some overview of the different stages. – Kevin Sep 21 '20 at 13:07
-1

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>