目录
- **你能学到**
- **前言**
- **g++指令**
- **单文件编译**
- **多文件编译**
- **tasks.json**
- **launch.json**
- **最后**
你能学到
- 一些g++编译指令
- tasks.json、launch.json在C++构建任务中的常用的键值对的含义
前言
本文仅讲解 tasks.json、launch.json 文件常用的地方,以 VScode 自动生成的两个 json 文件为例。
json是一种数据交换格式,不了解的自行百度。其实也没有太大必要了解很深,在本文中你只需知道它是用来存储配置信息的即可。
因为此格式便于计算机解析,大家都约定使用而已。换言之,只要你NB,设计的新格式合理,好用,没准大家都使用你的,那不大赚一笔?打住,想money想疯了-_-
在说这两个json文件之前,有必要先说说g++的编译指令。为什么呢?
tasks.json 顾名思义是用来定义任务的。使用 VScode 一键运行,通常执行的就是此文件中定义的任务。而现在我们的主要任务是构建 C++项目,编译出可执行文件 .exe。
用 VScode 来写代码,主要的无非就几个要求:
- 编译C++项目文件
- 调试程序
- 代码错误提示
等,这些功能可由 GCC工具链 中的 g++、gcc、gdb 提供。
换言之,你只要下载了 GCC工具链(或者其他C++编译器),即便不用 VScode 也可以写 C++项目,然后使用相关指令调用 g++、gdb,进行编译、调试等(就像有人开玩笑说,大神都在用记事本写代码)。但是这样是很繁琐的,下面演示 g++ 相关的编译指令:
g++指令
本文重点在两个json文件,所以只是简单的讲解部分指令*(因为会用到,如果你已经会了自行跳过)* ,想要了解更多的自行百度。
常用的参数
- -g : 生成 debug 版本程序,包含可供 gdb 使用的调试信息
如果不加此参数,那么无法生成能被调试的程序
- -o : 指定输出文件的路径
- -I : 指定头文件包含目录,用于搜索头文件
单文件编译
- 初始状态
- 输出指令调用 g++,编译 1.cpp,生成 1.exe
- 运行 1.exe,成功
多文件编译
- 项目结构如下
add.h 中为 add() 函数的声明语句,add.cpp 为其定义语句,现在在 main.cpp 中调用 add() 函数
- 输入指令
因为 main.cpp 中导入的 add.h 不在当前目录,无法识别,因此需要使用 -I 参数指明其所在目录 (省略则默认为当前目录,比如下图中当前目录为 D:\10.cmake\demo\htf\text)
如果没有指明 add.h 所在目录,则会报错:
- 运行,没有问题
tasks.json
作者的另外一篇文章(VScode配置C++环境)中说了自动生成 tasks.json 的方法,其内容如下:
- type
任务的类型。
VScode 内置任务类型为 shell、process。cppbuild 是为 C\C++ 插件提供的。(使用此类型,以便更好地与 C\C++ 插件集成,使用其功能)
- tasks
其后跟的 [ ] 中为对应的值,说明了任务是什么,怎么做。
既然是 task
s
,那么也就是说任务可以有多个,在 [ ] 中,每个任务的相关信息在 { } 中,以 “,” 隔开。比如上述 tasks.json 只有一个任务 (红框中)
- label
既然可以有多个任务,那总该有唯一标识一个任务的键值,label 就是起此作用,接收一个 string。
-
command
接收一个 string,用于在 shell 中 执行。比如之前用到的 g++ -
args
接收一个 string数组,用于给 command 传递参数。像之前的 g++,书写调用指令需要指定参数。
- 比如 g++ 1.cpp 指令,g++ 对应 command,而 g++ 后跟的参数对应 args
${file}
:是一种固定用法,表示取变量file的值。
file 是 VScode 已经定义好了的变量(就像 C++ 的预定义宏一样),表示当前打开的文件的路径,会在执行任务时自动替换。
${变量} 表示取变量的值。
想了解其他的预定义变量你可查看 VScode官方文档
当我们一键运行时,会发现终端出现如下情况(重点在 && 的后面跟的)
很显然,上述 tasks.json 的主要任务是 一键运行后,自动在终端执行 command + args
由于 g++ 所在路径已经加入环境变量,因此你可以将 指令 “C:\msys64\ucrt64\bin\g++.exe” 简单写为 “g++”
-fdiagnostics-color=always 表示 g++ 在输出错误信息时采用有颜色的字体输出。比如之前的没有写 -I 的那张图片的报错信息,有的单词被标红
- options
在执行任务时使用的命令选项,可省略
上述tasks.json中的 cwd 用于指明任务的执行目录,如果省略是默认是项目的根目录。
- 因为 g++指令 中处理的是路径,存在相对路径,所以要指定一个合适的目录,保证之后的相对路径正确,绝对路径那就无所谓了。
- ${fileDirname} 表示 取当前打开文件(file)的路径所在目录(dirname)
- detail
接收一个 string,用于描述任务详情,相当于注释
其他键值对目前用不到,不在过多说明。
所以其实重要的地方就两个:command、args。针对编译C++程序而言,二者提供了调用g++的指令 (这就是为什么要先说 g++ 指令的原因) 。下面来分析:
- file:当前打开的文件对应的路径。
- fileDirname (file dirname) :当前打开的文件对应的目录。
- fileBasenameNoExtension:
- Basename:路径中最后不包含文件路径分隔符的部分 (比如 ./file.h 为 file.h,C:\dir\file 为 file)
- NoExtension:没有扩展名
合起来也就是 当前打开文件的无扩展名的文件名。
所以,上述的 command + args = ‘g++ -g 当前打开的文件 -o 当前打开的文件.exe’,也就是说它只能处理单文件编译的情况。那么多文件的项目怎么办呢?无非还是修改 args,举例:
本人比较喜欢的一种格式,bin 目录用来装程序,inc 为头文件,src 为源文件。
如果用之前自动生成的tasks.json显然不合适,因为它只适合单文件编译,现在会是多文件,可如下进行修改
workspaceFolder:工作区目录 (在 VScode 中打开的目录,比如上图为 根目录TEXT)
- 第一条红线:TEXT 目录下的 src 目录下的所有以 .cpp 结尾的文件 (*.cpp,通配符匹配路径)
- 第二条红线:由于前一个是 -o 参数,所以指 输出文件为 TEXT 目录下的 bin 目录下的 main.exe
一个程序只对应一个.exe,在编译单文件的 json 文件中,我们使用的是当前打开的文件的文件名,而现在是直接指定程序名称为 main.exe
- 第三条红线:由于前一个是 -I 参数,所以指 头文件包含目录 为 TEXT 目录下的 inc 目录
- 第四条红线:因为上述从 args 的描述可知,此指令应该在 TEXT 目录下执行,才能确保路径正确
现在一键构建 (Ctrl + Shift + B)
运行程序,成功
launch.json
有必要注意的就三个
- program:对应所生成的程序的路径,因为你要调试的程序就是它
- externalConsole:默认情况下使用的是 VScode 内置的控制台。设为 true,那么将启用新的控制台
-
- false
-
- true
- miDebuggerPath:调试器路径,以便 VScode 调用 gdb
最后
可以看到,VScode 自动生成的 tasks.json 只适用于单文件编译,但是在一个 C++ 项目中,大多采用头文件与源文件分离的情况,因为这样方便管理项目。
C++ 分文件写法不明白的可以见作者的另外一篇文章:c++ 分文件写法
在写的过程中你会发现一个重复性的工作:一个函数需要写两次,并进行一些增删,比如:
// 头文件
namespace std
{
void fic(const string& s = "");
}
// 源文件
namespace std
{
void fic(const string& s) // 删除默认参数
{
// ...
}
}
代码少时没多大感觉,但较多时就比较麻烦,这里推荐作者自己写的一个命令行小工具(我称为 header_to_file),能够 读取头文件中的声明语句,自动生成定义语句,并输出到源文件中,避免重复性工作,有兴趣的前往 header_to_file 了解。
文章参考VScode官方文档,如有错误,欢迎指正。
如果本文对你有用,欢迎点赞,或者分享给有需要的人(注明出处即可),谢谢。