006 - CMake 安装动态库并生成 XxxConfig.cmake 文件

本文介绍了使用CMake安装动态库并生成XxxConfig.cmake文件的方法。CMake通过find_package找动态库,会调用相关Config文件。文中展示了CMakeLists.txt,还对其中的set_target_properties、target_include_directories等命令进行了简单解释,说明了各命令的作用和用法。

CMake 安装动态库并生成 XxxConfig.cmake 文件

引言

之前说了一下《使用 CMake 生成动态库/静态库》,既然写了动态库,那肯定是要提供给别人调用的,我们就来看看要怎么调用

写过 cmake 的都应该知道,cmake 通过 find_package 去找动态库,find_package 会去调用 XxxConfig.cmake 或 xxx-config.cmake 或 FindXxx.cmake 文件去找动态库,上述文件出现的顺序就是调用的优先级,前两个文件一般是库作者提供的,后一个主要用于库作者没提供前两个文件的时候我们自己编写一个给 find_package 调用。

展示

直接上 CMakeLists.txt

cmake_minimum_required(VERSION 3.16)

project(FooLibrary VERSION 1.0.0)

set(CMAKE_CXX_STANDARD 11)

add_library(${PROJECT_NAME} SHARED library.cpp)

# 这个使用了生成器表达式,其他项目引入包的时候就可以同时引入头文件包含路径
target_include_directories(${PROJECT_NAME} INTERFACE
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
        $<INSTALL_INTERFACE:include>)

set(CONFIG_FILE_PATH share/cmake/${PROJECT_NAME})

include(GNUInstallDirs)

include(CMakePackageConfigHelpers)

configure_package_config_file(FooLibraryConfig.cmake.in
        ${CMAKE_BINARY_DIR}/FooLibraryConfig.cmake
        INSTALL_DESTINATION ${CONFIG_FILE_PATH}
        PATH_VARS CMAKE_INSTALL_INCLUDEDIR)

write_basic_package_version_file(
        ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
        VERSION ${CMAKE_PROJECT_VERSION}
        COMPATIBILITY SameMajorVersion)

install(TARGETS ${PROJECT_NAME}
        EXPORT ${PROJECT_NAME}Targets)

install(EXPORT ${PROJECT_NAME}Targets
        DESTINATION ${CONFIG_FILE_PATH})

