VS Code 配置 C/C++ 環境


寫作原因

  • 微軟的 VSCode 一直以來為人詬病的一個問題就是對於 C/C++ 工程的編譯以及調試支持度有限,配置起來比較復雜,但是 vscode-cpptools 團隊經過一段時間的 bug 修復之后,為我們帶來了眾多新特性
  • 截止到本文作成時 (2017-8-4) 此擴展已經更新到 0.12.1 版本,經過嘗試使用,新版本對於 C/C++ 的支持有了很大提升,但目前中文博客很少有提到如何使用新版的 vscode-cpptools,而舊版與新版之間的區別也比較明顯,所以這里記錄一個 C/C++ 工作環境配置方案以供參考

面向的問題

  • 一直以來,寫一個小型的 C/C++ 代碼工程是非常令人頭疼的一件事,比如有一個只有幾個源文件的代碼工程需要編輯和編譯:
    • 打開 IDE 進行編輯,會有種殺雞焉用牛刀的感覺,本可以在 IDE 打開的過程中就完成修改和編譯工作
    • 使用代碼編輯器配合命令行進行編譯,如果代碼有配合 Makefile,那么編譯不成問題,但是調試又是一個麻煩,命令行下的調試工具沒有那么直觀,學習起來也很耗費時間
  • 所以能不能做個折衷,直接在輕量級的代碼編輯器完成編輯、編譯、調試的工作呢?直到最近 vscode-cpptools 做了大量更新,這個想法才得以更好地實現

准備工作

工具准備

  1. 安裝 VS Code: 由於我們這里記錄的是工具配置,所以暫不介紹安裝流程,但相信點進這篇博客的讀者具備安裝工具的能力,或者已經安裝好了 VS Code
  2. 安裝 vscode-cpptools: 在 VS Code 的插件安裝欄中搜索 C/C++ 即可找到微軟官方出品的這個工具,根據指引安裝並重載窗口即可
  3. 編譯工具安裝: 一般來講在 VS Code 中進行開發並不涉及編譯工具版本,但是由於其對 Clang 的支持比較好,我推薦有能力的讀者安裝 Clang ,當然其他的任何編譯工具都是可以的,包括 GCC,MSVC等
    • 但是這里不得不提的一點是,在 Windows 下安裝 Clang 是一件不太愉快的事情,如果您在安裝時遇到困難,大可放棄安裝 Clang ,轉而安裝 GCC
    • 本文講解的內容是在 Windows 下實現的,在其他系統當中僅需對工具目錄等進行簡單的修改即可復現這個過程

方案選擇

  • 根據應用環境不同,本文提出兩種解決 C/C++ 工作環境配置的方案:
    1. 第一種是完全依賴 VS Code 的解決方案,即只使用其內置工具實現工作環境配置。這種方案比較簡單,但是對於代碼的遷移和擴展造成了一定的困擾。
    2. 第二種是 VS Code 配合 Makefile 的解決方案,即使用 VS Code 的代碼編輯功能,配合 Makefile 的編譯支持來配置工作環境。相對第一種解決方案,這種方案更適合代碼的遷移
      • 例如代碼從 Windows 平台的 VS Code 中遷移到服務器的 Linux 命令行下時,可以在 Windows 中使用 VS Code 來編輯和編譯,將代碼遷移后在 Linux 下使用 Makefile來編譯

方案一:VS Code 原生工具編譯

1. 新建測試工程

首先新建一個文件夾 VSC-CPP 並編寫幾個源文件,作為測試樣例
這個工程包含五個文件,包括兩對 .cpp + .h 的函數聲明與實現,以及一個調用這兩個函數的 main.cpp
目錄結構

- add.h     // add() 函數聲明
- add.cpp   // add() 函數實現
- sub.h     // sub() 函數聲明
- sub.cpp   // sub() 函數實現
- main.cpp  // 調用 add() 與 sub()

   
   
   
           
  • add.h:
#ifndef _ADD_H_
#define _ADD_H_

int add(int a, int b);

endif // ! ADD_H

  • add.cpp:
#include "add.h"

int add(int a, int b) { return a + b; }

  • sub.h:
#ifndef _SUB_H_
#define _SUB_H_

int sub(int a, int b);

endif // ! SUB_H

  • sub.cpp:
#include "sub.h"

int sub(int a, int b) { return a - b; }

  • main.cpp:
#include "add.h"
#include "sub.h"
#include <iostream>

int main() {
std::cout << add(1, 2) << std::endl;
std::cout << sub(2, 1) << std::endl;
return 0;
}

2. 配置環境

