可以使用gcc/g++、make、cmake编译

基础环境

  1. ubuntu24.04
  2. 安装VSCode
  3. 在VSCode中安装C++拓展

1. gcc/g++

1.1. 环境配置

  1. 首先确保ubuntu系统已安装gcc,使用gcc -v命令查看
  2. 如果能够正确打印出当前gcc的版本信息,则表示已经预装。若没有预装,则用如下命令安装安装 GNU 编译器工具和 GDB 调试器:
    1
    2
    sudo apt update # 更新软件包源 
    sudo apt-get install build-essential gdb

1.2. 配置

项目的配置文件位于.vscode文件夹下:

c_cpp_properties.json (compiler path and IntelliSense settings)
tasks.json (compiler build settings) 
launch.json (debugger settings)
  1. lauch.json负责的是启动任务,执行文件(可执行文件)
  2. tasks.json负责的是配置相关任务。简单来说就是负责编译链接生成可执行文件,其实就是执行终端的编译指令[g++ -g main.cpp -o main.o]。所以在执行launch.json文件之前必须先执行tasks.json
  3. launch.json和tasks.json通过launch.json中的preLaunchTask关联起来。launch.json中的preLaunchTask是为了启动tasks.json的,所以preLaunchTask对应的标签应该与task.json一致。
  4. c_cpp_properties.json—编译环境相关的设置

1.2.1. 内置变量

1
2
3
4
5
6
7
1 ${workspaceFolder}:表示当前workspace(工作区、工作空间)文件夹的路径,也即当前项目绝对路径。例如:D:\code,code就是一个工作区。
2 ${fileDirname}:表示当前打开文件的绝对路径,但不包括文件名。例如打开hello.c文件,该文件所在的绝对路径(${fileDirname})为:D:\code\day1,day1就是hello.c文件的目录。
3 ${workspaceRootFolderName}:表示workspace(工作区、工作空间)文件夹名字,也就是当前项目所在文件夹名字,例如code文件夹。
4 ${file}:表示当前打开的文件,指的是当前活动文件。包括绝对路径,文件名,文件后缀名。例如:D:\code\day1\hello.c。
5 ${fileBasename}:当前打开含有后缀的文件名,不包括路径。
6 ${fileBasenameNoExtension}:表示当前打开的文件名,但不包括路径和后缀名。
7 cwd:当前工作目录,它是操作系统当前正在运行进程所在的目录。在命令行界面(比如,cmd)中,用户输入命令时,默认情况下会在cwd下执行。

1.2.2. tasks.json

  tasks.json文件的作用是告诉 VS Code 如何构建(编译)程序,将调用 g++编译器从源代码创建一个可执行文件。
  在上方的主菜单中,选择 终端>配置默认生成任务 ,将出现一个下拉菜单,显示 C++ 编译器的各种预定义编译任务。选择 C/C++: g++ build active file。
  也可以自己建立文件,直接复制下面内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++ 生成活动文件",
"command": "/usr/bin/g++",
"args": [
"-fdiagnostics-color=always",
"-g",
"${fileDirname}/*.cpp",
"-o",
"${fileDirname}/${fileBasenameNoExtension}"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "调试器生成的任务。"
}
],
"version": "2.0.0"
}

说明:
1
2
3
4
5
6
7
8
1. “type”:任务类型,可以取cppbuild、shell、process,三种执行时稍有差异,这里选择默认cppbuild。
2. “label”:任务标签(标记),也称任务名称,对应的值可以更改。tasks.json文件中label对应的值要和launch.json里面"preLaunchTask"对应的值一致。
3. “command”:编译器及其路径。.c用gcc.exe编译器(C语言编译器),.cpp用g++.exe编译器(C++语言编译器),还可以是Cmake、make。
4. “args”:方括号里面是传给gcc命令或g++命令的一系列参数,用于实现某些功能。
5. “-g”:生成和调试有关的信息,launch.json会用到这些信息。如果少了这个"-g",生成的可执行文件就不能被调试了。
6. “${file}”:编译当前打开的.c(或.cpp)文件。此处修改成"${fileDirname}/*.cpp",就可以一次编译多个.cpp文件了。
7. “-o”:指定编译的输出,windows系统下输出.exe文件。
8. "${fileDirname}\\${fileBasenameNoExtension}.exe":表示在当前工作目录下生成一个与源代码同名的可执行文件,即在day1目录下生成一个hello.exe文件。如果将${fileDirname}修改为${workspaceFolder},那么就会在当前工作区code文件夹下生成一个hello.exe文件。也可以在工作区code文件夹中建立一个bin文件夹,接着将编译后输出的可执行文件路径设置为:"${fileDirname}\\bin\\${fileBasenameNoExtension}.exe"。同时需要将launch.json文件中的参数"program"设置为:"${fileDirname}\\bin\\${fileBasenameNoExtension}.exe"。那么就会在bin文件夹下生成一个可执行文件(.exe)。

