首页 > 其他分享 >CMake 入门教程: 从基础到实践

CMake 入门教程: 从基础到实践

时间:2025-01-16 20:33:05浏览次数:3  
标签:exe cmake CXX 入门教程 实践 build CMake main

什么是 CMake?

CMake(全称为 “Cross-Platform Make”)是一种免费并开源的跨平台构建工具, 用于生成构建系统文件(如 Makefile 和 Visual Studio 工程文件), 从而控制软件的编译和链接过程.

为什么选择 CMake?

CMake 为项目工程解决了以下问题:

  • 跨平台构建: 支持为多种平台生成配置文件, 如 Linux 上的 Makefile 和 Windows 上的 Visual Studio 工程.
  • 适用于复杂项目: 便于管理含有多个子项目和层级的大型工程.
  • 自动化和通用配置: 通过 CMakeLists.txt 文件轻松管理依赖和配置, 大幅简化流程.

无论是管理小型项目还是大型复杂工程, CMake 都是现代 C++ 开发中不可或缺的工具.


Modern CMake 的崛起

随着 CMake 的发展, “Modern CMake” 的概念逐渐兴起, 以简洁和模块化的方式管理项目配置, 避免传统 CMake 脚本中的复杂性.

Modern CMake 的特点

  1. 目标驱动构建:
    使用 target 概念, 清晰地管理目标(如可执行文件或库)及其属性.

    add_library(my_library src1.cpp src2.cpp)
    target_include_directories(my_library PUBLIC include/)
    target_link_libraries(my_library PRIVATE other_library)
    
  2. 接口与私有依赖管理:
    通过 PUBLIC, PRIVATEINTERFACE 明确依赖范围, 避免全局污染.

  3. 模块化设计:
    使用 find_packageFetchContent 管理第三方依赖, 无需手动设置路径.

    include(FetchContent)
    FetchContent_Declare(
        googletest
        URL https://github.com/google/googletest/archive/refs/tags/release-1.12.1.zip
    )
    FetchContent_MakeAvailable(googletest)
    
  4. 生成器表达式:
    简化复杂逻辑表达式, 提高脚本可读性和灵活性.

Modern CMake 极大改进了使用体验, 使其更适应当代软件工程的需求.


CMake 在现代 C++ 生态中的位置

社区支持与流行应用

  • 广泛支持: 许多开源项目(如 LLVM, Qt 和 OpenCV)选择 CMake 作为首选构建工具.
  • 工具集成: 与包管理工具(如 Conan 和 vcpkg)深度集成, 简化依赖管理.
  • 适应性强: 从小型库到大型复杂项目, CMake 都能高效管理.

与主流 IDE 的无缝集成

  • Visual Studio: 内置支持, 用户可直接打开 CMakeLists.txt 文件.
  • CLion: JetBrains CLion 将 CMake 作为默认构建系统, 提供出色的开发体验.
  • Xcode: 支持生成适配 macOS 的工程文件.
  • VSCode: 通过 CMake Tools 插件, 提供调试, 配置和目标管理功能.

安装 CMake

使用包管理器安装 CMake

  1. Ubuntu/Debian:

    sudo apt update
    sudo apt install cmake
    
  2. CentOS/RHEL:

    sudo yum install epel-release
    sudo yum install cmake
    
  3. macOS:

    brew install cmake
    
  4. Windows:

    • 使用 winget 安装:
      winget 是微软提供的一个包管理工具, 作用类似Ubuntu上的apt.

      winget install -e --id Kitware.CMake
      
    • 手动下载: 访问 CMake 官方下载页面.

从源码安装

当需要最新功能或修复时, 可以从源码安装:

步骤 1: 下载源码

访问 CMake 官网下载页面, 选择最新版本的源码压缩包, 并下载.

例如, 得到 cmake-3.xx.x.tar.gz 文件.

步骤 2: 解压

在命令行中执行:

tar -xzvf cmake-3.xx.x.tar.gz
cd cmake-3.xx.x
步骤 3: 构建并安装
./bootstrap
make
sudo make install

这里:

  • ./bootstrap 用于初始化构建环境.
  • make 进行源码编译.
  • sudo make install 将构建的 CMake 安装到系统.

确认安装成功

在命令行执行以下命令:

cmake --version

应显示安装的版本信息:

cmake version 3.xx.x

如果显示最新版本, 则说明安装成功.

通过连续升级和选择适合版本, 从源码构建可以确保项目最大限度地适配项目构建需求.