首先假定我們使用的編譯工具如下:

  1. 編譯工具:g++
  2. 調試工具:gdb
  • 在 VS Code 中打開工具窗口 (默認Ctrl+Alt+P) ,輸入 C/CPP: Edit Configurations來生成配置文件
    生成配置
  • 然后在自動打開的c_cpp_properties.json中配置 Include路徑等內容 (一般而言自動生成的就是可用的,但是 Windows 下可能需要額外配置)
    配置Include環境
  • 上一步結束后,一些 C/C++ 的代碼提示等功能應該就可以正常工作了,接下來我們讓 VS Code 能處理編譯工作
  • 打開工具窗口 (默認Ctrl+Shift+P) \rightarrow 輸入Tasks: Configure Task Runner,彈出窗口中選擇 Others (這里是假定我們要用 GCC 來編譯,如果使用 MSBuild 做這項工作,那么可以直接選擇 MSBuild 選項) \rightarrow 在新打開的tasks.json中配置如下 注意:復制這段代碼的時候請刪除其中的注釋,否則可能會報錯
    • task.json:
{
    "version": "2.0.0",
    "tasks": [
        {
            // 默認第一條為編譯命令
            "taskName": "build",
            // 使用 g++ 編譯
            "command": "g++",
            // 參數包含所有使用到的源文件
            "args": [
                "main.cpp",
                "add.cpp",
                "sub.cpp",
                "-o",
                "main.exe"
            ],
            // 默認在 shell 中執行編譯命令
            "type": "shell"
        },
        {
            // 編譯 debug 用的目標文件
            "taskName": "build-debug",
            "command": "g++",
            // -g 參數用於編譯可 debug 的目標文件
            "args": [
                "-g",
                "main.cpp",
                "add.cpp",
                "sub.cpp",
                "-o",
                "debug.exe"
            ],
            "type": "shell"
        }
    ]
}

   
   
   
           
  • 至此代碼應該可以正常編譯了:打開工具窗口 (默認Ctrl+Alt+P) \rightarrow 輸入Tasks: Run Tasks \rightarrow 此時應該已經可以看到兩個不同的任務,分別為 buildbuild-debug,與上一步定義的相同
    編譯過程

  • 選擇 build 並執行輸出得到的目標文件即可看到結果,說明編譯執行是正確無誤的
    運行結果

  • 接下來嘗試對代碼進行調試,進入調試窗口 \rightarrow 點擊調試配置按鈕 (如圖中紅圈所示)
    這里寫圖片描述

  • 選擇 C++(GDB/LLDB) (如果使用 MSVC 編譯,可以選擇C++(Windows)) \rightarrow 此時會生成調試配置文件 launcher.json
    launcher.json

  • 使用配置如下,根據您的具體系統環境進行修改

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Launch",
            "type": "cppdbg",
            "request": "launch",
            // g++ -g 生成的調試用目標文件名
            "program": "${workspaceRoot}/debug.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceRoot}",
            "environment": [],
            "externalConsole": true,
            "MIMode": "gdb",
            // 輸入 gdb 的路徑 (有些情況下需要絕對路徑)
            "miDebuggerPath": "gdb.exe",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            // task.json 中指定的調試目標文件編譯命令
            // 這樣可以在調試前免去手動執行 build-debug 的一步
            "preLaunchTask": "build-debug"
        }
    ]
}

   
   
   
           
  • 在源文件中添加一個斷點,點擊調試界面中的開始調試按鈕來調試
    調試

  • 至此編譯和調試工作都可以正常進行了,如果 GDB 版本足夠高,在調試 STL 程序時也會有很好的效果
    STL調試

  • 第一種方案的配置到這里基本結束了,大家可以繼續探索這種方案,不過這種方案比較受制於 VS Code ,可移植性不高。接下來我們提出另一種方式來提高 VS Code 的 C/C++ 工程的靈活性。

方案二:VS Code 配合 Makefile 來提高 C/C++ 工程的可移植性

准備工作

  • 在方案一的基礎上仍需准備如下內容:
  • 准備一套 Makefile 模板,比如說 https://github.com/TheNetAdmin/Makefile-Templates ,或者也可以自行寫一套模板,一個好的 Makefile 模板可以省去很多麻煩
  • 安裝編譯工具與 make 工具:尤其是在 Windows 下,使用 make 是一個比較麻煩的事情,推薦大家使用 msys 提供的一套工具,這里有一個打包供下載 https://pan.baidu.com/s/1kV5hx3p

方案說明

  • 這個方案的思路是:使用 Makefile 來構建工程, VS Code 通過 Tasks 調用 make 工具來編譯,再通過調用 gdb 來調試
  • 其優點在於不是過分依賴 VS Code 自身的配置,一個合適的 Makefile 可以在各個平台上執行編譯,但是在開發過程中又可以用到 VS Code 自身的插件帶來的便利,減少命令輸入,減少命令行 gdb 調試帶來的煩惱

