Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake target_include_directories meaning of scope

Tags:

cmake

People also ask

What is Target_include_directories?

target_include_directories adds an include directory to a target. PUBLIC doesn't mean much for an executable; for a library it lets CMake know that any targets that link to this target must also need that include directory.

What are target directories?

Specifies include directories to use when compiling a given target. The named <target> must have been created by a command such as add_executable() or add_library() and must not be an ALIAS target. By using AFTER or BEFORE explicitly, you can select between appending and prepending, independent of the default.

What are targets in CMake?

Introduction. A CMake-based buildsystem is organized as a set of high-level logical targets. Each target corresponds to an executable or library, or is a custom target containing custom commands.

What does private mean in CMake?

PRIVATE. All the objects following PRIVATE will only be used for linking to the current target. INTERFACE. All the objects following INTERFACE will only be used for providing the interface to the other targets that have dependencies on the current target.


These keywords are used to tell when the list of include directories you're passing to the target are needed. By when, it means if those include directories are needed:

  • To compile that target itself.
  • To compile other targets that depend on that target (like using its public headers).
  • In both of the above situations.

When CMake is compiling a target, it uses the targets INCLUDE_DIRECTORIES, COMPILE_DEFINITIONS, and COMPILE_OPTIONS properties. When you use the PRIVATE keyword in target_include_directories() and alike, you tell CMake to populate those target properties.

When CMake detects a dependency between a target A and another target B (like when you use the target_link_libraries(A B) command), it transitively propagates B usage requirements to the A target. Those target usage requirements are the include directories, compile definitions, etc. that any target that depends on B must meet. They are specified by the INTERFACE_* version of the properties listed above (like INTERFACE_INCLUDE_DIRECTORIES), and are populated by using the INTERFACE keyword when calling the target_*() commands.

The PUBLIC keyword means roughly PRIVATE + INTERFACE.

Therefore, suppose you are creating a library A that uses some Boost headers. You would do:

  • target_include_directories(A PRIVATE ${Boost_INCLUDE_DIRS}) if you only use those Boost headers inside your source files (.cpp) or private header files (.h).
  • target_include_directories(A INTERFACE ${Boost_INCLUDE_DIRS}) if you don't use those Boost headers inside your source files (therefore, not needing them to compile A). I can't actually think of a real-world example for this.
  • target_include_directories(A PUBLIC ${Boost_INCLUDE_DIRS}) if you use those Boost headers in your public header files, which are included BOTH in some of A's source files and might also be included in any other client of your A library.

CMake 3.0 documentation has more details on this build specification and usage requirements properties.


The INTERFACE, PUBLIC and PRIVATE keywords are required to specify the scope of the following arguments. PRIVATE and PUBLIC items will populate the INCLUDE_DIRECTORIES property of < target >. PUBLIC and INTERFACE items will populate the INTERFACE_INCLUDE_DIRECTORIES property of < target >. The following arguments specify include directories.

From the documentation: http://www.cmake.org/cmake/help/v3.0/command/target_include_directories.html

To rephrase the documentation with my own words:

  • you want to add a directory to list of include directory for a target
  • with PRIVATE the directory is added to the target's include directories
  • with INTERFACE the target is not modified, but the INTERFACE_INCLUDE_DIRECTORIES is extended by the directory. The variable is a list of public include directories for a library.
  • with PUBLIC both actions from PRIVATE and INTERFACE are performed.