cmake - CMake:add_subdirectory 两次作为共享项目
问题描述
我已经在互联网上到处搜索,但这个问题没有简单的答案。我读过这个:CMake: Attempted to add link library to target which is not built in this directory
但是我不想将它们target_link_libraries
放入同一个 cmake 列表中,而是我想将链接命令留在每个相应的列表中,因为库 cmake 列表必须知道它必须与哪个库依赖项链接。
Mine项目的结构是这样的:
<main_exe> : /main
| : |
<main_lib> : +- /_3dparty
/ \ : | |
<lib_A> <lib_B> : | +- /lib_A/CMakeLists.txt
\ / : | +- /lib_B/CMakeLists.txt
<lib_X> : | +- /lib_X/CMakeLists.txt
: |
: +- /CMakeLists.txt
所有 3 个库都是独立且静态的,我不想将它们作为彼此的子目录。
但是,当我尝试分别add_subdirectory
使用外部二进制目录lib_A
时lib_B
:
if (NOT TARGET lib_X)
add_subdirectory(${lib_X_ROOT} ${CMAKE_BUILD_ROOT}/_3dparty/lib_X)
endif()
add_dependencies(${PROJECT_NAME} lib_X)
target_link_libraries(${PROJECT_NAME}
PUBLIC
lib_X
)
,然后cmake抛出一个错误:
Attempt to add link library "lib_X" to target "lib_B" which is not built in
this directory
有没有办法让它在不过度ExternalProject_Add
使用的情况下工作?
编辑:
我在最小的例子中重现了这个问题。
库 libB 实际上的结构略有不同:
/main
|
+- /_3dparty
| |
| +- /lib_A/CMakeLists.txt
| +- /lib_B
| | |
| | +- /libsubdir/CMakeLists.txt
| | +- /CMakeLists.txt
| |
| +- /lib_X/CMakeLists.txt
|
+- /CMakeLists.txt
这就是问题的原因。
/CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(main_project)
set(CMAKE_BUILD_ROOT ${CMAKE_CURRENT_LIST_DIR}/_build)
set(CMAKE_LIBS_ROOT ${CMAKE_CURRENT_LIST_DIR}/_3dparty)
add_library(mainlib ${CMAKE_CURRENT_LIST_DIR}/main.cpp)
add_subdirectory(${CMAKE_LIBS_ROOT}/libA ${CMAKE_BUILD_ROOT}/_3party/libA)
add_subdirectory(${CMAKE_LIBS_ROOT}/libB ${CMAKE_BUILD_ROOT}/_3party/libB)
target_link_libraries(mainlib
PUBLIC
libA
libB
)
/_3dparty/libA/CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(libA_project)
add_library(libA STATIC ${CMAKE_CURRENT_LIST_DIR}/main.cpp)
add_subdirectory(${CMAKE_LIBS_ROOT}/libX ${CMAKE_BUILD_ROOT}/_3party/libX)
target_link_libraries(libA
PUBLIC
libX
)
/_3dparty/libB/CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(libB_project)
#add_library(libB STATIC ${CMAKE_CURRENT_LIST_DIR}/libsubdir/main.cpp)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/libsubdir) # the root cause of the issue
#add_subdirectory(${CMAKE_LIBS_ROOT}/libX ${CMAKE_BUILD_ROOT}/_3party/libX) # would be an error if add this twice
target_link_libraries(libB # <- the issue error is here
PUBLIC
libX
)
/_3dparty/libB/libsubdir/CMakeLists.txt
add_library(libB STATIC main.cpp)
/_3dparty/libX/CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(libX_project)
add_library(libX STATIC ${CMAKE_CURRENT_LIST_DIR}/main.cpp)
输出:
x:\_cmake_test\_out>cmake .. -G "Visual Studio 14 2015"
CMake Error at _3dparty/libB/CMakeLists.txt:11 (target_link_libraries):
Attempt to add link library "libX" to target "libB" which is not built in
this directory.
-- Configuring incomplete, errors occurred!
See also "X:/_cmake_test/_out/CMakeFiles/CMakeOutput.log".
如果取消注释add_library(libB ...
和注释,add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/libsubdir)
则问题消失。
有什么建议如何在不编辑 3dparty 库的情况下解决这个问题?
解决方案
不要add_subdirectory()
在可能被用作子目录的 cmake-projects 中执行此操作。
而是创建一个超级项目,它add_subdirectory()
在同一级别(在同一 CMakeLists.txt 中)执行所有操作。顺序并不重要,target_link_libraries()
一旦处理完所有 CMakeLists.txt,CMake 就会解决目标依赖关系(通过 完成)。
这是我最终在所有项目中使用的方法。它有一些缺点,例如每个库的单元测试可能很困难,但这可以通过使用变量调节测试来解决。
推荐阅读
- docker - 如何在 Docker 中使用 Chromium 运行 Canopy
- python - 检查数据库中的句子是否包含字典中的某些单词
- javascript - 在 Google Script Web 应用程序上向用户确认工作表更新
- python - 在 MAC 中创建一个仅对系统/管理员具有写入权限的文件
- python-3.x - 计算给定代码的while循环时间复杂度
- typescript - 为 Node 重用已加载的块
- c++ - #define 在 qml 代码中
- node.js - findById 请求,在 mongodb 集合中找不到我的数据
- mysql - mysql RC多线程先搜索后删除,但有些搜索只返回1行
- python - 将列表项映射到字典