install(FILES
        ${CMAKE_BINARY_DIR}/FooLibraryConfig.cmake
        ${CMAKE_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
        DESTINATION ${CONFIG_FILE_PATH})

FooLibraryConfig.cmake.in

@PACKAGE_INIT@

include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")

FooLibraryConfig.cmake.in

下面这几句主要是为了设置 <PackageName>_NCLUDE_DIR <PackageName>_NCLUDES <PackageName>_LIBRARY <PackageName>_LIBRARIES <PackageName>_LIBS 等变量,但是这些变量 CMake 没有要求且各个库提供的都不一样,所以也可以不设置。


                
<think> 我们正在讨论如何编写一个Config.cmake文件(使用Config模式)。Config模式是CMake中用于让其他项目通过find_package()找到你的库的标准方式。这种模式需要你提供一个<PackageName>Config.cmake文件(或<package-name>-config.cmake),该文件会被安装到特定位置,以便其他项目使用。 根据引用内容,以下是编写Config.cmake文件的关键步骤和最佳实践: ### 一、基本结构 一个完整的Config.cmake文件通常包含以下内容: 1. **目标导出**:将项目中构建的目标导出,以便其他项目可以链接它们。 2. **版本管理**:使用`write_basic_package_version_file`生成一个版本文件,用于兼容性检查。 3. **配置模板**:创建一个`<PackageName>Config.cmake.in`模板文件,通过`configure_file`生成最终的Config文件。 ### 二、具体步骤 #### 1. 创建Config模板文件(例如:`MyProjectConfig.cmake.in`) ```cmake @PACKAGE_INIT@ # 这个宏由CMake提供,用于初始化一些基本变量和函数 # 包含导出的目标 include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_EXPORT_NAME@Targets.cmake") # 检查依赖项(如果有) # 例如:find_dependency(OpenCV REQUIRED) # 设置变量(可选) # 例如:set(MyProject_VERSION @PROJECT_VERSION@) ``` #### 2. 在主CMakeLists.txt中配置 ```cmake # 首先,导出项目中的目标(以便在Config.cmake中引用) install(TARGETS MyLibrary EXPORT MyProjectTargets ARCHIVE DESTINATION lib LIBRARY DESTINATION lib RUNTIME DESTINATION bin INCLUDES DESTINATION include ) # 安装导出目标文件 install(EXPORT MyProjectTargets FILE MyProjectTargets.cmake NAMESPACE MyProject:: DESTINATION lib/cmake/MyProject ) # 创建版本兼容文件 include(CMakePackageConfigHelpers) write_basic_package_version_file( MyProjectConfigVersion.cmake VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion # 或ExactVersion, AnyNewerVersion等 ) # 配置Config模板文件 configure_package_config_file( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/MyProjectConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/MyProjectConfig.cmake INSTALL_DESTINATION lib/cmake/MyProject PATH_VARS INCLUDE_INSTALL_DIR # 如果有其他路径变量需要替换,在这里列出 ) # 安装生成文件 install(FILES ${CMAKE_CURRENT_BINARY_DIR}/MyProjectConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/MyProjectConfigVersion.cmake DESTINATION lib/cmake/MyProject ) ``` ### 三、关键点说明 1. **`@PACKAGE_INIT@`的作用**:这个宏由CMake提供,它会展开为一段代码,用于初始化一些变量(如`PACKAGE_PREFIX_DIR`)和宏(如`set_and_check`),帮助正确处理相对路径和包前缀[^3]。 2. **导出目标**:通过`install(EXPORT ...)`命令将目标导出到`MyProjectTargets.cmake`文件中,这个文件会被包含在生成Config文件中。 3. **版本文件**:`write_basic_package_version_file`会生成一个`MyProjectConfigVersion.cmake`文件,用于检查版本兼容性(当其他项目使用`find_package(MyProject VERSION 1.2)`时会自动调用)。 4. **`configure_package_config_file`**:这个命令类似于`configure_file`,但专门用于生成Config文件。它会自动处理路径变量,使得生成Config文件支持重定位(即安装后移动到其他位置仍能工作)[^2]。 5. **命名空间**:在`install(EXPORT ...)`中使用`NAMESPACE MyProject::`,这样导出的目标会有命名空间前缀(例如`MyProject::MyLibrary`),避免与其他项目冲突。 ### 四、完整示例 假设我们有一个名为`MyProject`的库,其目录结构如下: ``` MyProject/ ├── CMakeLists.txt ├── include/ │ └── MyProject/ │ └── mylib.h ├── src/ │ └── mylib.cpp └── cmake/ └── MyProjectConfig.cmake.in ``` **MyProjectConfig.cmake.in**内容: ```cmake @PACKAGE_INIT@ include(CMakeFindDependencyMacro) # 如果依赖其他库,可以在这里使用find_dependency # find_dependency(OpenCV REQUIRED) include("${CMAKE_CURRENT_LIST_DIR}/MyProjectTargets.cmake") # 可选:提供变量 set(MyProject_VERSION @PROJECT_VERSION@) ``` **主CMakeLists.txt**中相关部分: ```cmake project(MyProject VERSION 1.0.0) add_library(MyLib SHARED src/mylib.cpp) target_include_directories(MyLib PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include> ) # ...(前面的导出和配置步骤) # 安装文件 install(DIRECTORY include/ DESTINATION include) ``` ### 五、注意事项 1. **路径重定位**:使用`configure_package_config_file`和`@PACKAGE_INIT@`可以确保生成文件安装后即使被移动到其他位置(如通过打包工具)也能正确工作[^2]。 2. **依赖传递**:如果你的库依赖其他库,在Config文件中应使用`find_dependency`(而不是`find_package`)来确保依赖关系正确传递[^3]。 3. **目标命名空间**:建议始终为目标添加命名空间,以避免冲突。 > **最佳实践**:将生成Config文件安装到`lib/cmake/<PackageName>`目录下,这是CMake社区的标准约定。 [^2]: 006 - CMake 安装动态库生成 XxxConfig.cmake 文件 [^3]: 如何创建一个ProjectConfig.cmake文件 §§相关问题§§ 1. Config模式与Module模式在CMake中有什么区别? 2. 如何为Config.cmake文件添加对第三方库的依赖管理? 3. CMake导出的目标如何支持不同构建类型(Debug/Release)? 4. 如何处理Config.cmake文件中的路径重定位问题? 5. 如何测试生成Config.cmake文件是否正常工作? </think> ### 使用Config模式编写Config.cmake文件的方法 在CMake中,Config模式是创建可重定位包配置的标准方式。以下是核心步骤和示例: --- ### 一、基本文件结构 ```bash YourProject/ ├── CMakeLists.txt ├── cmake/ │ ├── YourProjectConfig.cmake.in # 配置文件模板 │ └── YourProjectConfigVersion.cmake.in # 版本文件模板 └── src/ ``` --- ### 二、核心步骤(主CMakeLists.txt) #### 1. 定义安装目标和导出集 ```cmake install(TARGETS YourLibrary EXPORT YourProjectTargets ARCHIVE DESTINATION lib LIBRARY DESTINATION lib RUNTIME DESTINATION bin INCLUDES DESTINATION include ) ``` #### 2. 生成配置文件和版本文件 ```cmake include(CMakePackageConfigHelpers) # 生成版本配置文件 write_basic_package_version_file( YourProjectConfigVersion.cmake VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion ) # 配置主模板文件 configure_package_config_file( cmake/YourProjectConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/YourProjectConfig.cmake INSTALL_DESTINATION lib/cmake/YourProject PATH_VARS INCLUDE_INSTALL_DIR # 可添加其他路径变量 ) # 安装配置文件 install(FILES ${CMAKE_CURRENT_BINARY_DIR}/YourProjectConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/YourProjectConfigVersion.cmake DESTINATION lib/cmake/YourProject ) # 安装导出目标 install(EXPORT YourProjectTargets FILE YourProjectTargets.cmake NAMESPACE YourProject:: DESTINATION lib/cmake/YourProject ) ``` --- ### 三、配置文件模板示例(YourProjectConfig.cmake.in) ```cmake @PACKAGE_INIT@ # CMake提供的初始化宏 # 包含导出目标 include("${CMAKE_CURRENT_LIST_DIR}/YourProjectTargets.cmake") # 设置变量(示例) set(YourProject_VERSION @PACKAGE_VERSION@) set(YourProject_INCLUDE_DIRS "@PACKAGE_INCLUDE_INSTALL_DIR@") # 检查依赖(可选) include(CMakeFindDependencyMacro) find_dependency(Threads REQUIRED) # 验证变量(确保路径有效) check_required_components(YourProject) ``` --- ### 四、关键特性说明 1. **`@PACKAGE_INIT@`宏** 提供基本功能: - 初始化`PACKAGE_PREFIX_DIR` - 引入`set_and_check()`和`check_required_components()`宏 2. **路径重定位支持** 使用`@PACKAGE_VAR@`代替绝对路径: ```cmake set_and_check(YourProject_INCLUDE_DIRS "@PACKAGE_INCLUDE_INSTALL_DIR@") ``` 3. **版本兼容性控制** `COMPATIBILITY`选项支持: - `AnyNewerVersion` - `SameMajorVersion` - `ExactVersion` 4. **依赖传递处理** 使用`find_dependency()`而非`find_package()`确保依赖链正确传递[^3]: ```cmake find_dependency(OpenCV REQUIRED) ``` --- ### 五、使用方法(客户端项目) ```cmake find_package(YourProject CONFIG REQUIRED) target_link_libraries(MyApp YourProject::YourLibrary) ``` > **最佳实践**: > 1. 命名规范:`<PackageName>Config.cmake`或`<PackageName>-config.cmake` > 2. 安装路径:`lib/cmake/<PackageName>` > 3. 使用`configure_package_config_file()`代替`configure_file()`确保路径重定位[^2] > 4. 始终包含`check_required_components()`验证组件 [^2]: 使用`configure_package_config_file`可确保路径变量正确重定位 [^3]: `find_dependency`正确处理依赖传递关系 ---
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值