CMake、make、GCC 是什么关系?

你可能在 Qt Creator 里见过 CMake,在 Linux 教程里见过 make,在安装说明里见过 GCC。

它们到底是什么关系?

一句话:

CMake 生成构建文件,make 执行构建,GCC 真正编译代码

先看关系图

你写代码 (main.cpp)
      ↓
CMake 读取 CMakeLists.txt
      ↓
生成 Makefile(或其他构建文件)
      ↓
make 读取 Makefile
      ↓
调用 GCC/编译器
      ↓
生成 exe

一句话分清三者

工具角色一句话
CMake元构建系统生成 Makefile 的跨平台工具
make构建工具读取 Makefile,调用编译器
GCC编译器把代码变成机器码

用最土的比喻

CMake = 写菜谱的人
Makefile = 菜谱
make = 按菜谱做菜的厨师
编译器 (GCC) = 火和锅

详细区别

1. CMake 是干嘛的?

跨平台元构建系统

CMake 不是编译器,不是构建工具 —— 它是生成构建系统的工具。

  • 输入:CMakeLists.txt
  • 输出:Makefile、Ninja build.ninja、Visual Studio 解决方案等
  • 特点:不直接编译代码,只生成平台相关的构建文件
# CMakeLists.txt 示例
cmake_minimum_required(VERSION 3.16)
project(MyApp)

add_executable(myapp main.cpp utils.cpp)

CMake 读取这个文件,根据平台生成对应的构建文件。

CMake 的核心价值

问题直接写 Makefile用 CMake
跨平台每个平台写一份CMakeLists.txt 通用
复杂依赖手写很痛苦CMake 自动处理
可读性Makefile 语法晦涩CMake 更直观
IDE 支持需手动配置自动生成 IDE 项目文件

Out-of-Source Builds(重要)

CMake 推荐源外构建(Out-of-Source Build):

# 创建独立构建目录
mkdir build
cd build

# 从构建目录运行 CMake
cmake ..

好处

  • 构建产物不污染源代码目录
  • 可以创建多个构建目录(Debug、Release、不同编译器)
  • 清理构建只需删除 build 目录

2. make 是干嘛的?

构建执行工具

  • 只认 Makefile
  • 解析依赖关系
  • 调用编译器(g++/clang/MSVC)
  • 只重新编译修改过的文件(增量构建)
# 运行 make
make
# make 会读取 Makefile,执行编译命令

# 清理构建产物
make clean

make 的核心机制

Makefile 规则格式:
target: prerequisites
	command

例如:
main.o: main.cpp header.h
	g++ -c main.cpp -o main.o

含义:要构建 main.o,需要 main.cppheader.h,然后执行 g++ 命令。

3. GCC 是什么?

GNU Compiler Collection(GNU 编译器套装)

  • gcc:编译 C 语言
  • g++:编译 C++(Qt 用的就是这个)
  • 支持多种架构:x86、ARM、RISC-V 等

GCC 编译过程

源文件 (.cpp)
    ↓
预处理 (.i) - 处理 #include、#define
    ↓
编译 (.s) - 生成汇编代码
    ↓
汇编 (.o) - 生成目标文件
    ↓
链接 (exe) - 链接库文件,生成可执行文件

现代构建:CMake + Ninja

在 2026 年,越来越多的项目使用 Ninja 替代 make:

CMake 生成
    ↓
Ninja 构建文件 (build.ninja)
    ↓
ninja 执行构建
    ↓
GCC/Clang 编译

Ninja 优势

  • 速度更快(专注于并行构建)
  • 语法更简洁
  • 大项目(如 Chrome、LLVM)都在用

真实执行顺序

传统方式(make)

1. 写 CMakeLists.txt
2. mkdir build && cd build
3. cmake ..       # 生成 Makefile
4. make           # 编译
5. ./myapp        # 运行

现代方式(Ninja)

1. 写 CMakeLists.txt
2. mkdir build && cd build
3. cmake -G Ninja ..  # 生成 build.ninja
4. ninja               # 编译(更快)
5. ./myapp            # 运行

Qt Creator 自动化

你用 Qt Creator 点"运行",内部自动帮你:

1. 运行 CMake 配置
2. 运行 make/ninja 编译
3. 运行程序

你看不到中间过程,但顺序不变。

常见编译器对照

编译器用途常见平台特点
gcc编译 CLinux/WSLGNU 项目标配
g++编译 C++Linux/WSLQt 开发常用
clang编译 C/C++macOS/现代 Linux错误信息更友好
cl.exe编译 C/C++Windows (MSVC)Visual Studio 内置
MinGWWindows 移植版 GCCWindows不需要 VS

完整工具链全景

现在你之前学的一串工具可以串起来了:

源代码 (main.cpp)
      ↓
CMake(生成构建文件)
      ↓
Makefile / build.ninja
      ↓
make / ninja(调度编译)
      ↓
GCC/g++/Clang(真正编译)
      ↓
可执行文件 (exe)
      ↓
调试器运行
      ↓
运行环境加载

实战示例

Linux/WSL 下从零编译 C++ 程序

# 1. 创建项目目录
mkdir myproject && cd myproject

# 2. 写 CMakeLists.txt
cat > CMakeLists.txt << 'EOF'
cmake_minimum_required(VERSION 3.16)
project(MyApp)
set(CMAKE_CXX_STANDARD 17)
add_executable(myapp main.cpp)
EOF

# 3. 写 main.cpp
cat > main.cpp << 'EOF'
#include <iostream>
int main() {
    std::cout << "Hello from CMake + make + GCC!" << std::endl;
    return 0;
}
EOF

# 4. 源外构建
mkdir build && cd build

# 5. 生成 Makefile
cmake ..

# 6. 编译
make

# 7. 运行
./myapp

使用 Ninja 加速

# 只需更改生成器
cmake -G Ninja ..
ninja

对于大型项目,Ninja 可以比 make 快很多。

超简总结(背这三句)

CMake 生成构建文件(Makefile 或 Ninja)
make/Ninja 执行构建文件,调用编译器
GCC/g++/Clang 真正把代码编译成机器码

总结

工具角色比喻
CMake生成构建规则写施工图纸
make/Ninja按规则指挥包工头
GCC/g++真正干活搬砖工人

理解了这三层关系,你就理解了整个 C/C++ 构建体系的核心。


参考资料