使用VsCode+makefile开发C/C++

使用VsCode+makefile开发C/C++

1. 介绍

vscode作为现在越来越受欢迎的编辑器之一,因为可以使用插件让vscode支持几乎市面上所有的编程语言,由于笔者主要接触的是 C/C++ 方面,因此在这里简单介绍一下如何搭建vscode编译、调试C/C++项目的过程;整套环境完全使用开源软件进行搭建,只需要做很少的改变就可以无缝搬移到linux中;采用的方案是:vscode+git+mingw gcc+makefile;最后有详细的技术说明和资源分享(GitHub 项目:vscode_c_demo);

介绍一下笔者搭建的平台和所需要的软件:

Windows

VsCode

Git

MinGW

C/C++插件

简体中文包

  1. win7 以上;

  2. VS Code 官方下载地址

  3. Git (官方下载地址);

  4. mingw GUN 编译工具 (官方下载地址);

  5. 在VS Code中你需要安装

    5.1. C/C++ 插件(用于智能代码提示);

    5.2. Chinese (Simplified) Language Pack(中文简体支持包,英文好的请忽略)

下载安装VsCode插件比较简单;点击右侧图标搜索即可;
插件

,或者 快捷键 "Ctrl+Shift+X",搜索上述插件名称即可;

笔者不建议在mingw 的官网下载GCC 编译器;因为网络的速度会很慢,会等很久;很多开源的编译器都会自带mingwGcc编译器;例如DEVC++ 、Qt 等;

这里提供一个百度链接 https://pan.baidu.com/s/1x-jXHtiiWI0Kc1l34M_LrA 提取码:8q0d ;里面有上述所需要的所有安装包;截至2019年11月8日,里面的安装包均是最新版本,里面请区分32bit和64bit;

** 2.安装软件**

上述所有软件下载好之后,我们就可以开始安装程序了,所有程序可以一起安装,这里我们只讲解安装过程中的注意事项;

首先安装中,安装路径中不能出现中文;尽量避免空格 !

---------------------------------------------------------------------------------------华丽丽分割线---------------------------------------------------------------------------------------

2.1 mingw GUN GCC 编译器

mingw 在我的百度云链接中是压缩包,我们把他解压到指定位置后(我解压的位置是C:/mingw32 ),将编译器的bin目录添加到系统环境变量;如何添加系统环境变量请自行百度;

查看是否添加成功:打开 cmd(window + R 输入cmd打开命令行窗口) 输入 ** g++ --version ** 如果出现类似以下字样表示设置环境变量成功;

查看GCC版本

---------------------------------------------------------------------------------------华丽丽分割线---------------------------------------------------------------------------------------

2.2 Git

git 的默认编辑器是 vim 如果你从来没有听说过Git,那么请一路 next 安装;如果你有听过git ;我想我这个菜鸟也帮不了你啥~;如果你正在学习git,你可以看看这篇文章:git学习笔记--基础运用

---------------------------------------------------------------------------------------华丽丽分割线---------------------------------------------------------------------------------------

2.3 VS Code

安装vscode 也比较简单,只有一个需要注意

安装VsCode

一定要将 “通过Code 打开操作” 添加到目录的上下文菜单,后期作用会比较大;其他选项请自行选择;

---------------------------------------------------------------------------------------华丽丽分割线---------------------------------------------------------------------------------------

2.4 安装插件

安装C语言插件

安装中文包插件

插件安装之后会提示重启vscode 激活插件,重启即可

---------------------------------------------------------------------------------------华丽丽分割线---------------------------------------------------------------------------------------

3.配置参数

** 1. 导入一个示例项目**

这边你们可以随便导入一个项目,可以有多个文件夹,文件夹中可以有.c/.h文件,但是有一个要求,就是在里面的文件不存在冲突;即文件夹里面的源文件都是需要用到的,就算没有用到,也没有命名冲突等系列问题;

