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

pkln4tw6  于 2022-11-11  发布在  其他
关注(0)|答案(2)|浏览(283)

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

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是按照它们出现的样子放进去的。即使它起作用了,我想我会得到比include更多的东西,因为我认为目标也包括了库。也许这不是一个好的方法。
那么,我在这里能做些什么呢?我如何从每个目标中提取包含目录,以便在定制命令中使用?我发现如果我find_package(Foo REQUIRED),我可以访问Foo_DIR,但它指向的是构建目录,而不是包含目录所在的源目录。

yyyllmsg

yyyllmsg1#

您可以使用get_target_property()从每个目标提取包含目录。目标的INCLUDE_DIRECTORIES属性包含该目标的包含目录。由于您有两个目标,LibraryALibraryB,因此我们必须调用它两次。然后,我们可以使用foreach()将包含目录列表连接在一起。如果您在编译器命令中使用这些包含目录(例如MSVC),您也可以将/Icompiler 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
)

如果你想要更简洁的东西,你可以使用这里的生成器表达式示例,它获取目标的包含目录,并在你的自定义目标命令中内联展开它们。

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

v7pvogib2#

作为评论,目前接受的答案没有处理传递依赖。这个问题已经困惑了我一整天,所以我现在整理出来。
我在构建LibraryLinkUtilities here .这是我在项目中使用的CMakeLists.txt文件:

cmake_minimum_required(VERSION 3.15.0)

project ("CMakeProject1")

set(LLU_ROOT "D:/test/LibraryLinkUtilities/install")
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE)

find_package(LLU NO_MODULE PATH_SUFFIXES LLU)

add_library(${PROJECT_NAME} SHARED ${PROJECT_NAME}.cpp)

target_link_libraries(${PROJECT_NAME} PRIVATE LLU::LLU)

当我用 Visual Studio 打开**.sln时,它运行得很好,我的意思是我可以用任何构建类型构建它。但是我发现 Configuation 中的 include directories 是空的。这让我抓狂,因为我想知道项目包含了哪个目录。然后我使用函数print_target_properties fixed here打印了关于导入目标**的所有属性:

function(print_target_properties target)
    if(NOT TARGET ${target})
      message(STATUS "There is no target named '${target}'")
      return()
    endif()

    foreach(property ${CMAKE_PROPERTY_LIST})
        string(REPLACE "<CONFIG>" "DEBUG" property ${property})

        get_property(was_set TARGET ${target} PROPERTY ${property} SET)
        if(was_set)
            get_target_property(value ${target} ${property})
            message("${target} ${property} = ${value}")
        endif()
    endforeach()
endfunction()

print_target_properties(LLU::LLU)

注意红线处,LLU::LLU依赖于WSTP::WSTPWolframLibrary::WolframLibrary .所以我用这段代码打印所有包含的目录:

include(CMakePrintHelpers)
get_target_property(LLUDEPENDS LLU::LLU INTERFACE_LINK_LIBRARIES)
cmake_print_properties(TARGETS LLU::LLU ${LLUDEPENDS} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES)

相关问题