Cmake Include_Directories Order After/Before

cmake include_directories order AFTER/BEFORE

I don't think this is a problem with CMake; I believe gcc will always find your "time.h" before the system one, regardless of whether you use quotes or brackets in the #include and regardless of the various options in include_directories. See the entries for -I and -isystem in the gcc documentation

The AFTER option of CMake's include_directories relates only to the order of the directories as listed in the gcc command, it doesn't relate to gcc's -idirafter flag.

It's not a great plan to have your own files with identical names to system files, but if your hands are tied, you could avoid this issue without renaming time.h by qualifying the path for your own includes more fully, so rather than e.g.

CMakeLists.txt:  include_directories(${PROJECT_SOURCE_DIR}/src)

header file: #include <time.h> // we want but don't get system one
#include "time.h" // we want and get own custom one

something more like

CMakeLists.txt:  include_directories(${PROJECT_SOURCE_DIR})

header file: #include <time.h> // we want and get system one
#include "src/time.h" // we want and get own custom one



An alternative option would be to stick with your current #include setup (using angle brackets for the system time.h and quotes for your own) and not use include_directories at all in the CMakeLists.txt. Instead I think you could replace it with something like:

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -iquote ${PROJECT_SOURCE_DIR}/src")

Using -iquote is probably a better option than -idirafter since the directory specified by -idirafter is (in this case incorrectly) treated as a system directory, and as such has warnings suppressed, etc.

If you do go for this choice, it's probably worth commenting the CMakeLists.txt to explain why there is no include_directories to avoid future refactoring reverting back to use the more normal include_directories command.

All in all, your best option if at all possible would be to rename your "time.h" file though.

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.

How to properly add include directories with CMake

Two things must be done.

First add the directory to be included:

target_include_directories(test PRIVATE ${YOUR_DIRECTORY})

In case you are stuck with a very old CMake version (2.8.10 or older) without support for target_include_directories, you can also use the legacy include_directories instead:

include_directories(${YOUR_DIRECTORY})

Then you also must add the header files to the list of your source files for the current target, for instance:

set(SOURCES file.cpp file2.cpp ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h)
add_executable(test ${SOURCES})

This way, the header files will appear as dependencies in the Makefile, and also for example in the generated Visual Studio project, if you generate one.

How to use those header files for several targets:

set(HEADER_FILES ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h)

add_library(mylib libsrc.cpp ${HEADER_FILES})
target_include_directories(mylib PRIVATE ${YOUR_DIRECTORY})
add_executable(myexec execfile.cpp ${HEADER_FILES})
target_include_directories(myexec PRIVATE ${YOUR_DIRECTORY})

Cmake include_directories()

Quoting the documentation for include_directories:

The include directories are added to the directory property
INCLUDE_DIRECTORIES for the current CMakeLists file. They are also
added to the target property INCLUDE_DIRECTORIES for each target in
the current CMakeLists file. The target property values are the ones
used by the generators.

The INCLUDE_DIRECTORIES directory property is inherited to all subdirectories and all targets in the directory.

  • Specifying ${CMAKE_CURRENT_SOURCE_DIR} for include_directories is redundant as relative paths are interpreted as relative to this directory by default. You should throw it out to increase readability.
  • Specifying an include directory in both a subdirectory and its parent is redundant. You should avoid this and settle on one location.
  • Use get_property and message to double-check that all directories and targets end up with the correct entries in their INCLUDE_DIRECTORIES property.
  • If you are free to require CMake 2.8.11 as a minimum requirement, consider abandoning include_directories completely and use target_include_directories instead. This has the advantage that include dependencies get resolved on a per-target basis exclusively which is usually the more desirable behavior.

What is the difference between include_directories and target_include_directories in CMake?

include_directories(x/y) affects directory scope. All targets in this CMakeList, as well as those in all subdirectories added after the point of its call, will have the path x/y added to their include path.

target_include_directories(t x/y) has target scope—it adds x/y to the include path for target t.

You want the former one if all of your targets use the include directories in question. You want the latter one if the path is specific to a target, or if you want finer control of the path's visibility. The latter comes from the fact that target_include_directories() supports the PRIVATE, PUBLIC, and INTERFACE qualifiers.



Related Topics



Leave a reply



Submit