CMake:导入静态lib目标及其依赖的所有lib

时间:2014-06-15 16:13:19

标签: cmake

我有一个名为“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的编译和安装工作正常。

现在,我有另一个独特的静态库,名为“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”可执行项目依赖于“中间”。再次,在其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编译正常,并将OK链接到Middle,但无法链接到Base。但是我可以看到Base.lib存在于TopApp项目设置中(我在Windows / Visual Studio上)。 Middle.lib的路径是绝对的,指向应该的位置,而对于Base,它只是没有路径的“Base.lib”。

我的目标当然是TopApp只是说它依赖于Middle。希望TopApp.exe能够自动链接到Middle.lib及其所有依赖项(在我的情况下为Base.lib),这要归功于CMake导入/导出系统。

我这应该是可能的,我怀疑我在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级别的未知目标,链接失败。 我想我应该在中级导出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}")

1 个答案:

答案 0 :(得分:1)

我从阅读http://www.itk.org/Wiki/CMake/Tutorials/How_to_create_a_ProjectConfig.cmake_file(或参见http://www.cmake.org/cmake/help/v3.0/manual/cmake-packages.7.html for v.3.x)获得的印象是

Middle-config.cmake应该设置以下变量:

MIDDLE_INCLUDE_DIRS - include directories for Middle MIDDLE_LIBRARIES - libraries to link against MIDDLE_EXECUTABLE - the bar executable

这样调用find_package()的配置文件的用户可以使用它们来使链接器满意。

您已经使用在Middle-config.cmake中设置的值调用include_directories(),因此我相信您应该使用MIDDLE_LIBRARIES调用target_link_libraries()。