天天看點

vscode中如何使用Makefile在Linux下編譯C/C++程式

作者:山城科技峰

前言

vscode号稱宇宙最強IDE,由于是插件化,非常友善支援各類應用的開發,程式設計體驗簡直好到爆,在Linux中寫C/C++程式的時候,如果源檔案很少,vscode是可以直接調用clang/gcc/g++編譯的,如果源檔案較多,則相對比較麻煩一些,還是使用原始的makefile更友善管理,也更友善在github上做自動編譯。

插件安裝

C/C++插件

要開發C/C++程式,首先要在vscode中安裝C/C++插件和C/C++ Extension Pack,如下圖:

vscode中如何使用Makefile在Linux下編譯C/C++程式

Makefile Creator插件

Makefile Creator插件可以自動生成Makefile的模闆(非常熟悉Makefile的可以忽略這一步)

vscode中如何使用Makefile在Linux下編譯C/C++程式

測試工程

建立源碼

  • 在vscode中,打開一個目錄(這裡我是在Windows中遠端連接配接到一個Linux系統中,關于如何配置遠端開發,以後有空再寫文章)
  • 建立一個源代碼檔案main.cpp,輸入Hello world經典源碼,如下:
#include <iostream>
using namespace std;
int main()
{
    cout << "Hello world!" << endl;
    return 0;
}
           

工程初始配置

此步驟對于已經熟悉vscode的tasks.json和Launch.json的配置,可以不用,不過這一步可以自動建立處配置檔案的模闆,即使熟悉了我也經常這樣做。

直接按“F5”,此時,會提示選擇配置,直接選擇第一個即可,如下圖:

vscode中如何使用Makefile在Linux下編譯C/C++程式

選擇後,會提供配置配置Launch,忽略掉後,程式不會直接運作,但會建立兩個json檔案。

  • Launch.json是運作調試的配置檔案,此時預設建立的應該是空檔案,如下
{
    "version": "0.2.0",
    "configurations": []
}
           
  • tasks.json是編譯的配置檔案,此時應該是預設使用了g++指令進行編譯,如下:
{
    "tasks": [
        {
            "type": "cppbuild",
            "label": "C/C++: g++ 生成活動檔案",
            "command": "/usr/bin/g++",
            "args": [
                "-fdiagnostics-color=always",
                "-g",
                "${file}",
                "-o",
                "${fileDirname}/${fileBasenameNoExtension}"
            ],
            "options": {
                "cwd": "${fileDirname}"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "detail": "調試器生成的任務。"
        }
    ],
    "version": "2.0.0"
}
           

預設編譯和運作

直接按下“CTRL+ALT+B”快捷鍵,就會執行tasks.json中配置的預設build任務,生成可執行檔案main,如下圖:

vscode中如何使用Makefile在Linux下編譯C/C++程式

在終端中執行./main,程式已經可以運作了,如下:

[ferris@cfnotes test]$ ll
total 24
-rwxrwxr-x 1 fawn fawn 19584 Sep 17 22:13 main
-rw-rw-r-- 1 fawn fawn   106 Sep 17 22:05 main.cpp
[ferris@cfnotes test]$ ./main
Hello world!
           

配置Launch.json和調試

菜單->運作->添加配置,此時會彈出配置模闆選擇,如下圖:

vscode中如何使用Makefile在Linux下編譯C/C++程式

選擇第一個,會根據模闆自動生成運作的配置檔案,如下:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) 啟動",
            "type": "cppdbg",
            "request": "launch",
            "program": "輸入程式名稱,例如 ${workspaceFolder}/a.out",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${fileDirname}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "為 gdb 啟用整齊列印",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                },
                {
                    "description":  "将反彙編風格設定為 Intel",
                    "text": "-gdb-set disassembly-flavor intel",
                    "ignoreFailures": true
                }
            ]
        }

    ]
}
           

将program修改為:${workspaceFolder}/main就進行調試了,打上斷點後,按“F5”即可啟動調試,如下圖:

vscode中如何使用Makefile在Linux下編譯C/C++程式

建立Makefile

安裝了Makefile Creator插件,可以在左側空白處點選右鍵,彈出菜單中有“Create Makefile”,如下圖:

vscode中如何使用Makefile在Linux下編譯C/C++程式

單擊後,會提示輸入Makefile的名稱,不輸入,預設可自動建立檔案名為“Makefile”的檔案。

建立後的Makefile檔案内容如下:

CXX = g++
CXXFLAGS = -Wall -Werror -Wextra -pedantic -std=c++17 -g -fsanitize=address
LDFLAGS =  -fsanitize=address

SRC = 
OBJ = $(SRC:.cc=.o)
EXEC = main

all: $(EXEC)

$(EXEC): $(OBJ)
	$(CXX) $(LDFLAGS) -o $@ $(OBJ) $(LBLIBS)

clean:
	rm -rf $(OBJ) $(EXEC)
           

Makefile中OBJ = $(SRC:.cpp=.o) 是一個Makefile替換表達式,表示SRC目錄庫下的所有.cpp檔案都有相應的.o檔案,編譯時會自動編譯,這樣就不用一個一個指定需要編譯的檔案了。

此時,直接在中斷中執行make,就可以直接編譯生成可執行的main檔案了。

啟用Makefile

雖然,Makefile已經建立成功了,但vscode中還沒有啟動,如果直接執行編譯,是不會調用Makefile的。

我們隻需要将前文所述生成的tasks.json檔案稍作修改即可,修改後的檔案如下:

{
    "tasks": [
        {
            "type": "cppbuild",
            "label": "C/C++: g++ 生成活動檔案",
            "command": "make",
            "args": [
            ],
            "options": {
                "cwd": "${fileDirname}"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "detail": "調試器生成的任務。"
        }
    ],
    "version": "2.0.0"
}
           

以上json是将“command”修改未“make”,“args”都删除掉,将"cwd"修改為"${workspaceFolder}"。

此時,執行編譯就可以直接試用makefile進行編譯了。

Make前執行clean

有時候我們編譯前想先執行以下clean,或者需要手動執行clean,修改tasks.json檔案如下:

{
    "tasks": [
        {
            "type": "cppbuild",
            "label": "C/C++: g++ 生成活動檔案",
            "command": "make",
            "args": [
            ],
            "options": {
                "cwd": "${workspaceFolder}"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "detail": "調試器生成的任務。",
            "dependsOn":["make clean"]
        },        
        {
            "type": "shell",
            "label": "make clean",
            "command": "make",
            "args": [
                "clean"
            ],
            "options": {
                "cwd": "${workspaceFolder}"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "none",
                "isDefault": false
            },
        }
    ],
    "version": "2.0.0"
}
           

我們添加了一個"make clean"的task,執行指令"make clean",此外在之前的編譯task中增加了 “dependsOn”:[“make clean”] 字段的配置,此時,執行編譯就會先執行"make clean",再執行"make"。如果不需要先“make clean”,可以将dependsOn删掉即可。