手把手教你在優麒麟上搭建 RISC-V 交叉編譯環境
由於 RISC-V 裝置價格昂貴、不易採購等諸多原因,許多小夥伴雖然很感興趣,但仍無法參與 RISC-V 開發工作,今天就教大家如何在優麒麟上搭建 RISC-V 交叉編譯環境,快學起來吧!
交叉編譯(Cross Compile)指編譯程式碼的平臺,和執行編譯後原始碼的平臺是兩個不同的平臺,比如在 x86/Linux 平臺下使用交叉編譯工具鏈編譯 ARM/Linux 平臺下的可執行檔案。今天我們要講的就是在優麒麟(x86/Linux)上編譯 RISC-V 架構可執行檔案的方法。
我們為什麼需要交叉編譯呢,主要有以下考慮:
01.效能與速度 交叉編譯的目標平臺往往 CPU 效能較差,記憶體和磁碟效能也可能不能滿足編譯的要求,這時候就要依賴效能資源更好的編譯主機進行編譯。 02.缺乏編譯條件 就算目標平臺效能足夠且資源充足,可以本地編譯,但第一個在目標平臺執行的本地編譯器總是需要我們通過交叉編譯獲得。 03.軟體編譯環境 一個完整的 Linux 發行版需要由數百個包構成,而我們往往只關注需要在目標主機上安裝的包,所以我們可以在交叉編譯的主機上配置這些環境,而不是把時間浪費在配置目標主機的編譯依賴上。 |
本文包含以下兩部分:
1、如何搭建一個 RISC-V 的交叉編譯環境。
2、交叉編譯 Linux 核心。
一、搭建 RISC-V 交叉編譯環境。
通常來講,在搭建交叉編譯環境時需要考慮不同體系架構的不同特性,包括 CPU 架構是 64 位還是 32 位系統、位元組序是大端( big-endian )或小端( little-endian )、記憶體位元組對齊方式等,不過好在 RISC-V 已經有完善的工具鏈,包含交叉編譯所需的 binutils 、 gcc 和 glibc 3 個部分。
● 首先需要 RISC-V 交叉編譯工具鏈,如果網路較慢,可以忽略其中的 qemu 子專案
git clone --recursive https://github.com/riscv/riscv-gnu-toolchain
這是 RISC-V 的 C/C++ 交叉編譯工具鏈,其支援兩種構建模式:
1. 通用 ELF/Newlib 工具鏈
2. Linux-ELF/glibc 工具鏈
● 安裝所需依賴包
sudo apt-get install -y autoconf automake autotools-dev curl libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev libncurses-dev device-tree-compiler libssl-dev gdisk swig
● 接下來開始編譯
cd riscv-gnu-toolchain ./configure --prefix=/opt/riscv(路徑可以根據個人習慣自定義) sudo make linux -j `nproc`
編譯完成後,剛才指定的路徑 opt/riscv/bin 下會生成以下檔案:
交叉編譯所需的工具,包括 Binutils(ld,as,ar 等,瞭解詳情可參考https://sourceware.org/binutils/docs-2.37/binutils/index.html )、gcc 、gdb 等都在其中。
可以將這個路徑新增到環境變數中:
export PATH=/opt/riscv/bin:$PATH
也可以新增到:
echo "export PATH=/opt/riscv/bin:$PATH" >> ~/.bashrc
到這裡我們就完成了交叉編譯所需環境的搭建。
二、編譯 Linux 核心
接下來我們以核心原始碼為例,瞭解一下上述交叉編譯工具鏈的使用方法。
● 首先下載核心原始碼
git clone https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
● 不過這裡下載較慢,可以去國內的映象站下載,比如清華大學映象站
git clone https://mirrors.tuna.tsinghua.edu.cn/git/linux-stable.git
● 下載完成後
git checkout
接下來將需要打上你想要編譯的開發板的 patch ,以 hifive unmatched 為例
● 首先下載
git clone https://github.com/sifive/meta-sifive
這裡面還包含了編譯 OpenSBI 和 U-Boot 所需的 patch ,編譯過程大同小異,如果想要自己構建一個系統映象,可以分別編譯這兩個工具。這裡以核心為例:
● 打上所有 patch
for f in path to /meta-sifive/recipes-kernel/linux/files/*.patch; do echo $f;patch -p1 < $f;done
● 複製 defconfig 配置檔案
cp path to /meta-sifive/recipes-kernel/linux/files/defconfig ./.config
如果想避免產生額外字尾名,可以新增
touch .scmversion
接下來開始編譯核心,這裡需要指定 make 的兩個引數:
1、CROSS_COMPILE:交叉編譯器的字首,表示將程式碼編譯編譯成目標CPU指令的工具,如果不指定,make 會預設使用系統自帶的 gcc 來編譯,這裡指定我們之前編譯出來的 riscv64-unknown-linux-gnu- 為字首。
2、ARCH:即 architecture ,用於選擇編譯哪種 CPU 架構,也就是編譯 arch/ 目錄下的哪個子目錄,這裡指定 ARCH=riscv ,arch/riscv 目錄下也包含此架構特有的 Kconfig 配置檔案,所以 make menuconfig 時也會用到這個目錄。
make CROSS_COMPILE=riscv64-unknown-linux-gnu- ARCH=riscv olddefconfig
make CROSS_COMPILE=riscv64-unknown-linux-gnu- ARCH=riscv -j`nproc`
也可以將核心和核心模組打成 tar 包或 deb 包
make CROSS_COMPILE=riscv64-unknown-linux-gnu- ARCH=riscv INSTALL_MOD_STRIP=1 -j`nproc` tarbz2-pkg make CROSS_COMPILE=riscv64-unknown-linux-gnu- ARCH=riscv INSTALL_MOD_STRIP=1 -j`nproc` bindeb-pkg
新增版本號
version=`cat include/config/kernel.release`;echo $version
編譯完成後,會生成 path to/arch/riscv/boot/Image 核心映象檔案和 path to/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dtb 硬體 dtb 檔案。
如果選擇打成 deb 包,會生成三個 .deb 檔案:
1. linux-headers-...
2. linux-libc-dev_...
3. linux-image-...
(其中省略號表示版本號)
到這裡我們就完成了 RISC-V 架構 Linux 核心的編譯,接下來便可以基於這個核心製作自己的系統映象。
各位小夥伴,你學會了嗎?
參考文件:
https://github.com/sifive/meta-sifive/tree/2021.12/recipes-kernel/linux/files