RISC-V GNU Toolchain工具链

一、GNU 工具链内容

工具链包含以下内容:

  • gcc(GNU C Compiler):编译器
  • C运行库:包括glibc、newlib、musl三种运行库,为C标准库提供函数实现支持,可以根据需求进行自定义修改。
  • Binutils:二进制程序处理工具,包括ar(静态库处理)、as(汇编器)、ld(链接器)等。
  • GDB:用于项目调试。
  • DeJaGNU:程序测试框架,为所有测试提供一个前端支持。

二、运行时库

riscv-gnu-toolchain 工具链分为elf-gcclinux-gnu-gcc两个版本,以及他们对应的32位和64位版本。两个的主要区别在于:

  • elf-gcc:(riscv32-unknown-elf-*,riscv64-unknown-elf-*)使用的newlib库(面向嵌入式的C库),而且只支持静态链接,不支持动态链接。
  • linux-gnu-gcc:(riscv32-unknown-linux-gnu-*,riscv64-unknown-linux-gnu-*)使用的是glibc标准库支持动态链接

从名字上便可以区分两者的使用场景,如果是编译简单,较小的elf程序,使用elf-gcc版本即可,如果编译比较大的程序或者需要动态库(比如编译linux,或opencv库等),推荐使用linux-gnu-gcc版本。

newlib

newlib是redhat社区维护的一个C运行时库,与glibc相比,其最大的特点是代码体积小、可移植性强,特别适合嵌入式开发环境

例如,newlib重写了printf、scanf、malloc函数,减少调用开销;并默认开启-Os编译开关,对代码体积进行压缩。

glibc

musl

三、Binutils工具介绍

  • as:汇编器
  • ld:链接器
  • ar:生成静态链接库
  • ldd:查看一个可执行程序所需要的依赖库
  • size:查看一个可执行程序各部分的大小(数据段、代码段等)

四、安装步骤

Step 1:安装依赖工具

1
sudo apt-get install git autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf patchutils bc libexpat-dev libglib2.0-dev ninja-build zlib1g-dev pkg-config libboost-all-dev libtool libssl-dev libpixman-1-dev libpython-dev virtualenv libmount-dev libsdl2-dev

Step 2:下载riscv工具链

github项目:riscv-collab/riscv-gnu-toolchain: GNU toolchain for RISC-V, including GCC (github.com)

1
git clone https://github.com/riscv-collab/riscv-gnu-toolchain.git

**gitee项目:**https://gitee.com/mirrors/riscv-dejagnu

1
git clone https://gitee.com/mirrors/riscv-gnu-toolchain

ps:最好用github,它是最新的

Step 3:下载各种submodule

下载 RISC-V 平台的 C 语言编译器源代码仓库

1
git clone -b riscv-gcc-10.2.0 https://gitee.com/mirrors/riscv-gcc

下载测试框架源代码仓库,即 riscv-dejagnu

1
git clone https://gitee.com/mirrors/riscv-dejagnu

下载 GNU 的 C 库源代码仓库,也就是 riscv-glibc

1
git clone -b riscv-glibc-2.29 https://gitee.com/mirrors/riscv-glibc

下载用于嵌入式的轻量级 C 库源代码仓库,即 riscv-newlib

1
git clone https://gitee.com/mirrors/riscv-newlib

下载二进制工具集合源代码仓库 riscv-binutils

1
git clone -b riscv-binutils-2.35 https://gitee.com/mirrors/riscv-binutils-gdb riscv-binutils

下载 GDB 软件调试器源代码仓库 riscv-gdb

1
git clone -b fsf-gdb-10.1-with-sim https://gitee.com/mirrors/riscv-binutils-gdb riscv-gdb

Step 3:使用./configure进行配置

1
./configure --prefix=xxx --with-arch=xxx --with-abi=xxx

(–prefix=)选项

安装后的目标文件夹

例如--prefix=/opt/riscv/,则安装后的可执行文件如下:

image-20240226193037166

(–with-arch=)选项

由于RISC-V的指令集是模块化的指令集,因此在为目标RISC-V平台进行交叉编译之时,需要通过选项指定目标RISC-V平台所支持的模块化指令集组合,该选项为(-march=),有效的选项值如下:

  • rv32i[m][a][f[d]][c]
  • rv32g[c]
  • rv64i[m][a][f[d]][c]
  • rv64g[c]

注意:在上述选项中rv32表示目标平台是32位架构,rv64表示目标平台是64位架构,其他i/m/a/f/d/c/g分别代表了RISC-V模块化指令子集的字母简称。

(–with-abi=)选项

由于RISC-V的指令集是模块化的指令集,因此在为目标RISC-V平台进行交叉编译之时,需要通过选项指定嵌入式RISC-V目标平台所支持的ABI函数调用规则

RISC-V定义了两种整数的ABI调用规则和三种浮点ABI调用规则,通过选项(-abi=)指明,有效的选项值如下:

  • ilp32
  • ilp32f
  • ilp32d
  • lp64
  • lp64f
  • lp64d

在上述选项中两种前缀(ilp32和lp64)表示的含义如下:

  • 前缀ilp32表示目标平台是32位架构,在此架构下,C语言的“int”和“long”变量长度为32比特,“long long”变量为64位;
  • 前缀lp64表示目标平台是64位架构,C语言的“int”变量长度为32比特,而“long”变量长度为64比特。

