☞ ░ 前往老猿Python博客 ░ https://blog.csdn.net/LaoYuanPython
一、引言
在《信创之国产浪潮电脑+统信UOS操作系统体验2:安装visual studio code和cmake搭建C++开发环镜》介绍了在国产浪潮电脑+统信UOS操作系统中安装visual studio code和cmake搭建C++开发环镜的过程及案例,但上述过程仅限于编译,无法执行调试,且编译需要在控制台输入cmake和make指令才能执行。
实际上vscode是支持通过配置可以实现类似Visual C++等IDE开发工具使用菜单和快捷键直接进行程序编译构建的,这样构建的任务可以结合后续的调试配置进行IDE环境的程序调试,不过在之前必须先配置编译构建任务配置文件tasks.json。关于任务配置文件tasks.json的详细介绍请参考老猿在CSDN的博文《信创之国产浪潮电脑+统信UOS操作系统体验8:Visual Studio Code中的任务文件tasks.json和任务配置要素介绍》。
二、通过vscode界面配置编译构建任务
为了将编译构建过程集成到vscode界面中,需要在vscode中配置相关编译构建的设置。
详细配置过程如下:
- 通过菜单打开需要配置的源代码文件夹(如test),并打开至少一个需要编译的C或C++文件(如hello.cpp);
- 通过菜单选择配置任务:
终端->配置默认生成任务
,如图所示:
可以看到在安装cmake和C++的插件后有多种cmake和C++的任务选择(如果没有打开C或C++文件,是无法看到这些编译任务选项的),如图:
由于本次使用不执行cmake和make,因此不需要先生成CMakeLists.txt,在此直接选择C++相关的任务,可以看到有多个C和C++的编译器,选择任何一个都可以,如图:
实际上这些编译生成模式对应的只有两个编译模式,一个是aarch64-linux-gnu-gcc-8
、一个是aarch64-linux-gnu-g++-8
,其他的编译模式的指令都是对应这两个编译器的软连接,但编译器并不知道,因此还是列出来了所有的编译指令。
从下面截图可以看到,g++
是g++-8
的软连接,g++-8
是aarch64-linux-gnu-g++-8
的软连接:
类似的gcc
是gcc-8
的软连接,gcc-8
是aarch64-linux-gnu-gcc-8
的软连接,如图:
我们选择g++编译器,实际上gcc和g++都可以编译C和C++程序,不过g++将C程序和C++程序都作为C++文件编译,gcc则将C程序作为C程序编译,C++则作为C++编译。
在完成上步的配置后,就会在当前工程的.vscode
目录下生成tasks.json
编译构建任务配置文件。
通过上面步骤配置生成的编译构建配置文件task.json内容默认如下:
{"version": "2.0.0","tasks": [{"type": "cppbuild","label": "C/C++: g++ 生成活动文件","command": "/usr/bin/g++","args": ["-fdiagnostics-color=always","-g","${file}","-o","${fileDirname}/${fileBasenameNoExtension}"],"options": {"cwd": "${fileDirname}"},"problemMatcher": ["$gcc"],"group": {"kind": "build","isDefault": true},"detail": "编译器: /usr/bin/g++"}]
}
本次案例生成的tasks.json
文件是用于编译构建目标代码的,其实只要tasks.json
的文件内容正确,不通过上述配置步骤也可以指定编译构建的配置,并且有时候必须通过手工调整配置内容才能达成目标,如一个项目涉及2个及以上CPP源文件时,上述配置文件就无法完成构建任务,按上述配置只会编译当前打开文件。
三、测试的C++工程案例
3.1、测试的代码介绍
老猿这个测试案例用了两个cpp文件和一个头文件,分别是set.cpp、hello.cpp和set.h,其中hello.cpp引用了set.cpp中的testSet函数。相关代码如下:
用于定义整数集合类的头文件set.h
#ifndef SET_H
#define SET_H#include <memory.h>
#include <sstream>#include <iostream>#define MAXARRSIZE 200class set
{public:set(){_num=0;}set(const int *arr,int count) ;bool insert(int x);//添加 bool insert(set *pSet);bool insert(set vSet){return &vSet;};bool del(int x);//删除 void output();int index(int x);//查找bool find(int x){ return index(x)!=-1; }void clear(){_num = 0;};int size(){return _num;};int& getVal(int index); int& operator[](int index) {return getVal(index);};set unionSet(set t);//并集set interSet(set t);//交集set diffSet(set t);//差集private:int _arr[MAXARRSIZE];int _num;
};
int testSet();
#endif
用于实现整数的集合操作类set.cpp
//set.cpp
#include "set.h"using namespace std;set::set(const int *arr,int count)
{unsigned long arrSize;memcpy(_arr,arr,count*sizeof(int));_num = count;
}int& set::getVal(int index)
{if(index>=_num){stringstream ss;ss << "数组访问越界:数组元素总个数为"<<+_num<<"个访问索引值为:"<<index;throw ss.str().c_str();}else return _arr[index];
}bool set::insert(int x)
{ if(_num>=MAXARRSIZE)return false;if(!find(x)){_arr[_num]=x;_num++;}return true;
}bool set::insert(set *pSet)
{ int loop;int size = pSet->size();for(loop=0;loop<size;loop++)if(!insert((*pSet)[loop]))return false;return true;}bool set::del(int x)
{ int i,pos;pos=index(x);if(pos!=-1){memcpy(_arr+pos,_arr+pos+1,(_num-pos-1)*sizeof(_arr[0])) ;_num--;return true;}else return false;
}
void set::output()
{ int i;cout<<"{";for(i=0;i<_num;i++)cout<<_arr[i]<<" ";cout<<"}"<<endl;
}int set::index(int x){ //查找 int i;for(i=0;i<_num;i++)if(_arr[i]==x)return i;return -1;
}set set::unionSet(set t)//并集
{ set temp;temp.insert(this);temp.insert(&t);return temp;
}
set set::interSet(set t) //交集
{ set temp;int loop,size,val;size = t.size();for(loop=0;loop<size;loop++){val = t[loop];if(find(val))temp.insert(val);}return temp;
}set set::diffSet(set t) //差集
{set temp;int loop,val;for(loop=0;loop<_num;loop++){val = _arr[loop];if(!t.find(val))temp.insert(val);}return temp;
}int testSet()
{set s2;const int sInt1[] = {7,10,11,112,13,14,20,22}; set s1 (sInt1,sizeof(sInt1)/sizeof(int));cout<<"集合s1为:" ;s1.output();s2.insert(8); s2.insert(9);s2.insert(10);s2.insert(11);s2.insert(12);s2.del(8);//删除 s2.del(12);//删除 cout<<"集合s2为:";s2.output();cout<<"交集为:"<<endl;s1.interSet(s2).output();cout<<"并集为:"<<endl; s1.unionSet(s2).output();cout<<"差集为:"<<endl; s1.diffSet(s2).output();return 0;
}
用于测试的hello.cpp
#include <iostream>
#include "set.h"using namespace std;int main()
{int loop;cout<<"hello,world!"<<endl;testSet();return 0;
}
3.2、使用默认生成的tasks.json文件进行编译构建测试
由于该测试工程包含了2个CPP文件,因此用上面步骤配置生成的tasks.json无法直接使用,下面进行测试验证一下。
在包含两个或更多CPP文件(如老猿测试用的项目包含hello.cpp和set.cpp)的情况下,用以上配置通过终端->运行生成任务...
进行编译构建测试,发现相关情况如下:
- 工作区不打开任何CPP文件,则编译时报错:
无法解析变量 ${file}。请打开一个编辑器。
; - 工作区打开1个或2个CPP文件,但当前选择文件为hello.cpp,则编译时报错:
fatal error: set.h: 没有那个文件或目录
; - 工作区打开1个或2个CPP文件,但当前选择文件为set.cpp,则连接时报错:
/usr/bin/ld: /usr/lib/gcc/aarch64-linux-gnu/8/../../../aarch64-linux-gnu/crt1.o: in function `_start':
(.text+0x18): undefined reference to `main'
/usr/bin/ld: (.text+0x1c): undefined reference to `main'
因此为了编译含多个CPP源文件的工程,必须修改该缺省的编译任务配置文件,因为在编译命令中使用了${file}这个变量,从上面的介绍中可以知道,这个变量表示:“当前打开文件的绝对路径”,也就是vscode中当前显示在编辑窗口文件的文件名,如果没有打开文件,这个变量就无法解释,就会出现无法解析变量的报错。关于vscode的预定义变量请参考老猿在CSDN的博文《vscode中tasks.json文件使用的预定义变量及国产统信操作系统UOS下配置一个任务显示相关预定义变量的案例》的介绍。
3.3、修订任务配置文件
为了支持编译这种包含这种多个文件的C++项目,需要手工修改配置文件的编译指令参数,将涉及到的文件包含进来,具体修改为编译指令command的附加参数选项args,用如下的两条配置替换原来的"${file}"配置,修改后的tasks.json配置文件如下:
{"version": "2.0.0","tasks": [{"type": "cppbuild","label": "C/C++: g++ 生成活动文件","command": "/usr/bin/g++","args": ["-fdiagnostics-color=always","-g","hello.cpp","set.cpp","-o","${fileDirname}/${fileBasenameNoExtension}"],"options": {"cwd": "${fileDirname}"},"problemMatcher": ["$gcc"],"group": {"kind": "build","isDefault": true},"detail": "编译器: /usr/bin/g++"}]
}
修改的这两行也可以用 " f i l e D i r n a m e / h e l l o . c p p " 、 " {fileDirname}/hello.cpp"、 " fileDirname/hello.cpp"、"{fileDirname}/set.cpp"替换,没有本质区别。
这样配置后,就可以通过运行生成任务执行项目的编译了,不过需要注意,此时必须打开一个CPP文件或h文件,否则vscode无法找到需要编译的文件,如果打开的是tasks.json,也找不到文件,大家想想为什么?不清楚的可以回看老猿在CSDN的博文《vscode中tasks.json文件使用的预定义变量及国产统信操作系统UOS下配置一个任务显示相关预定义变量的案例》的介绍。下面是运行的结果截图:
四、小结
本文介绍了通过vscode构建配置任务并手工调整配置文件后,生成用于编译多个文件的C++项目的生成任务过程及配置解释,有助于大家熟练使用vscode编译C++项目。实际上老猿认为,除了这种方法,也可以通过配置其他任务方式执行C++项目的编译,比如对于更复杂的需要makefile的工程,应该是用配置任务使用make指令来构建编译任务,具体等后面老猿验证后再介绍。
写博不易,敬请支持:
如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!
更多关于VSCODE介绍的内容请参考专栏《国产信创之光》的其他文章。
关于老猿的付费专栏
- 付费专栏《https://blog.csdn.net/laoyuanpython/category_9607725.html 使用PyQt开发图形界面Python应用》专门介绍基于Python的PyQt图形界面开发基础教程,对应文章目录为《 https://blog.csdn.net/LaoYuanPython/article/details/107580932 使用PyQt开发图形界面Python应用专栏目录》;
- 付费专栏《https://blog.csdn.net/laoyuanpython/category_10232926.html moviepy音视频开发专栏 )详细介绍moviepy音视频剪辑合成处理的类相关方法及使用相关方法进行相关剪辑合成场景的处理,对应文章目录为《https://blog.csdn.net/LaoYuanPython/article/details/107574583 moviepy音视频开发专栏文章目录》;
- 付费专栏《https://blog.csdn.net/laoyuanpython/category_10581071.html OpenCV-Python初学者疑难问题集》为《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的伴生专栏,是笔者对OpenCV-Python图形图像处理学习中遇到的一些问题个人感悟的整合,相关资料基本上都是老猿反复研究的成果,有助于OpenCV-Python初学者比较深入地理解OpenCV,对应文章目录为《https://blog.csdn.net/LaoYuanPython/article/details/109713407 OpenCV-Python初学者疑难问题集专栏目录 》
- 付费专栏《https://blog.csdn.net/laoyuanpython/category_10762553.html Python爬虫入门 》站在一个互联网前端开发小白的角度介绍爬虫开发应知应会内容,包括爬虫入门的基础知识,以及爬取CSDN文章信息、博主信息、给文章点赞、评论等实战内容。
前两个专栏都适合有一定Python基础但无相关知识的小白读者学习,第三个专栏请大家结合《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的学习使用。
对于缺乏Python基础的同仁,可以通过老猿的免费专栏《https://blog.csdn.net/laoyuanpython/category_9831699.html 专栏:Python基础教程目录)从零开始学习Python。
如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。