4

我正在使用 建模依赖关系target_link_libraries,就像在这篇博文中所做的那样。

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,但这指向构建目录而不是包含所在的源目录。

4

1 回答 1

11

您可以使用 . 从每个目标中提取包含目录get_target_property()。目标的INCLUDE_DIRECTORIES属性包含该目标的包含目录。由于您有两个目标,LibraryA并且LibraryB,我们必须调用它两次。然后,我们可以使用foreach(). 如果您将这些用作编译器命令(例如 MSVC)中的包含目录,您也可以将/I 编译器选项附加到循环中的每个目录:

# 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
)

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

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
)
于 2019-11-08T13:53:47.350 回答