上述选项中的三种后缀类型(无后缀、后缀f、后缀d)表示的含义如下:

  • 无后缀:在此架构下,如果使用了浮点类型的操作,直接使用RISC-V浮点指令进行支持。但是当浮点数作为函数参数进行传递之时,无论单精度浮点数还是双精度浮点数均需要通过存储器中的堆栈进行传递。
  • f:表示目标平台支持硬件单精度浮点指令。在此架构下,如果使用了浮点类型的操作,直接使用RISC-V浮点指令进行支持。但是当浮点数作为函数参数进行传递之时,单精度浮点数可以直接通过寄存器传递,而双精度浮点数需要通过存储器中的堆栈进行传递。
  • d:表示目标平台支持硬件双精度浮点指令。在此架构下,如果使用了浮点类型的操作,直接使用RISC-V浮点指令进行支持。当浮点数作为函数参数进行传递之时,无论单精度还是双精度浮点数都可以直接通过寄存器传递。

Step 4:使用make命令进行构建

makemake allmake newlib 命令构建使用newlib的elf-gcc

make linux 命令构建使用glibc的linux-gnu-gcc

开启-j选项可以启动多线程编译

Step 5 设置环境变量

~/.bashrc文件末尾加入以下语句来将(yourtpath)路径加入环境变量

1
export PATH=$PATH:(yourpath)

再在终端中执行以下命令更新环境变量

1
source ~/.bashrc

Step 6 检查配置

通过相应gcc的-v命令,可以得到该工具链的配置信息,例如:

1
2
3
4
5
6
7
8
$ riscv32-unknown-elf-gcc -v
Using built-in specs.
COLLECT_GCC=./riscv32-unknown-elf-gcc
COLLECT_LTO_WRAPPER=/opt/riscv/libexec/gcc/riscv32-unknown-elf/8.2.0/lto-wrapper
Target: riscv32-unknown-elf
Configured with: /tools/riscv-gnu-toolchain-1/build/../riscv-gcc/configure --target=riscv32-unknown-elf --prefix=/opt/riscv --disable-shared --disable-threads --enable-languages=c,c++ --with-system-zlib --enable-tls --with-newlib --with-sysroot=/opt/riscv/riscv32-unknown-elf --with-native-system-header-dir=/include --disable-libmudflap --disable-libssp --disable-libquadmath --disable-libgomp --disable-nls --src=../../riscv-gcc --enable-checking=yes --disable-multilib --with-abi=ilp32 --with-arch=rv32imc 'CFLAGS_FOR_TARGET=-Os -mcmodel=medlow' 'CXXFLAGS_FOR_TARGET=-Os -mcmodel=medlow'
Thread model: single
gcc version 8.2.0 (GCC)

可以看出

1
2
3
4
5
6
--target=riscv32-unknown-elf: 指定工具为riscv32-unknow-elf
--prefix=/opt/riscv32: 指定工具生成的目录
--enable-languages=c,c++: 支持c,c++语言
--with-newlib: c运行库使用newlib
--with-abi=ilp32: 工具链支持的abi方式是ilp64
--with-arch=rv32imc: 工具链支持的riscv架构是 rv64imc

常用配置下RISCV工具链配置与编译

  1. riscv32-unknown-elf-gcc

    1
    2
    ./configure --prefix=/opt/riscv32 --with-arch=rv32imc --with-abi=lp32
    make

    编译完成后,在/opt/riscv32/bin目录下,有riscv32-unknown-elf-gcc的所有工具。

  2. riscv64-unknown-elf-gcc

    1
    2
    ./configure --prefix=/opt/riscv64 --with-arch=rv64imc --with-abi=lp64
    make

    编译完成后,在/opt/riscv64/bin目录下,有riscv64-unknown-elf-gcc的所有工具。

  3. riscv32-unknown-linux-gnu-gcc

    1
    2
    ./configure --prefix=/opt/riscv32-linux --with-arch=rv32imc --with-abi=ilp32 --enable-linux
    make linux

    编译完成后,在/opt/riscv32-linux/bin目录下,有riscv32-unknown-linux-gnu-gcc的所有工具。

  4. riscv64-unknown-linux-gnu-gcc

    1
    2
    ./configure --prefix=/opt/riscv64-linux --with-arch=rv64imafdc --with-abi=lp64 --enable-linux
    make linux

    编译完成后,在/opt/riscv64-linux/bin目录下,有riscv64-unknown-linux-gnu-*的所有工具。

构建默认riscv工具链的全部命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
sudo apt-get install git autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf patchutils bc libexpat-dev libglib2.0-dev ninja-build zlib1g-dev pkg-config libboost-all-dev libtool libssl-dev libpixman-1-dev libpython-dev virtualenv libmount-dev libsdl2-dev
git clone https://gitee.com/mirrors/riscv-gnu-toolchain

cd riscv-gnu-toolchain

git clone -b riscv-gcc-10.2.0 https://gitee.com/mirrors/riscv-gcc

git clone https://gitee.com/mirrors/riscv-dejagnu

git clone -b riscv-glibc-2.29 https://gitee.com/mirrors/riscv-glibc

git clone https://gitee.com/mirrors/riscv-newlib

git clone -b riscv-binutils-2.35 https://gitee.com/mirrors/riscv-binutils-gdb riscv-binutils

git clone -b fsf-gdb-10.1-with-sim https://gitee.com/mirrors/riscv-binutils-gdb riscv-gdb

./configure --prefix=/opt/riscv

make linux -j4

参考博客

riscv-gnu-toolchain 交叉编译器如何构建? - 知乎 (zhihu.com)https://blog.csdn.net/u014558361/article/details/135372254)

riscv-gnu-toolchain工具链-从下载到运行_riscv toolchain-CSDN博客

参考视频

20201019_RISCV-GNU-Toolchain_陈嘉炜_哔哩哔哩_bilibili