快速在VSCode中建立多檔案多目錄C++專案
對於輕量級的VSCode編輯器,我想像使用那些IDE一樣,通過簡單的幾步就能構建出自己的專案檔案樹,類似於下面的結構。所以特地寫了一個指令碼,用於自動建立一個基本的專案。
.
├── Headers
│ └── test.hpp
├── makefile
├── Output
│ └── bin
└── Sources
├── main.cpp
└── test.cpp
下面直接提供指令碼:
### new.sh
# 輸入一個檔名 $projectname
read projectname
# 新增字首
filename="VSC_CPP_"$projectname
# 原始檔目錄
Src="$filename/Sources"
# 標頭檔案目錄
Inc="$filename/Headers"
# 建立專案樹
mkdir -p $Src $Inc $filename/Output/bin
# 建立makefile檔案
touch $filename/makefile
# 建立 main.cpp檔案
touch $Src/main.cpp
# 檔名小寫轉換
#declare -l lfilename=$projectname
lfilename="${projectname,,}"
# 原始檔
cpp_file=$Src"/"${lfilename}".cpp"
# 標頭檔案
hpp_file=$Inc"/"${lfilename}".hpp"
# 建立一對專案檔案
touch $cpp_file $hpp_file
# 向main.cpp中寫入內容
echo "#include <iostream> " >> $Src/main.cpp
echo "#include \"$lfilename.hpp\"" >> $Src/main.cpp
echo "" >> $Src/main.cpp
echo "using namespace std;" >> $Src/main.cpp
echo "" >> $Src/main.cpp
echo "int main()" >> $Src/main.cpp
echo "{" >> $Src/main.cpp
echo " cout << \"Hello VSC\" << endl;" >> $Src/main.cpp
echo " return 0;" >> $Src/main.cpp
echo "}" >> $Src/main.cpp
# 向*.hpp中寫入內容
echo "#pragma once" >> $Inc/$lfilename.hpp
echo "#include <iostream>" >> $Inc/$lfilename.hpp
echo "using namespace std;" >> $Inc/$lfilename.hpp
echo "" >> $Inc/$lfilename.hpp
echo "class $projectname" >> $Inc/$lfilename.hpp
echo "{" >> $Inc/$lfilename.hpp
echo "public:" >> $Inc/$lfilename.hpp
echo " $projectname();" >> $Inc/$lfilename.hpp
echo " $projectname($projectname &&) = default;" >> $Inc/$lfilename.hpp
echo " $projectname(const $projectname &) = default;" >> $Inc/$lfilename.hpp
echo " $projectname &operator=($projectname &&) = default;" >> $Inc/$lfilename.hpp
echo " $projectname &operator=(const $projectname &) = default;" >> $Inc/$lfilename.hpp
echo " ~$projectname();" >> $Inc/$lfilename.hpp
echo "" >> $Inc/$lfilename.hpp
echo "protected:" >> $Inc/$lfilename.hpp
echo "" >> $Inc/$lfilename.hpp
echo "private:" >> $Inc/$lfilename.hpp
echo "" >> $Inc/$lfilename.hpp
echo "};" >> $Inc/$lfilename.hpp
# 向*.cpp中寫入內容
echo "#include \"$lfilename.hpp\"" >> $Src/$lfilename.cpp
echo "" >> $Src/$lfilename.cpp
echo "$projectname::$projectname()" >> $Src/$lfilename.cpp
echo "{" >> $Src/$lfilename.cpp
echo "}" >> $Src/$lfilename.cpp
echo "" >> $Src/$lfilename.cpp
echo "$projectname::~$projectname()" >> $Src/$lfilename.cpp
echo "{" >> $Src/$lfilename.cpp
echo "}" >> $Src/$lfilename.cpp
# 匯入makefile
# cat "./makefile" >> $filename/makefile
echo "# 描述: C++ 專案 makefile檔案" >> $filename/makefile
echo "# 版本: v3.0" >> $filename/makefile
echo "# 修改記錄: 1.先測試普通的cpp檔案的編譯執行" >> $filename/makefile
echo "# 2.使用變數來改進我們的makefile檔案" >> $filename/makefile
echo "# 3.新加了一個原始檔" >> $filename/makefile
echo "# 4.使用偽目標,加上clean規則" >> $filename/makefile
echo "# 5.使用wildcard函式,自動掃描當前目錄下的原始檔" >> $filename/makefile
echo "# 6.加入了自動規則依賴" >> $filename/makefile
echo "# 7.改變依賴關係的生成模式" >> $filename/makefile
echo "# 8.提供多目錄檔案編譯" >> $filename/makefile
echo "" >> $filename/makefile
echo "# 標頭檔案存放目錄" >> $filename/makefile
echo "INC_DIR=./Headers" >> $filename/makefile
echo "" >> $filename/makefile
echo "# 可執行檔案存放目錄" >> $filename/makefile
echo "BIN_DIR=./Output/bin" >> $filename/makefile
echo "" >> $filename/makefile
echo "# 原始檔存放目錄" >> $filename/makefile
echo "SRC_DIR=./Sources" >> $filename/makefile
echo "" >> $filename/makefile
echo "# 其它中間檔案存放目錄" >> $filename/makefile
echo "OBJ_DIR=./Output" >> $filename/makefile
echo "" >> $filename/makefile
echo "# 原始檔列表" >> $filename/makefile
echo "SRC := \${wildcard \${SRC_DIR}/*.cpp}" >> $filename/makefile
echo "" >> $filename/makefile
echo "# obj檔案列表" >> $filename/makefile
echo "OBJ := \${patsubst %.cpp, \$(OBJ_DIR)/%.o, \${notdir \${SRC}}}" >> $filename/makefile
echo "" >> $filename/makefile
echo "# 定義編譯命令變數" >> $filename/makefile
echo "CC := g++" >> $filename/makefile
echo "rm := rm -rf" >> $filename/makefile
echo "" >> $filename/makefile
echo "# 定義可執行檔案變數" >> $filename/makefile
echo "executable := main" >> $filename/makefile
echo "BIN_TARGET=\${BIN_DIR}/\${executable}" >> $filename/makefile
echo "" >> $filename/makefile
echo "# 終極目標規則:生成可執行檔案" >> $filename/makefile
echo "\${BIN_TARGET}:\${OBJ}" >> $filename/makefile
echo " \${CC} \${OBJ} -o \[email protected]" >> $filename/makefile
echo "" >> $filename/makefile
echo "# 子目標規則:生成連結檔案" >> $filename/makefile
echo "\${OBJ_DIR}/%.o:\${SRC_DIR}/%.cpp" >> $filename/makefile
echo " \${CC} -o \[email protected] -c $< -I\${INC_DIR}" >> $filename/makefile
echo "" >> $filename/makefile
echo "#clean規則" >> $filename/makefile
echo "#.PHONY: clean" >> $filename/makefile
echo "#clean:" >> $filename/makefile
echo "#清除編譯生成的所有檔案" >> $filename/makefile
echo "## \$(RM) \$(BIN_TARGET) \$(OBJ_DIR)/*.o" >> $filename/makefile
echo "#清除編譯生成的所有檔案,不包括可執行檔案" >> $filename/makefile
echo "# \$(RM) \$(OBJ_DIR)/*.o" >> $filename/makefile
現在對指令碼進行簡單的介紹:
- 首先我們需要從外部讀入一個專案名稱,用於建立資料夾和內部的標頭檔案以及原始檔。需要注意的時,這個檔名需要是英文,並且最好是遵守駝峰命名法,因為專案檔案中的類名與這個名稱一致。指令碼中對專案名加字首是為了好與其他型別的專案進行區別。
$ bash new.sh
# 在終端中輸入Test作為這個專案名
Test
-
建立專案樹。建立Headers資料夾用於存放標頭檔案,建立Sources資料夾用於存放原始檔,建立Output檔案用於存放可執行檔案以及中間檔案,可執行檔案存放在Output的子資料夾bin中。
-
建立檔案。main.cpp, test.cpp, test.hpp, makefile。其中test.hpp和test.cpp是根據讀入的專案名建立的兩個檔案,檔名都經過了小寫轉換。
-
向檔案中寫入基本的內容。這裡是通過echo的重定向操作實現寫入。以下是具體的寫入內容。
// main.cpp
#include <iostream>
#include "test.hpp"
using namespace std;
int main()
{
cout << "Hello VSC" << endl;
return 0;
}
// test.hpp
#pragma once
#include <iostream>
using namespace std;
class Test
{
public:
Test();
Test(Test &&) = default;
Test(const Test &) = default;
Test &operator=(Test &&) = default;
Test &operator=(const Test &) = default;
~Test();
protected:
private:
};
// test.cpp
#include "test.hpp"
Test::Test()
{
}
Test::~Test()
{
}
# makefile
# 描述: C++ 專案 makefile檔案
# 版本: v3.0
# 修改記錄: 1.先測試普通的cpp檔案的編譯執行
# 2.使用變數來改進我們的makefile檔案
# 3.新加了一個原始檔
# 4.使用偽目標,加上clean規則
# 5.使用wildcard函式,自動掃描當前目錄下的原始檔
# 6.加入了自動規則依賴
# 7.改變依賴關係的生成模式
# 8.提供多目錄檔案編譯
# 標頭檔案存放目錄
INC_DIR=./Headers
# 可執行檔案存放目錄
BIN_DIR=./Output/bin
# 原始檔存放目錄
SRC_DIR=./Sources
# 其它中間檔案存放目錄
OBJ_DIR=./Output
# 原始檔列表
SRC := ${wildcard ${SRC_DIR}/*.cpp}
# obj檔案列表
OBJ := ${patsubst %.cpp, $(OBJ_DIR)/%.o, ${notdir ${SRC}}}
# 定義編譯命令變數
CC := g++
rm := rm -rf
# 定義可執行檔案變數
executable := main
BIN_TARGET=${BIN_DIR}/${executable}
# 終極目標規則:生成可執行檔案
${BIN_TARGET}:${OBJ}
${CC} ${OBJ} -o [email protected]
# 子目標規則:生成連結檔案
${OBJ_DIR}/%.o:${SRC_DIR}/%.cpp
${CC} -o [email protected] -c $< -I${INC_DIR}
#clean規則
#.PHONY: clean
#clean:
#清除編譯生成的所有檔案
## $(RM) $(BIN_TARGET) $(OBJ_DIR)/*.o
#清除編譯生成的所有檔案,不包括可執行檔案
# $(RM) $(OBJ_DIR)/*.o
這樣一個基本的專案就建立完成了。那麼應該在VS Code怎麼使用呢?
在這裡預設大家對在Linux環境下VS Code開發C++有一定的瞭解了。如果不瞭解的話,可以參考本人的相關部落格。
首先,我們需要對coder-runner外掛的配置檔案進行部分的改動。
在User Settings 中搜索 code-runner.executorMap
對C++專案檔案的執行命令進行更改。
更改如下:
"cpp": "cd $dir && cd .. && make && cd ./Output/bin && ./main && cd ../../"
解釋一下,$dir
是我們在VS Code 中當前開啟的檔案目錄,一般是標頭檔案和原始檔(如果是makefile檔案,那麼執行這個外掛是沒有用的),首先會開啟這個目錄,然後回退到有makefile檔案的檔案目錄中,然後 進行make
,我們使用VS Code 並不僅僅是為了生成可執行檔案,還需要看到執行結果,所以還需要瀏覽到可執行檔案所在的資料夾中,執行可執行檔案,在makefile中預設可執行檔名是main,執行完到這裡後,我是讓終端的當前目錄回到最初的目錄。
最後執行產生的專案檔案樹:
.
├── Headers
│ └── test.hpp
├── makefile
├── Output
│ ├── bin
│ │ └── main
│ ├── main.o
│ └── test.o
└── Sources
├── main.cpp
└── test.cpp