- [原始內容請參閱此處](https://rissun-mu-yasorganization.gitbook.io/rissun-mu-yasorganizartion/riscvcpu-shi-zuo-dao-lun/vscode-zheng-he-huan-jing-pei-zhi) 當 RISC-V 工具鏈配置好後,很自然會開始覺得如果能夠直接在 Vscode 執行就好了,確實這樣就能夠創造類似 IDE 的環境每次都能夠快速編譯和輸出結果到終端,而不必每次都要打一堆指令去編譯和執行。 ## 安裝 Vscode 在 Ubuntu Ubuntu 用戶可以在 App Center 搜索 找到 Vscode,只要直接安裝就能使用。 開啟 Vscode ,有了前面一篇的經驗我們大致知道,我們應該先安裝 C/C++ 的語法插件 以及 RISC-V 的語法插件,至於插件的選擇基本上沒有硬性規定,功能也大同小異,只要選自己喜歡的就好了,個人是配置了以下這幾個: 到這裡基本上就完成了 Vscode 的基本安裝了。 配置自動化編譯腳本基於 bash shell 有鑑於前一篇,我們已經非常熟悉在 bash 的編譯操作,所以我們優先配置腳本 - build_cpp.sh - build_c.sh - build_as.sh 以開啟自動化編譯之路。build_cpp.sh 基本上就是前一篇的流程加上一些錯誤判斷的機制而已 ```bash=1 #!/bin/bash # 輸入欲編譯之檔案名稱 echo "請輸入要編譯的檔案名稱:" read filename # 檢查是否存在欲編譯檔案 if [[ ! -f "$filename.cpp" ]];then echo "錯誤:找不到檔案 $filename.cpp" exit 1 fi # 編譯 echo "正在為你的程序編譯..." riscv32-unknown-elf-g++ -g -o "$filename.elf" "$filename.cpp" # 檢查編譯是否成功 if [[ $? -ne 0 ]]; then echo "編譯失敗,請檢查程式碼。" exit 1 fi # 執行 echo "即將為你執行程序.." qemu-riscv32 "$filename.elf" ``` 然後,一樣拿前一篇的測試程式碼來測試 首先,第一次執行 會需要給予該腳本 執行權限所以 ```bash $ chmod +x build_cpp.sh ``` 然後,開始執行編譯程序 ```bash $ ./build_cpp.sh 請輸入要編譯的檔案名稱: test ; 正在為你的程序編譯... 即將為你執行程序.. Hello, RISC-V! ``` 看到正確輸出代表 自動化腳本配置已經完成。 build_c.sh 由於內容大同小異,直接複製前一份修改即可 ```bash $ cp build_cpp.sh build_c.sh ``` 然後,開啟該檔案修正如下: ```bash=1 #!/bin/bash # 輸入欲編譯之檔案名稱 echo "請輸入要編譯的檔案名稱:" read filename # 檢查是否存在欲編譯檔案 if [[ ! -f "$filename.c" ]];then echo "錯誤:找不到檔案 $filename.c" exit 1 fi # 編譯 echo "正在為你的程序編譯..." riscv32-unknown-elf-gcc -g -o "$filename.elf" "$filename.c" # 檢查編譯是否成功 if [[ $? -ne 0 ]]; then echo "編譯失敗,請檢查程式碼。" exit 1 fi # 執行 echo "即將為你執行程序.." qemu-riscv32 "$filename.elf" ``` 接著一樣利用 test.c 測試程式碼 ```bash $ ./build_c.sh 請輸入要編譯的檔案名稱: test ; 正在為你的程序編譯... 即將為你執行程序.. Hello, RISC-V! ``` 完成後,就可以繼續處理組合語言的編譯了build_as.sh 雖然差異最大的一個,不過主要結構仍然大同小異, 所以直接複製前一個檔案即可 ```bash $ cp build_c.sh build_as.sh ``` 然後,依據前一篇的邏輯修改 ```bash=1 #!/bin/bash # 輸入欲編譯之檔案名稱 echo "請輸入要編譯的檔案名稱:" read filename # 檢查是否存在欲編譯檔案 if [[ ! -f "$filename.as" ]];then echo "錯誤:找不到檔案 $filename.as" exit 1 fi # 編譯 echo "正在為你的程序編譯..." riscv32-unknown-elf-as -g -o "$filename.o" "$filename.as" riscv32-unknown-elf-ld -g -o "$filename.elf" "$filename.o" # 檢查編譯是否成功 if [[ $? -ne 0 ]]; then echo "編譯失敗,請檢查程式碼。" exit 1 fi # 執行 echo "即將為你執行程序.." qemu-riscv32 "$filename.elf" ``` 同樣的來測試看看 test.as 能不能作用, ```bash $ ./build_as.sh 請輸入要編譯的檔案名稱: test 正在為你的程序編譯... 即將為你執行程序.. Hello, RISC-V! ``` 同樣順利執行後,我們可以開始思考如何把這些腳本配置到 Vscode 了,原因是雖然目前確實可以顯著簡少我們使用指令的數量,但是仍然和我們期待寫程式碼的同時能夠偵錯和獲取結果存在差距,所以必須讓它進入到 Vscode 才能解決這個問題,並達成我們的目標! Vscode 自動化配置 要配置 Vscode 環境首先必須要先擁有一個能夠專注讓,Vscode 運作的環境具體作法最簡單就是直接新增一個乾淨的資料夾 ```bash=1 $ cd ~/Desktop $ mkdir test $ cd test ``` 由於 Vscode 的編譯運作仰賴 .vscode 的配置,但是這也意味著當一個空間包含多個語言時候,可能環境會變得相當複雜管理,所以簡單起見我們至少在新增2個工做環境分別給予 C/C++, Asm 由於事實上,g++ 可以同時處理 C/C++ 因此我們可以直接都使用它來處理就好,這樣只需要2個工作區域。 ```bash $ mkdir test_cpp $ mkdir test_asm ``` 配置 test_cpp 將剛剛多次使用過得 test.c,test.cpp 放入此資料夾,並且在 Vscode 開啟這個資料夾 具體應該如下: Ctrl + Shift + P 開啟命令面板,輸入 Tasks: Configure Task,然後選擇 "Create tasks.json file from template"。 得到一個類似這樣的範本: 理想上的配置流程應該是,執行初期要確保環境是沒有過去的執行檔,否則可能造成潛在的誤會和錯誤,所以應該第一步驟為清除過去的 .elf ,第二步驟是開始串接剛剛配置的 build_cpp.sh 具體實現是如下: ```json=1 { "version": "2.0.0", "tasks": [ { "label": "Clean", "type": "shell", "command": "rm", "args": [ "-f", "${fileDirname}/${fileBasenameNoExtension}.elf", "${fileDirname}/${fileBasenameNoExtension}.o" ], "presentation": { "reveal": "always", "clear": true }, "group": "build", "detail": "清除先前的編譯檔案" }, { "label": "Build with build_cpp.sh", "type": "shell", "command": "${fileDirname}/build_cpp.sh", "args": [], "problemMatcher": [], "presentation": { "reveal": "always", "clear": false }, "group": "build", "dependsOn": "Clean", "dependsOrder": "sequence", "detail": "使用 build_cpp.sh 自動化編譯流程" }, { "label": "Build and Run (C++)", "dependsOn": "Build with build_cpp.sh", "dependsOrder": "sequence", "group": "build", "problemMatcher": [] }, { "type": "cppbuild", "label": "C/C++: g++ build active file", "command": "/usr/bin/g++", "args": [ "-fdiagnostics-color=always", "-g", "${file}", "-o", "${fileDirname}/${fileBasenameNoExtension}" ], "options": { "cwd": "${fileDirname}" }, "problemMatcher": [ "$gcc" ], "group": { "kind": "build", "isDefault": true }, "detail": "Task generated by Debugger." } ] } ``` 接著打開 C/C++ 的檔案,按下 Ctrl + F5 理論上可以成功 如下: 到這裡基本上已經完成 C/C++ 在 Vscode 基本的環境整合 配置 Asm 整合環境 有了以上經驗,整合 Asm 理論上不成問題了,直接進入到 test_asm, 同樣做好 .vscode 配置,然後開啟 tasks.json 配置: 事實上,與前者同樣大同小異,可以直接修改前者就好了,但是要留意的是,在 Vscode .as 不會被視為可用的所以必須要 修改 build_as.sh: ``` bash=1 #!/bin/bash # 輸入欲編譯之檔案名稱 echo "請輸入要編譯的檔案名稱:" read filename # 檢查是否存在欲編譯檔案 if [[ ! -f "$filename.s" ]];then echo "錯誤:找不到檔案 $filename.s" exit 1 fi # 編譯 echo "正在為你的程序編譯..." riscv32-unknown-elf-as -g -o "$filename.o" "$filename.s" riscv32-unknown-elf-ld -g -o "$filename.elf" "$filename.o" # 檢查編譯是否成功 if [[ $? -ne 0 ]]; then echo "編譯失敗,請檢查程式碼。" exit 1 fi # 執行 echo "即將為你執行程序.." qemu-riscv32 "$filename.elf" ``` 然後,在Vscode 同樣建立一個 test.s 內容,因為其內容和 test.as 相同所以可以直接 ```bash $ cp test.as test.s ``` 接著配置任務 ```json=1 { "version": "2.0.0", "tasks": [ { "label": "Clean (ASM)", "type": "shell", "command": "rm", "args": [ "-f", "${fileDirname}/${fileBasenameNoExtension}.elf", "${fileDirname}/${fileBasenameNoExtension}.o" ], "presentation": { "reveal": "always", "clear": true }, "group": "build", "detail": "清除組合語言的舊編譯檔" }, { "label": "Build with build_as.sh", "type": "shell", "command": "${fileDirname}/build_as.sh", "args": [ "${fileBasenameNoExtension}" // 傳遞檔案名稱作為引數 ], "problemMatcher": [], "presentation": { "reveal": "always", "clear": false }, "group": "build", "dependsOn": "Clean (ASM)", "dependsOrder": "sequence", "detail": "使用 build_as.sh 編譯與執行組合語言程式" }, { "label": "Build and Run (ASM)", "dependsOn": "Build with build_as.sh", "dependsOrder": "sequence", "group": { "kind": "build", "isDefault": false }, "problemMatcher": [] } ] } ``` 和前者不同,由於組合語言更為底層,經過多次測試後,覺得還是只能麻煩一點就是每次要編譯使用 Ctrl+Shift+B ,跑出編譯選單, 選擇最下面的選項 Build and Run, 接著會要求輸入欲編譯的檔案, 輸入當前檔案名稱即可 得到編譯結果 雖然組合語言部份沒有辦法做到更簡化,不過和原始的相比目前已經可以實現全程在 Vscode 作業了,也確實免除了大多數的指令,總之到目前為止已經完成了編譯上在 Vscode 的整合。