我目前正在尝试让可执行文件与它需要的所有依赖项正确链接。
这是依赖项的示例结构:
exe -> libA -> libB
Run Code Online (Sandbox Code Playgroud)
exe并libA拥有自己的存储库。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)
Run Code Online (Sandbox Code Playgroud)
libAlibB以类似的方式拉入:
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)
Run Code Online (Sandbox Code Playgroud)
我可以libA很好地构建,以及正确链接到libB. 但是,当我尝试构建时exe,它只链接到libA而不是libB. 我怎样才能让 CMake 知道之间的依赖libA和libB不应该通过 ExternalProject 丢失?
编辑:
我创建了一些依赖关系图,希望能阐明我想要的:
实际的:

我的期望:

任何帮助将不胜感激。谢谢。
编辑2:
我最终使用以下作为解决方案:
在 libA 的 CMakeLists.txt 中(libA${MODULE_NAME}中某个模块的名称在哪里):
export(TARGETS ${MODULE_NAME}
NAMESPACE "${CMAKE_PROJECT_NAME}-"
APPEND FILE ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}-targets.cmake)
Run Code Online (Sandbox Code Playgroud)
在 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)
Run Code Online (Sandbox Code Playgroud)
注意:现在需要使用以下两次运行来构建项目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
Run Code Online (Sandbox Code Playgroud)
据我所知,没有办法通过使用单个配置运行和 ExternalProject 功能来实现您想要做的事情。您似乎只是在使用${libA_libs}/libA.a,这当然没有任何进一步的信息。由于项目 libA 和 libB 可能来自完全不同的供应商,因此在配置时无法从您的主项目中得知 LibA 甚至包含链接依赖项 libB(这也是在 libA 中构建的偶然性)。
我将假设您想使用传递链接的(相当自然的)想法。根据你是否自己开发libA/libB,有不同的选择。我将解释这样做的“最干净”的方式。缺点是这也需要修改 libA 项目 cmake。[如果你不能这样做,你将需要手动添加 libB.a 作为硬编码的链接库;即解决传递性..对不起!]
以传递链接的关键是,你需要导入实际的目标由CMake的创建中libA,然后正确地拥有target_link_libraries信息libB一切都会工作。libA可以使用cmake 中的INSTALL (.. EXPORT ) 功能提供的目标配置,然后允许您使用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>)
Run Code Online (Sandbox Code Playgroud)
这将在链接时包含 libB 并设置正确的包含路径(如果在target_include_directories(libA PUBLIC ${LIBA_INCDIR}.. 中定义了 PUBLIC )
关键问题是在同一配置运行中添加外部项目当然不能产生将由 find_package 设置的所有内容,因为尚未编译/安装任何内容。外部项目背后的想法是你告诉它把东西放在哪里,这样你就知道应该在哪里找到东西,但不幸的是,这永远不会包括像链接库这样的可传递的东西。
有(一如既往)更快和更脏的解决方案,但是,模块化包并通过 find_package 在 CONFIG 模式下将它们用作目标的“新”cmake 方法是将 cmake 感知项目相互包含的最佳且简单的方法。
| 归档时间: |
|
| 查看次数: |
2384 次 |
| 最近记录: |