样例一: 构建 Hello World

1. 创建项目文件

创建一个目录demo, 包含如下文件:

demo/
├── CMakeLists.txt
└── main.cpp
代码
  1. main.cpp:

    #include <iostream>
    
    int main() {
      std::cout << "Hello, CMake!" << std::endl;
      return 0;
    }
    
  2. CMakeLists.txt

    # 设置最低的 CMake 版本
    cmake_minimum_required(VERSION 3.10)
    
    # 定义项目名称和语言
    project(CMakeDemo CXX)
    
    # 设置 C++ 标准
    set(CMAKE_CXX_STANDARD 11)
    set(CMAKE_CXX_STANDARD_REQUIRED True)
    
    # 添加可执行文件
    add_executable(demo.exe main.cpp)
    

    需要注意的是 cmake_minimum_required 是第一句, 必须要指定最低版本要求. 其他的语句则是非常直白的, 命令本身就很清晰.

2. 创建构建目录

创建一个目录用来做构建目录, 即存放编译过程中的临时文件以及最后生成的二进制文件. 这个目录可以任选, 为了符合大多数人用的惯例, 我们就在demo目录下创建一个 build 文件夹.

mkdir build

3. Configure 项目

进入build目录并执行:

cd build
cmake ..

我们将会看到有如下的输出:

-- The CXX compiler identification is GNU 13.3.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (0.8s)
-- Generating done (0.0s)
-- Build files have been written to: /home/aronic/playground/CSDNBlogSampleCode/cmake/build

这一步通常被称为"生成项目文件"(Generating Project Files). 在这一步我们可以指定 CMake 生成何种项目, 可以是下面之一:

  1. Unix Makefiles(Linux 默认的生成工具)
  2. Ninja: 跨平台构建工具
  3. Visual Studio 17 2022: 适合 Windows Visual Studio 使用

可以通过-G命令指定.

4. Build 项目

cmake --build .

我们将会看到

[ 50%] Building CXX object CMakeFiles/demo.exe.dir/main.cpp.o
[100%] Linking CXX executable demo.exe
[100%] Built target demo.exe

构建成功之后我们会看到有一个二进制文件demo.exe.
执行该程序:

./demo.exe

输出

Hello, CMake!

样例二: 区分 Debug 版本和 Release 版本

在编译项目的时候通常我们会编译两个版本:

  1. Debug 版本: 适合调试, 测试, 保留符合(代码行数)
  2. Release 版本: 适合在生产环境运行或者发布. 通常会进行优化.

更新CMakeLists.txt, 将其内容改为:

# 设置最低的 CMake 版本
cmake_minimum_required(VERSION 3.10)

# 定义项目名称和版本
project(CMakeDemo VERSION 1.0)

# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# 为不同的编译类型设置编译选项
# Debug 模式下开启调试信息和额外警告
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra -DDEBUG")

# Release 模式下开启优化
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")

# 输出当前的编译类型(仅用于调试)
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")

# 添加可执行文件
add_executable(demo.exe main.cpp)

main.cpp改为:

#include <iostream>

int main() {
#ifdef DEBUG
  std::cout << "Running in Debug mode" << std::endl;
#else
  std::cout << "Running in Release mode" << std::endl;
#endif
  return 0;
}

Configure 项目

为了区分不同编译类型, 需要在生成项目的时候指定编译类型CMAKE_BUILD_TYPE:

  1. 编译 Debug 版本

    cmake -DCMAKE_BUILD_TYPE=Debug ..
    
  2. 编译 Release 版本

    cmake -DCMAKE_BUILD_TYPE=Release ..
    

编译并运行

在选定了编译类型之后, 可以开始编译, 编译步骤与上一节一致.

# 编译
cmake --build .

# 运行
./demo.exe

Debug版本将会输出:

Running in Debug mode

Release版本将会输出

Running in Release mode

样例三: 链接第三方库

如果我们需要使用一些第三方库来完成一个功能, 比如音视频编解码, 访问 HTTP API, 解析json等等. 在 CMake 中集成第三方库是很方便的, 下面这个例子中我们使用了fmt库, 用来方便的输出容器.

main.cpp文件

#include <fmt/core.h>
#include <fmt/ranges.h>

#include <iostream>
#include <map>
#include <vector>

int main() {
  std::vector<int> vec{1, 2, 3, 4, 5};
  std::map<std::string, std::string> table = {{"name", "cmake"},
                                              {"function", "build"}};

  fmt::println("vec is: {}", vec);
  fmt::println("table is: {}", table);
  return 0;
}

