gpt4 book ai didi

CMake 静态库依赖项不随 ExternalProject_Add 传播

转载 作者:行者123 更新时间:2023-12-05 01:36:53 28 4
gpt4 key购买 nike

我目前正在尝试让可执行文件与它需要的所有依赖项正确链接。

这是依赖项的示例结构:

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)

我可以 build libA很好,以及正确链接到 libB 的测试可执行文件.但是,当我尝试构建 exe ,它只链接到 libA但不是 libB .如何让 CMake 知道 libA 之间的依赖关系和 libB不应该通过 ExternalProject 丢失?

编辑:

我创建了一些依赖关系图,希望能阐明我想要什么:

实际的:

exe actual libA actual

我的期望:

expected

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

编辑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 添加为硬编码的链接库;即解决传递性..对不起!]

传递链接的关键是需要在libA中导入CMake创建的实际目标。 ,然后正确地具有 target_link_libraries信息到libB,一切都会奏效。 libA的目标配置可以使用 INSTALL 提供(.. EXPORT ) cmake 中的功能,然后允许您使用 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 将它们作为目标提供的"new" cmake 方式是将 cmake 感知项目包含到彼此中的最佳且简单的方式。

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

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com