INTERFACE_INCLUDE_DIRECTORIES not transitive for target_link_libraries

Env

  • OS: Linux
  • cmake: 3.21.1

Test Code

cmake_minimum_required(VERSION 3.20)

project(test_cmake_transitive_deps LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

macro(dump_target_includes TARGET_NAME)
    message("=====================dump_target_includes begin (${TARGET_NAME})=====================")
    get_target_property(PROP_TMP
                        ${TARGET_NAME}
                        INCLUDE_DIRECTORIES)
    message(----INCLUDE_DIRECTORIES----)
    foreach(PATH_TMP ${PROP_TMP})
        message("* " ${PATH_TMP})
    endforeach()

    get_target_property(PROP_TMP
                        ${TARGET_NAME}
                        INTERFACE_INCLUDE_DIRECTORIES)
    message(----INTERFACE_INCLUDE_DIRECTORIES----)
    foreach(PATH_TMP ${PROP_TMP})
        message("* " ${PATH_TMP})
    endforeach()
    message("=====================dump_target_includes end (${TARGET_NAME})=====================")
endmacro()

add_library(a a/a.cpp)
target_include_directories(a PUBLIC a)
dump_target_includes(a)

add_library(b b/b.cpp)
target_link_libraries(b PUBLIC a)
dump_target_includes(b)

project file structure

CMakeLists.txt
a/a.h
a/a.cpp
b/b.h
b/b.cpp

Problem

for

  • target_include_directories(a PUBLIC a)
  • target_link_libraries(b PUBLIC a)

dump_target_includes for b is as below, why no inlucde paths for b?

=====================dump_target_includes begin (b)=====================
----INCLUDE_DIRECTORIES----
* PROP_TMP-NOTFOUND
----INTERFACE_INCLUDE_DIRECTORIES----
* PROP_TMP-NOTFOUND
=====================dump_target_includes end (b)=====================

This property is computed at generation time. Requesting it at configuration time will not give you the expected value.

If you need the final information, you have to use generator expression $<TARGET_PROPERTY:...> which is evaluated at generation time.

What does generation time mean?
Does it mean buid time?
How to check *_INCLUDE_DIRECTORIES for b here?

generation time is the step where build system files (Makefiles, ninja or whatever depending on what you specify with option -G) are generated by CMake.

To manipulate target properties with the right information, use generator expressions. See also file(GENERATE).

file(GENERATE OUTPUT test_debug_genex.log
     CONTENT $<TARGET_PROPERTY:b, INCLUDE_DIRECTORIES>)

The code above failed, logs as below

file Unknown argument to GENERATE subcommand.

BTW, does it have to save the output to a file, or anyway to output to stdout/stderr?

Use quotes for CONTENT:

file(GENERATE OUTPUT test_debug_genex.log
     CONTENT "$<TARGET_PROPERTY:b,INCLUDE_DIRECTORIES>")
1 Like

It works, thanks very much.
BTW space after comma in genex is not allowed.