CMakeLists.txt文件为:

# 设置最低的 CMake 版本
cmake_minimum_required(VERSION 3.10)

# 定义项目名称和其使用语言
project(CMakeDemo CXX)

# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# 查找 fmt 库
find_package(fmt CONFIG REQUIRED)

# 添加可执行文件
add_executable(demo.exe main.cpp)
# 链接 fmt 库
target_link_libraries(demo.exe PRIVATE fmt::fmt)

Configure 项目

mkdir build
cd build
cmake ..

编译并运行

# 编译
cmake --build .

# 运行
./demo.exe

输出:

vec is: [1, 2, 3, 4, 5]
table is: {"function": "build", "name": "cmake"}

样例四: 单元测试

测试代码是实际工程中不可缺少的内容. CMake 提供了对测试的支持, 可以使用ctest命令来执行所有测试样例.

  1. 测试文件test.cpp:
#include <gtest/gtest.h>

// 示例测试用例
TEST(SampleTest, Addition) { EXPECT_EQ(1 + 1, 2); }

TEST(SampleTest, Multiplication) { EXPECT_EQ(2 * 3, 6); }
  1. CMakeLists.txt

此处我们使用了FetchContent来获取第三方库. CMake 会自动下载并编译.

# 设置最低的 CMake 版本
cmake_minimum_required(VERSION 3.28)

# 定义项目名称和其使用语言
project(CMakeDemo CXX)

# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

enable_testing()
# FetchContent 模块
include(FetchContent)

# 添加 Google Test
FetchContent_Declare(
    googletest
    URL https://github.com/google/googletest/archive/refs/heads/main.zip
)
FetchContent_MakeAvailable(googletest)

# 设置编译选项, 避免在构建测试时污染主工程的设置
set(GTEST_SHUFFLE 1)

# 创建测试可执行文件
add_executable(test.exe test.cpp)

# 链接 Google Test 库
target_link_libraries(test.exe PRIVATE gtest gtest_main)

# 添加测试到 CTest
add_test(NAME test.exe COMMAND test.exe)

Configure 项目

mkdir build
cd build
cmake ..

编译并运行

cmake --build .

编译输出

[ 10%] Building CXX object _deps/googletest-build/googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o
[ 20%] Linking CXX static library ../../../lib/libgtest.a
[ 20%] Built target gtest
[ 30%] Building CXX object _deps/googletest-build/googletest/CMakeFiles/gtest_main.dir/src/gtest_main.cc.o
[ 40%] Linking CXX static library ../../../lib/libgtest_main.a
[ 40%] Built target gtest_main
[ 50%] Building CXX object CMakeFiles/test.exe.dir/test.cpp.o
[ 60%] Linking CXX executable test.exe
[ 60%] Built target test.exe
[ 70%] Building CXX object _deps/googletest-build/googlemock/CMakeFiles/gmock.dir/src/gmock-all.cc.o
[ 80%] Linking CXX static library ../../../lib/libgmock.a
[ 80%] Built target gmock
[ 90%] Building CXX object _deps/googletest-build/googlemock/CMakeFiles/gmock_main.dir/src/gmock_main.cc.o
[100%] Linking CXX static library ../../../lib/libgmock_main.a
[100%] Built target gmock_main

执行测试:

./test.exe

输出

