编译进阶
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 的优势
-
自动化编译:使用
make
命令即可编译整个项目,无需手动输入多个编译命令。 -
依赖管理:如果
calculator.c
或calculator.h
被修改,Makefile 将仅重新编译calculator.o
,而不是整个项目。 -
可配置性:通过修改 Makefile 中的
CC
和CFLAGS
变量,可以轻松更改编译器和编译选项。
Make 的常用命令¶
make
:执行默认目标,与make all
等效。make <target>
:执行定义的<target>
目标,如果没有这个目标将返回错误信息。make -j
:并行执行构建,使用本机的全部线程
参考链接¶
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)
参考链接¶
- 逐级介绍了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"