步驟說明

  • 首先構建一個 Makefile ,如果沒有合適的可以到這里找到一些現成模板
# originating https://github.com/TheNetAdmin/Makefile-Templates
# tool marcros
CC := g++
CCFLAG := -std=c++14
DBGFLAG := -g
CCOBJFLAG := $(CCFLAG) -c

path marcros

BIN_PATH := bin
OBJ_PATH := obj
SRC_PATH := src
DBG_PATH := debug

compile marcros

TARGET_NAME := main
ifeq ($(OS),Windows_NT)
TARGET_NAME := $(addsuffix .exe,$(TARGET_NAME))
endif
TARGET := $(BIN_PATH)/$(TARGET_NAME)
TARGET_DEBUG := $(DBG_PATH)/$(TARGET_NAME)
MAIN_SRC := src/main.cpp

src files & obj files

SRC := $(foreach x, $(SRC_PATH), $(wildcard $(addprefix $(x)/,.c)))
OBJ := $(addprefix $(OBJ_PATH)/, $(addsuffix .o, $(notdir $(basename $(SRC)))))
OBJ_DEBUG := $(addprefix $(DBG_PATH)/, $(addsuffix .o, $(notdir $(basename $(SRC)))))

clean files list

DISTCLEAN_LIST := $(OBJ)
$(OBJ_DEBUG)
CLEAN_LIST := $(TARGET)
$(TARGET_DEBUG)
$(DISTCLEAN_LIST)

default rule

default: all

non-phony targets

$(TARGET): $(OBJ)
$(CC) $(CCFLAG) -o $@ $?

$(OBJ_PATH)/%.o: $(SRC_PATH)/%.c*
$(CC) $(CCOBJFLAG) -o $@ $<

$(DBG_PATH)/%.o: $(SRC_PATH)/%.c*
$(CC) $(CCOBJFLAG) $(DBGFLAG) -o $@ $<

$(TARGET_DEBUG): $(OBJ_DEBUG)
$(CC) $(CCFLAG) $(DBGFLAG) $? -o $@

phony rules

.PHONY: all
all: $(TARGET)

.PHONY: debug
debug: $(TARGET_DEBUG)

.PHONY: clean
clean:
@echo CLEAN $(CLEAN_LIST)
@rm -f $(CLEAN_LIST)

.PHONY: distclean
distclean:
@echo CLEAN $(CLEAN_LIST)
@rm -f $(DISTCLEAN_LIST)

  • 根據這個 Makefile,構建一個目錄結構如下的工程目錄
- Project
	- Makefile
	- src: 所有源文件 (不得放在子目錄)
		- add.cpp
		- add.h
		- sub.cpp
		- sub.h
		- main.cpp
	- obj
		- 空
	- debug
		- 空
	- bin
		- 空

   
   
   
           
  • 然后對於 VS Code 的 tasks.json 和 launch.json 做一些修改如下
  • tasks.json
{
    "version": "2.0.0",
    "tasks": [
        {
            "taskName": "build",
            "command": "make",
            "args": ["default"],
            "type": "shell"
        },
        {
            "taskName": "build-debug",
            "command": "make",
            "args": ["debug"],
            "type": "shell"
        },
        {
            "taskName": "clean",
            "command": "make",
            "args": ["clean"],
            "type": "shell"
        }
    ]
}

   
   
   
           
  • launch.json:
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Launch",
            "type": "cppdbg",
            "request": "launch",
            // 修改為新的測試目標文件路徑
            "program": "${workspaceRoot}/debug/main.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceRoot}",
            "environment": [],
            "externalConsole": true,
            "MIMode": "gdb",
            "miDebuggerPath": "gdb.exe",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "build-debug"
        }
    ]
}

   
   
   
           
  • 之后就如方案一中的步驟使用編譯和調試工具即可

guide2

  • 這樣的話將這個工程遷移到其他平台也不用擔心沒有 VS Code 而無法使用
  • 同時,如果工程發生重構,那么只需要更改 Makefile 與工程結構即可,不需要在 VS Code 中修改過多

總結

  • 總體而言,經過微軟官方團隊一段時間的努力, VS Code 上的 C/C++ 開發體驗有了很大提升,在面對一個比較小型的工程時,我們可以免去開啟 IDE 的時間以及處理 IDE 目錄結構的時間,從而快速打開工程,快速開發並驗證思路

  • 但是 VS Code 畢竟只是一個代碼編輯器,無論我們賦予它多少功能,其對大型工程的處理能力終究是不如 IDE 的。比如 Refactor ,包管理,動態類型糾錯,語法糾錯等功能一直是 IDE 的強項,所以在面對比較復雜的工程時,不用多想,還是乖乖使用 IDE 吧

      </div>

原文地址:https://blog.csdn.net/wzxlovesy/article/details/76708151


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM