---
# System prepended metadata

title: 自行編譯toolchain
tags: [toolchain, RISC-V]

---

## 源起 
Mac M3 因為要跑 qemu risc-v 32 但是官方缺乏工具鏈
```
brew tap riscv/riscv
brew install riscv-gnu-toolchain
```
當輸入 riscv64-unknown-elf-gcc --version
或者在終端機按下 risc tab 鍵時，都是跳出 64 位元 toolchain。查了相關方式只能由官方 git 下載自行安裝

## 操作步驟

在 macOS（包含搭載 M3 晶片的機型）上，系統預設的 make 工具版本通常較舊，名稱為「make」；而透過 Homebrew 安裝的新版 GNU Make 會以「gmake」的名稱安裝（即 GNU Make 的別名）。
在編譯如 GCC 等開源軟體時，通常需要使用 GNU Make，因此若系統內建的 make 版本過舊，建議改用「gmake」以確保編譯流程正確。

總結如下：
* GCC 本身是編譯器，與 make 是不同的工具；make 負責自動化編譯流程。
* 在 macOS 上，若預設的 make 版本過舊，使用 gmake（GNU Make）會更合適。
* 在編譯 RISC-V 交叉編譯器時，建議使用 gmake 而非 macOS 內建的 make。
* 透過 Homebrew 安裝 GNU Make 後，可使用指令「gmake」來呼叫。因此，你需要確認編譯環境中的 make 版本與功能，並建議安裝並使用 gmake 來編譯 GCC 交叉編譯器。

```shell=
// 1.基本套件
brew install autoconf automake libtool gmp mpfr libmpc isl gawk
brew install gnu-make

// 2.下載 src code
git clone https://github.com/riscv-collab/riscv-gnu-toolchain.git
cd riscv-gnu-toolchain
mkdir build
cd build

// 3.這邊關鍵是 apple 的 gmp, mpfr,libmpc 因為透過 homebrew 安裝，所以要用 export 增加收尋路徑，否則 gcc 預設是收尋 /usr/bin 編譯會找不到位置
export CPPFLAGS="-I/opt/homebrew/opt/gmp/include -I/opt/homebrew/opt/mpfr/include -I/opt/homebrew/opt/libmpc/include"
export LDFLAGS="-L/opt/homebrew/opt/gmp/lib -L/opt/homebrew/opt/mpfr/lib -L/opt/homebrew/opt/libmpc/lib"

// 4.安裝放到 $HOME 就不會產生權限問題了
../configure --prefix=$HOME/riscv32 \
--with-arch=rv32ima_zicsr \
--with-abi=ilp32 \
--enable-multilib

// 5.開始編譯
gmake -j$(sysctl -n hw.ncpu)
```
:::info
apple 的 gmp, mpfr,libmpc 因為透過 homebrew 安裝，所以要用 export 增加收尋路徑，否則 gcc 預設是收尋 /usr/bin 編譯會找不到位置
:::
::: info
brew --prefix gmp
brew --prefix mpfr
brew --prefix libmpc
這三行預期會出現在 /opt/homebrew/opt/gmp 底下
:::

編譯。cd 到 ~/risc32/bin 下方查看
```bash=
➜  bin pwd
/Users/wangliang/riscv32/bin
➜  bin ls
riscv32-unknown-elf-addr2line     riscv32-unknown-elf-gcc-nm        riscv32-unknown-elf-lto-dump
riscv32-unknown-elf-ar            riscv32-unknown-elf-gcc-ranlib    riscv32-unknown-elf-nm
riscv32-unknown-elf-as            riscv32-unknown-elf-gcov          riscv32-unknown-elf-objcopy
riscv32-unknown-elf-c++           riscv32-unknown-elf-gcov-dump     riscv32-unknown-elf-objdump
riscv32-unknown-elf-c++filt       riscv32-unknown-elf-gcov-tool     riscv32-unknown-elf-ranlib
riscv32-unknown-elf-cpp           riscv32-unknown-elf-gdb           riscv32-unknown-elf-readelf
riscv32-unknown-elf-elfedit       riscv32-unknown-elf-gdb-add-index riscv32-unknown-elf-run
riscv32-unknown-elf-g++           riscv32-unknown-elf-gprof         riscv32-unknown-elf-size
riscv32-unknown-elf-gcc           riscv32-unknown-elf-gstack        riscv32-unknown-elf-strings
riscv32-unknown-elf-gcc-15.1.0    riscv32-unknown-elf-ld            riscv32-unknown-elf-strip
riscv32-unknown-elf-gcc-ar        riscv32-unknown-elf-ld.bfd
➜  bin file riscv32-unknown-elf-gcc
riscv32-unknown-elf-gcc: Mach-O 64-bit executable arm64
```

## 問題與討論
1. 之後跑起來發現會出現 mcause=2，illegal instrucion 
查起來binutils 版本問題
![圖片](https://hackmd.io/_uploads/H10igP-gbe.png)
.insn 2, 0x0000 是無法支援的指令
![圖片](https://hackmd.io/_uploads/rk31WDbgbx.png)

原始程式碼怎麼會編成這樣＠＠？
==2025.11.13 更新==
最後看到好像是編譯選項的問題，多加入一個Ｃ支援擴展語法就可以
// 更改前
-march=rv32ima_zicsr
// 更改後
-march=rv32imac_zicsr
其中多一個c就沒有出現 .insn 問題，但這邊有許多問題，理論上我沒有加入支援擴充不應該使用擴充語法？我編譯cross-complier 時也沒有多加選項，目前就是先繞過去
```
// 4.安裝放到 $HOME 就不會產生權限問題了
../configure --prefix=$HOME/riscv32 \
--with-arch=rv32ima_zicsr \
--with-abi=ilp32 \
--enable-multilib
```

## Reference
* [riscv-gnu-toolchain](https://github.com/riscv-collab/riscv-gnu-toolchain)

