<Package>Config.cmake 用于库包
<Package>Config.cmake for a library package
我们按照 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}")
搜索图书馆。 las,它打印
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)
有什么问题吗?有什么遗漏吗?为什么它不起作用?
披露:
- 来自 https://discourse.cmake.org/t/find-package-config-mode-wont-find-library/4573 的交叉发布。
- 看过相关讨论Create CMake/CPack <Library>Config.cmake for shared library。在这里,我对一个解决方案感兴趣,它可以执行 CMake 教程中推荐的所有自动文件生成。
CMake 通过
生成的脚本 formfactorTargets.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)
读取)为您的包提供额外信息 and/or 它的额外用法。
例如你可以设置变量 formfactor_INCLUDE_DIRS
和 formfactor_LIBRARIES
因此下游可以通过“旧方式”使用您的库,假设变量 formfactor_INCLUDE_DIR
包含包含目录,变量 formfactor_LIBRARIES
包含 link 所需的库文件:
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)
我们按照 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}")
搜索图书馆。 las,它打印
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)
有什么问题吗?有什么遗漏吗?为什么它不起作用?
披露:
- 来自 https://discourse.cmake.org/t/find-package-config-mode-wont-find-library/4573 的交叉发布。
- 看过相关讨论Create CMake/CPack <Library>Config.cmake for shared library。在这里,我对一个解决方案感兴趣,它可以执行 CMake 教程中推荐的所有自动文件生成。
CMake 通过
生成的脚本formfactorTargets.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)
读取)为您的包提供额外信息 and/or 它的额外用法。
例如你可以设置变量 formfactor_INCLUDE_DIRS
和 formfactor_LIBRARIES
因此下游可以通过“旧方式”使用您的库,假设变量 formfactor_INCLUDE_DIR
包含包含目录,变量 formfactor_LIBRARIES
包含 link 所需的库文件:
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)