目录

1.简介

2.为什么需要 CMake Modules?

3.内置模块:开箱即用的工具

3.1.依赖查找模块(FindXXX.cmake)

3.2.功能检测模块(CheckXXX.cmake)

3.3.通用工具模块(如 FetchContent.cmake、CTest.cmake)

4.自定义模块:封装项目特有逻辑

5.注意事项

6.总结

相关链接


1.简介

        CMake Modules(CMake 模块)是一系列预定义或自定义的 .cmake 脚本文件,用于封装可重用的 CMake 逻辑(如依赖查找、功能检测、自定义命令等)。它们是简化 CMake 配置、实现代码复用和跨项目一致性的核心工具,尤其在大型项目或多项目管理中能显著提升配置效率。

        CMake 模块是扩展名为 .cmake 的文本文件,包含 CMake 命令、函数、宏或变量定义,用于封装特定功能(如 “查找 OpenSSL 库”“设置通用编译选项”“生成版本文件” 等)。

  • 内置模块:CMake 自带大量预定义模块(如 FindZLIB.cmakeFetchContent.cmake),位于 CMake 安装目录的 Modules 文件夹下(可通过 cmake --help-module-list 查看所有内置模块)。

文件夹如下面的目录:

  • 自定义模块:用户可根据项目需求编写自己的模块,放在项目目录中(如 cmake/Modules/),供多个子项目或目标复用。

2.为什么需要 CMake Modules?

1.代码复用:将重复的配置逻辑(如依赖查找、编译选项设置)封装到模块中,避免在多个 CMakeLists.txt 中重复编写。

2.简化主配置:主 CMakeLists.txt 只需通过 include(ModuleName) 调用模块,聚焦项目核心逻辑,减少冗余代码。

3.跨项目一致性:同一团队或生态的多个项目可共享模块,确保依赖管理、编译标准等配置统一。

4.隐藏复杂性:将复杂逻辑(如跨平台适配、条件检测)封装在模块中,主配置文件更简洁易懂。

3.内置模块:开箱即用的工具

CMake 内置了数百个模块,覆盖常见依赖查找、功能检测、平台适配等场景,无需手动编写复杂逻辑。

