我目前正在尝试使用可执行文件正确链接所需的所有依赖项。
以下是依赖项的示例结构:
exe -> libA -> libB
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)
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知道libA
和libB
之间的依赖关系不应该通过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
答案 0 :(得分:4)
据我所知,使用单个配置运行和ExternalProject功能无法实现您想要的功能。您似乎只使用${libA_libs}/libA.a
,这当然没有任何进一步的信息。由于项目libA和libB可能来自完全不同的供应商,因此无法在主项目的配置时告诉LibA甚至包含链接依赖性libB(也是由libA中构建的入射)。
我将假设你想要使用传递链接的(相当自然的)想法。 根据您是否自己开发libA / libB,有不同的选项。我会解释最干净的""这样做的方式。缺点是这需要修改libA项目cmake。 [如果你不能这样做,你需要手动添加libB.a作为硬编码的链接库;即解决传染性问题..对不起!]
传递链接的关键是你需要导入libA
中由CMake创建的实际目标,然后正确地将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设置的所有内容,因为尚未编译/安装任何内容。外部项目背后的想法是你告诉它在哪里放置东西,以便你随后知道应该找到什么东西,但遗憾的是,它永远不会包含链接库这样的传递内容。
有(一如既往)更快,更脏的解决方案,然而,&#34;新&#34;在CONFIG模式下通过find_package模块化模块并使它们可用作目标的方法是将cmake感知项目相互包含在一起的最佳和简单的方法。