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 - When to include include_directories in a CMakeLists.txt file
How to know whether a library should be included using
include_directories
ortarget_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.
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}
forinclude_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
andmessage
to double-check that all directories and targets end up with the correct entries in theirINCLUDE_DIRECTORIES
property. - If you are free to require CMake 2.8.11 as a minimum requirement, consider abandoning
include_directories
completely and usetarget_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.
include_directory inheritance within CMake?
Yes, that is the standard behavior for CMake's include_directories
command. If you want properties to propagate to dependents, use the target_include_directories
command that became standard with version 3. Specifically, locations with headers that are needed by client code should be in the PUBLIC
or INTERFACE
section. If SubL also needs to include headers there, use PUBLIC
. Look at the whole family of target_*
commands for property propagation to dependents.
CMake include_directories does not help to find header files
'include_directories' affects the include directories of targets in that CMakeLists.txt, and its descendants. I think the issue is that the executable is added (targeted) in CMakeLists.txt 1; src.cpp isn't actually in CMakeLists 2's target/build scope, so it isn't affected by 'include_directories' calls in CMakeLists 2.
Why is CMake removing some include directories from INCLUDE_DIRECTORIES() calls?
After a few days I couldn't find a better answer so I'll post this answer-to-self since it works.
During the compiler detection, CMake will extract a series of implicit include paths which usually are always available and, if added to include paths, might break the compilation process (Thanks to @Tsyvarev for the caveat). However, if this path gets incorrectly added to the excluded paths, the only way I could find to override this is removing the exclusion list alltogether using:
unset(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES)
unset(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES)
As described on https://gitlab.kitware.com/cmake/cmake/issues/17966 but this solution is using CMake internals so it may do or break depending on your compiler or environment. In this particular case the fix worked.
On a similar situation, again with a proprietary + ancient gcc toolchain, simply updating to the latest CMake version worked, apparently due to better compiler detection.
How to set include_directories from a CMakeLists.txt file?
include_directories()
populates a directory property called INCLUDE_DIRECTORIES
:
http://www.cmake.org/cmake/help/v2.8.12/cmake.html#prop_dir:INCLUDE_DIRECTORIES
Note that CMake 2.8.11 learned the target_include_directories
command, which populates the INCLUDE_DIRECTORIES
target property.
http://www.cmake.org/cmake/help/v2.8.12/cmake.html#command:target_include_directories
Note also that you can encode the fact that 'to compile against the headers of the lib
target, the include directory lib/inc
is needed' into the lib
target itself by using target_include_directories
with the PUBLIC
keyword.
add_library(lib STATIC ${lib_hdrs} ${lib_srcs}) # Why do you list the headers?
target_include_directories(lib PUBLIC "${ROOT_SOURCE_DIR}/lib/inc")
Note also I am assuming you don't install the lib
library for others to use. In that case you would need to specify different header directories for the build location and for the installed location.
target_include_directories(lib
PUBLIC
# Headers used from source/build location:
"$<BUILD_INTERFACE:${ROOT_SOURCE_DIR}/lib/inc>"
# Headers used from installed location:
"$<INSTALL_INTERFACE:include>"
)
Anyway, that's only important if you are installing lib
for others to use.
After the target_include_directories(lib ...)
above you don't need the other include_directories()
call. The lib
target 'tells' proj1 the include directories it needs to use.
See also target_compile_defintions()
and target_compile_options()
.
Related Topics
Template Function Inside Template Class
Qt/Qml:Send Qimage from C++ to Qml and Display the Qimage on Gui
Safely Override C++ Virtual Functions
Under What Circumstances Are C++ Destructors Not Going to Be Called
Can You Allocate a Very Large Single Chunk of Memory ( > 4Gb ) in C or C++
"Roll-Back" or Undo Any Manipulators Applied to a Stream Without Knowing What the Manipulators Were
Platform-Independent Guid Generation in C++
Using Condition Variable in a Producer-Consumer Situation
Stl Deque Accessing by Index Is O(1)
Ad Hoc Polymorphism and Heterogeneous Containers with Value Semantics
Templates: Template Function Not Playing Well with Class's Template Member Function
Should C++ Eliminate Header Files
C++ Integer->Std::String Conversion. Simple Function
How to Execute a Piece of Code Only Once
Cygwin Make Bash Command Not Found
How to Temporarily Disable a MACro Expansion in C/C++