Modern CMake is target-oriented. Build properties are attached to targets and propagated according to three keywords.


PRIVATE

Only this target needs it.

target_include_directories(calcpack
    PRIVATE
        src
)

Only calcpack can use headers from src/.

Consumers do not inherit this path.

Typical uses:

  • Internal headers
  • Internal compile definitions
  • Implementation-only libraries

PUBLIC

This target needs it, and everyone using this target also needs it.

target_include_directories(calcpack
    PUBLIC
        include
)

Both

calcpack

and

applications linking calcpack

receive the include directory.

Typical uses:

  • Public API headers
  • Public compile definitions
  • Public library dependencies

INTERFACE

This target does not need it, but consumers do.

Example:

add_library(math INTERFACE)
 
target_include_directories(math
    INTERFACE
        include
)

Useful for:

  • Header-only libraries
  • Interface-only compile options
  • Interface compile definitions

Propagation

PRIVATE

App
 
calcpack


uses include path

Only the library receives the property.


PUBLIC

App


calcpack


include path

Both receive the property.


INTERFACE

App


Header-only library

Only consumers receive the property.


Applies to More Than Include Directories

The same keywords are used with:

target_link_libraries()
target_compile_definitions()
target_compile_options()
target_sources()

Example:

target_compile_definitions(calcpack
    PUBLIC
        CALCPACK_VERSION=1
)

Both the library and its users can access:

CALCPACK_VERSION

Rule of Thumb

KeywordUsed by this targetUsed by consumers
PRIVATE
PUBLIC
INTERFACE

Memory Trick

  • PRIVATEOnly I need it.
  • PUBLICI need it, and anyone using me needs it too.
  • INTERFACEI don’t need it, but my users do.

Typical Usage

SituationKeyword
Internal implementation headers (src/)PRIVATE
Public API headers (include/)PUBLIC
Header-only libraryINTERFACE
Internal helper libraryPRIVATE
Dependency exposed in public headersPUBLIC

Key Takeaways

  • Modern CMake revolves around targets, not global settings.
  • Build properties propagate according to PRIVATE, PUBLIC, or INTERFACE.
  • Think in terms of who needs the property, rather than memorizing syntax.