我已经搜索了整个互联网,但是没有简单的答案可以解决这个问题。 我读过这篇文章:CMake: Attempted to add link library to target which is not built in this directory
但是我不想将target_link_libraries
放在同一个cmake列表中,相反,我想将链接命令留在每个列表中,因为一个库cmake列表必须知道它必须是哪个库依赖项链接。
矿山项目的结构是这样的:
<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库的建议?
答案 0 :(得分:0)
在可能会用作子目录本身的cmake项目中不要执行add_subdirectory()
。
相反,创建一个超级项目,该项目在同一级别(在同一CMakeLists.txt中)执行所有add_subdirectory()
。顺序并不重要,一旦处理完所有CMakeLists.txt,CMake就会解决目标依赖性(通过target_link_libraries()
完成)。
这是我最终在所有项目中使用的一种方法。它有一些缺点,例如可能很难对每个库进行单元测试,但这可以通过使用变量对测试进行条件化来解决。