【问题标题】:How do I Install bundled interface dependencies with modern CMake?如何使用现代 CMake 安装捆绑的接口依赖项?
【发布时间】:2018-10-01 13:01:42
【问题描述】:

在 Modern CMake 中安装捆绑接口依赖项的正确方法是什么?

我有一个库MyLib,它具有对libDep 的接口依赖(MyLib.hpp 包含#include <libDep.h>)。任何依赖于MyLib 的东西也会传递地依赖于libDep

libDep 是取自要点的单个标头,因此我将其包含在 MyLib 的源树中的一部分

$ tree
.
├── CMake
│   ├── MyLibConfig.cmake.in
│   └── modules
│       └── FindlibDep.cmake
├── CMakeLists.txt
├── include
│   └── MyLib
│       └── MyLib.hpp
├── src
│   └── MyLib.cpp
└── third_party
    └── libDep
        └── libDep.h

我想安装libDepmyLib,路径类似于include/MyLib/third_party/libDep


这是MyLib 的 CMakeLists

cmake_minimum_required(VERSION 3.3.0)
Project(MyLib
    DESCRIPTION "Library with bundled interface dependency"
    LANGUAGES CXX)

include(GNUInstallDirs)
include(CMakePackageConfigHelpers)

set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMake/modules)

# Find LibDep dependency
find_package(libDep REQUIRED)

# MyLib library
add_library(MyLib STATIC
    ${CMAKE_SOURCE_DIR}/src/MyLib.cpp)

target_include_directories(MyLib
    PUBLIC $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include/MyLib>
    PUBLIC $<INSTALL_INTERFACE:include/MyLib>)

target_link_libraries(MyLib
    INTERFACE libDep)

MyLib 定位 libDepFindlibDep.cmake 位于 CMAKE_MODULE_PATH

find_path(LibDep_INCLUDE_DIR
    NAMES LibDep.hpp
    PATHS third_party/libDep)
    PATH_SUFFIXES Mylib/third_party/libDep)

mark_as_advanced(LibDep_FOUND LibDep_INCLUDE_DIR)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LibDep
    REQUIRED_VARS
        LibDep_INCLUDE_DIR
)

if(LibDep_FOUND)
    set(LibDep_INCLUDE_DIRS ${LibDep_INCLUDE_DIR})
endif()

if(LibDep_FOUND AND NOT TARGET MyLib::LibDep)
    add_library(MyLib::LibDep INTERFACE IMPORTED)
    set_target_properties(MyLib::LibDep PROPERTIES
        INTERFACE_INCLUDE_DIRECTORIES ${LibDep_INCLUDE_DIR})
endif()

我安装MyLiblike

install(TARGETS MyLib
    EXPORT MyLibTargets
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib
    RUNTIME DESTINATION bin
    INCLUDES DESTINATION include)

include(CMakePackageConfigHelpers)
write_basic_package_version_file(MyLibConfigVersion.cmake)

install(EXPORT MyLibTargets
    FILE MyLibTargets.cmake
    NAMESPACE MyLib::
    DESTINATION lib/cmake/MyLib)

configure_file(CMake/MyLibConfig.cmake.in MyLibConfig.cmake @ONLY)
install(FILES
    "${CMAKE_CURRENT_BINARY_DIR}/MyLibConfig.cmake"
    "${CMAKE_CURRENT_BINARY_DIR}/MyLibConfigVersion.cmake"
    DESTINATION lib/cmake/MyLib)

install(DIRECTORY ${MyLib_PUBLIC_INCLUDE_DIR}
    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

# Package with CPack
include(InstallRequiredSystemLibraries)
include(CPack)

MyLibConfig.cmake.in 声明对libDep 的依赖

include(CMakeFindDependencyMacro)

# Dependencies
add_library(libDep REQUIRED)

# Add the targets file
include("${CMAKE_CURRENT_LIST_DIR}/MyLibTargets.cmake")

libDep 被安装到MyLib 的树中

install(DIRECTORY ${libDep_INCLUDE_DIRS}
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/MyLib/third_party)

然后我用

复制查找模块
install(FILES
    ${CMAKE_MODULE_PATH}/FindlibDep.cmake
    DESTINATION lib/cmake/MyLib)

很遗憾,MyLib 的用户默认看不到 FindlibDep.cmake

$ cmake ..
CMake Error at /usr/share/cmake-3.10/Modules/CMakeFindDependencyMacro.cmake:48 (find_package):
  By not providing "FindlibDep.cmake" in CMAKE_MODULE_PATH this project has
  asked CMake to find a package configuration file provided by "libDep", but
  CMake did not find one.

  Could not find a package configuration file provided by "libDep" with any
  of the following names:

    libDepConfig.cmake
    libDep-config.cmake

  Add the installation prefix of "libDep" to CMAKE_PREFIX_PATH or set
  "libDep_DIR" to a directory containing one of the above files.  If "libDep"
  provides a separate development package or SDK, be sure it has been
  installed.
Call Stack (most recent call first):
  /usr/local/lib/cmake/MyLib/MyLibConfig.cmake:5 (find_dependency)
  CMakeLists.txt:9 (find_package)

-- Configuring incomplete, errors occurred!

用户可以手动定位FindlibDep.cmake并将其添加到他们的CMAKE_MODULE_PATH,但这不是必需的。


此问题的复制品是available on GitHub

【问题讨论】:

    标签: c++ cmake dependency-management packaging cmake-modules


    【解决方案1】:

    您需要对源目录使用 PROJECT_ 变量而不是 CMAKE_ 变量:

    set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMake/modules)
    

    PROJECT_SOURCE_DIR 从最近执行的 project() 指令(在本例中为您的库)获取源目录。

    您还应该将当前的 CMAKE_MODULE_PATH 添加到新路径,如上所示。

    【讨论】:

    • 感谢您的回答卡尔!不幸的是,它并没有解决我的问题。我不确定我描述的情况是否足够好,所以我已将a repository reproducing the issue 添加到 GitHub。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-01
    • 2014-11-20
    • 2014-12-31
    • 2021-08-17
    相关资源
    最近更新 更多