What is the difference between include_directories and interface_include_directories with headers only library

Viewed 1485

I'm trying to understand the difference between the scope that one can specify in target_include_directories, specifically PRIVATE and INTERFACE. The documentation says (the specific context is header only library):

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 . PUBLIC and INTERFACE items will populate the INTERFACE_INCLUDE_DIRECTORIES property of . (IMPORTED targets only support INTERFACE items.) The following arguments specify include directories.

So basically using either PRIVATE or INTERFACE modifies INCLUDE_DIRECTORIES or INTERFACE_INCLUDE_DIRECTORIES. I do struggle to understand the difference between the two of them. From the description in the doc INCLUDE_DIRECTORIES seems to be the argument of the flag -I when compiling a C++ project.

I don't understand at all the latter instead, can anyone clarify?

Also apparently using INTERFACE is better when using headers only library, why is that?

1 Answers

Interface targets is for headers only libraries. Declaring such target will not produce any content at compile time (CMake will not generate rules to produce objects, executables or library for these targets).

Thus, CMake need to differentiate headers that will be used to compile targets that produce objects.

As I remember, the main use of these 2 properties is the following: (please note that I'm not 100% sure of everything).

An executable target

  • Can have the INCLUDE_DIRECTORIES property set with the list of directories needed to compile files for this target
  • Cannot have INTERFACE_INCLUDE_DIRECTORIES set, because other targets cannot depends on an executable target (I'm not sure about that)

A library target

  • Can have the INCLUDE_DIRECTORIES property set with the list of directories needed to compile files for this target
  • Can have the INTERFACE_INCLUDE_DIRECTORIES set with a list of directories needed to compile other targets that depends on this target

An interface target

  • Cannot have INCLUDE_DIRECTORIES property set because it will never be compiled
  • Most probably have the INTERFACE_INCLUDE_DIRECTORIES set because it contains only header files, so other targets that depends on will need to include those headers

Since this is a difficult question, and many people are asking this, I will turn this answer into community answer ASAP so by iterative refinement we will hopefully find a way to correctly explain this point.

Related