1.2.3. lunch.json

  launch.json 文件用于在 Visual Studio Code 中配置调试器
  从主菜单中,选择 运行 > 添加配置,选择C++ (GDB/LLDB)。 之后将看到展示各种预定义调试配置的下拉列表,选择 g++ build and debug active file。将自动生成launch.json文件。也可以自己建立文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "C/C++ g++ 生成和调试活动文件",
"type": "cppdbg",
"request": "launch",
"program": "${fileDirname}/${fileBasenameNoExtension}",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "将反汇编风格设置为 Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
],
"preLaunchTask": "C/C++: g++ 生成活动文件",
"miDebuggerArgs": "-q -ex quit; wait() { fg >/dev/null; }; /usr/bin/gdb -q --interpreter=mi"
}

]
}

说明:
1
2
3
4
5
6
7
8
9
1. “name”:自定义命名运行与调式的名称,将在左侧运行和调试的菜单中显示名称。
2. “type”:配置类型,调试器类型,cppdbg为C/C++的调试类型。
3. “request”:配置请求类型,可以为launch(启动)或attach(附加)。
4. “program”:在windows系统下需要进行调试的可执行文件(.exe文件)及其路径,应该与tasks.json编译后输出的可执行文件(.exe文件)及其路径一致。
5. “args”:程序调试时传递给程序的命令行参数,一般设为空即可,这里提到的程序实际就上面的.exe文件。
6. “stopAtEntry”:设为true时程序将暂停在程序入口处,一般设置为false。
7. “cwd”:当前工作目录(路径)。
8. “environment”:添加到程序的环境变量。
9. “externalConsole”:true开启外部控制台窗口,false会使用vscode内部控制台窗口。

1.2.4. c_cpp_properties.json

c_cpp_properties.json 文件,允许你更改设置,例如编译器的路径、包含路径、C++ 标准(默认为 C++17),等等。 可以通过从命令面板 (Ctrl+Shift+P) 运行命令 C/C++: Edit Configurations (UI) 来查看 C/C++ 配置 UI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${default}",
"${workspaceFolder}/**"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c17",
"cppStandard": "gnu++14",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}

说明:
1
2
3
4
5
6
7
8
1. “name”:名称。操作系统根据这个名称识别对应的属性配置,windows系统:Win32;Linux系统:Linux;macOS系统:Mac。
2. “includePath”:头文件路径。以便IntelliSense(智能感知)引擎的搜索。
3. "${workspaceFolder}/**":当前项目所在根目录并递归搜索子目录,也就是当前工作区文件夹的路径(例如:D:\code),而且还会递归查找其所有的子目录。
4. “defines”:IntelliSense(智能感知)引擎在分析文件时要使用的预处理器定义列表。
5. “cStandard”:用于IntelliSense(智能感知)引擎的c标准(版本)。
6. “cppStandard”:用于IntelliSense(智能感知)引擎的c++标准(版本)。
7. “intelliSenseMode”:IntelliSense(智能感知)的模式。
8. “compilerPath”:根据该路径查询编译器(gcc.exe、g++.exe),以便启用更加准确的IntelliSense(智能感知)。这里并不是调用编译器,真正启用编译器编译的是在tasks.json文件里。

1.3. 实例

1.3.1. 单.cpp文件

