在VS Code中使用Clang作為你的C++編譯器

相比龐大的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

Visual Studio 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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容