跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
C++

CMake与Makefile:核心区别与实战指南

综述由AI生成对比了CMake与Makefile在本质、跨平台性及语法复杂度上的区别,指出CMake是跨平台构建生成器而Makefile是底层编译规则脚本。随后详细解析了CMake常用命令,包括基础配置(版本、项目名)、变量操作(定义、列表、预定义变量、字符串替换)、编译构建(头文件路径、源码查找、可执行目标、库链接)、流程控制(文件判断、循环、日志)及高级操作(自定义命令、子目录、安装路径)。文章强调现代CMake推荐使用target_*系列命令替代全局命令,并提供了调试与安装部署的最佳实践。

佛系玩家发布于 2026/3/21更新于 2026/5/314 浏览

cmake与makefile的区别

维度CMakeMakefile
本质跨平台构建工具(生成器)编译规则脚本(依赖Make工具执行)
核心作用自动生成适配不同平台/编译器的Makefile(或VS工程、Ninja文件等)定义源码编译的依赖关系、编译命令,由Make解析执行
跨平台性天然跨平台(Windows/Linux/macOS),语法统一平台相关(如Windows需MinGW/MSYS,语法依赖Make工具版本)
语法复杂度高层抽象语法(如add_executable),易维护底层脚本语法(需手动写依赖、命令),复杂项目易臃肿
适用场景中大型/跨平台项目,适配多编译环境小型Linux/Unix项目,需精准控制编译流程
执行逻辑先执行cmake生成构建文件,再执行make编译直接执行make解析Makefile完成编译

核心总结: CMake是「构建文件生成器」,通过跨平台语法生成适配不同环境的Makefile(或其他构建文件);Makefile是「编译规则文件」,直接定义编译依赖和命令,依赖Make工具执行,仅适配类Unix环境。

CMake 常用命令详解

本文整理了CMake构建过程中最常用的核心命令,涵盖版本设置、变量定义、项目配置、编译构建、安装部署等全流程,方便快速查阅和使用。

基础配置命令

1. 指定CMake最低版本
cmake_minimum_required(VERSION 3.1.3)
  • 作用:限定构建当前项目所需的CMake最低版本,低于该版本会直接报错,确保语法和特性兼容。
  • 示例:cmake_minimum_required(VERSION 3.20)(推荐使用项目兼容的较高稳定版本)
2. 设置项目名称
project(project_name) # 扩展:指定项目语言和版本 project(project_name LANGUAGES C CXX VERSION 1.0.0)
  • 作用:定义项目名称,同时会自动生成PROJECT_NAME、PROJECT_VERSION等预定义变量。
  • 参数说明:
    • LANGUAGES:指定项目支持的编程语言(如C、CXX/C++、Fortran等);
    • VERSION:设置项目版本号。

变量操作命令

