【发布时间】:2014-06-15 16:13:19
【问题描述】:
我有一个名为“Base”的静态库,其中包含以下 CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
project(Base)
add_library(${PROJECT_NAME} STATIC Base.h Base.cpp )
install(FILES ${PROJECT_NAME}.h DESTINATION include )
install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}-targets DESTINATION lib)
install(EXPORT ${PROJECT_NAME}-targets DESTINATION lib)
install(FILES ${PROJECT_NAME}-config.cmake DESTINATION lib)
Base-config.cmake 的灵感来自 CMake 教程:
get_filename_component(SELF_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
include(${SELF_DIR}/Base-targets.cmake)
get_filename_component(Base_INCLUDE_DIRS "${SELF_DIR}/../include" ABSOLUTE)
Base的编译和安装都OK。
现在,我有另一个名为“Middle”的独特静态库,它依赖于“Base”。在其 CMakeLists.txt 中,我找到了 Base 包并定义了安装/导出步骤,如下所示:
cmake_minimum_required(VERSION 2.8)
project(Middle)
find_package(Base REQUIRED)
if ( Base_FOUND )
message( "Base found!")
endif()
include_directories(${Base_INCLUDE_DIRS})
add_library(${PROJECT_NAME} STATIC Middle.h Middle.cpp )
target_link_libraries( ${PROJECT_NAME} Base )
install(FILES ${PROJECT_NAME}.h DESTINATION include )
install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}-targets DESTINATION lib)
install(EXPORT ${PROJECT_NAME}-targets DESTINATION lib)
install(FILES ${PROJECT_NAME}-config.cmake DESTINATION lib)
Middle-config.cmake 文件与 Base 的非常相似:
get_filename_component(SELF_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
include(${SELF_DIR}/Middle-targets.cmake)
get_filename_component(Middle_INCLUDE_DIRS "${SELF_DIR}/../include" ABSOLUTE)
这可以正常工作:找到 Base 并且 Middle 编译和安装正确。
最后,我有一个完全独立的“TopApp”可执行项目,它依赖于“Middle”。同样,在它的 CMakeLists.txt 文件中,我寻找“中间”包并像这样使用它:
cmake_minimum_required(VERSION 2.8)
project(TopApp)
find_package(Middle REQUIRED)
if ( Middle_FOUND )
message( "Middle found!")
endif()
include_directories(${Middle_INCLUDE_DIRS})
add_executable(TopApp main.cpp )
target_link_libraries( ${PROJECT_NAME} Middle )
因此,TopApp 编译成功,并与 Middle 链接 OK,但无法链接到 Base。但是我可以看到 Base.lib 存在于 TopApp 项目设置中(我在 Windows/Visual Studio 上)。 Middle.lib 的路径是绝对的,并且指向它应该指向的位置,而对于 Base,它只是没有路径的“Base.lib”。
我的目标当然是 TopApp 只是声明它依赖于 Middle。感谢 CMake 导入/导出系统,希望 TopApp.exe 应该自动链接到 Middle.lib 及其所有依赖项(在我的例子中是 Base.lib)。
我这应该是可能的,我怀疑我在 Middle 的 CMakeLists.txt 或 Middle-config.cmake 中遗漏了一些东西,但我有点困惑。
(请注意,我不希望这 3 个项目位于同一棵树中(基本上使用 add_subdirectories),因为我打算将它们分别发布到一些公共存储库上)
编辑:在 wojciii 的回复之后,我重新修改了 XXX-config.cmake 文件。这是 Base-config.cmake:
# - Config file for the Base package
# It defines the following variables
# BASE_INCLUDE_DIRS - include directories for Base
# BASE_LIBRARIES - libraries to link against
# Compute paths
get_filename_component(BASE_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
get_filename_component(BASE_INCLUDE_DIRS "${BASE_CMAKE_DIR}/../include" ABSOLUTE)
# Our library dependencies (contains definitions for IMPORTED targets)
if(NOT TARGET Base AND NOT Base_BINARY_DIR)
include("${BASE_CMAKE_DIR}/Base-targets.cmake")
endif()
# These are IMPORTED targets created by BaseTargets.cmake
set(BASE_LIBRARIES Base)
这里是 Middle-config.cmake:
# - Config file for the Base package
# It defines the following variables
# MIDDLE_INCLUDE_DIRS - include directories for Middle
# MIDDLE_LIBRARIES - libraries to link against
# Compute paths
get_filename_component(MIDDLE_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
get_filename_component(MIDDLE_INCLUDE_DIRS "${MIDDLE_CMAKE_DIR}/../include" ABSOLUTE)
# Our library dependencies (contains definitions for IMPORTED targets)
if(NOT TARGET Middle AND NOT Middle_BINARY_DIR)
include("${MIDDLE_CMAKE_DIR}/Middle-targets.cmake")
#include("${MIDDLE_CMAKE_DIR}/Base-targets.cmake")
endif()
# These are IMPORTED targets created by MiddleTargets.cmake
set(MIDDLE_LIBRARIES Middle Base)
这样更干净。我还按照建议将 Base 添加到 MIDDLE_LIBRARIES 变量(最后一行)。但是这并不能解决问题:Base 是 TopApp 级别的未知目标,并且链接失败。 我想我应该在 Middle 级别导出 Base-config/targets 文件,但是当我将其添加到 Middle 的 CMakeLists.txt 时,它会抱怨:
install TARGETS given target "Base" which does not exist in this directory.
Base 似乎是一个未知的安装目标,但我仍然可以在 Middle 的 CMakeLists 中做到这一点:
get_property(Base_location TARGET Base PROPERTY LOCATION)
message("Base_location == ${Base_location}")
【问题讨论】:
-
是否为您在
target_link_libraries指令(如target_link_libraries( ${PROJECT_NAME} Middle Base))解决方案中添加Base库名称? -
很遗憾没有。我希望 TopApp 将“target_link_libraries”简单地添加到 Middle,并且在后台使用 Base.lib。我还尝试将“Base”添加到 TopApp 的 target_link_libraries,正如您提到的那样只是为了检查,但它不起作用,因为那里的 Base 目标是未知的。
-
This question 看起来与您的问题有关。
-
这确实是相关的。但是我希望 CMake 依赖系统能够帮助我解决这个问题。当所有目标都在同一棵树中时,它的效果非常好,但是对于导出/导入的目标,我无法做到这一点。
-
啊。我想知道什么是错的。链接器不知道 CMake 目标 - 它知道库。所以它需要“-lBase -L/path/to/lib”或任何其他方式来指定链接什么而不是 CMake 目标。
标签: cmake