通过终端创建一个名为C++_Project_g++的文件夹以保存我们的VSCode项目,并创建子文件夹project1,在C++_Project_g++/project1目录下打开vscode。
在C++_Project_g++/project1目录下新建main.cpp文件

添加代码

1
2
3
4
5
#include<stdio.h>
int main(){
printf("hello word");
return 0;
}


运行,调试即可

1.3.2. 多.cpp文件

只需在task.json文件中修改

1
“${file}”:编译当前打开的.c(或.cpp)文件。此处修改成"${fileDirname}/*.cpp",就可以一次编译多个.cpp文件了。

2. 用 Makefile 来管理 C++ 项目

2.1. 实例

建立一个project,如下所示

核心是makefile文件的编写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 编译器与参数
CXX = g++
CXXFLAGS = -g -Wall -Iinclude

# 文件夹
SRC_DIR = src
BIN_DIR = build
TARGET = $(BIN_DIR)/main

# 所有源文件
SRC = $(wildcard $(SRC_DIR)/*.cpp)

# 默认目标
all: $(TARGET)

# 编译并链接成最终可执行文件(不保存 .o 文件)
$(TARGET): $(SRC)
@mkdir -p $(BIN_DIR)
$(CXX) $(CXXFLAGS) $(SRC) -o $(TARGET)

# 清理
clean:
rm -rf $(BIN_DIR)

原代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//main.cpp
#include <iostream>

#include "hello.h"

int main() {
say_hello();
return 0;
}

//hello.cpp
#include "hello.h"

#include <iostream>

void say_hello() { std::cout << "Hello from src/hello.cpp!" << std::endl; }

//hello.h
#pragma once

void say_hello();

编译方法:

  1. 在工程目录下make

    在build目录下,生成可执行文件main
  2. 进入build目录,执行可执行文件./main

2.2. 通用模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 编译器设置
CXX := g++
CXXFLAGS := -Wall -Wextra -g -Iinclude

# 目录设置
SRC_DIR := src
INC_DIR := include
BUILD_DIR := build
TARGET := $(BUILD_DIR)/main

# 文件收集
SRCS := $(wildcard $(SRC_DIR)/*.cpp)
OBJS := $(patsubst $(SRC_DIR)/%.cpp, $(BUILD_DIR)/%.o, $(SRCS))
DEPS := $(OBJS:.o=.d)

# 默认目标
all: $(TARGET)

# 链接生成最终可执行文件
$(TARGET): $(OBJS)
@mkdir -p $(BUILD_DIR)
$(CXX) $(CXXFLAGS) $^ -o $@

# 编译每个 .cpp 为 .o,并生成 .d 依赖文件
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp
@mkdir -p $(BUILD_DIR)
$(CXX) $(CXXFLAGS) -MMD -c $< -o $@

# 自动包含依赖(头文件修改自动触发重编译)
-include $(DEPS)

# 清理所有中间文件和目标
clean:
rm -rf $(BUILD_DIR)

.PHONY: all clean

3. 用 Cmake 来管理 C++ 项目

安装cmake

3.1. 单个项目


编写CMakeLists.txt文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
cmake_minimum_required(VERSION 3.10)
project(MyApp)

# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 17)

# 包含头文件目录
include_directories(include)

# 查找所有源文件
file(GLOB_RECURSE SOURCES "src/*.cpp")

# 可执行文件输出目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})

# 构建目标
add_executable(main ${SOURCES})

编译流程

  1. cd build
  2. cmake ..
  3. make
  4. ./main

3.2. 嵌套 Cmake


顶层 CMakeLists.txt

1
2
3
4
5
6
7
8
9
10
11
cmake_minimum_required(VERSION 3.10)
project(NestedApp)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})

include_directories(include)

# 添加模块
add_subdirectory(src/hello)
add_subdirectory(src/app)

src/hello/CMakeLists.txt(构建为静态库)
1
2
add_library(hello STATIC hello.cpp)
target_include_directories(hello PUBLIC ${CMAKE_SOURCE_DIR}/include)

src/app/CMakeLists.txt(构建可执行文件并链接库)
1
2
add_executable(main main.cpp)
target_link_libraries(main hello)

编译流程

  1. mkdir build
  2. cd build
  3. cmake ..
  4. make
  5. ./main