学习目标
- 理解 CMake 是什么、为什么需要它
- 掌握 CMakeLists.txt 的基本语法
- 能够构建简单的 C/C++ 项目
Day 1:CMake 是什么?
一句话理解 CMake
CMake = 项目构建工具,它根据你的配置文件(CMakeLists.txt)生成特定平台的项目文件(如 Makefile),然后用这些文件来编译代码。
为什么需要 CMake?
不用 CMake 的问题
想象一下:你写了一个 C++ 项目,有 100 个 .cpp 文件分布在不同目录,你要手动写 Makefile:
# 手动编写 Makefile - 繁琐易错
CC = g++
CFLAGS = -Wall -O2
INCLUDES = -I./include -I./src
SRCS = src/main.cpp src/utils.cpp src/calc.cpp ...
OBJS = $(SRCS:.cpp=.o)
TARGET = myapp
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(TARGET) $(OBJS)
问题:
❌ 每个平台要写不同的 Makefile(Windows 用 nmake,Linux 用 make)
❌ 手动管理文件依赖关系容易出错
❌ 添加/删除文件要手动更新 Makefile
❌ 大型项目 Makefile 非常复杂,难以维护
用 CMake 的解决方案
# CMakeLists.txt - 简洁直观
cmake_minimum_required(VERSION 3.16)
project(MyApp)
add_executable(myapp main.cpp utils.cpp calc.cpp)
一条命令生成项目并编译:
cmake -B build # 生成构建文件到 build 目录
cmake --build build # 执行构建
优势:
✓ 跨平台:同一套配置生成 Windows/Linux/macOS 的项目文件
✓ 自动处理依赖:CMake 自动分析文件依赖关系
✓ 易于维护:添加文件只需修改 CMakeLists.txt
✓ 功能强大:支持复杂项目的构建需求
CMake 工作原理图解
┌──────────────────┐
│ CMakeLists.txt │ ← 你写的构建配置
└────────┬─────────┘
│ cmake 命令
▼
┌──────────────────┐ 平台1 ┌──────────────────┐
│ CMake 生成器 │ ─────────────────────► │ Makefile │ (Linux/macOS)
│ │ ─────────────────────► │ .vcxproj │ (Windows)
│ 根据平台生成 │ ─────────────────────► │ .xcodeproj │ (macOS Xcode)
│ 对应的构建文件 │ └──────────────────┘
└──────────────────┘
然后用各平台的构建工具执行:
Linux/macOS: make -f Makefile
Windows: msbuild .vcxproj
安装 CMake
Windows 安装
# 方法1:从官网下载安装包
# https://cmake.org/download/
# 下载 cmake-3.x.x-windows-x86_64.msi 安装即可
# 方法2:使用 winget(推荐)
winget install Kitware.CMake
# 方法3:使用 Chocolatey
choco install cmake
# 验证安装
cmake --version
# CMake 3.28.1
Linux 安装
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install cmake
# CentOS/RHEL
sudo yum install cmake
# 验证
cmake --version
macOS 安装
# 方法1:使用 Homebrew(推荐)
brew install cmake
# 方法2:从官网下载 .dmg 安装包
# 验证
cmake --version
CMake GUI 工具
对于初学者,可以使用 CMake 的图形界面:
# 启动 CMake GUI
cmake-gui
# 或者命令行模式(更常用)
# 这是我们之后主要使用的方式
Day 2:CMakeLists.txt 基本结构
最小 CMake 项目
项目结构
hello/
├── CMakeLists.txt
└── main.cpp
源代码 main.cpp
// main.cpp
#include <iostream>
int main() {
std::cout << "Hello CMake!" << std::endl;
return 0;
}
CMakeLists.txt
# ============================================
# CMake 最小配置文件
# ============================================
# 1. 指定 CMake 最低版本(必须放在第一行)
# 作用:确保使用正确版本的 CMake 功能
cmake_minimum_required(VERSION 3.16)
# 2. 定义项目名称
# 格式:project(项目名)
# 这一行会定义一些变量,如 PROJECT_NAME、PROJECT_SOURCE_DIR
project(MyApp)
# 3. 生成可执行文件
# 格式:add_executable(目标名 源文件1 源文件2 ...)
# 目标名:生成的可执行文件名
# 源文件:要编译的 .cpp/.c 文件
add_executable(myapp main.cpp)
命令详解
cmake_minimum_required
# 指定 CMake 最低版本
# CMake 3.16 是一个较好的起点版本(2019年发布)
cmake_minimum_required(VERSION 3.16)
# 如果系统 CMake 版本低于要求,会报错
# FATAL: CMake version 3.15 or higher is required
为什么必须指定版本?
- 不同版本支持不同特性
- 确保团队成员使用兼容的版本
- 避免使用过时或不可用的功能
project
# 基本用法
project(MyApp)
# 完整用法(指定语言版本)
project(MyApp VERSION 1.0.0
DESCRIPTION "My Application"
LANGUAGES CXX)
# project() 会定义以下变量:
# - PROJECT_NAME = "MyApp"
# - PROJECT_SOURCE_DIR = 项目根目录
# - PROJECT_BINARY_DIR = 构建目录
# - MyApp_VERSION_MAJOR = 1
# - MyApp_VERSION_MINOR = 0
# - MyApp_VERSION_PATCH = 0
构建项目
# ============================================
# 标准构建流程(推荐:源码与构建分离)
# ============================================
# 1. 创建构建目录(不要在源码目录构建!)
mkdir build
cd build
# 2. 运行 CMake 生成构建文件
cmake ..
# 3. 编译项目
cmake --build .
# 或者简写
make
# 4. 运行程序
./myapp
# 输出:Hello CMake!
# ============================================
# 命令详解
# ============================================
# cmake ..
# ^ ^
# | 指向源码目录(上级目录)
# |
# 在当前目录(build)生成 Makefile
# cmake --build .
# 根据 Makefile 执行编译
# 常见错误:不要在源码目录构建!
# 在源码目录运行 cmake 会污染源码
CMake 常用变量
# 预定义变量
${PROJECT_NAME} # 项目名
${PROJECT_SOURCE_DIR} # 源码目录(CMakeLists.txt 所在目录)
${PROJECT_BINARY_DIR} # 构建目录(运行 cmake 的目录)
${CMAKE_SOURCE_DIR} # 最顶层 CMakeLists.txt 的源码目录
${CMAKE_BINARY_DIR} # 最顶层构建目录
# 系统信息
${CMAKE_SYSTEM_NAME} # 操作系统名(Linux、Darwin、Windows)
${CMAKE_CXX_COMPILER} # C++ 编译器路径
${CMAKE_C_COMPILER} # C 编译器路径
# 构建类型
${CMAKE_BUILD_TYPE} # Debug、Release、RelWithDebInfo、MinSizeRel
构建类型
# ============================================
# 指定构建类型
# ============================================
# Debug 模式(调试版本)
cmake -B build -DCMAKE_BUILD_TYPE=Debug
# 特点:包含调试信息,不优化,便于调试
# Release 模式(发布版本)
cmake -B build -DCMAKE_BUILD_TYPE=Release
# 特点:优化过的代码,用于生产环境
# RelWithDebInfo(带调试信息的发布版)
cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo
# MinSizeRel(最小体积版本)
cmake -B build -DCMAKE_BUILD_TYPE=MinSizeRel
Day 3:add_executable 与 add_library
生成可执行文件
# ============================================
# add_executable - 生成可执行文件
# ============================================
# 基本语法:
# add_executable(目标名 源文件1 [源文件2] ...)
# 单个源文件
add_executable(myapp main.cpp)
# 多个源文件
add_executable(myapp
main.cpp
utils.cpp
config.cpp
)
# 使用变量(更灵活)
set(SOURCES
main.cpp
utils.cpp
config.cpp
math.cpp
)
add_executable(myapp ${SOURCES})
# 使用通配符(方便但不够精确)
file(GLOB SOURCES "src/*.cpp")
add_executable(myapp ${SOURCES})
生成库文件
# ============================================
# add_library - 生成库文件
# ============================================
# 库类型:
# STATIC - 静态库(.a 或 .lib),编译时链接
# SHARED - 动态库/共享库(.so 或 .dll),运行时加载
# MODULE - 插件式动态库,不能链接,只能运行时加载
# 生成静态库
add_library(mylib STATIC utils.cpp)
# 生成:libmylib.a
# 生成动态库
add_library(mylib SHARED utils.cpp)
# Linux 生成:libmylib.so
# Windows 生成:libmylib.dll
# macOS 生成:libmylib.dylib
# 生成动态库(简化写法)
add_library(mylib SHARED utils.cpp)
# 默认生成类型取决于平台
# Linux: STATIC
# Windows: SHARED
完整示例:多文件项目
项目结构
calc/
├── CMakeLists.txt
├── main.cpp
├── add.cpp
├── add.h
├── sub.cpp
├── sub.h
├── mul.cpp
└── mul.h
头文件
// add.h

1025

被折叠的 条评论
为什么被折叠?



