【问题标题】:<Package>Config.cmake for a library package<Package>Config.cmake 用于库包
【发布时间】:2022-01-07 10:32:43
【问题描述】:

我们按照 CMake 教程的第 11 步为库包配备了 *Config.cmake 文件。然而,我们的下游软件无法找到该库。

我们的包被称为“formfactor”[https://jugit.fz-juelich.de/mlz/libformfactor]。它提供了一个共享库(libformfactor)和一些头文件。

我们的下游代码使用

find_package(formfactor REQUIRED CONFIG)
message(STATUS "formfactor: found=${formfactor_FOUND}, include_dirs=${formfactor_INCLUDE_DIR}, "
    "lib=${formfactor_LIBRARY}, version=${formfactor_VERSION}")

搜索库。唉,它打印出来了

formfactor: found=1, include_dirs=/usr/local/include, lib=, version=0.1

也就是说,它没有找到库,尽管我们说“需要”,但它没有引发致命错误。

包“formfactor”包含以下所有内容:

CMakeLists.txt:

cmake_minimum_required(VERSION 3.6 FATAL_ERROR)
project(formfactor VERSION 0.1.1 LANGUAGES CXX)

if(NOT DEFINED BUILD_SHARED_LIBS)
    option(BUILD_SHARED_LIBS "Build as shared library" ON)
endif()
option(WERROR "Treat warnings as errors" OFF)

add_subdirectory(ff)

install(EXPORT formfactorTargets
  FILE formfactorTargets.cmake
  DESTINATION cmake
)

include(CMakePackageConfigHelpers)
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
    "${CMAKE_CURRENT_BINARY_DIR}/formfactorConfig.cmake"
    INSTALL_DESTINATION cmake
    NO_SET_AND_CHECK_MACRO
    NO_CHECK_REQUIRED_COMPONENTS_MACRO
    )

write_basic_package_version_file(
    "${CMAKE_CURRENT_BINARY_DIR}/formfactorConfigVersion.cmake"
    VERSION "${formfactor_VERSION_MAJOR}.${formfactor_VERSION_MINOR}"
    COMPATIBILITY AnyNewerVersion
    )

install(FILES
    ${PROJECT_BINARY_DIR}/formfactorConfig.cmake
    ${PROJECT_BINARY_DIR}/formfactorConfigVersion.cmake
    DESTINATION cmake)

export(EXPORT formfactorTargets
  FILE ${CMAKE_CURRENT_BINARY_DIR}/formfactorTargets.cmake
)

Config.cmake.in:


set(formfactor_INCLUDE_DIR @CMAKE_INSTALL_PREFIX@/include)
include(${CMAKE_CURRENT_LIST_DIR}/formfactorTargets.cmake)

ff/CMakeLists.txt:

set(lib formfactor)
set(${lib}_LIBRARY ${lib} PARENT_SCOPE)

file(GLOB src_files *.cpp)
set(api_files Polyhedron.h PolyhedralTopology.h PolyhedralComponents.h)

add_library(${lib} ${src_files})

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

set_target_properties(
    ${lib} PROPERTIES
    OUTPUT_NAME ${lib}
    VERSION ${formfactor_VERSION}
    SOVERSION ${formfactor_VERSION_MAJOR})

install(
    TARGETS ${lib}
    EXPORT formfactorTargets
    LIBRARY DESTINATION lib
    RUNTIME DESTINATION lib
    ARCHIVE DESTINATION lib)

install(
    FILES ${api_files}
    DESTINATION include/ff)

有什么问题吗?有什么遗漏吗?为什么还不行?

披露:

【问题讨论】:

  • 您为什么期望对find_package(formfactor) 的调用会设置formfactor_LIBRARY 变量?你的脚本Config.cmake.in 没有设置它。
  • CMake 教程中第 11 步还有什么目的?
  • 无论如何,如果没有“EXPORT ..Targets”开销,我会很高兴。如果我知道如何在Config.cmake.in 中设置formfactor_LIBRARY
  • find_package(formfactor) 的“现代”用法是与formfactor target (通过add_library 调用和安装)。精确生成的脚本formfactorTargets.cmake 负责创建该目标。与目标的链接关心包含目录、库和其他一些东西。 find_package 的“旧”使用模式是使用 *_LIBRARY*_INCLUDE_DIRECTORIES 变量。脚本formfactorTargets.cmake 不会创建这些变量,因此应在Config.cmake.in 中设置它们。
  • “那么我们需要在下游进行哪些更改以找到格式因子包含目录并进行链接?” - 正如我上面所说,下游只需要target_link_libraries(&lt;downstream_exe&gt; PUBLIC formfactor)。该命令将添加包含目录、库和其他所有内容。

标签: c++ cmake deployment


【解决方案1】:

脚本formfactorTargets.cmake,由CMake通过

生成
install(EXPORT formfactorTargets
  FILE formfactorTargets.cmake
  DESTINATION cmake
)

定义仅目标,该目标已添加到具有该名称 (formfactorTargets) 的导出集中。

因为你只添加了一个库

set(lib formfactor)
...
install(
    TARGETS ${lib}
    EXPORT formfactorTargets
    LIBRARY DESTINATION lib
    RUNTIME DESTINATION lib
    ARCHIVE DESTINATION lib)

脚本只定义了一个库target formfactor

与该目标相关联的是find_package 结果的“现代”用法:

# downstream
find_package(formfactor REQUIRED CONFIG)
target_link_libraries(<my executable> PUBLIC formfactor)

由您的Config.cmake.in 脚本(将安装为formfactorConfig.cmake,由find_package(formfactor) 读取)为您的包和/或其其他用途提供更多信息。

例如你可以设置变量formfactor_INCLUDE_DIRSformfactor_LIBRARIES 因此下游可以通过“旧方式”使用您的库,假设变量 formfactor_INCLUDE_DIR 包含包含目录,变量 formfactor_LIBRARIES 包含需要链接的库文件:

find_package(formfactor REQUIRED CONFIG)
include_directories(${formfactor_INCLUDE_DIRS})
add_executable(my_exe <sources>)
target_link_libraries(my_exe PUBLIC ${formfactor_LIBRARIES})

您(作为包的开发者)很难提供库的绝对路径。但是您可以在 a 中分配变量 formfactor_LIBRARIES “正常工作”的方式:

# Config.cmake.in

# Value of 'formfactor_INCLUDE_DIRS' is real: it contains the include directory.
set(formfactor_INCLUDE_DIRS @CMAKE_INSTALL_PREFIX@/include)

# Value of 'formfactor_LIBRARIES' is fake: it doesn't contain a library path.
# But linking with ${formfactor_LIBRARIES} will work, as it will link
# to the **target**, and CMake will extract a library path from it.
set(formfactor_LIBRARIES formfactor)

# In any case we need to include the export script generated by CMake:
# exactly this script defines 'formfactor' target.
include(${CMAKE_CURRENT_LIST_DIR}/formfactorTargets.cmake)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-26
    • 2016-12-30
    • 2016-09-23
    • 1970-01-01
    • 2010-11-11
    • 2018-10-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多