如何从目标中获取包含目录以便在 add_custom_target 中使用?

How to get include directories from a target for use in add_custom_target?

我正在使用 target_link_libraries 建模依赖关系,正如在 this 博客 post 中所做的那样。

target_link_libraries(Foo
    LibraryA
    LibraryB
)

这很好用,但由于各种原因,我需要使用 add_custom_target 通过自定义命令预处理文件。问题是,这个自定义目标依赖于 LibraryA 和 LibraryB 的包含。我真的很希望像 target_link_libraries 的工作方式一样执行以下操作(参见 LibraryA 和 LibraryB 位):

add_custom_target(Bar ALL
    COMMAND ${CMAKE_C_COMPILER} thing.cpp LibraryA LibraryB /P
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/Path/Here
    COMMENT "Preprocessing to a file"
    VERBATIM
)

但是,这不起作用。 LibraryA 和 LibraryB 按它们出现的样子放入。即使它确实有效,我想我会得到比包含更多的东西,因为我认为目标也包括库。也许这不是一个好方法。

那么,我可以在这里做什么?如何从每个目标中提取包含目录,以便在自定义命令中使用?我发现如果我 find_package(Foo REQUIRED) 我可以访问 Foo_DIR,但它指向构建目录而不是包含所在的源目录。

您可以使用 get_target_property(). A target's INCLUDE_DIRECTORIES property contains the include directories for that target. Since you have two targets, LibraryA and LibraryB, we have to call it twice. Then, we can concatenate the list of include directories together using foreach(). If you are using these as include directories in a compiler command (such as MSVC), you can append the /I compiler option 从每个目标提取包含目录到循环中的每个目录:

# Get the include directories for the target.
get_target_property(LIBA_INCLUDES LibraryA INCLUDE_DIRECTORIES)
get_target_property(LIBB_INCLUDES LibraryB INCLUDE_DIRECTORIES)

# Construct the compiler string for the include directories.
foreach(dir ${LIBA_INCLUDES} ${LIBB_INCLUDES})
    string(APPEND INCLUDE_COMPILER_STRING "/I${dir} ")
endforeach()

然后,您可以使用构造的INCLUDE_COMPILER_STRING变量调用自定义目标命令:

add_custom_target(Bar ALL
    COMMAND ${CMAKE_C_COMPILER} thing.cpp ${INCLUDE_COMPILER_STRING} /P
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/Path/Here
    COMMENT "Preprocessing to a file"
    VERBATIM
)

如果您想要更简洁的内容,可以使用生成器表达式示例 here,它会在您的自定义目标命令中获取目标的包含目录并内联扩展它们。像这样的东西也可以工作:

add_custom_target(Bar ALL
    COMMAND ${CMAKE_C_COMPILER} thing.cpp 
        "/I$<JOIN:$<TARGET_PROPERTY:LibraryA,INCLUDE_DIRECTORIES>,;/I>"
        "/I$<JOIN:$<TARGET_PROPERTY:LibraryB,INCLUDE_DIRECTORIES>,;/I>"
        /P
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/Path/Here
    COMMENT "Preprocessing to a file"
    VERBATIM
    COMMAND_EXPAND_LISTS
)