因为接下来的这个makefile会自动将你项目文件夹下所有的.c/.h文件全部编译,如果出现冲突,那么请你自己解决;最好的情况是:你用到了哪些文件你就放入哪些文件,不需要的文件可以修改他的后缀名;

为了方便展示,我从github 上clone 一个项目到文件夹下;在文件夹空白处右键单击,选择git bash here 输入:

git clone https://github.com/KimAlittleStar/vscode_c_demo.git

克隆成功后,右键点击生成出来的 vscode_c_demo文件夹;open with vscode ;文件树如下:

项目文件树

---------------------------------------------------------------------------------------华丽丽分割线---------------------------------------------------------------------------------------

2.设置默认的shell 命令行

点击左下角 齿轮图标 选择 设置 或者 点击 文件->首选项->设置 打开如下界面

如果你选择用户,那么更改的是默认配置,如果你选择工作区,那么你做的设置只会在这个文件夹内部起作用;

修改shell

---------------------------------------------------------------------------------------华丽丽分割线---------------------------------------------------------------------------------------

3.让VScode 提供智能提示

修改编译器默认路径
//C:/Git/bin/bash.exe 应该是你安装的git的bin目录下的bash.exe//C:/mingw32/bin/gcc.exe 应该是你安装的mingw下bin目录的gcc.exe//如果你的项目是C++ ,请换成 g++.exe//如果复制此段单吗到你的 setting.json文件后出错,请删除注释{    "terminal.integrated.automationShell.windows":"C:/Git/bin/bash.exe",    "C_Cpp.default.compilerPath": "C:/mingw32/bin/gcc.exe"}

---------------------------------------------------------------------------------------华丽丽分割线---------------------------------------------------------------------------------------

4.设置编译任务task.json 和 运行设置 launch.json

{ // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format    //此 json 文件中需要注意的就是 执行makefile的执行文件是 mingw32-make.exe ,如果你使用qmake 或者其他make 执行文件,替换它即可;其他不需要修改
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build", //task的名字,调用方式就是 task build  
            "command": "mingw32-make.exe", //会在命令行中调用此命令  
            "args": [ //调用上述 mingw32-make.exe 传递给它的参数  
                "target=${workspaceRootFolderName}.exe" //${workspaceRootFolderName} 会被替换成 根目录 即:vscode_c_demo            
            ],
            "type": "shell",
            "problemMatcher": []
        }, //此命令等效展开:mingw32-make.exe target=vscode_c_demo.exe        
        {
            "label": "build-debug",
            "command": "mingw32-make.exe",
            "args": [
                "target=${workspaceRootFolderName}.exe",
                "DEBUG=-g", //添加debug 参数 使gcc 生成调试信息
                "PREDEF=Debug" //相当于在程序中定义了一个宏定义#define Debug            
            ],
            "type": "shell"
        }, //此命令等效展开为:mingw32-make.exe target=vscode_c_demo.exe DEBUG=-g PREDEF=Debug        
        {
            "label": "clean",
            "command": "mingw32-make.exe",
            "args": [
                "clean",
                "target=${workspaceRootFolderName}.exe"
            ],
            "type": "shell",
            "problemMatcher": []
        }, //此命令等效展开为:mingw32-make.exe clean target=vscode_c_demo.exe        
        {
            "label": "runing",
            "command": "./runExcute.sh",
            "args": [
                "${workspaceRootFolderName}.exe" // 传给脚本的参数            
            ],
            "type": "shell"
        } //此命令等效展开为:mingw32-make.exe target=vscode_c_demo.exe  然后执行 ./vscode_c_demo.exe    
    ]
}
{
    // 使用 IntelliSense 了解相关属性。 
    // 悬停以查看现有属性的描述。
    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
    // 
    //这里我们需要注意修改的是:"miDebuggerPath": "C:/Qt/Tools/mingw730_64/bin/gdb.exe"
    //
    //这里gdb的路径应该是你自己的gdb 文件路径
    // 
    // "program": "${workspaceFolder}/${workspaceRootFolderName}.exe"
    // 这里调用的exe 应就是 task build-debug 中生成的可执行文件;
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) 启动", //名字,会显示在debug 的选项中
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/${workspaceRootFolderName}.exe", //表示要调试的可执行文件在当前打开的文件下下的这个文件,此名称需要和task 中的target=<>,一一对应;
            "args": [],
            "stopAtEntry": false, //时候要在main函数处自动停止,false表示不会停止,true表示会在main函数处自动停止;
            "cwd": "${workspaceFolder}", //表示首先要切换到当前目录下
            "environment": [],
            "externalConsole": false, //为true时,会新建一个黑窗口运行程序,如果为false ,就会在vscode中新建终端,
            //不过这样就需要在用户设置中设置默认bash 为 gitbash,否则会报错
            "MIMode": "gdb",
            "miDebuggerPath": "E:/userFile/userSoftware/Qt/Tools/mingw730_64/bin/gdb.exe", // 这里填写的应该是你自己gdb.exe文件的路径;一般与g++.exe minwg32-make.exe 在同一文件夹下
            "setupCommands": [
                {
                    "description": "为 gdb 启用整齐打印",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "build-debug" //在执行这个gdb launcher 之前,首先执行task build-debug;
        }
    ]
}
调用 task

