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
calcpackand
applications linking calcpackreceive 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 pathOnly the library receives the property.
PUBLIC
App
▲
│
calcpack
▲
│
include pathBoth receive the property.
INTERFACE
App
▲
│
Header-only libraryOnly 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_VERSIONRule of Thumb
| Keyword | Used by this target | Used by consumers |
|---|---|---|
| PRIVATE | ✅ | ❌ |
| PUBLIC | ✅ | ✅ |
| INTERFACE | ❌ | ✅ |
Memory Trick
- PRIVATE → Only I need it.
- PUBLIC → I need it, and anyone using me needs it too.
- INTERFACE → I don’t need it, but my users do.
Typical Usage
| Situation | Keyword |
|---|---|
Internal implementation headers (src/) | PRIVATE |
Public API headers (include/) | PUBLIC |
| Header-only library | INTERFACE |
| Internal helper library | PRIVATE |
| Dependency exposed in public headers | PUBLIC |
Key Takeaways
- Modern CMake revolves around targets, not global settings.
- Build properties propagate according to
PRIVATE,PUBLIC, orINTERFACE. - Think in terms of who needs the property, rather than memorizing syntax.