我目前正在尝试获取可执行文件以正确链接其所需的所有依赖项。

这是依赖项的示例结构:

exe -> libA -> libB


exelibA有自己的存储库。 exe拉入libA像这样:

add_executable(exe ${sources})

ExternalProject_Add(
    libA
    GIT_REPOSITORY http://some/git/url/libA.git
    ...
)

target_include_directories(exe PRIVATE ${libA_includes})
target_link_libraries(exe ${libA_libs}/libA.a)

add_dependencies(exe libA)


libA以类似的方式引入libB

add_library(libA STATIC ${sources})

ExternalProject_Add(
    libB
    URL http://some/artifact/repo/libB.tgz
    ...
)

target_include_directories(libA PRIVATE ${libB_includes})
target_link_libraries(libA ${libB_libs}/libB.a)

add_dependencies(libA libB)


我可以很好地构建libA,以及可以正确链接到libB的测试可执行文件。但是,当我尝试构建exe时,它仅链接到libA,而不链接到libB。如何使CMake知道libAlibB之间的依赖关系不应通过ExternalProject丢失?

编辑:

我创建了一些依赖关系图,以期阐明我想要的内容:

实际:



我的期望:



任何帮助将不胜感激。谢谢。

编辑2:

我最终使用以下解决方案:

在libA的CMakeLists.txt中(其中${MODULE_NAME}是libA中某个模块的名称):

export(TARGETS ${MODULE_NAME}
       NAMESPACE "${CMAKE_PROJECT_NAME}-"
       APPEND FILE ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}-targets.cmake)


在exe的CMakeLists.txt中:

ExternalProject_Add(
    libA ...
)

ExternalProject_Get_Property(libA source_dir)
ExternalProject_Get_Property(libA binary_dir)

target_include_directories(${PROJECT_NAME} PRIVATE ${source_dir})

set(LIBA_TARGETS_FILE ${binary_dir}/libA-targets.cmake)
if(EXISTS ${LIBA_TARGETS_FILE})
    include(${LIBA_TARGETS_FILE})
    target_link_libraries(${MODULE_NAME} libA-module_in_liba)
endif()

add_dependencies(${MODULE_NAME} libA)


注意:现在确实需要使用两次cmake运行来构建项目,如下所示:

mkdir build; cd build
cmake .. # initial configuration
make # download the external projects
cmake .. # be able to include targets cmake file from external projects
make # this should now link everything properly

最佳答案

据我所知,没有办法通过使用单个配置运行和ExternalProject功能来实现您想要的功能。您似乎只是在使用${libA_libs}/libA.a,这当然没有任何更多信息。由于项目libA和libB可能来自完全不同的供应商,因此无法在配置时从您的主项目中得知LibA甚至包含链接依赖项libB(通过关联,它也内置在libA中)。

我将假设您要使用(相当自然的)传递链接的思想。
根据您是否自己开发libA / libB,有不同的选择。我将解释这样做的“最干净”的方式。缺点是这也需要修改libA项目cmake。 [如果无法执行此操作,则需要手动将libB.a添加为硬编码的链接库;即围绕传递性工作。对不起!]

传递链接的关键是您需要将CMake创建的实际目标导入到libA中,然后将正确的target_link_libraries信息导入libB,并且所有目标都将起作用。可以使用cmake中的INSTALL(.. EXPORT)功能提供libA的目标配置,然后可以使用find_package(LIBA CONFIG)导入目标。然后,您的exe CMakeLists.txt应该看起来像

find_package(LIBA CONFIG QUIET)
if (NOT LIBA_FOUND)
    AddExternalProject(libA .....)
    return
else()
    add_executable(exe ${sources})
    target_link_libraries(exe <libA-target-name>)


这将在链接时包含libB并设置正确的包含路径(如果在target_include_directories(libA PUBLIC ${LIBA_INCDIR}中定义了PUBLIC。)

关键问题是,在同一配置运行时添加外部项目当然不能产生将由find_package设置的所有内容,因为尚未编译/安装任何内容。外部项目背后的想法是,您告诉它在哪里放置东西,以便随后知道应该在哪里找到东西,但是不幸的是,它将永远不会包含诸如链接库之类的可传递东西。

有(一如既往)更快,更肮脏的解决方案,但是,将软件包模块化并使之通过CONFIG模式下的find_package使其成为目标的“新” cmake方法是将cmake感知项目相互包含在一起的最佳且简单的方法。

关于c - CMake静态库依赖项不与ExternalProject_Add一起传播,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28240849/

10-10 21:29