贴一下task.josn 和 launch.json 的代码

---------------------------------------------------------------------------------------华丽丽分割线---------------------------------------------------------------------------------------

5.尝试运行

快捷键 CTRL + P 打开命令行 输入 task+空格+任务命令 即可执行相应命令

task.json中一共创建了4个命令; 分别是 build build-debug clean running

task build #创建一个文件夹名字相同的可执行文件;并且所有的中间文件都会生成放在build文件夹下;

task build-debug #与build类似,但是会生成调试信息,如果你想使用gdb等工具调试,那么必须使用此选项;

task clean #清除所有由build带来的文件

task runing #一共分两步,首先build ,其次调用其可执行文件;
运行

---------------------------------------------------------------------------------------华丽丽分割线---------------------------------------------------------------------------------------

** 6 DEBUG 选项**

vscode Debug使用的是mingw32中的gdb.exe调试,与平常的断点调试并无太大差异;

具体使用方法如下:点击左侧导航键 虫子的图标,选择(gdb)启动,点击右方绿色的开始图标,vscode会自动开始编译,运行到断点处会自动停止,更多设置请参考上文launch.json中的注释

debug单步调试

---------------------------------------------------------------------------------------华丽丽分割线---------------------------------------------------------------------------------------

4.原理分析

    整个环境搭建最主要的工作在于:**mingw32-make.exe** 中,实际上,如果你安装了git ,并按照上述方式修改了默认的终端为 gitbash,那么你只需要在终端中输入 mingw32-make.exe target=a.exe ,也会自动生成一个a.exe的可执行文件,在终端输入mingw32-make.exe clean target=a.exe,也可以清除所有由build带来的所有新建的中间依赖文件;task.json的作用就在于 当我 输入 task build 时 ,就相当于我在gitbash中输入了mingw32-make.exe target=DirName.exe 这个命令;

接下来我们会分析为什么mingw32-make.exe 可以做到这些,如果你仔细观察我们的文件树,你会发现文件树中有一个没有后缀的文件叫 makefile,我们可以打开makefile 文件,

#此项目源文件后缀类型
PROJECTTYPE = .c

#您想要生成可执行文件的名字 如果外部没有赋值,那么使用obj.out
target ?= obj.out

