CMake:add_subdirectory两次作为共享项目

时间:2018-07-10 18:41:31

标签: cmake static-libraries

我已经搜索了整个互联网,但是没有简单的答案可以解决这个问题。 我读过这篇文章: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_subdirectorylib_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库的建议?

1 个答案:

答案 0 :(得分:0)

在可能会用作子目录本身的cmake项目中不要执行add_subdirectory()

相反,创建一个超级项目,该项目在同一级别(在同一CMakeLists.txt中)执行所有add_subdirectory()。顺序并不重要,一旦处理完所有CMakeLists.txt,CMake就会解决目标依赖性(通过target_link_libraries()完成)。

这是我最终在所有项目中使用的一种方法。它有一些缺点,例如可能很难对每个库进行单元测试,但这可以通过使用变量对测试进行条件化来解决。