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

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


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.


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.


I see a couple of things that may help you improve your code.

Avoid overspecifying minimum version

I generally like to make sure that my CMake scripts don't overspecify the version. It seems to me that in this script, anything more than version 3.1 would work. So I'd be inclined to change that first line to this:

cmake_minimum_required(VERSION 3.1)

Handle packages consistently

As you know, find_package() generally sets the package_INCLUDE_DIRS and package_LIBRARIES for the package. I find that consistently using such variables is much better for simplifying maintenance of the CMake script than trimming to the bare minimum. Therefore I'd not worry about whether they're required or not and do this:

find_package(CURL REQUIRED)include_directories(${CURL_INCLUDE_DIRS})add_executable(imu_data_access_cmake_test imu_data_access.cpp)target_link_libraries(imu_data_access_cmake_test ${CURL_LIBRARIES})

Don't put system includes in sources

Note that I have omitted this line:

set(SOURCES imu_data_access.cpp ${CURL_INCLUDE_DIRS}/curl/curl.h)

Not every library include file needs to be or should be listed as a source. As a general rule, I only include my sources, and that's what I'd advice for your projects as well.