跳转至

编译进阶

C++构建系统与Vscode工作流

引言

为什么需要构建系统

在开发复杂的C++项目时,手动编译多个源文件和外部库既耗时又容易出错。构建系统自动化了从源代码到可执行文件的转化过程,确保构建的一致性和可重现性。它能管理依赖关系、编译选项、库链接等复杂任务,提高开发效率,减少人为错误,并支持复杂项目的管理。

本教程的目标读者

本教程适合对C/C++开发有一定了解的程序员,尤其是那些希望掌握现代构建工具(如Make和CMake),并在VSCode中进行配置和调试的开发者。我们将帮助你解决在VSCode中常见的问题,使你的开发环境更高效、更稳定。

Make 基础

什么是 Make

Make 是一个自动化构建工具,使用 Makefile 文件来定义如何编译和链接程序。它通过检查文件的时间戳来决定哪些文件需要重新编译。

Makefile 的基本结构

Makefile 的基本结构由目标、依赖和命令组成,通常形式为:

target: dependencies
    command

Makefile 示例

让我们考虑一个简单的 C 语言项目,该示例将展示如何使用 Makefile 来编译一个具有多个源文件和头文件的程序,并展示 Makefile 相比手动命令行编译的优势。

假设我们有一个简单的计算器程序,它包括以下文件:

  • main.c:程序的主入口点。
  • calculator.c:包含计算逻辑的源文件。
  • calculator.h:头文件,声明 calculator.c 中的函数。
  • Makefile:项目的构建脚本。
#include "calculator.h"

int main() {
    // 使用 calculator 模块进行计算
    int result = add(5, 3);
    printf("5 + 3 = %d\n", result);
    return 0;
}
#include "calculator.h"

int add(int a, int b) {
    return a + b;
}
#ifndef CALCULATOR_H
#define CALCULATOR_H

int add(int a, int b);

#endif
# 定义编译器
CC=gcc

# 定义编译选项
CFLAGS=-Wall -g

# 定义目标文件
TARGET=calculator

# 定义对象文件
OBJS=main.o calculator.o

# 默认目标
all: $(TARGET)

# 从 .c 文件生成 .o 文件
$(TARGET): $(OBJS)
    $(CC) $(CFLAGS) -o $@ $^

# 编译单个 .c 文件到 .o 文件
%.o: %.c
    $(CC) $(CFLAGS) -c $<

# 清理编译生成的文件
clean:
    rm -f $(TARGET) $(OBJS)

# 伪目标,防止 make 将某个文件名当作默认目标
.PHONY: all clean

尝试进行下述操作以体会Makefile的优势:

  • 在仅含这4个文件的文件目录下执行make命令,观察输出
  • 再次执行make命令,观察输出
  • 尝试修改calculator.c再次执行make命令,观察输出
  • 执行make clean命令,观察输出与当前目录文件的变化
  • 现在我希望发布我的程序,因此我需要编译时不带调试信息,并使用-O2的优化进行编译。请通过修改Makefile并进行make实现这一步。
  • 尝试使用上一节中的知识进行命令行编译

通过上述步骤的实验,尝试总结Makefile相比命令行的优势。

使用 Makefile 的优势
  1. 自动化编译:使用 make 命令即可编译整个项目,无需手动输入多个编译命令。

  2. 依赖管理:如果 calculator.ccalculator.h 被修改,Makefile 将仅重新编译 calculator.o,而不是整个项目。

  3. 可配置性:通过修改 Makefile 中的 CCCFLAGS 变量,可以轻松更改编译器和编译选项。

Make 的常用命令

  • make:执行默认目标,与make all等效。
  • make <target>:执行定义的<target>目标,如果没有这个目标将返回错误信息。
  • make -j:并行执行构建,使用本机的全部线程

参考链接

Makefile教程

CMake 入门

CMake 简介

CMake 是一个跨平台的构建工具,使用 CMakeLists.txt 文件来定义构建过程。它可以生成 Makefile 或其他 IDE 的项目文件。

CMakeLists.txt 文件结构

CMakeLists.txt 的基本结构包括:

cmake_minimum_required(VERSION 3.10)
project(MyProject)

add_executable(my_program main.cpp)

基本的 CMake 命令

  • cmake .:在当前目录生成构建文件。
  • cmake --build .:构建项目。

构建简单的 C/C++ 项目

创建一个简单的 C++ 项目,使用以下 CMakeLists.txt:

cmake_minimum_required(VERSION 3.10)
project(MyApp)

add_executable(MyApp main.cpp)

参考链接

CMake教程博客

上海交通大学IPADS-CMake入门培训视频

  • 逐级介绍了make和cmake的使用方法,推荐初学者观看

Compile Database

什么是 Compile Database

Compile Database 是一个 JSON 格式的文件,包含了项目中每个编译单元的编译命令和参数。Compile Database 使得你的编辑器能够获取编译信息,启用代码跳转和高亮功能,从而提高开发效率。

生成 Compile Database

使用 CMake 生成

在 CMake 命令中添加参数:

cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .

使用其他工具生成(如 Bear)

Bear 是一个工具,可以在构建时捕获编译命令并生成 compile_commands.json 文件。

使用方法:

bear -- make

在 VSCode 中使用 Compile Database

在cpp plugin中配置compile commands选项

"compileCommands": "${workspaceFolder}/build/compile_commands.json"