1. 普通变量定义与赋值
# 单值赋值
set(variable "content")
# 多值赋值(列表形式)
set(variable content1 content2 content3)
# 设置C++标准(核心常用)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) # 强制要求指定的C++标准,不兼容则报错
  • 作用:定义自定义变量或修改CMake预定义变量,支持单值/多值(列表)赋值。
  • 注意:CMAKE_CXX_STANDARD用于指定编译时的C++特性标准(如11/14/17/20),需配合CMAKE_CXX_STANDARD_REQUIRED确保生效。
  • 2. 列表操作(添加元素)
    # 初始化空列表
    set(variable_name "")
    # 向列表追加元素
    list(APPEND variable_name "content1")
    list(APPEND variable_name "content2" "content3")
    
    • 作用:管理列表类型变量,常用于收集源码文件、头文件路径等。
    3. 预定义核心变量
    变量名说明
    CMAKE_CXX_STANDARD指定C++编译标准(如11、17)
    CMAKE_CURRENT_BINARY_DIRCMake执行命令时的工作目录(编译产物输出目录)
    CMAKE_CURRENT_SOURCE_DIR当前CMakeLists.txt文件所在的目录
    CMAKE_INSTALL_PREFIX项目默认安装路径(默认:Unix为/usr/local,Windows为C:\Program Files)
    4. 字符串替换
    string(REPLACE ".old" ".new" dest_variable "original_string.old")
    
    • 作用:将源字符串中的指定子串替换为新子串,并将结果存入目标变量。
    • 示例:执行后dest_variable的值为original_string.new。

    编译构建命令

    1. 添加头文件搜索路径
    include_directories(
        ${CMAKE_CURRENT_SOURCE_DIR}/include
        ${CMAKE_CURRENT_SOURCE_DIR}/third_party/include
    )
    
    • 作用:指定编译器查找头文件的目录,等价于GCC的-I参数。
    • 推荐用法:现代CMake更推荐使用target_include_directories(针对具体目标),避免全局污染。
    2. 查找目录下的所有源码文件
    aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src src_files)
    
    • 作用:递归查找指定目录下的所有源码文件(.c/.cpp),并将文件路径列表存入变量。
    • 注意:若目录下文件结构复杂,建议手动列出源码文件,避免意外引入无关文件。
    3. 添加可执行目标
    add_executable(app_name ${src_files} main.cpp)
    
    • 作用:指定编译生成的可执行文件名称,并关联对应的源码文件。
    • 参数:app_name为可执行文件名称,后续为依赖的源码文件列表。
    4. 链接库文件
    target_link_libraries(app_name
        # 系统库/第三方库
        pthread
        # 自定义库(需先通过add_library定义)
        ${CMAKE_CURRENT_SOURCE_DIR}/lib/libxxx.a
        my_custom_lib
    )
    
    • 作用:为指定目标链接依赖的库文件,等价于GCC的-l参数。
    • 分类:支持静态库(.a)、动态库(.so/.dll),优先链接系统库,再链接自定义库。

    流程控制命令

    1. 文件存在性判断
    if (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/config.h)
        message(FATAL_ERROR "配置文件config.h不存在,请检查!")
    endif()
    
    • 作用:判断文件/目录是否存在,配合if/endif实现条件逻辑。
    • 扩展:支持EXISTS(存在)、NOT EXISTS(不存在)、IS_DIRECTORY(是否为目录)等判断条件。
    2. 循环遍历
    set(numbers 1 2 3 4 5)
    foreach(val IN LISTS numbers)
        message(STATUS "当前值:${val}")
    endforeach()
    
    • 作用:遍历列表中的每个元素,执行循环体中的命令。
    • 语法:foreach(变量 IN LISTS 列表变量) 或 foreach(变量 元素1 元素2)。
    3. 打印日志/错误
    # 普通状态提示(编译时输出,不中断)
    message(STATUS "当前编译目录:${CMAKE_CURRENT_BINARY_DIR}")
    # 警告提示(黄色输出,不中断)
    message(WARNING "未指定C++标准,默认使用C++11")
    # 致命错误(红色输出,中断编译)
    message(FATAL_ERROR "缺少核心依赖库,请安装后重试!")
    
    • 作用:输出构建过程中的信息,辅助调试和错误排查。

    高级操作命令

    1. 执行自定义命令
    add_custom_command(
        TARGET app_name
        # 关联到指定目标
        PRE_BUILD
        # 执行时机:编译目标前(可选:PRE_LINK/POST_BUILD)
        COMMAND echo "开始编译app_name..."
        # 要执行的指令
        ARGS -n "编译时间:$(date)"
        # 指令参数
        DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/version.h
        # 依赖文件(文件更新则重新执行)
        COMMENT "执行预编译检查..."
        # 编译时打印的提示信息
    )
    
    • 执行时机可选值:
      • PRE_BUILD:目标编译前(仅Visual Studio支持);
      • PRE_LINK:编译完成后、链接前;
      • POST_BUILD:链接完成后(最常用)。
    • 作用:在构建流程的指定阶段执行自定义指令(如脚本、系统命令)。
    2. 添加子目录(嵌套CMake)
    add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib)
    add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/test EXCLUDE_FROM_ALL)
    
    • 作用:指定子目录,CMake会递归处理该目录下的CMakeLists.txt。
    • 参数:EXCLUDE_FROM_ALL表示子目录目标不加入默认构建(需手动指定构建)。
    3. 设置安装路径
    # 安装可执行文件到指定目录
    INSTALL(TARGETS app_name
        RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
        # 可执行文件安装路径
        LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
        # 动态库安装路径(Unix)
        ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
        # 静态库安装路径(Unix)
    )
    # 安装头文件
    INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/app.h
        DESTINATION ${CMAKE_INSTALL_PREFIX}/include
    )
    
    • 作用:指定目标文件/头文件的安装路径,执行make install时自动拷贝文件到对应目录。
    • 常用参数:
      • RUNTIME:可执行文件(Windows下的.exe、Unix下的可执行程序);
      • LIBRARY:共享库(.so/.dylib);
      • ARCHIVE:静态库(.a)。

    总结

    以上命令覆盖了CMake从基础配置、变量操作、编译构建到安装部署的核心场景:

    • 基础配置:cmake_minimum_required、project 是每个CMakeLists.txt的必选开头;
    • 现代CMake推荐:优先使用target_*系列命令(如target_include_directories、target_link_libraries)替代全局命令,降低耦合;
    • 调试技巧:通过message(STATUS)打印变量值,排查路径、依赖等问题;
    • 安装部署:INSTALL命令配合CMAKE_INSTALL_PREFIX实现跨平台的安装路径控制。

    目录

    1. cmake与makefile的区别
    2. CMake 常用命令详解
    3. 基础配置命令
    4. 1. 指定CMake最低版本
    5. 2. 设置项目名称
    6. 变量操作命令
    7. 1. 普通变量定义与赋值
    8. 单值赋值
    9. 多值赋值(列表形式)
    10. 设置C++标准(核心常用)
    11. 2. 列表操作(添加元素)
    12. 初始化空列表
    13. 向列表追加元素
    14. 3. 预定义核心变量
    15. 4. 字符串替换
    16. 编译构建命令
    17. 1. 添加头文件搜索路径
    18. 2. 查找目录下的所有源码文件
    19. 3. 添加可执行目标
    20. 4. 链接库文件
    21. 流程控制命令
    22. 1. 文件存在性判断
    23. 2. 循环遍历
    24. 3. 打印日志/错误
    25. 普通状态提示(编译时输出,不中断)
    26. 警告提示(黄色输出,不中断)
    27. 致命错误(红色输出,中断编译)
    28. 高级操作命令
    29. 1. 执行自定义命令
    30. 2. 添加子目录(嵌套CMake)
    31. 3. 设置安装路径
    32. 安装可执行文件到指定目录
    33. 安装头文件
    34. 总结
    • 💰 8折买阿里云服务器限时8折了解详情
    • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
    • 代充Chatgpt Plus/pro 帐号了解详情
    • 🤖 一键搭建Deepseek满血版了解详情
    • 一键打造专属AI 智能体了解详情
    极客日志微信公众号二维码

    微信扫一扫,关注极客日志

    微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

    更多推荐文章

    查看全部
    • C++ 入门进阶:引用、内联函数与 nullptr 详解
    • C++ 入门进阶:引用、内联函数与 nullptr 详解
    • Java transient 关键字详解与 Flink State 实践
    • OpenClaw 及主流 AI Agent 框架横评与场景推荐
    • Spring AI 框架核心特性与实战指南
    • 前端练习:使用 Three.js 实现星辰宇宙效果
    • Visual C++ 运行库安装失败常见场景与解决方案
    • AI 深度早报:GTC 开幕,Agent 平台与具身智能技术突破
    • 深入剖析 Linux 文件系统数据结构实现机制
    • CISP 认证适用职位及含金量深度解析
    • 与模型对话:理解并预防 ChatGPT 中的常见误解
    • 基于 WebRTC+AI 的智能远程控制解决方案
    • Whisper-WebUI 语音转文字工具搭建与功能解析
    • Mixtral 8X7B Instruct v0.1 llamafile 部署与应用实战指南
    • Agent Memory 相关文献追踪:异构存储与经验记忆
    • OpenClaw 实战部署:从服务器配置到 AI 员工养成指南
    • OSCP 实战:Net-NTLMv2 哈希传递与中继攻击详解
    • OpenAI 文生视频大模型 Sora 技术深度解析
    • Python 调用高德地图 MCP 服务查询天气示例
    • VS Code 切换或退出 GitHub Copilot 账号指南

    相关免费在线工具

    • Base64 字符串编码/解码

      将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

    • Base64 文件转换器

      将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

    • Markdown转HTML

      将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

    • HTML转Markdown

      将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

    • JSON 压缩

      通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

    • JSON美化和格式化

      将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online