前言
每次想用vscode写个代码,一到运行或者其它操作就报错, 希望能通过记录各种bug,加深自己对vscode的理解,最后,祝自己早日掌控它。
文章目录
- 前言
- 一、头文件的include问题
- 1. 问题描述及原因
- 2. 问题解决
- 3. 总结与展望
- 二、学习Vscode的一些网站
- 1、预变量的学习
- 三、.json配置文件
- 1、`task.json`
- 2、`launch.json`
- 3、`c_cpp_configuration.json`
- 4、优先级
- 5、编译变量选项(`.json`文件下的args)
- 四、预处理、编译、汇编、链接
- 五、makefile文件的简单编写
- 1、需要再看的
- 伪目标
一、头文件的include问题
1. 问题描述及原因
从报错来看,基本上是因为编译器找不到对应的头文件,所以无法进行编译。
这两天看了网上大部分的解决方案,一个一个试了一下,这里给一个总结,因为有些方法并没有解决我的问题,但相信对看到这篇文章的人会有很大得帮助。
2. 问题解决
方法一: 在当前目录下的 .vscode 文件下找到tasks.json文件,在 “args” 下添加如下命令
"-I",
"E:\\vscode\\c_and_c++\\c++\\eigen-3.4.0" //输入自己的Eigen路径,注意不要有中文
添加后如图所示
使用-I
参数可以告诉编译器在哪些目录中搜索头文件,当然若已经在c_cpp_properties.json文件中的IncludePath中配置了就不需要这个了,下一个办法也就是这个。
方法二: 在当前目录下的 .vscode 文件下找到c_cpp_properties.json文件,在 “includePath” 下添加如下命令
"E:/vscode/c_and_c++/c++/eigen-3.4.0"
添加后如图所示
这相当于告诉编译器可以在这些includePath
下找到头文件,给了编译器寻找头文件的路径。
当然,以上两种方法对我的vscode没有效果,且多数人的博客记载的也是这两种方法。于是受到上面第二种方法的启发,就有了下面的两种方法。
方法三: 既然在c_cpp_properties.json
文件中添加新的includePath
路径没有用,那我就直接把这个Eigen
文件夹复制到现有的includePath
路径下,让编译器自己去现有的路径下寻找,这里我把它复制到了E:\MinGW\mingw64\lib\gcc\x86_64-w64-mingw32\8.1.0\include
下
最后成功运行。
方法四: 既然代码中可以允许出现#include <Eigen/Dense>
的语句,那我干脆直接把这个头文件的绝对路径写进去,这样也是可以编译的。
#include <iostream>
#include <E:/vscode/c_and_c++/c++/eigen-3.4.0/Eigen/Dense>
3. 总结与展望
这里只是对于一个Eigen库而言,对于以后需要新的头文件,而路径下没有的情况,可以仿照这些办法解决。可惜的是方法一和方法二失败的原因还未找到,等找到了再更新。未完待续…
二、学习Vscode的一些网站
1、预变量的学习
预变量的使用是配置文件具备迁移性的一个重要因素。
三、.json配置文件
1、task.json
任务配置文件:这个配置文件是用来执行你预定的任务的,比如说你修改了你的代码,调试之前,肯定要重新生成新的程序后再调试,那么你就可以配置它告诉vscode怎么重新生成这个新的程序。点击运行之后,VS Code将从tasks.json中查看如何构建并运行程序。
其中的args变量,顾名思义,执行的是命令行的操作,类似于将本可以在命令行中执行的操作移到这个里面。
args数组指定将传递给g++的命令行参数。这些参数按照编译器期望的特定顺序列在该文件中。
需要注意的是,tasks中可以有多个任务,在一个列表中保存,根据自己需要添加或删除。下面是官网中给出的一个task.json
文件例子,tasks中只有一个任务。
{
"version": "2.0.0",
"tasks": [
{
"type": "cppbuild",//指定了任务的类型,即 C/C++ 构建任务
"label": "C/C++: g++ build active file",//这是任务的标签,用于在 Visual Studio Code 中标识这个任务,可以随便命名。
"command": "/usr/bin/g++",//这是要执行的命令,填写编译器的路径,即 g++ 编译器的路径。
"args": ["-g", //在目标文件中添加调试信息,便于gdb调试或objdump反汇编
"${file}", //当前打开的文件
//你也可以通过更改 tasks.json来构建多个C++文件,只需要将${file}更改
//为"${workspaceFolder}/*.cpp"。
//这样更改参数将会构建当前文件夹下所有的.cpp文件,需要注意的是此时-o后的文件只能是下面这种情况。
"-o", //指定生成文件的文件名
"${fileDirname}/${fileBasenameNoExtension}"//生成文件的文件名,命名规则可以参看预变量命名
//可以更改输出文件的文件名,
//例如将"${fileDirname}\\${fileBasenameNoExtension}"更改
//为"${workspaceFolder}\\${fileBasenameNoExtension}.exe"这样的命名。
//这样生成的就是一个带拓展.exe的编译文件。
],
//command + args类似于在命令行中输入:
// g++ -g ${file} -o ${fileDirname}/${fileBasenameNoExtension}
"options": {
"cwd": "/usr/bin" //current work direct :指定了当前工作目录为 /usr/bin。
},//options:这里指定了任务的选项。
"problemMatcher": ["$gcc"],
"group": {
"kind": "build",//表示这是一个构建任务。
"isDefault": true//表示这是默认的构建任务。
},//group:定义了任务的分组信息。
//注:如果需要更改默认编译器,可以通过删除group中的 "isDefault": true ,
//这样在编译的时候vscode会重新弹出编译器选项。
//换句话说,如果你想在每次编译的时候都希望vscode会重新弹出编译器选项,
//那就将"isDefault": true改为"isDefault": false
"detail": "Task generated by Debugger."
}
]
}
学习来自官网与vscode一键配置C/C++多个C及CPP文件编译与tasks.json和launch.json原理。
2、launch.json
这个配置文件是告诉vscode如何来启动调试你的代码程序的,这其中包括你的程序在哪个位置,你用什么工具来调试,调试的时候需要给调试工具传什么参数等。
需要注意的是,configurations中可以有多个调试配置的设置,在一个列表中保存,根据自己需要添加或删除。
下面是官网中给出的一个launch.json
文件例子,configuration中只有一个调试配置设置。
{
"version": "0.2.0",
"configurations": [
{
"name": "C/C++: g++ build and debug active file",//这是调试配置的名称,用于在 Visual Studio Code 中标识这个调试配置,可以随便命名。
"type": "cppdbg",//这指定了调试器的类型,即 C/C++ 调试器。
"request": "launch",//这指定了调试器的请求类型,即启动调试。
"program": "${fileDirname}/${fileBasenameNoExtension}",//这是要调试的程序的路径和名称,即当前活动文件的路径和名称。
"args": [],//这是传递给程序的参数列表。在这里,为空列表,表示没有额外的启动参数。
"stopAtEntry": false,//这指定了是否在程序入口处停止,这里设置为 false,表示不在程序入口处停止。
"cwd": "${workspaceFolder}",//这是指定程序的当前工作目录,即工作区的根目录。
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "/usr/bin/gdb",//这是指定 GDB 调试器的路径。
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "C/C++: g++ build active file"//这是指定在启动调试之前运行的任务,即在启动调试之前会先运行名为 "C/C++: g++ build active file" 的构建任务。
}
]
}
3、c_cpp_configuration.json
如果要更好地控制 C/C++ 扩展名,可以创建一个文件,该文件将允许您更改设置,例如编译器的路径、包含路径、C++ 标准(默认为 C++17)等。
您可以通过从命令面板 (Ctrl+Shift+P) 运行命令 C/C++:编辑配置 (UI) 来查看 C/C++ 配置 UI。
这将打开“C/C++ 配置”页。在此处进行更改时,VS Code 会将其写入c_cpp_configuration.json
文件中。如果不习惯写代码修改配置,也可以直接在这样的一个交互页面进行配置修改。
仅当程序包含不在工作区或标准库路径中的头文件时,才需要修改“包含路径”设置。
Visual Studio Code 将这些设置放在c_cpp_configuration.json
中。如果直接打开该文件,它应该如下所示:
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**" //表示包含工作区中所有文件的路径
// 注意:/路径/** 表示的是 /路径 下的所有文件(也包括文件夹)
],//这是指定了包含文件的路径列表,可以看上图中的解释
"defines": [],
"compilerPath": "/usr/bin/gcc",//这是指定了编译器的路径,即 GCC 编译器的路径。
"cStandard": "c17",
"cppStandard": "gnu++14",//这是指定了 C++ 标准的版本,这里设置为 GNU++14。
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}
4、优先级
这三个配置文件将统一放在.vscode
文件夹里,位于当前运行的.cpp
文件同级目录下的.vscode
文件夹具有最高的优先级,运行的配置先看这里的配置,没有则往上级目录逐级寻找.vscode
文件夹。
VS Code 现在配置为在 Linux 上使用 gcc。该配置适用于当前工作区。若要重复使用配置,只需将 JSON 文件复制到新项目文件夹(工作区)中的.vscode
文件夹,并根据需要更改源文件和可执行文件的名称。
5、编译变量选项(.json
文件下的args)
vsode下多个文件的编译参看——GCC 同时编译多个 C/C++ 文件
注意
,由于在程序预处理阶段,gcc / g++ 编译器会自行处理各个 .c/.cpp 文件内部引入的 .h 头文件(将 .h 文件中的代码直接拷贝到当前 .c / .cpp 源文件中),因此编译运行项目时,我们只需要提供所有的源文件即可,不需要处理头文件。
四、预处理、编译、汇编、链接
-o
选项用于指定要生成的文件名。-c
编译、汇编指定的源文件,但不进行链接。
在此,我想多说关于程序编译的一些规范和方法。一般来说,无论是C还是C++,首先要把源文件编译成中间代码文件,在Windows下也就是 .obj 文件,UNIX下是 .o
文件,即Object File,这个动作叫做编译(compile)(广义)。然后再把大量的Object File合成可执行文件,这个动作叫作链接(link)。
编译时,编译器需要的是语法的正确,函数与变量的声明的正确。对于后者,通常是你需要告诉编译器头文件的所在位置(头文件中应该只是声明,而定义应该放在C/C++文件中),只要所有的语法正确,编译器就可以编译出中间目标文件。一般来说,每个源文件都应该对应于一个中间目标文件( .o
文件或 .obj
文件)。
链接时,主要是链接函数和全局变量。所以,我们可以使用这些中间目标文件( .o
文件或 .obj
文件)来链接我们的应用程序。链接器并不管函数所在的源文件,只管函数的中间目标文件(Object File),在大多数时候,由于源文件太多,编译生成的中间目标文件太多,而在链接时需要明显地指出中间目标文件名,这对于编译很不方便。所以,我们要给中间目标文件打个包,在Windows下这种包叫“库文件”(Library File),也就是.lib
文件,在UNIX下,是Archive File,也就是 .a
文件。
摘自一起写makefile文件——概述
g++ -E main.cpp -o main.ii //将main.cpp预处理成名为main.ii文件
g++ -o main.ii -E main.cpp //这样也是可以的,写makefile的时候发现的,
//其他类似,基本就是引用文件前加带“-”的命令语句就行
g++ -S main.ii -o main.s //将main.ii编译成名为main.s文件
g++ -S main.cpp -o main.s //将main.cpp编译成名为main.s文件
g++ -c main.s -o main.o //将main.s汇编成名为main.o文件
g++ -c main.cpp -o main.o //将main.cpp直接经过前面几步汇编成名为main.o文件。-c (compile 编译)
g++ main.o **.o -o main //将main.o 、**.o文件链接成main这个可执行文件
####
g++ main.cpp **.cpp -o main //将main.cpp 、**.cpp文件直接经过前面几步链接成main这个可执行文件
g++ -o main main.cpp **.cpp //这样也是可以的,写makefile的时候发现的
五、makefile文件的简单编写
1、需要再看的
伪目标