安裝套件
- cmake extension
c++ extension
- 安裝編譯器GCC、除錯器DBG
1 2 3
sudo apt-get update sudo apt-get install build-essential gdb gcc -v #確認GCC安裝成功
- 安裝CMake 直接用
sudo apt install cmake
,安裝的版本會比較舊,因此如果想用CMake最新的功能可以按照官方網站的安裝方式,安裝後我們可以測試一下CMake安裝成功,在這裡我們CMake的版本至少要大於3.151
cmake --version
編譯C++檔
用以下指令建立一個專案資料夾,最後一行code .
會直接打開一個新的VScode並且以這個資料夾作為工作目錄
1
2
3
4
5
mkdir projects
cd projects
mkdir helloworld
cd helloworld
code .
在helloworld資料夾建立helloworld.cpp
檔案並且寫入以下程式碼,然後按下編譯按鈕,並且選擇g++作為編譯器(如下圖所示)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<string> msg {"Hello", "C++", "World", "from", "VS Code", "and the C++ extension!"};
for (const string& word : msg)
{
cout << word << " ";
}
cout << endl;
}
成功編譯後,你會在Terminal
看到程式成功輸出文字
第一次按下執行compiler後,VScode會幫你建立一個.vscode
資料夾和一個,tasks.json
。或是你可以自己建立一個.vscode
資料夾並且放入tasks.json
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: gcc-9 build active file",
"command": "/usr/bin/gcc-9",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-o",
"${fileDirname}/${fileBasenameNoExtension}"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "Task generated by Debugger."
}
],
"version": "2.0.0"
}
在這個資料夾下可以有三種檔案,每個檔案各有自己的用處,關於tasks.json
詳細設定可以參考這裡
- tasks.json (compiler build settings)
- launch.json (debugger settings)
- c_cpp_properties.json (compiler path and IntelliSense settings)
在tasks.json
裡面有幾個的比較重要的點
args
是給GCC的參數,要符合GCC參數的順序- 在這裡我們用
${file}
這個變數告訴GCC目前打開的檔案讓他編譯 ${fileDirname}
這個變數告訴GCC目前的資料夾位置,讓他在這個位置產生我們的執行檔${fileBasenameNoExtension}
變數取出目前開啟的檔名但是不包含副檔名,我們用這個名字作為我們的執行檔名,也就是helloworldlabel
會顯示在task清單detail
會顯示在task清單的詳細描述。先按下Ctrl+P
並且輸入task
(task後面有空白),就會顯示task清單,包含我們建立的task(如下圖所示)- 如果有多個task,可以利用
group
裡面isDefault
屬性設定預設task
除錯、設中斷點
- 在程式碼下一個中斷點,並且點及旁邊的執行按鈕並且選擇Debug就可以開始除錯了
設定在啟動程式時傳入參數給程式
如果像在啟動程式時傳入一些參數,可以利用launch.json
,要建立launch.json
只需要案價旁邊的齒輪並選擇G++,VSCode就會自動幫你建立一份
在launch.json
裡面有幾個的比較重要的點
program
是要執行的執行檔名稱,也就是我們編譯後產生的helloworld
檔args
是執行時要傳給執行檔的參數
C/C++的其他設定
通常編寫C/C++的時候也會用到很多函式庫,我們可以指定這些函式庫的路徑讓VSCode的Intelligence Scope懂這些函式庫。
首先按下Ctrl+Shift+P
並且輸入C/C++,按下C/C++: Edit Configurations (UI)
,後VSCode會幫我們產生一個c_cpp_properties.json
。 在Include path
的地方加入我們要包含的路徑。或者我們也可以在c_cpp_properties.json
configurations下的includePath直接做修改
g++ include OpenCV函式庫
首先我們先按照Linux安裝prebuild函式庫以OpenCV為例這篇文章安裝prebuild的OpenCV library。 接下來建立一個ShowImage.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
using namespace cv;
int main()
{
std::string image_path = samples::findFile("starry_night.jpg");
Mat img = imread(image_path, IMREAD_COLOR);
if(img.empty())
{
std::cout << "Could not read the image: " << image_path << std::endl;
return 1;
}
imshow("Display window", img);
int k = waitKey(0); // Wait for a keystroke in the window
if(k == 's')
{
imwrite("starry_night.png", img);
}
return 0;
}
我們可以發現VSCode的Intelligence scope找不到OpenCV標頭檔而顯示紅色虛線。
這時候我們需要修改前面步驟提到的c_cpp_properties.json
include OpenCV的路徑就可以了,而因為我們是安裝prebuild的OpenCV,所以我們的標頭檔已經被安裝在/usr/include/opencv4/
裡面,因此修改後的c_cpp_properties.json
如下。我們在includePath
的清單中加入了/usr/include/opencv4/**
,之後你就可以看到Intelligence scope成功認出OpenCV,而且OpenCV的函示可以順利顯示說明文字
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/usr/include/opencv4/**"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "gnu17",
"cppStandard": "gnu++17",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}
不過這時候g++依然不知道OpenCV的標頭檔在哪裡,所以如果直接編譯還是會出錯。
pkg-config幫我們列出全部的標頭檔位置和opencv的名稱
標頭檔路徑只需要加上g++選項-I/usr/include/opencv4
就可以了,不過如果要把所有用到的library都手動寫出來實在很麻煩,這時候pkg-config
可以幫我們把全部的opencv library全部列出來,我們可以試看看在終端機輸入下面指令pkg-config --libs --cflags opencv4
(如果安裝的是opencv 2.x或3.x要輸入pkg-config --libs --cflags opencv
),終端機的回應應該會長的像下面這樣。
1
2
$ pkg-config --libs --cflags opencv4
-I/usr/include/opencv4 -lopencv_stitching -lopencv_alphamat -lopencv_aruco -lopencv_barcode -lopencv_bgsegm -lopencv_bioinspired -lopencv_ccalib -lopencv_dnn_objdetect -lopencv_dnn_superres -lopencv_dpm -lopencv_face -lopencv_freetype -lopencv_fuzzy -lopencv_hdf -lopencv_hfs -lopencv_img_hash -lopencv_intensity_transform -lopencv_line_descriptor -lopencv_mcc -lopencv_quality -lopencv_rapid -lopencv_reg -lopencv_rgbd -lopencv_saliency -lopencv_shape -lopencv_stereo -lopencv_structured_light -lopencv_phase_unwrapping -lopencv_superres -lopencv_optflow -lopencv_surface_matching -lopencv_tracking -lopencv_highgui -lopencv_datasets -lopencv_text -lopencv_plot -lopencv_ml -lopencv_videostab -lopencv_videoio -lopencv_viz -lopencv_wechat_qrcode -lopencv_ximgproc -lopencv_video -lopencv_xobjdetect -lopencv_objdetect -lopencv_calib3d -lopencv_imgcodecs -lopencv_features2d -lopencv_dnn -lopencv_flann -lopencv_xphoto -lopencv_photo -lopencv_imgproc -lopencv_core
我們可以發現回傳的文字可以直接當成g++的選項來用,因此我們修改tasks.json
,在給g++的參數args
的list加入
1
"`pkg-config --libs --cflags opencv4`"
改好後tasks.json
如下,注意pkg-config --libs --cflags opencv4
被兩個引號包圍,因為原本g++的指令是長這樣
1
/usr/bin/g++ -g main.cpp -o main `pkg-config --libs --cflags opencv4`
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++ build active file",
"command": "/usr/bin/g++",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-o",
"${fileDirname}/${fileBasenameNoExtension}",
"`pkg-config --libs --cflags opencv4`"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "Task generated by Debugger."
}
],
"version": "2.0.0"
}
接下來VSCode就可以順利編譯程式並產生執行檔了。
用CMake管理跨Windows和Linux的C++專案以Darknet為例
如果開發團隊中有人用Windows OS開發,有人用Linux OS開發,而Windows的人只熟悉Visual Studio。這時候要一起合作完成專案在編譯的時候就會遇到困難。CMake跨平台的專案產生器就是專門解決這個問題。只要寫好一次CMake檔,他就可以在Windows幫你產生Visual Studio專案檔.sln,或是在Linux產生Makefile。很多時候我們會想要直接編譯別人的開源程式,這裡我們將以Darknet作為範例。開始這個範例之前你必須先在電腦上安裝好OPenCV
下載Darknet
1
2
git clone git@github.com:AlexeyAB/darknet.git
cd darknet
建立CMake的task.json
按下ctrl + shift + p
並且輸入task,選擇Tasks: Configure task
,然後再選擇CMake: build
,就task設定就會產生在${workspaceFolder}/.vscode/tasks.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"version": "2.0.0",
"tasks": [
{
"type": "cmake",
"label": "CMake: build",
"command": "build",
"targets": [
"all"
],
"group": "build",
"problemMatcher": [],
"detail": "CMake template build task"
}
]
}
這個檔案會編譯所有的CMake Targets,你也可以指定你想編譯的targets。
設定build參數
首先我們先查看Darknet有哪些CMake項可以設定,輸入cmake -S . -B build -LH
就可以看到選項。在這個範例不想要使用CUDA,所以要把ENABLE_CUDA:BOOL=ON
設為OFF
。我們可以建立一個設定檔在${workspaceFolder}/.vscode/settings.json
,並且輸入以下內容。更多其他的CMake設定可以在這裡查到。另外因為Darknet已經存在build資料夾,所以我們指定其他資料夾作為build資料夾cmake.buildDirectory": "${workspaceFolder}/local-build
,不過通常我們可以直接用預設值,並不需要另外設定cmake.buildDirectory
1
2
3
4
5
6
7
{
"cmake.configureArgs": [
"-DENABLE_CUDA=OFF",
"-DVCPKG_BUILD_OPENCV_WITH_CUDA=OFF"
],
"cmake.buildDirectory": "${workspaceFolder}/local-build"
}
CMake Config
首先我們要先跑一次CMake Config,按下ctrl + shift + p
輸入cmake選擇CMake:Configure
,在Output的地方會看到有沒有錯誤,如果出現錯誤歡迎在下面留言板留言。
建立launch.json
接下來要設定啟動,先建立一個launch.json位於${workspaceFolder}/.vscode/launch.json
,並且複製以下內容。在這裡用到許多CMake extension提供的變數,可以在這裡查詢更多的變數。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
// Resolved by CMake Tools:
"program": "${command:cmake.launchTargetPath}",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
// add the directory where our target was built to the PATHs
// it gets resolved by CMake Tools:
"name": "PATH",
"value": "${env:PATH}:${command:cmake.getLaunchTargetDirectory}"
},
{
"name": "OTHER_VALUE",
"value": "Something something"
}
],
"console": "externalTerminal",
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}
{= file:’launch.json’}
設定啟動時參數
首先要先下載yolov1.cfg
和yolov1.weights
並且放到cfg
資料夾 Darknet執行檔啟動時需要參數,我們可以在launch.json
的args
設定。
1
"args": ["detect", "cfg/yolov1.cfg", "cfg/yolov1.weights", "data/dog.jpg"],
執行
參考:
Build with CMake Tools
https://github.com/microsoft/vscode-cmake-tools/blob/f4804bcd2d376b4ad850c537d6ebdae46cfdcf3c/docs/build.md
https://code.visualstudio.com/docs/cpp/config-linux
Display an image in an OpenCV window
https://docs.opencv.org/4.x/db/deb/tutorial_display_image.html
pkg-config尋找opencv函式庫 https://answers.opencv.org/question/227890/using-l-in-g-command-line/
Get started with CMake Tools on Linux https://code.visualstudio.com/docs/cpp/cmake-linux
CMake Tools for Visual Studio Code documentation https://github.com/microsoft/vscode-cmake-tools/blob/main/docs/README.md
Guide: “A modern, open source C++ dev environment with Visual Studio Code, vcpkg, and CMake”
https://www.reddit.com/r/cpp/comments/j1dh9w/guide_a_modern_open_source_c_dev_environment_with/