相比龐大的Visual Studio來(lái)說(shuō),VS Code實(shí)在是一款非常便捷的編輯器,如果你對(duì)使用Visual Studio來(lái)寫(xiě)C++內(nèi)心有極大的抗拒或者只是想拿一個(gè)簡(jiǎn)單的工具來(lái)寫(xiě)C++的話(huà),不妨可以考慮一下給VS Code 配置上編譯器,在VS Code 中完成輕量級(jí)的工作。
說(shuō)到編譯器,你最先想到的可能是GCC,本文使用的是Clang,相比GCC,Clang有很多優(yōu)點(diǎn),優(yōu)點(diǎn)不是本文所討論的內(nèi)容。如果使用GCC作為編譯器,可參考我的這篇文章。
Clang 是一個(gè)C、C++、Objective-C和Objective-C++編程語(yǔ)言的編譯器前端。它采用了底層虛擬機(jī)作為其后端。它的目標(biāo)是提供一個(gè)GNU編譯器套裝的替代品。作者是克里斯·拉特納,在蘋(píng)果公司的贊助支持下進(jìn)行開(kāi)發(fā),而源代碼授權(quán)是使用類(lèi)BSD 的開(kāi)源授權(quán)。 Clang 項(xiàng)目包括Clang 前端和Clang 靜態(tài)分析器等。
編寫(xiě)中為了能提高效率,我們可以使用VS Code的一些C++的擴(kuò)展來(lái)實(shí)現(xiàn)智能感知和調(diào)試功能,且聽(tīng)我娓娓道來(lái)。
安裝VS Code
安裝LLVM
LLVM Download Page,在網(wǎng)頁(yè)中找到適用于Windows
64位的最新預(yù)編譯版本,不需要下載sig簽名文件。安裝過(guò)程中注意選擇為所有用戶(hù)安裝,這樣會(huì)為你添加到環(huán)境變量。
這兩步完成以后打開(kāi)cmd,輸入clang應(yīng)該可以看到如下輸出。