3.1.依赖查找模块(FindXXX.cmake

最常用的一类模块,用于查找系统中的第三方库(如 ZLIB、OpenSSL、Python 等),内部通过 find_pathfind_library 等命令实现查找,并暴露统一的接口变量(如 XXX_INCLUDE_DIRSXXX_LIBRARIES)。

CMake指令:find_package_cmake find package-CSDN博客

示例:使用 FindZLIB.cmake 查找 zlib 库

# 主 CMakeLists.txt
cmake_minimum_required(VERSION 3.14)
project(MyProject)# 加载内置的 FindZLIB.cmake 模块(无需手动 include,find_package 自动查找)
find_package(ZLIB REQUIRED)  # 内部调用 FindZLIB.cmake# 使用模块提供的变量
add_executable(myapp main.cpp)
target_include_directories(myapp PRIVATE ${ZLIB_INCLUDE_DIRS})
target_link_libraries(myapp PRIVATE ${ZLIB_LIBRARIES})

FindZLIB.cmake 模块已封装了所有查找逻辑(如适配不同平台的库名、路径),用户无需关心底层细节,直接使用即可。

3.2.功能检测模块(CheckXXX.cmake

用于检测编译器特性、函数 / 头文件是否存在等,辅助条件编译。

CMake进阶: 检查函数/符号存在性、检查类型/关键字/表达式有效性和检查编译器特性-CSDN博客

CMake进阶:检查头文件存在性(check_include_file 和 check_include_fileCXX)_cmake编译头文件的查找-CSDN博客

示例:使用 CheckFunctionExists.cmake 检测函数是否存在

include(CheckFunctionExists)  # 加载内置模块# 检测系统是否有 posix_memalign 函数
check_function_exists(posix_memalign HAVE_POSIX_MEMALIGN)# 根据检测结果设置宏,供代码中使用
if(HAVE_POSIX_MEMALIGN)add_definitions(-DHAVE_POSIX_MEMALIGN=1)
endif()

代码中可通过宏判断是否使用该函数:

#ifdef HAVE_POSIX_MEMALIGN// 使用 posix_memalign
#else// 备选实现
#endif

3.3.通用工具模块(如 FetchContent.cmakeCTest.cmake

提供通用功能,如下载依赖、集成测试等。

CMake进阶: 使用FetchContent方法基于gTest的C++单元测试_cmake fetchcontent-CSDN博客

示例:使用 FetchContent.cmake 下载外部依赖

include(FetchContent)  # 加载内置模块# 下载并集成 googletest
FetchContent_Declare(googletestGIT_REPOSITORY https://github.com/google/googletest.gitGIT_TAG v1.15.0
)
FetchContent_MakeAvailable(googletest)  # 自动下载、配置、构建

4.自定义模块:封装项目特有逻辑

CMake基础:宏(macro)和函数(function)_cmake macro-CSDN博客

当内置模块无法满足需求(如项目特有依赖、自定义工具链)时,可编写自定义模块,实现逻辑复用。

1.自定义模块的创建步骤

步骤 1:创建模块文件(.cmake

在项目中新建 cmake/Modules 目录,创建模块文件(如 AddMyTest.cmake),封装自定义逻辑(如简化测试用例添加):

# cmake/Modules/AddMyTest.cmake
# 自定义函数:简化测试用例添加,自动链接 gtest 并设置属性
function(add_my_test test_name test_src)add_executable(${test_name} ${test_src})target_link_libraries(${test_name} PRIVATE gtest_main)set_target_properties(${test_name} PROPERTIESCXX_STANDARD 17CXX_STANDARD_REQUIRED ON)add_test(NAME ${test_name} COMMAND ${test_name})
endfunction()

步骤 2:指定模块路径

在主 CMakeLists.txt 中通过 CMAKE_MODULE_PATH 告诉 CMake 去哪里查找自定义模块:

# 主 CMakeLists.txt
cmake_minimum_required(VERSION 3.14)
project(MyProject)# 添加自定义模块路径(${CMAKE_CURRENT_SOURCE_DIR} 是当前 CMakeLists.txt 所在目录)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")

步骤 3:使用自定义模块

# 加载自定义模块
include(AddMyTest)# 调用模块中的 add_my_test 函数(无需重复编写测试配置)
add_my_test(test1 tests/test1.cpp)
add_my_test(test2 tests/test2.cpp)

2.自定义模块的典型场景

  • 封装项目通用编译选项:如 SetCompilerFlags.cmake,统一设置 -Wall-O2 等编译 flags。
  • 处理项目特有依赖:如 FindMySDK.cmake,查找团队内部 SDK 的头文件和库。
  • 生成自定义文件:如 GenerateVersion.cmake,封装 configure_file 逻辑生成版本头文件。

5.注意事项

1.命名规范

  • 内置模块通常遵循 FindXXX.cmake(查找依赖)、CheckXXX.cmake(功能检测)等命名。
  • 自定义模块建议使用项目相关前缀(如 MyProjectUtils.cmake),避免与内置模块重名。

2.路径管理

  • 自定义模块统一放在项目的 cmake/Modules 目录,便于维护。
  • 通过 CMAKE_MODULE_PATH 动态添加路径(而非硬编码),确保模块可被正确找到。

3.接口设计

  • 模块中定义的函数 / 宏应清晰易懂,参数明确(如 add_my_test(test_name src_files))。
  • 暴露的变量建议添加前缀(如 MY_MODULE_XXX),避免与其他模块冲突。

4.文档说明

在模块开头添加注释,说明模块功能、使用方法、依赖项(如 # AddMyTest.cmake: 简化 GTest 测试用例添加,依赖 googletest)。

6.总结

CMake Modules 是简化配置的 “瑞士军刀”:

  • 内置模块提供开箱即用的功能(依赖查找、特性检测等),避免重复造轮子;
  • 自定义模块封装项目特有逻辑,提升配置复用性和一致性。

通过合理使用模块,可将复杂的 CMake 配置简化为 “引入模块 + 调用接口” 的简洁形式,尤其适合大型项目或多项目管理,显著降低维护成本。

相关链接

  • CMake 官网 CMake - Upgrade Your Software Build System
  • CMake 官方文档:CMake Tutorial — CMake 4.1.0 Documentation
  • CMake 源码:https://github.com/Kitware/CMake
  • CMake 源码:CMake · GitLab
  • 中文版基础介绍: CMake 入门实战 | HaHack
  • wiki: Home · Wiki · CMake / Community · GitLab
  • Modern CMake 简体中文版:  Introduction · Modern CMake

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/94040.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/94040.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/94040.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Docker】Ubuntu上安装Docker(网络版)

【Docker】Ubuntu上安装Docker注意:一、环境准备1. 系统要求2. 卸载旧版本二、安装步骤1.配置仓库源2.安装 Docker引擎3.验证安装情况三、解决报错1、检查网络连接2、检查Docker服务状态3、换源4.重载生效、重启服务、查看是否配置成功5.验证解决情况四、权限与配置…

Socket 编程 TCP

TCP 网络程序 和刚才 UDP 类似. 实现一个简单的英译汉的功能。TCP是面向字节流的可靠传输,如同前文的管道流,只要是流,它的操作就是文件的写出与读入。TCP socket API 详解下面介绍程序中用到的 socket API,这些函数都在 sys/socket.h 中。so…

使用AWS S3 + Lambda + MediaConvert 实现上传视频文件并自动转码

前言 最近团队在做短视频平台的技术调研,其中有一个环节便是音视频开发,即对用户上传的视频进行自适应转码。自适应的原理其实就是预先将视频转换为几个常用的分辨率,app端根据用户手机分辨率拉取相应分辨率的视频。 目前尝试了两种方案&…

QT之QWaitCondition降低cpu占用率,从忙等待到高效同步

在多线程编程中,线程间的同步是一个核心问题。在处理线程等待时,经常会写出高CPU占用率的代码,其中最典型的就是使用忙等待(busy waiting)。本文将详细介绍如何使用Qt框架中的QWaitCondition类来优雅地解决这一问题&am…

pcl求平面点云的边界凸包点

基本流程1,读入点云,并去除无效点2,拟合平面3,去除离平面距离较远的点4,对点云进行平面投影5,进行convex_hull运算初学者,暂时不知道能用来干嘛。练手还是非常不错的!#define _CRT_S…

Windows系统上使用GIT

首先破除一下畏惧心理:在Windows上使用git和在linux系统中的使用方法是一样的,只是安装方式没那么便捷,毕竟linux中安装git只需要一行命令 GIT下载地址 如果你的电脑的CPU是64位的,就点击: Git-2.50.1-64-bit.exe 如果…

《设计模式之禅》笔记摘录 - 17.模板方法模式

模板方法模式的定义模板方法模式(Template Method Pattern)是如此简单,以致让你感觉你已经能够掌握其精髓了。其定义如下:Define the skeleton of an algorithm in an operation, deferring some steps to subclasses.Template Method lets subclasses r…

SpreadJS 协同服务器 MongoDB 数据库适配支持

为了支持 SpreadJS 协同编辑场景,协同服务器需要持久化存储文档、操作、快照及里程碑数据。本文介绍了 MongoDB 数据库适配器的实现方法,包括集合初始化、适配器接口实现以及里程碑存储支持。 一、MongoDB 集合初始化 协同编辑服务需要以下集合&#x…

Ubuntu 主机名:精通配置与管理

主机名(hostname)是Linux系统中用于标识网络上特定设备的名称,它在网络通信、服务配置(如 Kubernetes 集群、数据库)以及日志记录中扮演着至关重要的角色。对于初学者来说,配置主机名似乎很简单&#xff0c…

C/C++ 协程:Stackful 手动控制的工程必然性

🚀 C/C 协程:Stackful 手动控制的工程必然性 引用: C/C 如何正确的切换协同程序?(基于协程的并行架构) #mermaid-svg-SXgplRf3WRYc8A7l {font-family:"trebuchet ms",verdana,arial,sans-serif;…

新手向:使用STM32通过RS485通信接口控制步进电机

新手向:使用STM32通过RS485通信接口控制步进电机 准备工作 本文使用的STM32芯片是STM32F407ZGTx,使用的电机是57步进电机,驱动器是用的是时代超群的RS485总线一体化步进电机驱动器(42 型:ZD-M42P-485)。使…

设计模式笔记_行为型_命令模式

1.命令模式介绍命令模式(Command Pattern)是一种行为设计模式,它将请求或操作封装为对象,使得可以用不同的请求对客户端进行参数化。命令模式的核心思想是将方法调用、请求或操作封装到一个独立的命令对象中,从而使得客…

详解MySQL中的多表查询:多表查询分类讲解、七种JOIN操作的实现

精选专栏链接 🔗 MySQL技术笔记专栏Redis技术笔记专栏大模型搭建专栏Python学习笔记专栏深度学习算法专栏 欢迎订阅,点赞+关注,每日精进1%,与百万开发者共攀技术珠峰 更多内容持续更新中!希望能给大家带来…

vue3+elemeent-plus, el-tooltip的样式修改不生效

修改后的样式&#xff0c;直接贴图&#xff0c;经过删除出现悬浮1、在书写代码的时候切记effect“light”&#xff0c;如果你需要的是深色的样式:disabled"!multiple" 是否禁用<el-tooltip effect"light" placement"top" content"请先选…

网页作品惊艳亮相!这个浪浪山小妖怪网站太治愈了!

大家好呀&#xff01;今天要给大家分享一个超级治愈的网页作品——浪浪山小妖怪主题网站&#xff01;这个纯原生开发的项目不仅颜值在线&#xff0c;功能也很能打哦&#xff5e;至于灵感来源的话&#xff0c;要从一部动画说起。最近迷上了治愈系动画&#xff0c;就想做一个温暖…

搭建最新--若依分布式spring cloudv3.6.6 前后端分离项目--步骤与记录常见的坑

首先 什么拉取代码&#xff0c;安装数据库&#xff0c;安装redis&#xff0c;安装jdk这些我就不说了 导入数据库 &#xff1a;数据库是分库表的 &#xff0c;不要建错了 【一定要注意&#xff0c;不然nacos读取不到配置文件】这个是给nacos用的这个是给项目配置或项目用的2. 服…

分布式唯一 ID 生成方案

在复杂分布式系统中&#xff0c;往往需要对大量的数据和消息进行唯一标识。如在美团点评的金融、支付、餐饮、酒店、猫眼电影等产品的系统中&#xff0c;数据日渐增长&#xff0c;对数据分库分表后需要有一个唯一 ID 来标识一条数据或消息&#xff0c;数据库的自增 ID 显然不能…

飞算JavaAI赋能高吞吐服务器模拟:从0到百万级QPS的“流量洪峰”征服之旅

引言&#xff1a;当“流量洪峰”来袭&#xff0c;如何用低代码驯服高并发&#xff1f; 在数字化时代&#xff0c;从电商平台的“双11”大促到社交网络的突发热点事件&#xff0c;再到金融系统的实时交易高峰&#xff0c;服务器时刻面临着**高吞吐量&#xff08;High Throughput…

C#数据访问帮助类

一.中文注释using System; using System.Data; using System.Xml; using System.Data.SqlClient; using System.Collections;namespace Microsoft.ApplicationBlocks.Data.Ch {/// <summary>/// SqlServer数据访问帮助类/// </summary>public sealed class SqlHelp…

B站 韩顺平 笔记 (Day 21)

目录 1&#xff08;面向对象高级部分练习题&#xff09; 1.1&#xff08;题1&#xff09; 1.2&#xff08;题2&#xff09; 1.3&#xff08;题3&#xff09; Vehicles接口类&#xff1a; Horse类&#xff1a; Boat类&#xff1a; Plane类&#xff1a; VehiclesFactory…