使用VsCode+makefile開發C/C++html
1. 介紹linux
vscode做爲如今愈來愈受歡迎的編輯器之一,由於可使用插件讓vscode支持幾乎市面上全部的編程語言,因爲筆者主要接觸的是 C/C++ 方面,所以在這裏簡單介紹一下如何搭建vscode編譯、調試C/C++項目的過程;整套環境徹底使用開源軟件進行搭建,只須要作不多的改變就能夠無縫搬移到linux中;採用的方案是:vscode+git+mingw gcc+makefile;最後有詳細的技術說明和資源分享(GitHub 項目:vscode_c_demo);git
介紹一下筆者搭建的平臺和所須要的軟件:github
1. win7 以上;shell
2. VS Code 官方下載地址;編程
3. Git (官方下載地址);json
4. mingw GUN 編譯工具 (官方下載地址);vim
5. 在VS Code中你須要安裝windows
5.1. C/C++ 插件(用於智能代碼提示);bash
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 若是出現相似如下字樣表示設置環境變量成功;
---------------------------------------------------------------------------------------華麗麗分割線---------------------------------------------------------------------------------------
2.2 Git
git 的默認編輯器是 vim 若是你歷來沒有據說過Git,那麼請一路 next 安裝;若是你有聽過git ;我想我這個菜鳥也幫不了你啥~;若是你正在學習git,你能夠看看這篇文章:git學習筆記--基礎運用
---------------------------------------------------------------------------------------華麗麗分割線---------------------------------------------------------------------------------------
2.3 VS Code
安裝vscode 也比較簡單,只有一個須要注意
必定要將 「經過Code 打開操做」 添加到目錄的上下文菜單,後期做用會比較大;其餘選項請自行選擇;
---------------------------------------------------------------------------------------華麗麗分割線---------------------------------------------------------------------------------------
2.4 安裝插件
插件安裝以後會提示重啓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 命令行
點擊左下角 齒輪圖標 選擇 設置 或者 點擊 文件->首選項->設置 打開以下界面
若是你選擇用戶,那麼更改的是默認配置,若是你選擇工做區,那麼你作的設置只會在這個文件夾內部起做用;
---------------------------------------------------------------------------------------華麗麗分割線---------------------------------------------------------------------------------------
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": true, //爲true時,會新建一個黑窗口運行程序,若是爲false ,就會在vscode中新建終端, //不過這樣就須要在用戶設置中設置默認bash 爲 gitbash,不然會報錯 "MIMode": "gdb", "miDebuggerPath": "C:/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.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中的註釋
---------------------------------------------------------------------------------------華麗麗分割線---------------------------------------------------------------------------------------
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 中,比較關鍵的語句在於
#獲取目錄下全部子目錄 AllDirs := $(shell cd $(pes_parent_dir); ls -R | grep '^\./.*:$$' | awk '{gsub(":","");print}') .
···
#對應關係 在本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 :遞歸輸入該目錄下的全部文件以及文件夾;若是是文件夾,那麼就會單獨起一行而後文件夾名字前有 ‘.’ 做爲標記 後面的grep 和 awk 、gsup 都是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 的編譯器中,gcc 、g++ 只是簡單的字符,只有將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一下,博客點個小贊;
讀書的時候就想了二、3年的事情,如今終於快要看到成功了;