如果看到上圖,說(shuō)明你的Clang安裝成功了。
那么如果你寫(xiě)了一個(gè)
.cpp的文件,比如一個(gè)hello world。
#include <iostream>
using namespace std;
int main()
{
cout << "hello world" << endl;
}
用命令clang hello.cpp編譯,你會(huì)發(fā)現(xiàn)如下錯(cuò)誤輸出。
clang.exe: warning: unable to find a Visual Studio installation; try running Clang from a developer command prompt [-Wmsvc-not-found]
main.cpp:1:10: fatal error: 'iostream' file not found
#include <iostream>
^~~~~~~~~~
1 error generated.
難道沒(méi)有頭文件???
如果你已經(jīng)安裝了Visual Studio 的C++工具,可能沒(méi)有這條錯(cuò)誤,能夠成功編譯,如果你不想用Visual Studio自帶的C++呢?我們還要在VS Code里調(diào)試呢。
為了解決這個(gè)錯(cuò)誤,我們需要MinGW-w64。
安裝MinGW-w64
MinGW-w64 - for 32 and 64 bit Windows,安裝時(shí)注意選擇體系架構(gòu)為x86_64。由于網(wǎng)絡(luò)原因,你可能不能把它下載下來(lái),經(jīng)過(guò)一點(diǎn)探索,安裝程序需要下載一個(gè)叫做x86_64-7.1.0-release-posix-seh-rt_v5-rev2的文件,其實(shí)我們可以直接在SourceForge上搜到這個(gè)MinGW-w64 - for 32 and 64 bit Windows,到里面選擇第一個(gè)下載。下載完成后解壓里面的mingw64文件夾中的內(nèi)容到你安裝LLVM的同一個(gè)目錄合并,合并里面所有文件夾,不會(huì)有沖突。
配置VS Code。
這里需要4個(gè)json配置文件。
用VS Code打開(kāi)你的工作區(qū)文件夾,新建一個(gè).vscode文件夾,注意有個(gè)點(diǎn)。
而后在這個(gè)文件夾下新建c_cpp_properties.json,這個(gè)文件用于指定一些頭文件的目錄,代碼如下,注意修改里面的路徑,我這里是F盤(pán)。
c_cpp_properties.json
{
"configurations": [
{
"name": "Win32",
"intelliSenseMode": "clang-x64",
"includePath": [
"${workspaceRoot}",
"F:/llvm/lib/gcc/x86_64-w64-mingw32/7.1.0/include/c++",
"F:/llvm/lib/gcc/x86_64-w64-mingw32/7.1.0/include/c++/x86_64-w64-mingw32",
"F:/llvm/lib/gcc/x86_64-w64-mingw32/7.1.0/include/c++/backward",
"F:/llvm/lib/gcc/x86_64-w64-mingw32/7.1.0/include",
"F:/llvm/include",
"F:/llvm/x86_64-w64-mingw32/include",
"F:/llvm/lib/gcc/x86_64-w64-mingw32/7.1.0/include-fixed"
],
"defines": [
"_DEBUG",
"UNICODE",
"__GNUC__=7",
"__cdecl=__attribute__((__cdecl__))"
],
"browse": {
"path": [
"F:/llvm/x86_64-w64-mingw32/include",
"F:/llvm/lib/gcc/x86_64-w64-mingw32/7.1.0/include",
"F:/llvm/lib/gcc/x86_64-w64-mingw32/7.1.0/include-fixed",
"F:/llvm/include/*",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
}
],
"version": 3
}
完成以后,再新建一個(gè)settings.json文件,還是需要修改路徑,注意。
settings.json
// 將設(shè)置放入此文件中以覆蓋默認(rèn)值和用戶(hù)設(shè)置。
{
"files.defaultLanguage": "c", // ctrl+N新建文件后默認(rèn)的語(yǔ)言
"c-cpp-flylint.cppcheck.enable": false,
"c-cpp-flylint.flexelint.enable": false,
"c-cpp-flylint.run": "onType", // 此選項(xiàng)貌似不起作用
"c-cpp-flylint.clang.includePaths": [
"${workspaceRoot}",
"F:/llvm/lib/gcc/x86_64-w64-mingw32/7.1.0/include/c++",
"F:/llvm/lib/gcc/x86_64-w64-mingw32/7.1.0/include/c++/x86_64-w64-mingw32",
"F:/llvm/lib/gcc/x86_64-w64-mingw32/7.1.0/include/c++/backward",
"F:/llvm/lib/gcc/x86_64-w64-mingw32/7.1.0/include",
"F:/llvm/include",
"F:/llvm/x86_64-w64-mingw32/include",
"F:/llvm/lib/gcc/x86_64-w64-mingw32/7.1.0/include-fixed"
],
"c-cpp-flylint.clang.defines": [
"_DEBUG",
"UNICODE",
"__GNUC__=7",
"__cdecl=__attribute__((__cdecl__))"
],
"c-cpp-flylint.standard": [ // 此選項(xiàng)貌似也不起作用
"c11",
"c++1z"
],
"code-runner.runInTerminal": true, // 設(shè)置成false會(huì)在“輸出”中輸出,無(wú)法交互
"code-runner.executorMap": {
"c": "cd $dir && clang $fileName -o $fileNameWithoutExt.exe -Wall -g -Og -static-libgcc -fcolor-diagnostics --target=x86_64-w64-mingw -std=c11 && $dir$fileNameWithoutExt",
"cpp": "cd $dir && clang++ $fileName -o $fileNameWithoutExt.exe -Wall -g -Og -static-libgcc -fcolor-diagnostics --target=x86_64-w64-mingw -std=c++1z && $dir$fileNameWithoutExt"
},
"code-runner.saveFileBeforeRun": true,
"C_Cpp.clang_format_sortIncludes": true,
"C_Cpp.errorSquiggles": "Disabled"
}
完成之后,繼續(xù)新建一個(gè)tasks.json,用于編譯參數(shù),直接復(fù)制就行,不用修改。
tasks.json
{
"version": "2.0.0",
"tasks": [
{
"taskName": "Compile", // 任務(wù)名稱(chēng),與launch.json的preLaunchTask相對(duì)應(yīng)
"command": "clang++", // 如果用MinGW,編譯C用gcc,編譯c++用g++
"args": [
"${file}",
"-o", // 指定輸出文件名,不加該參數(shù)則默認(rèn)輸出a.exe
"${fileDirname}/${fileBasenameNoExtension}.exe",
"-g", // 生成和調(diào)試有關(guān)的信息
"-Wall", // 開(kāi)啟額外警告
"-static-libgcc", // 靜態(tài)鏈接
"-fcolor-diagnostics",
"--target=x86_64-w64-mingw", // 默認(rèn)target為msvc,不加這一條就會(huì)找不到頭文件
"-std=c++1z" // c++1z即c++17,C語(yǔ)言最新標(biāo)準(zhǔn)為c11,或根據(jù)自己的需要進(jìn)行修改
], // 編譯命令參數(shù)
"type": "shell",
"group": {
"kind": "build",
"isDefault": true // 設(shè)為false可做到一個(gè)tasks.json配置多個(gè)編譯指令,需要自己修改本文件,我這里不多提
},
"presentation": {
"echo": true,
"reveal": "silent", // 設(shè)置是否在“終端”中顯示編譯信息,可以為always,silent,never。一些錯(cuò)誤提示也在這里,但是因?yàn)橛徐o態(tài)檢測(cè),我就設(shè)為silent了。
"focus": false,
"panel": "shared" // 不同的文件的編譯信息共享一個(gè)終端面板
},
"problemMatcher": {
"owner": "cpp",
"fileLocation": [
"relative",
"/"
],
"pattern": {
"regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$", // 正則表達(dá)式,用于描述在“問(wèn)題”欄中顯示的信息。
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
}
} // 1.11.0的更新日志里說(shuō)可以直接寫(xiě)"problemMatcher": "$gcc",但是我試了一下不行。
}
]
}
最后新建一個(gè)launch.json文件,里面是調(diào)試參數(shù)。
launch.json
// https://github.com/Microsoft/vscode-cpptools/blob/master/launch.md
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch", // 配置名稱(chēng),將會(huì)在啟動(dòng)配置的下拉菜單中顯示
"type": "cppdbg", // 配置類(lèi)型,這里只能為cppdbg
"request": "launch", // 請(qǐng)求配置類(lèi)型,可以為launch(啟動(dòng))或attach(附加)
"program": "${fileDirname}/${fileBasenameNoExtension}.exe", // 將要進(jìn)行調(diào)試的程序的路徑
"args": [], // 程序調(diào)試時(shí)傳遞給程序的命令行參數(shù),一般設(shè)為空即可
"stopAtEntry": false, // 設(shè)為true時(shí)程序?qū)和T诔绦蛉肟谔?,我一般設(shè)置為true
"cwd": "${workspaceRoot}", // 調(diào)試程序時(shí)的工作目錄
"environment": [], // (環(huán)境變量?)
"externalConsole": false, // 調(diào)試時(shí)是否顯示控制臺(tái)窗口,一般設(shè)置為true顯示控制臺(tái)
"MIMode": "gdb", // 指定連接的調(diào)試器,可以為gdb或lldb。但目前l(fā)ldb在windows下沒(méi)有預(yù)編譯好的版本。
"miDebuggerPath": "F:\\LLVM\\bin\\gdb.exe", // 調(diào)試器路徑。
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": false
}
],
"preLaunchTask": "Compile" // 調(diào)試會(huì)話(huà)開(kāi)始前執(zhí)行的任務(wù),一般為編譯程序。與tasks.json的taskName相對(duì)應(yīng)
}
]
}
安裝VS Code擴(kuò)展
為了能編譯并獲得自動(dòng)補(bǔ)全,還要漂亮,你可能需要如下VS Code 擴(kuò)展。
- C/C++
- C/C++ Snippets
- C/C++ Advanced Lint(vscode-c-cpp-flylint)
- Code Runner
- Include Autocomplete
- One Dark Pro:大概是VS Code安裝量最高的主題
其他
完成上面的操作之后,可以在工作區(qū)中創(chuàng)建C++文件了,寫(xiě)完以后使用快捷鍵Ctrl+Shift+B編譯,或者直接F5編譯并調(diào)試。
在上面的配置文件中,用到了一些VS Code 的變量,如果你想自定義一些東西,下面這些可能會(huì)有幫助。
${workspaceRoot} 當(dāng)前打開(kāi)的文件夾的絕對(duì)路徑+文件夾的名字
${workspaceRootFolderName} 當(dāng)前打開(kāi)的文件夾的名字
${file} 當(dāng)前打開(kāi)正在編輯的文件名,包括絕對(duì)路徑,文件名,文件后綴名
${relativeFile} 從當(dāng)前打開(kāi)的文件夾到當(dāng)前打開(kāi)的文件的路徑
${fileBasename} 當(dāng)前打開(kāi)的文件名+后綴名,不包括路徑
${fileBasenameNoExtension} 當(dāng)前打開(kāi)的文件的文件名,不包括路徑和后綴名
${fileDirname} 當(dāng)前打開(kāi)的文件所在的絕對(duì)路徑,不包括文件名
${fileExtname} 當(dāng)前打開(kāi)的文件的后綴名
${cwd} 同 pwd , 當(dāng)前絕對(duì)路徑
${lineNumber} 當(dāng)前打開(kāi)的文件,光標(biāo)所在的行數(shù)
文中配置文件參考了知乎的這個(gè)回答 https://www.zhihu.com/question/30315894/answer/154979413