[==========] Running 2 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 2 tests from SampleTest
[ RUN      ] SampleTest.Addition
[       OK ] SampleTest.Addition (0 ms)
[ RUN      ] SampleTest.Multiplication
[       OK ] SampleTest.Multiplication (0 ms)
[----------] 2 tests from SampleTest (0 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 1 test suite ran. (0 ms total)
[  PASSED  ] 2 tests.

总结

CMake 是现代 C++ 构建的基石, 凭借其跨平台能力, 灵活性和强大生态, 成为开源社区和企业的首选构建工具. 从基础到进阶, 学习 CMake 将帮助开发者显著提升构建效率.


学习资源

源码链接

源码链接

标签:exe,cmake,CXX,入门教程,实践,build,CMake,main
From: https://blog.csdn.net/arong_xu/article/details/145123224

相关文章

  • RSA的原理和简单实践
    RSA加密是一种非对称加密,原理是:使⽤算法可以⽣成两把钥匙A和B使⽤A加密的信息,使⽤B可以解开使⽤B加密的信息,使⽤A可以解开⽇常使⽤中,我们把⼀把作为公钥公开发布。⼀把作为私钥,⾃⼰保留。这样,任何⼈都可以使⽤我们的公钥加密信息发给我们,我们则可以使⽤⾃⼰的私......
  • 解决cmake编译时*ui,*h存放在不同文件夹下时*.ui无法生成ui_*.h问题
    使用的Qt版本为6.8.1,cmake版本为3.31.0-rc1。遇到问题原因原本的目录结构比较乱,代码文件一多就很不好找,在对文件进行分类管理的过程中发现*ui文件无法生成ui_*.h有问题部分的cmake本来想使用qt_wrap_ui和set(CMAKE_AUTOUICON)让他自动生成ui_*.h的,但是失败了cmake_minimum_......
  • Python生成成绩报告单:从理论到实践
    在教育信息化日益普及的今天,自动化生成和处理学生成绩报告单已成为学校和教育机构的一项重要任务。Python作为一种功能强大且易于学习的编程语言,非常适合用于这种数据处理和报告生成任务。本文将详细介绍如何使用Python生成成绩报告单,包括理论概述和完整的代码示例。一、理论概述......
  • 如何让项目进度一目了然?办公可视化工具的最佳实践
    在数字化办公浪潮中,信息的快速流转与精准解读成为提升竞争力的关键要素。办公可视化工具应运而生,它宛如一座桥梁,跨越了数据的繁杂海洋,将晦涩难懂的数据转化为直观易懂的视觉呈现。从项目管理角度来看,可视化工具能够将项目进度、任务分配等关键信息以清晰的图表、看板形式展现,让团......
  • 20221320 冯泰瑞 《信息安全综合实践》课程设计报告——基于文本文件信息隐藏和二值图
    20221320冯泰瑞《信息安全综合实践》课程设计报告——基于文本文件信息隐藏和二值图像信息隐藏的回声信息隐藏算法实现任务简介隐藏原理研究发现,HAS(HumanAudioSystem,人类听觉系统)存在感知掩蔽效应,即强信号的存在会使其附近的弱信号难以被感知。因此,当回声与原声的间隔充分......
  • 利用Python按关键字搜索阿里巴巴商品:代码示例与实践指南
    在电商领域,能够快速获取商品信息对于市场分析、选品上架、库存管理和价格策略制定等至关重要。阿里巴巴作为全球最大的电商平台之一,提供了丰富的商品数据。虽然阿里巴巴开放平台提供了官方API来获取商品信息,但有时使用爬虫技术来抓取数据也是一种有效的手段。本文将介绍如何利......
  • 探秘AutoGen框架:从入门到实践的全攻略(25/30)
    一、引言在人工智能技术日新月异的当下,多智能体协作与大型语言模型(LLM)的应用日益广泛。微软推出的AutoGen框架,犹如一颗璀璨的新星,为开发者们提供了一个强大的工具,以实现高效的多智能体对话和复杂任务的自动化处理。AutoGen框架致力于简化多智能体系统的开发过程,使开发者能......
  • 计算机毕业设计Springboot毕业学员志愿填报系统设计与实现 基于SpringBoot的毕业生志
    计算机毕业设计Springboot毕业学员志愿填报系统设计与实现f710g1r7(配套有源码程序mysql数据库论文)本套源码可以先看具体功能演示视频领取,文末有联xi可分享随着互联网技术的飞速发展,传统的毕业学员志愿填报方式已逐渐无法满足现代社会的需求。纸质填报不仅效率低下,而且容......
  • 基于Vector工具进行CAN协议错误帧的分析实践
    引言  CAN(ControllerAreaNetwork)协议是当前使用最普遍的车载通信协议之一,其优点不只体现在多主并行、最高达1Mbit/sec的传输速率(针对标准CAN)、基于优先级的仲裁机制以及广播发送的短帧结构,还体现在其错误检测机制上。通过总线数据以及总线波形来分析总线故障时,CAN协议错误......
  • 【大模型实战指南】AI大模型学习路线:从理论到实践,全面提升核心竞争力!
    一、初聊大模型1、什么是大模型?大模型,通常指的是在人工智能领域中的大型预训练模型。你可以把它们想象成非常聪明的大脑,这些大脑通过阅读大量的文本、图片、声音等信息,学习到了世界的知识。这些大脑(模型)非常大,有的甚至有几千亿个参数,这些参数就像是大脑中的神经元,它们通过......