XIAOZHAO·代码与日常
首页归档照片墙音乐说说留言友链关于后台

Cmake编译工程文件

2026/06/19 07:32开发#Cmake126 阅读

CMake 编译工程入门教程

1. CMake 是什么

CMake 不是编译器,它是一个“工程构建配置工具”。

简单理解:

  • GCC、Clang、MSVC 才是真正负责把代码编译成可执行文件的工具。
  • Make、Ninja、Visual Studio 工程文件负责执行具体编译过程。
  • CMake 负责根据 CMakeLists.txt 自动生成这些构建文件。

也就是说,CMake 的作用是:

C/C++ 源码
   ↓
CMakeLists.txt
   ↓
cmake 生成构建系统
   ↓
make / ninja / msbuild 编译
   ↓
生成可执行文件或库文件

2. 最简单的 CMake 工程结构

假设我们要创建一个最简单的 C 工程:

hello_cmake/
├── CMakeLists.txt
└── main.c

其中:

  • CMakeLists.txt:CMake 工程配置文件
  • main.c:程序源码文件

3. 编写 main.c

在工程目录下创建 main.c:

#include <stdio.h>

int main(void)
{
    printf("Hello CMake!\n");
    return 0;
}

4. 编写 CMakeLists.txt

在工程目录下创建 CMakeLists.txt:

cmake_minimum_required(VERSION 3.16)

project(hello_cmake C)

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)

add_executable(hello_cmake main.c)

说明:

cmake_minimum_required(VERSION 3.16)

表示当前工程最低需要 CMake 3.16。

project(hello_cmake C)

表示工程名叫 hello_cmake,使用 C 语言。

set(CMAKE_C_STANDARD 11)

表示使用 C11 标准。

add_executable(hello_cmake main.c)

表示把 main.c 编译成一个可执行文件,名字叫 hello_cmake。


5. 编译工程

进入工程目录:

cd hello_cmake

创建构建目录:

mkdir build
cd build

执行 CMake 配置:

cmake ..

开始编译:

cmake --build .

运行程序:

./hello_cmake

如果看到:

Hello CMake!

说明工程编译成功。


6. 为什么要新建 build 目录

推荐使用这种方式:

hello_cmake/
├── CMakeLists.txt
├── main.c
└── build/

这样做叫“外部构建”。

好处是:

  • 源码目录保持干净。
  • 编译生成的中间文件都在 build 目录。
  • 删除 build 目录就可以重新开始编译。
  • 不会污染源码文件夹。

如果想清理工程,直接删除 build 文件夹即可:

rm -rf build

7. 多文件工程

实际项目通常不止一个 .c 文件。

例如:

multi_file_project/
├── CMakeLists.txt
├── main.c
├── led.c
└── led.h

7.1 main.c

#include <stdio.h>
#include "led.h"

int main(void)
{
    led_init();
    led_on();

    printf("LED is on\n");

    return 0;
}

7.2 led.h

#ifndef LED_H
#define LED_H

void led_init(void);
void led_on(void);
void led_off(void);

#endif

7.3 led.c

#include <stdio.h>
#include "led.h"

void led_init(void)
{
    printf("LED init\n");
}

void led_on(void)
{
    printf("LED on\n");
}

void led_off(void)
{
    printf("LED off\n");
}

7.4 CMakeLists.txt

cmake_minimum_required(VERSION 3.16)

project(multi_file_project C)

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)

add_executable(multi_file_project
    main.c
    led.c
)

这里需要把所有参与编译的 .c 文件都写进去。

.h 文件一般不需要写进 add_executable(),因为头文件会通过 #include 被源文件引用。


8. 使用 include 目录

如果头文件单独放在 include 文件夹中,工程结构可以这样:

project/
├── CMakeLists.txt
├── src/
│   ├── main.c
│   └── led.c
└── include/
    └── led.h

这时 CMakeLists.txt 可以写成:

cmake_minimum_required(VERSION 3.16)

project(my_project C)

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)

add_executable(my_project
    src/main.c
    src/led.c
)

target_include_directories(my_project PRIVATE
    include
)

说明:

target_include_directories(my_project PRIVATE include)

表示告诉编译器:

编译 my_project 的时候,到 include 目录里找头文件。

这样源码里就可以写:

#include "led.h"

而不需要写:

#include "../include/led.h"

9. 生成静态库

有时候我们希望把某些模块编译成库文件。

例如:

library_project/
├── CMakeLists.txt
├── src/
│   ├── main.c
│   └── led.c
└── include/
    └── led.h

可以把 led.c 编译成静态库:

cmake_minimum_required(VERSION 3.16)

