Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cmake - When to include include_directories in a CMakeLists.txt file

I have a C++ project in which I have the following line:

#include <curl/curl.h>

I am using the CURL library to access IMU data from a sensor. I prepared a CMakeLists.txt file that looks like this:

cmake_minimum_required(VERSION 3.5.1)
project(imu_data_access_cmake_test)
set(CMAKE_CXX_STANDARD 11)
find_package(CURL REQUIRED)
include_directories(${CURL_INCLUDE_DIRS})
set(SOURCES imu_data_access.cpp ${CURL_INCLUDE_DIRS}/curl/curl.h)
add_executable(imu_data_access_cmake_test ${SOURCES})
#add_executable(imu_data_access_cmake_test imu_data_access.cpp)
target_link_libraries(imu_data_access_cmake_test ${CURL_LIBRARIES})

This works very well. However, if I remove the include_directories line and modify the add_executable line to just use my imu_data_access.cpp as source, the cmake does not throw an error and everything still works. I am assuming this is due to target_link_libraries line.

How to know whether a library should be included using include_directories or target_link_libraries? If the package/library has a .so file can we simply ignore include_directories for that package/library?

Edit: How to know whether a library should be included using include_directories vs. target_link_libraries?

like image 498
skr_robo Avatar asked Dec 18 '22 00:12

skr_robo


2 Answers

How to know whether a library should be included using include_directories or target_link_libraries?

Unless a library is a header-only library, call to target_link_libraries is required for use it.

If Find* script (called by find_package() call) sets variable with include directories (this information can be obtained from the script's documentation), it assumes that these directories will be included (via include_directories or target_include_directories).

Propagating include directories through the target_link_libraries occurred in case of IMPORTED target, usually named as <namespace>::<name>.


In your specific case include_directories have no effect only because given directory is searched by a compiler by default, this is usual when library is installed through package manager. But find_package is intended to work even with non-system installations.

like image 55
Tsyvarev Avatar answered Dec 24 '22 01:12

Tsyvarev


A good practice is to use target_include_directories() instead of include_directories(). The benefit is that you can indicate the visibility of the include, for example if you configure a library with:

add_library(foo foo.cpp)
target_include_directories(foo PUBLIC foo_include)
target_include_directories(foo PRIVATE private_include)

Then, if you link foo to an executable bar, then bar will have access to the foo_include directory, but not to private_include. Command include_directories() apply to the directory where the CMakeLists.txt contains the command, so it will apply to any library/executable declared in this directory and its sub-directories.

For target_link_libraries(), then the behavior varies, because it can be a list of libraries, in which case there is no notion of include directories. But it can be an IMPORTED library, where it can contain more information, such as include directories (for example, Boost and Qt do that).

In the case of cURL, the documentation indicates that CURL_LIBRARIES contains the list of libraries. In your case, the cURL headers are probably found because by default CMake will search for headers in standard locations, so target_link_libraries() has no impact regarding the includes in this case.

like image 41
piwi Avatar answered Dec 24 '22 02:12

piwi