# Build RISC-V GNU Tool Chain :::info **Latest Updated Date:** March 08, 2025 ::: 本教學文章為隨手紀錄操作流程,有錯誤或不詳盡之處請見諒。 大量圖片摘自參考資料,我轉載的文字及圖片著作權歸於參考資料之作者所有。 本教學文章針對 [ RISC-V ( Reduced Instruction Set Computer-V )](https://zh.wikipedia.org/zh-tw/RISC-V) ) RV32IM 指令集架構建構 ( build ) RISC-V Tool Chain > RV32:RISC-V 32bits > RV32I:最基礎 ( Base ) 整數指令集,其它指令集都可視為這個指令集的擴充 > RV32M:乘法、除法指令集擴充 ( Extension ) 本篇教學文章針對 [**RISC-V 官方 Tool Chain**](https://github.com/riscv-collab/riscv-gnu-toolchain) 建構流程所撰寫 ## 什麼是 Tool Chain? 參考資料:[你所不知道的 C 語言:編譯器和最佳化原理篇](https://hackmd.io/VerfJi2ZSIO0RbgeL2ppGQ?view) - HackMD Copyright (**慣C**) 2015, 2016, 2017 [宅色夫](http://wiki.csie.ncku.edu.tw/User/jserv) 假設有一高階程式語言檔案。 - hello.c: ```c int main() { return 1; } ``` 如果要在 GNU/Linux 的作業系統環境中,將高階程式語言檔案 ( 如 hello.c ) 編譯成可執行檔,需要在終端機上打入: - GNU/Linux 終端機: ```bash gcc -o hello hello.c ``` 高階程式語言檔案需要經過一系列的操作才可以被轉化為 GNU/Linux 作業系統環境中的可執行檔 ( 如 .elf 檔案 ) 。 - Compilation flow (過度精簡的) 編譯的流程還有格式  ## GNU Tool Chain 包括 gcc : GNU compiler collection as : GNU assembler ld : GNU linker gdb : GNU debugger ## 初探 RISC-V Tool Chain 由上可知,Tool Chain 是一系列工具的組合。而 RISC-V Tool Chain 則是可將高階程式語言檔案轉化為 RISV-V 硬體架構的可執行檔工具組合。 RISC-V 官方維護的 Tool Chain: https://github.com/riscv-collab/riscv-gnu-toolchain 該 Tool CHain 包括 gcc 。而 gcc 可視為一種 C、C++ cross-compiler。 > cross-compiler:在特定硬體架構下的作業系統環境,將高階程式語言轉化為另一種硬體架構的可執行檔之編譯器 像是廢話的結論:而 RISC-V Tool Chain 的目標指令集架構為:RISC-V 。 ## 建構 RISC-V Tool CHain 流程 - 本教學文章的操作流程基於 x86 指令集架構上的 GNU/Linux ( Ubuntu ) 作業系統環境 參考資料: 1. [Build riscv-gnu-toolchain](https://hackmd.io/@yrr-itri/Hk3uMlzI3) - HackMD Copyright [YT Cheng](https://hackmd.io/@yrr-itri) 2. [Getting Started with the RISC-V Open Source GNU Toolchain](https://privateisland.tech/dev/rv-getting-started) - company website Copyright [privateisland](https://privateisland.tech/) 我推薦更新以下工具: ``` Bash sudo apt-get upgrade ``` 我推薦安裝以下工具: ``` Bash sudo apt-get install vim tree git gcc make ``` --- ## **建構 Tool Chain 正式流程:** ## Step 0, Install packages needed ```Bash sudo apt-get install autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev ninja-build ``` ## Step 1, Clone from riscv-gnu-toolchain 在 Ubuntu 的目錄:/home/<user name of yours> ```Bash $ git clone --recursive https://github.com/riscv/riscv-gnu-toolchain Cloning into 'riscv-gnu-toolchain'... ... ``` 位置:/home/vboxuser ( 以我為例 ) 下載完畢進行測試: ```Bash! $ ls binutils configure contrib gcc glibc linux-headers Makefile.in newlib qemu regression spike uclibc-ng configure.ac dejagnu gdb LICENSE llvm musl pk README.md scripts test ``` :::danger Tool Chain 約 6.4 GB,下載時間依電腦 CPU 速度而定。 以我為例,Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz 3.41 GHz 下載長達 <font color="#f00">1.5 小時</font>。 ::: 請確保硬碟可用空間大於 15 GB,若空間不夠請自行參閱:[對VirtualBox內的Ubuntu虛擬機,擴充硬碟空間-一篇寫了8小時的技術文章](https://medium.com/@newpage0720/%E5%9C%A8virtualbox%E5%85%A7%E7%9A%84ubuntu%E8%99%9B%E6%93%AC%E6%A9%9F-%E5%9B%BA%E5%AE%9A%E5%AE%B9%E9%87%8F%E7%A1%AC%E7%A2%9F%E8%BD%89%E5%8B%95%E6%85%8B%E9%85%8D%E7%BD%AE%E7%A1%AC%E7%A2%9F-%E8%88%87%E6%93%B4%E5%85%85%E7%A1%AC%E7%A2%9F%E7%A9%BA%E9%96%93-6efe6b1abcb3) - Medium Copyright [陳國仁](https://medium.com/@newpage0720) ## Step 2, Create a installation dir and add it to PATH ```Bash cd riscv-gnu-toolchain/ ``` ```Bash mkdir build; cd build ``` ## Step 3, Generate Makefile according to target system ```Bash $ ../configure --help | grep abi --with-abi=lp64d Sets the base RISC-V ABI, defaults to lp64d ``` ```Bash $ ../configure --prefix=/opt/riscv32 --with-arch=rv32imzicsr --with-abi=ilp32 checking for gcc... gcc ... config.status: creating Makefile config.status: creating scripts/wrapper/awk/awk config.status: creating scripts/wrapper/sed/sed ``` 設定解析: - --prefix= 指定 make 好的檔案被放置的位置。 --with-arch= 指定指令集架構擴充 ( 例如 rv32imzicsr ),編譯好的指令將全部限縮在這個範圍。 - --with-abi= 指定 ilp32 這 1 個 ABI,所有的 int、long、pointer 皆為 32-bits。 > ABI ( Application Binary Interface ) 字面上定義為 2 個 binary ( 通常為執行檔 ) 檔案互動的介面,介面規範編譯器和連結器需遵循這些規則來編譯您的程式,包括程式中的函數、函數參數命名規則、函數參數傳遞方式等,以便使其正常運作。連結到同一執行檔的任何程式碼都必須符合相同的 ABI。而 ABI 依賴於硬體架構而定。 最簡單理解的方法為將 ABI 與 API ( Application Programming Interface ) 進行比較。兩者非常相似,可將 ABI 其視為 API 的編譯版本(或機器語言層級的 API),當您編寫高階語言程式碼時,您可以透過 API 存取該程式庫。程式碼編譯完成後,您的應用程式就會遵循 ABI 存取外部函式庫中的二進位資料。ABI 定義了編譯後的應用程式用來存取外部函式庫的結構和方法(就像 API 一樣)。 延伸閱讀:[What is an application binary interface (ABI)?](https://stackoverflow.com/questions/2171177/what-is-an-application-binary-interface-abi) - StackOverflow ## Step 4, After makefile is done, build toolchain ``` sudo make -j4 ``` > 設定解析: -j<number of threads> 建議使用硬體多執行緒來加快 make 速度,而執行緒數量則取決於電腦硬體而定。 :::danger 在 Tool Chain 的 GNU Make 設定完成之後,我們就可以 make 這個 Tool Chain 了,所有 make 好的檔案將自動被放置於: /opt/riscv32/ make 需耗費大量時間,make 時間依電腦 CPU 速度而定。 以我為例,我耗費了 2.5 小時。 ::: ## Step 5, Check the toolchain ```Bash $ ls build-binutils-newlib build-gcc-newlib-stage2 build-newlib config.log install-newlib-nano scripts build-gcc-newlib-stage1 build-gdb-newlib build-newlib-nano config.status Makefile stamps ``` ```Bash $ cd /opt/riscv32 $ tree -L 2 -d . ├── bin ├── include │ ├── gdb │ └── sim ├── lib │ ├── bfd-plugins │ └── gcc ├── libexec │ └── gcc ├── riscv32-unknown-elf │ ├── bin │ ├── include │ └── lib └── share ├── gcc-14.2.0 ├── gdb ├── info ├── locale └── man ``` 建立「暫時的」系統環境變數: ```Bash export PATH=/opt/riscv32/bin:$PATH ``` > 設定解析: PATH=<The path of yours executable file> 依照上述步驟,「riscv32-unknwon-elf」這 1 個可執行檔將被安裝於「/opt/riscv32/bin」目錄內。 - 這條指令只會影響當前終端機會話 ( Terminal session ) ,如果關閉終端機或重新開機,設定就會消失。若要讓它永久生效,可以將這行指令加到 ~/.bashrc 或 ~/.bash_profile(對於 Bash 使用者),或者 ~/.zshrc(對於 Zsh 使用者): ### 如何永久修改 PATH? ```Bash echo 'export PATH=/opt/riscv32/bin:$PATH' >> ~/.bashrc ``` 需重新開啟新的終端機,待設定生效。若不重開終端機,可運行: ```Bash source ~/.bashrc ``` ### 檢查 Tool Chain 資訊: ```Bash $ mkdir -p ~/Projects/riscv; cd ~/Projects/riscv $ source /opt/riscv32/env-riscv32 $ riscv32-unknown-elf-gcc --version riscv32-unknown-elf-gcc () 14.2.0 ... $ riscv32-unknown-elf-objcopy --version GNU objcopy (GNU Binutils) 2.43.1 ... ``` ### 檢查 Tool Chain 中的 Compiler 與 binutils: ```Bash $ riscv32-unknown-elf-gcc -dumpmachine riscv32-unknown-elf $ riscv32-unknown-elf-gcc -print-sysroot /opt/riscv32/riscv32-unknown-elf $ riscv32-unknown-elf-gcc -print-libgcc-file-name /opt/riscv32/lib/gcc/riscv32-unknown-elf/14.2.0/libgcc.a $ riscv32-unknown-elf-gcc -print-search-dirs install: /opt/riscv32/lib/gcc/riscv32-unknown-elf/14.2.0/ programs: =/opt/riscv32/libexec/gcc/riscv32-unknown-elf/14.2.0/:/opt/riscv32/libexec/gcc/riscv32-unknown-elf/14.2.0/:/opt/riscv32/libexec/gcc/riscv32-unknown-elf/:/opt/riscv32/lib/gcc/riscv32-unknown-elf/14.2.0/:/opt/riscv32/lib/gcc/riscv32-unknown-elf/:/opt/riscv32/lib/gcc/riscv32-unknown-elf/14.2.0/../../../../riscv32-unknown-elf/bin/riscv32-unknown-elf/14.2.0/:/opt/riscv32/lib/gcc/riscv32-unknown-elf/14.2.0/../../../../riscv32-unknown-elf/bin/ libraries: =/opt/riscv32/lib/gcc/riscv32-unknown-elf/14.2.0/:/opt/riscv32/lib/gcc/riscv32-unknown-elf/14.2.0/../../../../riscv32-unknown-elf/lib/riscv32-unknown-elf/14.2.0/:/opt/riscv32/lib/gcc/riscv32-unknown-elf/14.2.0/../../../../riscv32-unknown-elf/lib/:/opt/riscv32/riscv32-unknown-elf/lib/riscv32-unknown-elf/14.2.0/:/opt/riscv32/riscv32-unknown-elf/lib/:/opt/riscv32/riscv32-unknown-elf/usr/lib/riscv32-unknown-elf/14.2.0/:/opt/riscv32/riscv32-unknown-elf/usr/lib/ ``` 檢查是否有 newlib-nano library: ```Bash $ ls /opt/riscv32/riscv32-unknown-elf/lib crt0.o libc.a libg.a libgloss_nano.a libm.a libnosys.a libsim.a libstdc++.a-gdb.py libstdc++exp.la libsupc++.a nano.specs semihost.specs ldscripts libc_nano.a libgloss.a libg_nano.a libm_nano.a libsemihost.a libstdc++.a libstdc++exp.a libstdc++.la libsupc++.la nosys.specs sim.specs ``` 檢查 ToolChain 可搭配的 march 以及 mabi 兩個參數組合指令運行結果: ```Bash $ riscv64-unknown-elf-gcc --print-multi-lib .; rv32ec/ilp32e;@march=rv32ec@mabi=ilp32e rv32ec_zba_zbb/ilp32e;@march=rv32ec_zba_zbb@mabi=ilp32e rv32eac/ilp32e;@march=rv32eac@mabi=ilp32e rv32eac_zba_zbb/ilp32e;@march=rv32eac_zba_zbb@mabi=ilp32e rv32emc/ilp32e;@march=rv32emc@mabi=ilp32e rv32emc_zba_zbb/ilp32e;@march=rv32emc_zba_zbb@mabi=ilp32e rv32emac/ilp32e;@march=rv32emac@mabi=ilp32e rv32emac_zba_zbb/ilp32e;@march=rv32emac_zba_zbb@mabi=ilp32e rv32ic/ilp32;@march=rv32ic@mabi=ilp32 rv32ic_zba_zbb/ilp32;@march=rv32ic_zba_zbb@mabi=ilp32 rv32iac/ilp32;@march=rv32iac@mabi=ilp32 rv32iac_zba_zbb/ilp32;@march=rv32iac_zba_zbb@mabi=ilp32 rv32imc/ilp32;@march=rv32imc@mabi=ilp32 rv32imc_zba_zbb/ilp32;@march=rv32imc_zba_zbb@mabi=ilp32 rv32imac/ilp32;@march=rv32imac@mabi=ilp32 rv32imac_zba_zbb/ilp32;@march=rv32imac_zba_zbb@mabi=ilp32 rv32imfc/ilp32f;@march=rv32imfc@mabi=ilp32f rv32imfc_zba_zbb/ilp32f;@march=rv32imfc_zba_zbb@mabi=ilp32f rv32imafc/ilp32f;@march=rv32imafc@mabi=ilp32f rv32imafc_zba_zbb/ilp32f;@march=rv32imafc_zba_zbb@mabi=ilp32f rv32imfdc/ilp32d;@march=rv32imfdc@mabi=ilp32d rv32imfdc_zba_zbb/ilp32d;@march=rv32imfdc_zba_zbb@mabi=ilp32d rv32imafdc/ilp32d;@march=rv32imafdc@mabi=ilp32d rv32imafdc_zba_zbb/ilp32d;@march=rv32imafdc_zba_zbb@mabi=ilp32d rv64ic/lp64;@march=rv64ic@mabi=lp64 rv64ic/lp64/compact;@march=rv64ic@mabi=lp64@mcmodel=compact rv64ic_zba_zbb/lp64;@march=rv64ic_zba_zbb@mabi=lp64 rv64ic_zba_zbb/lp64/compact;@march=rv64ic_zba_zbb@mabi=lp64@mcmodel=compact rv64iac/lp64;@march=rv64iac@mabi=lp64 rv64iac/lp64/compact;@march=rv64iac@mabi=lp64@mcmodel=compact rv64iac_zba_zbb/lp64;@march=rv64iac_zba_zbb@mabi=lp64 rv64iac_zba_zbb/lp64/compact;@march=rv64iac_zba_zbb@mabi=lp64@mcmodel=compact rv64imc/lp64;@march=rv64imc@mabi=lp64 rv64imc/lp64/compact;@march=rv64imc@mabi=lp64@mcmodel=compact rv64imc_zba_zbb/lp64;@march=rv64imc_zba_zbb@mabi=lp64 rv64imc_zba_zbb/lp64/compact;@march=rv64imc_zba_zbb@mabi=lp64@mcmodel=compact rv64imac/lp64;@march=rv64imac@mabi=lp64 rv64imac/lp64/compact;@march=rv64imac@mabi=lp64@mcmodel=compact rv64imac_zba_zbb/lp64;@march=rv64imac_zba_zbb@mabi=lp64 rv64imac_zba_zbb/lp64/compact;@march=rv64imac_zba_zbb@mabi=lp64@mcmodel=compact rv64imfc/lp64f;@march=rv64imfc@mabi=lp64f rv64imfc/lp64f/compact;@march=rv64imfc@mabi=lp64f@mcmodel=compact rv64imfc_zba_zbb/lp64f;@march=rv64imfc_zba_zbb@mabi=lp64f rv64imfc_zba_zbb/lp64f/compact;@march=rv64imfc_zba_zbb@mabi=lp64f@mcmodel=compact rv64imafc/lp64f;@march=rv64imafc@mabi=lp64f rv64imafc/lp64f/compact;@march=rv64imafc@mabi=lp64f@mcmodel=compact rv64imafc_zba_zbb/lp64f;@march=rv64imafc_zba_zbb@mabi=lp64f rv64imafc_zba_zbb/lp64f/compact;@march=rv64imafc_zba_zbb@mabi=lp64f@mcmodel=compact rv64imfdc/lp64d;@march=rv64imfdc@mabi=lp64d rv64imfdc/lp64d/compact;@march=rv64imfdc@mabi=lp64d@mcmodel=compact rv64imfdc_zba_zbb/lp64d;@march=rv64imfdc_zba_zbb@mabi=lp64d rv64imfdc_zba_zbb/lp64d/compact;@march=rv64imfdc_zba_zbb@mabi=lp64d@mcmodel=compact rv64imafdc/lp64d;@march=rv64imafdc@mabi=lp64d rv64imafdc/lp64d/compact;@march=rv64imafdc@mabi=lp64d@mcmodel=compact rv64imafdc_zba_zbb/lp64d;@march=rv64imafdc_zba_zbb@mabi=lp64d rv64imafdc_zba_zbb/lp64d/compact;@march=rv64imafdc_zba_zbb@mabi=lp64d@mcmodel=compact ```
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.