CMake 静态库依赖项不传播 ExternalProject_Add
CMake static library dependencies not propagating with ExternalProject_Add
我目前正在尝试使用它需要的所有依赖项将可执行文件正确地 link。
下面是依赖关系的示例结构:
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
,以及一个可以 link 正确地针对 libB
的测试可执行文件。但是,当我尝试构建 exe
时,它仅针对 libA
link 而不是 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
据我所知,无法通过使用单个配置 运行 和 ExternalProject 功能来实现您想要做的事情。您似乎只是使用 ${libA_libs}/libA.a
,这当然没有任何进一步的信息。由于项目 libA 和 libB 可能来自完全不同的供应商,因此无法在配置时从您的主项目中判断 LibA 甚至包含 link 依赖项 libB(顺便说一下,它也在 libA 中构建)。
我将假设您想要使用传递性 linking 的(相当自然的)想法。
根据是否自己开发libA/libB,有不同的选择。我将解释执行此操作的 "cleanest" 方法。缺点是这也需要修改 libA 项目 cmake。 [如果你不能这样做,你需要手动添加 libB.a 作为 link 库硬编码;即解决传递性..抱歉!]
传递 linking 的关键是您需要导入由 CMake 在 libA
中创建的实际 target,然后正确地具有 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>)
这将在 link 时包含 libB 并设置正确的包含路径(如果在 target_include_directories(libA PUBLIC ${LIBA_INCDIR}
中定义 PUBLIC..)
关键问题是在 相同的配置 运行 添加外部项目当然不能产生将由 find_package 设置的所有内容,因为还没有 compiled/installed。外部项目背后的想法是,你告诉它把东西放在哪里,这样你随后就知道应该在哪里找到东西,但不幸的是,这永远不会包括像 link 库这样的传递性东西。
有(一如既往)更快和更脏的解决方案,但是,"new" cmake 模块化包并通过 find_package 在 CONFIG 模式下使它们作为目标可用的方法是最好且简单的将 cmake 感知项目相互包含的方法。
我目前正在尝试使用它需要的所有依赖项将可执行文件正确地 link。
下面是依赖关系的示例结构:
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
,以及一个可以 link 正确地针对 libB
的测试可执行文件。但是,当我尝试构建 exe
时,它仅针对 libA
link 而不是 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
据我所知,无法通过使用单个配置 运行 和 ExternalProject 功能来实现您想要做的事情。您似乎只是使用 ${libA_libs}/libA.a
,这当然没有任何进一步的信息。由于项目 libA 和 libB 可能来自完全不同的供应商,因此无法在配置时从您的主项目中判断 LibA 甚至包含 link 依赖项 libB(顺便说一下,它也在 libA 中构建)。
我将假设您想要使用传递性 linking 的(相当自然的)想法。 根据是否自己开发libA/libB,有不同的选择。我将解释执行此操作的 "cleanest" 方法。缺点是这也需要修改 libA 项目 cmake。 [如果你不能这样做,你需要手动添加 libB.a 作为 link 库硬编码;即解决传递性..抱歉!]
传递 linking 的关键是您需要导入由 CMake 在 libA
中创建的实际 target,然后正确地具有 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>)
这将在 link 时包含 libB 并设置正确的包含路径(如果在 target_include_directories(libA PUBLIC ${LIBA_INCDIR}
中定义 PUBLIC..)
关键问题是在 相同的配置 运行 添加外部项目当然不能产生将由 find_package 设置的所有内容,因为还没有 compiled/installed。外部项目背后的想法是,你告诉它把东西放在哪里,这样你随后就知道应该在哪里找到东西,但不幸的是,这永远不会包括像 link 库这样的传递性东西。
有(一如既往)更快和更脏的解决方案,但是,"new" cmake 模块化包并通过 find_package 在 CONFIG 模式下使它们作为目标可用的方法是最好且简单的将 cmake 感知项目相互包含的方法。