CMake基础详解

学习目标

  • 理解 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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值