#是否生成DEBUG选项
DEBUG ?=#系统之外的宏定义
PREDEF ?=#获取当前makefile绝对路径
pes_parent_dir:=$(dir $(abspath $(lastword $(MAKEFILE_LIST))))////#删除路径下最后一个 / pes_parent_dir:=$(subst /////,,$(pes_parent_dir))#获得mkfile 的实际路径  测试使用,  没有实际用到 可删除
mkPath:=$(dir $(abspath $(lastword $(MAKEFILE_LIST))))////mkPath:=$(subst /////,,$(mkPath))#将所有宏定义前方加入-D指令以便给编译器识别
DEF := $(foreach n,$(PREDEF),-D$(n))

#获取目录下所有子目录
AllDirs := $(shell cd $(pes_parent_dir); ls -R | grep '^./.*:$$' | awk '{gsub(":","");print}') .

#添加成为绝对路径
AllDirs := $(foreach n,$(AllDirs),$(subst .,$(pes_parent_dir),$(n)))

#获取所有 .c/.cpp文件路径
Sources := $(foreach n,$(AllDirs) , $(wildcard $(n)/*$(PROJECTTYPE)))

#设置*.o 和 *.d 文件的存放路径
buildPath :=$(foreach n,$(Sources),$(subst $(pes_parent_dir),$(pes_parent_dir)/build,$(n)))

#处理得到*.o 后缀文件名
OBJS := $(patsubst %$(PROJECTTYPE),%.o, $(buildPath))  

#同理得到 *.d文件名
Deps := $(patsubst %$(PROJECTTYPE),%.d, $(buildPath))  

#需要用到的第三方静态库
StaticLib :=

#需要用到的第三方动态链接库
DynamicLib := 

#真实二进制文件输出路径
Bin :=$(pes_parent_dir)/$(target)

#C语言编译器
CC = gcc

#C++编译器
CXX = g++

#简化rm -f
RM = rm -f

#C语言配置参数
CFLAGS = -g  -pedantic -std=c11 -Wall -o

#C++配置参数
CXXFLAGS = -g -Wall -std=c11 

#头文件搜索路径
INCLUDE_PATH = $(foreach n,$(AllDirs) , -I$(n))
LDFLAGS = 

#指定AllLibs为终极目标 即:最新的Bin 
AllLibs:$(Bin)

#声明这个标签 des 用于观察当前的路径是否正确
.PHONY:des
des:
    @echo OBJS =  $(OBJS)
    @echo cur_makefile_path = $(pes_parent_dir)
    @echo AllDirs = $(AllDirs)
    @echo Sources = $(Sources)
    @echo Deps = $(Deps)
    @echo makefilePath =$(mkPath)
    @echo bulidPath=$(buildPath)
    @echo PREDEF = $(DEF)
    @echo DEBUG = $(DEBUG)

#对应关系 在本makefile中以空格隔开的后缀为.c 都会为其生成一个新的.d文件
#$(pes_parent_dir)/build/%.d :$(pes_parent_dir)/%.c  
#       @echo 'finding $< depending head file'
#       @if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi;
#       @$(CC) -MT"$(<:.c=.o) $@" -MM $(INCLUDE_PATH) $(CPPFLAGS) $< > $@


#对应关系 在本makefile中以空格隔开的后缀为.c 都会为其生成一个新的.d文件
$(pes_parent_dir)/build/%.d :$(pes_parent_dir)/%.c
    @echo 'finding $< depending head file'
    @if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi;
    @set -e; rm -f $@; 
    $(CC) -MM $(INCLUDE_PATH) $(DEF) $(CPPFLAGS) $< > $@.$$$$; 
    sed 's,($*).o[ :]*,1.o $@ : ,g' < $@.$$$$ > $@; 
    rm -f $@.$$$$


#对于include中的*.d文件,只要里面任意有一个文件被修改,那么就会触发此规则生成一个新的*.o文件
%.o: %.d
    @echo compile $(patsubst %.d,%.c,$(subst build/,,$<)) 
    @$(CC) -c $(patsubst %.d,%.c,$(subst build/,,$<)) $(DEBUG) $(DEF) $(INCLUDE_PATH) $(CFLAGS) $@ 



$(Bin) : $(OBJS)  
    @echo bulding....
    @$(CC) $(OBJS)  $(CFLAGS) $(Bin)
    @echo created file: $(target)    

.PHONY : clean  
clean:   
        @echo '清理所有文件ing...'
        @$(RM) -r $(pes_parent_dir)/build/
        @echo '清理可执行文件ing...'
        @$(RM) $(Bin)
        @echo 'done'

.PHONY : cleanO
cleanO:
        @echo '清理Obj && Dep'
        @$(RM) -r $(pes_parent_dir)/build
        @echo 'done'
#main.out: $(OBJ)
#    cc -o main.out $(OBJ)

include $(buildPath:.c=.d)

在上述makefile 中,比较关键的语句在于

= $(shell cd $(pes_parent_dir);  -R |   |  ) .
···
#对应关系 在本makefile中以空格隔开的后缀为.c 都会为其生成一个新的.d文件
$(pes_parent_dir)/build/%.d :$(pes_parent_dir)/%.c
@echo 'finding $< depending head file'
@if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi;
@set -e; rm -f $@; 
$(CC) -MM $(INCLUDE_PATH) $(DEF) $(CPPFLAGS) $< > $@.$$$$; 
sed 's,($*).o[ :]*,1.o $@ : ,g' < $@.$$$$ > $@; 
rm -f $@.$$$$

shell cd $(pes_parent_dir) 表示切换路径到该makefile 的目录下,然后 ls -R:递归输入该目录下的所有文件以及文件夹;如果是文件夹,那么就会单独起一行然后文件夹名字前有 ‘.’ 作为标记 后面的grepawkgsup 都是linux下才有的命令;

同理在 下方if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi;所做的逻辑就是判断当前想要生成的.d文件的目标文件夹在不在, 不在则创建它, 其中dir mkdir 都是linux中才会有的命令,当然windows下也有与其差不多功能的命令,但是此makefile我希望在linux下也能用,这个时候怎么办呢,这个时候就要介绍我们的 Git 了,git在windows中使用的命令行软件 bash.exe 就把上面的命令都覆盖到了,也就是说,如果我们使用windows 自带的cmd.exe 或者 powerShell.exe 里面都会使得 dir mkdir 和其他命令找不到,导致makefile错误终止;所以我们才需要安装Git* ,所以我们才需要将Git bash 设置成为vsCode 默认的终端;因为只有git bash 中才可以调用上述makefile中的几个shell命令

还记的我们将mingw32编译器的路径加入到了系统环境变量里面去了~为什么呢?

#C语言编译器
CC = gcc#C++编译器
CXX = g++

因为 在makefile 的编译器中,gccg++ 只是简单的字符,只有将gcc 、g++ 的路径加入了环境变量,他们才能正确的被找到;

还有,如果我们想管理C++项目这个时候怎么办呢~我们只需要在 makefile中将所有的 $(CC) 替换成 $(CXX) 所有 的$(CFLAG) 替换成 $(CXXFLAG) 就可以了哦~

makefile中其他的只是我就不赘述了,你可以参考这个链接:一个自动管理项目的makefile

最后献上我整个项目的github地址https://github.com/KimAlittleStar/vscode_c_demo

里面有所有的项目文件,以及配置文件,和较为详细的注释;只需要修改几个简单的路径就可以完成上述的配置;我都有在json文件里面说明哦~~~

---------------------------------------------------------------------------------------华丽丽分割线---------------------------------------------------------------------------------------

如果关注度还可以的话;

我会选择更新:

一键/自动转换 C/C++ 项目的makefile,

编写一个只清楚中间文件,而不清除可执行文件的task

搭建VSCode + 嵌入式 ARM编译调试环境

码字不易,觉得稍微有点用的,可以在git里面 star一下,博客点个小赞;

读书的时候就想了2、3年的事情,现在终于快要看到成功了;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343