project(library_project C)

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)

add_library(led STATIC
    src/led.c
)

target_include_directories(led PUBLIC
    include
)

add_executable(app
    src/main.c
)

target_link_libraries(app PRIVATE
    led
)

说明:

add_library(led STATIC src/led.c)

生成一个名为 led 的静态库。

target_link_libraries(app PRIVATE led)

表示可执行程序 app 需要链接 led 这个库。


10. Debug 和 Release 编译

CMake 常见构建类型有:

  • Debug:调试版本,包含调试信息,优化较少。
  • Release:发布版本,优化较高,运行速度更快。

10.1 Debug 编译

cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build

10.2 Release 编译

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build

其中:

-S .

表示源码目录是当前目录。

-B build

表示构建目录是 build。

这种写法比先 cd build 更清晰。


11. 指定编译器

有时候系统里有多个编译器,可以手动指定。

11.1 指定 GCC

cmake -S . -B build -DCMAKE_C_COMPILER=gcc
cmake --build build

11.2 指定 Clang

cmake -S . -B build -DCMAKE_C_COMPILER=clang
cmake --build build

C++ 工程还可以指定:

-DCMAKE_CXX_COMPILER=g++

或者:

-DCMAKE_CXX_COMPILER=clang++

12. C++ 工程示例

工程结构:

cpp_project/
├── CMakeLists.txt
└── main.cpp

12.1 main.cpp

#include <iostream>

int main()
{
    std::cout << "Hello CMake C++!" << std::endl;
    return 0;
}

12.2 CMakeLists.txt

cmake_minimum_required(VERSION 3.16)

project(cpp_project CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(cpp_project main.cpp)

编译:

cmake -S . -B build
cmake --build build

运行:

./build/cpp_project

13. 常用 CMake 命令总结

13.1 配置工程

cmake -S . -B build

13.2 编译工程

cmake --build build

13.3 指定 Debug 模式

cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug

13.4 指定 Release 模式

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release

13.5 清理重新编译

rm -rf build
cmake -S . -B build
cmake --build build

13.6 并行编译

cmake --build build -j

或者指定线程数:

cmake --build build -j8

14. 在 VS Code 中使用 CMake

推荐安装插件:

  • C/C++
  • CMake Tools

基本流程:

  1. 打开工程文件夹。
  2. 安装 CMake Tools 插件。
  3. 按 Ctrl + Shift + P。
  4. 输入 CMake: Configure。
  5. 选择编译器。
  6. 再执行 CMake: Build。
  7. 生成的程序一般在 build 目录中。

如果 VS Code 提示选择 Kit,可以选择:

GCC
Clang
MinGW
Visual Studio

根据你电脑上安装的编译器决定。


15. Windows 下使用 CMake

Windows 下常见编译器有:

  • MinGW-w64
  • MSVC,也就是 Visual Studio 自带编译器
  • Clang

15.1 使用 MinGW

cmake -S . -B build -G "MinGW Makefiles"
cmake --build build

15.2 使用 Visual Studio

cmake -S . -B build -G "Visual Studio 17 2022"
cmake --build build

生成的 .exe 文件一般在:

build/Debug/

或者:

build/Release/

16. Linux / Ubuntu 下使用 CMake

安装工具:

sudo apt update
sudo apt install build-essential cmake

检查版本:

gcc --version
cmake --version

编译:

cmake -S . -B build
cmake --build build
./build/hello_cmake

17. 嵌入式工程中的 CMake 思路

嵌入式项目也可以使用 CMake,例如 STM32、MSPM0、ESP32 等。

不过嵌入式工程通常需要额外配置:

  • 交叉编译器,例如 arm-none-eabi-gcc
  • 链接脚本,例如 STM32F103C8Tx_FLASH.ld
  • 启动文件,例如 startup_stm32f103xb.s
  • 编译选项,例如 CPU 内核、FPU、优化等级
  • 生成 .elf、.hex、.bin 文件

嵌入式 CMake 的流程大概是:

源码
  ↓
CMakeLists.txt
  ↓
arm-none-eabi-gcc 编译
  ↓
生成 .elf
  ↓
objcopy 转换
  ↓
生成 .hex / .bin
  ↓
下载到单片机

18. STM32 CMake 示例思路

一个 STM32 工程结构可以类似这样:

stm32_project/
├── CMakeLists.txt
├── STM32F103C8Tx_FLASH.ld
├── startup_stm32f103xb.s
├── Core/
│   ├── Inc/
│   │   └── main.h
│   └── Src/
│       └── main.c
└── Drivers/
    └── STM32F1xx_HAL_Driver/

CMake 中通常需要配置:

set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(CMAKE_C_COMPILER arm-none-eabi-gcc)
set(CMAKE_ASM_COMPILER arm-none-eabi-gcc)
set(CMAKE_OBJCOPY arm-none-eabi-objcopy)

然后设置 MCU 参数:

set(MCU_FLAGS
    -mcpu=cortex-m3
    -mthumb
)

再设置链接脚本:

set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/STM32F103C8Tx_FLASH.ld)

