文章框架
前言
LOX(Lightweight Open-source Xplatform)是我正在編寫的一個(gè)全新文集,意思就如其名:輕量級(jí)-開源-跨平臺(tái)。就是這個(gè)系列中的文章和例程都符合輕量級(jí)(Lightweight)、開源(Open-Source)、跨平臺(tái)(Cross-Platform)。嗯,我這人吧,就好起一些新的名詞。
本篇作為LOX系列的第一篇,也向你展示了一個(gè)最簡單的LOX項(xiàng)目。如果想看一個(gè)稍微復(fù)雜一點(diǎn)的LOX項(xiàng)目,可以clone我Github上的一個(gè)Repo:2048 CLI。歡迎來搞~
單源文件
先從簡單的來,一個(gè)源文件。
工具
進(jìn)行本次LOX開發(fā)所需要工具,點(diǎn)擊下面的Title進(jìn)入官網(wǎng)下載。
VSCode是微軟出品的一款非常良心的輕量級(jí)編輯器,雖說是完全照著Sublime Text弄出來的,但它免費(fèi)啊,還開源啊,所以我也就不深究模仿不模仿了。(嗨呀,原則呢?嗯?)
需要的插件
插件 | 標(biāo)識(shí)符 | 說明 |
---|---|---|
C/C++ | ms-vscode.cpptools | C/C++語言支持,簡單的編輯、編譯、調(diào)試等功能。 |
這個(gè)工具是在Windows上需要的。因?yàn)閃indows沒有GNU工具包,MinGW就是為Windows而生的GNU工具包。
需要安裝的包
包 | 說明 |
---|---|
mingw32-gcc.bin | GNU C編譯器 |
mingw32-gcc-g++.bin | GNU C++編譯器 |
mingw32-gdb.bin | GNU 調(diào)試器 |
環(huán)境變量
在系統(tǒng)變量的PATH
中,添加MinGW安裝的根目錄中的bin文件夾(如C:\MinGW\bin
),且盡量將這一項(xiàng)往上移(為了優(yōu)先搜索該目錄)。
完成這一步后,如果打開了VSCode,記得要重啟VSCode。
編碼
建立工作空間
新建一個(gè)文件夾 - 右鍵 - Open with Code。使用這種方法的前提是你在安裝VSCode時(shí)選中了“”
或者在VSCode中 - 文件 - 打開文件夾,選中一個(gè)空文件夾作工作空間。
新建源文件
鼠標(biāo)移動(dòng)到新建的文件夾的根目錄處(我的是“HelloWorld”),點(diǎn)擊下圖藍(lán)色框住的圖標(biāo)(新建文件)。
之后在其中輸入文件名(包括后綴名),本例的后綴名寫".c"或".cpp"。然后在其中寫個(gè)最簡單的HelloWorld。
代碼
#include <stdio.h>
int main(){
printf("Hello World");
return 0;
}
編碼時(shí),如果想自動(dòng)補(bǔ)全,需要在包含指定頭文件后保存代碼,然后才會(huì)啟動(dòng)自動(dòng)補(bǔ)全。
也就是說,它只對保存后的代碼進(jìn)行探測。
生成
生成快捷鍵:Ctrl(Mac: Command)+Shift+B
第一次生成時(shí),VSCode會(huì)提示找不到生成的配置文件task.json
,點(diǎn)擊“配置生成任務(wù)”。
在給出的模板中選擇
Others
。在打開的task.json
中改為下述代碼。
{
"version": "0.1.0",
"command": "gcc",
"isShellCommand": true, // 是否為Shell命令
"args": ["-g","${file}","-o","${fileDirname}/${fileBasenameNoExtension}.out"],
"showOutput": "always"
}
其實(shí)作用就是代碼中所述的。
"command": "gcc"
和"args": ["-g","${file}","-o","${fileDirname}/${fileBasenameNoExtension}.out"]
就相當(dāng)于在Shell中直接鍵入gcc -c 源文件.c -o 源文件所在目錄/源文件.out
。將鼠標(biāo)放在Key(冒號(hào)前面的)上會(huì)顯示所對應(yīng)的意思(下面的Launch.json同)。
簡單的解釋一下其中幾個(gè)$
標(biāo)識(shí)
標(biāo)識(shí) | 作用 |
---|---|
${file} |
當(dāng)前文件的完整文件名(包括路徑、文件名、后綴名) |
${fileDirname} |
當(dāng)前文件的路徑 |
${fileBasenameNoExtension} |
當(dāng)前文件的文件名(不包括路徑、后綴名) |
其中所說的“當(dāng)前文件”指的是你在VSCode編輯器中打開的并正在編輯的文件。
完成task.json
的配置后,我們縮寫的程序已經(jīng)可以運(yùn)行了。生成的程序就是源文件所在根目錄中出現(xiàn)的與源文件同名但后綴名為.out
的文件。
調(diào)試
我們當(dāng)然不能僅僅滿足于生成出程序就行的,大部分情況我們是要調(diào)試的。
調(diào)試快捷鍵:F5
第一次按F5
時(shí)和生成時(shí)一樣,找不到配置文件,在打開的模板中選C++ (GDB/LLDB)
(可以跨平臺(tái))。
生成的配置文件為launch.json
將launch.json
改為下述代碼
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch", // 本配置的名稱,隨便起
"type": "cppdbg",
"request": "launch", // 如果調(diào)試的類型為附加進(jìn)程,需將這里改為attach
"program": "${fileDirname}/${fileBasenameNoExtension}.out", // 要調(diào)試的程序路徑
"stopAtEntry": false, // 是否在起點(diǎn)處停頓
"cwd": "${workspaceRoot}",
"externalConsole": true, // 在外部控制臺(tái)運(yùn)行。若為false,則運(yùn)行在VSCode自帶的控制臺(tái)中
"linux": { // Linux 系統(tǒng)下的配置
"MIMode": "gdb"
},
"osx": { // OS X系統(tǒng)下的配置
"MIMode": "lldb"
},
"windows": { // Windows 系統(tǒng)下的配置
"MIMode": "gdb",
"miDebuggerPath": "gdb.exe"
}
}
]
}
Windows默認(rèn)是沒有g(shù)db或lldb的,所以我們需要安裝MinGW中的gdb,并在這里設(shè)置gdb的路徑。只寫程序名是因?yàn)樵O(shè)置了環(huán)境變量。
完成launch.json
的配置并切換到源代碼編輯頁之后
再一次:F5
多源文件
什么!你不滿足于單源文件開發(fā)?!來來來,我給你看個(gè)寶貝。
的確,單源文件開發(fā)一般也就是個(gè)做做算法題,現(xiàn)在隨便寫個(gè)像樣的工程都是多個(gè)源文件編譯鏈接一條龍的。這樣VSCode可以嗎,也可以!但需要新的幫手:CMake。
工具
新需要的插件
實(shí)際上通過CMake在VSCode上進(jìn)行項(xiàng)目開發(fā)可以不需要任何插件,但是用上這些插件之后你會(huì)發(fā)現(xiàn)這個(gè)過程會(huì)變得特別方便!
除去單源文件中所提到的cpptools
,還需要下面的插件。
插件 | 標(biāo)識(shí)符 | 說明 |
---|---|---|
CMake | twxs.cmake | 提供CMake語法支持,包括高亮和自動(dòng)補(bǔ)全等 |
CMake Tools | vector-of-bool.cmake-tools | 這個(gè)屌!完全把CMake封裝成一套VSCode底邊欄的工具集 |
同樣這一步僅在Windows上做。
需要新安裝的包
包 | 說明 |
---|---|
mingw32-make.bin | GNU Make,根據(jù)makefiles(在這里makefiles由CMake搞定)生成項(xiàng)目 |
為了方便調(diào)用,我一般會(huì)把mingw32-make.exe
在其目錄中復(fù)制一份出來,命名為make.exe
。
這一步某種程度意義上講還蠻重要的,第一是方便自己調(diào)用(直接在shell里make
),第二是方便vscode的插件調(diào)用(如果不弄一個(gè)cmake.exe
出來的話,vector-of-bool.cmake-tools
會(huì)報(bào)錯(cuò),不過具體鍋是vector-of-bool.cmake-tools
還是twxs.cmake
的也不太清楚,目前vector-of-bool已經(jīng)把這個(gè)問題(#157
)標(biāo)記為bug
,并打算在0.10.0
版本解決。)。
安裝時(shí)記得將Add CMake to system PATH
勾上。是for all users
呢還是for current user
你自己看咯。
編碼
上個(gè)例子是C,那這個(gè)就上C++好了。
目錄結(jié)構(gòu)
我就不同目錄下多文件了啊,那沒啥意思。咱上多層級(jí)目錄多源文件的。
代碼
Printer.h
#pragma once
class Printer{
public:
void print();
Printer();
~Printer();
};
Printer.cpp
#include "Printer.h"
#include <iostream>
using namespace std;
void Printer::print(){
cout<<"Hello World"<<endl;
}
Printer::Printer() {
cout<<"Printer Object Constructed"<<endl;
}
Printer::~Printer(){
cout<<"Printer Object Destructed"<<endl;
}
- 'main.cpp'
#include "Lib/Printer.h"
int main(){
Printer* printer = new Printer();
printer->print();
delete printer;
return 0;
}
生成項(xiàng)目
編寫CMakeLists
每一個(gè)包含源文件的目錄中都要編寫CMakeLists.txt
-
CMakeLists.txt
根目錄中的CMakeLists.txt
,一般程序入口(main
函數(shù))在此。
# 使用CMake Tools插件(可選,如果這個(gè)項(xiàng)目去到一個(gè)沒有這個(gè)插件的機(jī)器也同樣可以生成項(xiàng)目)
include(CMakeToolsHelpers OPTIONAL)
# CMake 最低版本號(hào)要求
cmake_minimum_required(VERSION 2.8)
# 項(xiàng)目名稱
project(CMakeTest)
# 查找當(dāng)前目錄下的所有源文件
# 并將名稱保存到 DIR_ROOT_SRCS變量
aux_source_directory(. DIR_ROOT_SRCS)
# 添加 Lib子目錄
add_subdirectory(Lib)
# 指定生成目標(biāo)
add_executable(CMakeTest main.cpp ${DIR_ROOT_SRCS})
# 添加鏈接庫
target_link_libraries(CMakeTest PrinterLib)
-
Lib/CMakeLists.txt
子目錄中的CMakeLists.txt
,一般將子目錄中的源文件編譯為靜態(tài)鏈接庫。
include(CMakeToolsHelpers OPTIONAL)
cmake_minimum_required(VERSION 2.8)
aux_source_directory(. DIR_LIB_SRCS)
# 生成鏈接庫
add_library(PrinterLib ${DIR_LIB_SRCS})
Build
完成上面步驟后,就可以Build了,如果你安裝了vector-of-bool.cmake-tools
插件,VSCode左下角的底邊欄會(huì)有Build
按鈕。
點(diǎn)擊
Build
后,選擇Debug
(為了下一步演示調(diào)試,若不調(diào)試就Release
)輸出框會(huì)不停往出噴東西,只要最后輸出了
[vscode] cmake exited with return code 0
,就說明Build成功。目錄結(jié)構(gòu)
新增加的build文件夾是
vector-of-bool.cmake-tools
插件干的,它做的很好,如果我們手動(dòng)cmake - make
,那些生成文件會(huì)跑的到處都是。其中
build/CMakeTests.exe
就是我們生成的可執(zhí)行程序。
調(diào)試
調(diào)試設(shè)置
文件
- 首選項(xiàng)
- 設(shè)置
在CMake Tools configuration
中找到cmake.debugConfig
,生成設(shè)置:
"cmake.debugConfig": {
"miDebuggerPath": "gdb.exe", // Windows 下指定gdb路徑(已添加到PATH)
"externalConsole": true, // 使用外部控制臺(tái)
"stopAtEntry": false // 在起點(diǎn)處停頓(噢!在這停頓?。? },
Start Debugging
剛Build完你可能看不到這兩個(gè)按鈕:
其實(shí)他們藏起來了... 這應(yīng)該是個(gè)Bug,我已經(jīng)反饋給作者了。
重啟VSCode后他們就會(huì)出現(xiàn),或者直接點(diǎn)那兩個(gè)藏起來的按鈕(還有這種操作??。?strong>先點(diǎn)右邊選擇調(diào)試目標(biāo),再點(diǎn)左邊開始調(diào)試。
合影留念
結(jié)語
Code Everywhere, Build Everywhere.
這樣的搭配是不是很爽呢?除了MinGW是Windows特有的矯情外。其余的在任何平臺(tái)都是一樣的。雖說現(xiàn)在VSCode和上面的大部分插件都運(yùn)行的不太穩(wěn)定,但是我還是很喜歡這種組合進(jìn)行跨平臺(tái)的輕量級(jí)開發(fā)的。
FAQ
-
Q: VSCode或編譯器找不到頭文件?
A: 如果VSCode用綠色波浪線給你劃出那些找不到源的代碼時(shí),將鼠標(biāo)停留在波浪線上,然后會(huì)出現(xiàn)一個(gè)小 燈泡。點(diǎn)“Add include path to settings.”。然后它會(huì)自動(dòng)幫你建立一個(gè)名為“c_cpp_properties.json”的文件。
"name": "Mac",
"includePath": [
"${workspaceRoot}",
"/usr/include",
"/usr/local/include"
],
你會(huì)在其中找到類似上述代碼塊的地方,根據(jù)“name”后面所描述的系統(tǒng),在其下的“includePath”中手動(dòng)添加頭文件目錄。JSON語法。
-
Q: 為什么路徑動(dòng)不動(dòng)就寫成
${fileDirname}/${fileBasenameNoExtension}.out
?A: 這樣做的好處就是可以在同一配置下進(jìn)行多個(gè)單文件的編譯開發(fā),不用每次生成和調(diào)試的時(shí)候都去寫配置文件。使用場景嘛,主要就是寫寫算法題之類的。
我寫算法題時(shí)的目錄結(jié)構(gòu)
.out
后綴名就是自己瞎起的。不同平臺(tái)的可執(zhí)行后綴名都不一樣,這樣寫就跟誰都不沾邊了... -
Q: 如果我不用
vector-of-bool.cmake-tools
插件,要如何Build?A: 寫完
CMakeLists.txt
后,打開VSCode中自帶的終端(點(diǎn)擊底邊欄的輸出按鈕)
鍵入:
cmake .
會(huì)生成系統(tǒng)對應(yīng)的項(xiàng)目(如果你是Windows并安裝了Visual Studio,他就會(huì)生成VS項(xiàng)目)。若想生成
MinGW Makefiles
則鍵入cmake -G "MinGW Makefiles" .
(注意區(qū)分大小寫),之后會(huì)為你生成makefiles,然后再鍵入make
(若沒制作前面所提到的mingw32-make.exe
的名為make.exe
的副本,則鍵入mingw32-make
),最終生成可執(zhí)行文件。