链接参数示例:

target_link_options(app.elf PRIVATE
    ${MCU_FLAGS}
    -T${LINKER_SCRIPT}
    -Wl,-Map=${PROJECT_NAME}.map
    -Wl,--gc-sections
)

最后生成 .hex 和 .bin:

add_custom_command(TARGET app.elf POST_BUILD
    COMMAND ${CMAKE_OBJCOPY} -O ihex app.elf ${PROJECT_NAME}.hex
    COMMAND ${CMAKE_OBJCOPY} -O binary app.elf ${PROJECT_NAME}.bin
)

19. 常见错误和解决方法

19.1 cmake: command not found

说明没有安装 CMake。

Ubuntu:

sudo apt install cmake

Windows:

需要安装 CMake,并把 CMake 加入环境变量。


19.2 No CMAKE_C_COMPILER could be found

说明没有找到 C 编译器。

Ubuntu:

sudo apt install build-essential

Windows:

需要安装 MinGW 或 Visual Studio。


19.3 CMakeLists.txt 找不到

如果执行:

cmake ..

报错找不到 CMakeLists.txt,说明你当前目录位置不对。

正确结构应该是:

project/
├── CMakeLists.txt
└── build/

然后在 build 目录中执行:

cmake ..

或者直接在工程根目录执行:

cmake -S . -B build

19.4 头文件找不到

错误类似:

fatal error: led.h: No such file or directory

解决方法是在 CMakeLists.txt 中添加头文件路径:

target_include_directories(app PRIVATE
    include
)

19.5 undefined reference to xxx

这个错误一般表示:

  • 函数声明了,但是没有实现。
  • 对应的 .c 文件没有加入编译。
  • 库文件没有链接。

例如 led_on() 在 led.c 中实现了,但是 CMakeLists.txt 只写了:

add_executable(app main.c)

这时应该改成:

add_executable(app
    main.c
    led.c
)

20. 推荐的 CMake 工程模板

普通 C 工程可以使用这个结构:

my_project/
├── CMakeLists.txt
├── README.md
├── include/
│   └── led.h
├── src/
│   ├── main.c
│   └── led.c
└── build/

推荐 CMakeLists.txt:

cmake_minimum_required(VERSION 3.16)

project(my_project C)

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)

add_executable(${PROJECT_NAME}
    src/main.c
    src/led.c
)

target_include_directories(${PROJECT_NAME} PRIVATE
    include
)

编译命令:

cmake -S . -B build
cmake --build build
./build/my_project

21. 学习建议

初学 CMake 时,不要一开始就写复杂工程。

建议按这个顺序学习:

  1. 单文件编译。
  2. 多 .c 文件编译。
  3. 添加头文件目录。
  4. 生成静态库。
  5. 链接第三方库。
  6. 区分 Debug 和 Release。
  7. 再学习交叉编译和嵌入式 CMake。

对于普通 C/C++ 项目,掌握下面几个命令基本就够用:

cmake_minimum_required()
project()
add_executable()
add_library()
target_include_directories()
target_link_libraries()
target_compile_options()
target_link_options()

22. 总结

CMake 的核心思想是:

用 CMakeLists.txt 描述工程结构,
再让 CMake 自动生成对应平台的构建文件。

最常用的编译流程是:

cmake -S . -B build
cmake --build build

最常用的工程配置是:

cmake_minimum_required(VERSION 3.16)

project(my_project C)

add_executable(my_project
    src/main.c
)

如果工程有头文件目录,就加:

target_include_directories(my_project PRIVATE
    include
)

如果工程有库,就加:

target_link_libraries(my_project PRIVATE
    library_name
)

视频教程请观看:Cmake管理工程_哔哩哔哩_bilibili

掌握这些内容后,就可以独立搭建大部分 C/C++ 的 CMake 编译工程。

评论

你爹2026/6/26 03:41:50

写这么长傻逼吧,当论文写呢?懒得喷啊

你爹2026/6/26 03:42:25

不过说实话,写的真牛逼

小赵

记录开发、设计和日常想法。

最近文章

苹果下载Shadowrocket2026/06/04 06:10API2026/06/04 01:53住宅IP2026/06/04 01:16Django Blog Template2026/05/02 10:29