跳到主要内容

ubuntu安装riscv-gnu-toolchain

Docker构建riscv-gnu-toolchain环境

提示

mqylyl/riscv-gnu-toolchain镜像是基于ubuntu:22.04镜像进行构建,使用的是qemu模拟器,支持riscv32和riscv64

riscv-gnu-toolchain官方Github地址:https://github.com/riscv-collab/riscv-gnu-toolchain

拉取镜像

# 这里拉取的是elf-gcc的版本,大小:2G
# 是riscv-gnu-toolchain(2024/7/3的提交, commitid: 1358115963fb55cc445535d8a931e2f51dbe1940)
docker pull mqylyl/riscv-gnu-toolchain:elf_gcc_qemu_HEADE_1358115

tag解释:

  • riscv6432: 表示支持riscv64和riscv32
  • elf_gcc:内置riscv64-unknown-elf-gcc等交叉编译编译器工具
  • qemu:使用的是qemu模拟器
  • 20231018_nightly:对应官方release为2023.10.18-nightly
  • ubuntu2204_arm64:riscv-gnu-toolchain镜像是基于arm64的ubuntu:22.04进行构建
  • squashed:镜像中无源码,只有交叉编译二进制工具(没有squashed后缀的是带有riscv-gnu-toolchain完整源码的)

创建容器

# riscv toolchain是基于ubuntu 22.04镜像进行构建,这里设置一个端口与22端口进行映射便于使用ssh链接
docker run --name riscv64_elf_gcc \
-p 10022:22 \
-itd mqylyl/riscv-gnu-toolchain:elf_gcc_qemu_HEADE_1358115

进入容器

docker exec -it riscv64_elf_gcc /bin/bash

查看版本信息

$ riscv64-unknown-elf-gcc -v
Using built-in specs.
COLLECT_GCC=riscv64-unknown-elf-gcc
COLLECT_LTO_WRAPPER=/opt/riscv/libexec/gcc/riscv64-unknown-elf/13.2.0/lto-wrapper
Target: riscv64-unknown-elf
Configured with: /opt/source/riscv-gnu-toolchain/gcc/configure --target=riscv64-unknown-elf --prefix=/opt/riscv --disable-shared --disable-threads --enable-languages=c,c++ --with-pkgversion=gc891d8dc23e --with-system-zlib --enable-tls --with-newlib --with-sysroot=/opt/riscv/riscv64-unknown-elf --with-native-system-header-dir=/include --disable-libmudflap --disable-libssp --disable-libquadmath --disable-libgomp --disable-nls --disable-tm-clone-registry --src=.././gcc --enable-multilib --with-abi=lp64d --with-arch=rv64imafdc --with-tune=rocket --with-isa-spec=20191213 'CFLAGS_FOR_TARGET=-Os -mcmodel=medlow' 'CXXFLAGS_FOR_TARGET=-Os -mcmodel=medlow'
Thread model: single
Supported LTO compression algorithms: zlib
gcc version 13.2.0 (gc891d8dc23e)
$ qemu-system-riscv64 -version
QEMU emulator version 8.1.1 (v8.1.1)
Copyright (c) 2003-2023 Fabrice Bellard and the QEMU Project developers

编译运行C程序(hello_world.c)

编写hello_world.c文件

echo '#include <stdio.h>' > hello_world.c && \
echo 'int main() {' >> hello_world.c && \
echo ' printf("Hello, world!\n");' >> hello_world.c && \
echo ' return 0;' >> hello_world.c && \
echo '}' >> hello_world.c

编译运行riscv64

# 编译
$ riscv64-unknown-elf-gcc -march=rv64imafdc -mabi=lp64 -o hello_world_64 hello_world.c

# 查看二进制文件格式,64-bit
$ file hello_world_64
hello_world_64: ELF 64-bit LSB executable, UCB RISC-V, RVC, soft-float ABI, version 1 (SYSV), statically linked, with debug_info, not stripped

# 使用qemu运行程序
# qemu-riscv64:user mode运行
# -L: 用于加载模拟器的体系结构支持文件的目录(risc-v的一些库都在$RISCV/sysroot目录下)
# qemu-riscv64 -L $RISCV/sysroot ./hello_world_64
$ qemu-riscv64 ./hello_world_64
hello world!

编译运行riscv32

# 编译
$ riscv64-unknown-elf-gcc -march=rv32imafdc -mabi=ilp32 -o hello_world_32 hello_world.c

# 查看二进制文件格式,32-bit
$ file hello_world_32
hello_world_32: ELF 32-bit LSB executable, UCB RISC-V, RVC, soft-float ABI, version 1 (SYSV), statically linked, with debug_info, not strippe

# 运行
$ qemu-riscv32 ./hello_world_32
hello world!

二进制程序和源码目录

二进制程序放在在/opt/riscv

手动编译安装riscv-gnu-toolchain

信息

构建支持32位和64位的riscv elf-gcc交叉编译器

官方Github地址:https://github.com/riscv-collab/riscv-gnu-toolchain

中科院RISC-V工具链镜像使用帮助文档:https://help.mirrors.cernet.edu.cn/riscv-toolchains/

标准库安装(前置环境)

安装构建工具链所需要的标准包

sudo apt-get update && \
sudo apt-get upgrade -y && \
sudo apt-get install -y autoconf automake autotools-dev curl python3 python3-pip libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev ninja-build git cmake libglib2.0-dev libpixman-1-0 libpixman-1-dev

下载riscv-gnu-toolchain

GitHub(不推荐)

clone Github上的源码,更新子仓库这个过程十分的漫长可能需要很久很久很久,等待了几个小时最后可能因为网络的问题又失败了,建议使用中科院的镜像源

# clone 源代码,拉取仓库
git clone https://github.com/riscv/riscv-gnu-toolchain

# 更新子仓库
cd riscv-gnu-toolchain
git submodule update --init --recursive

中科院(推荐)

中科院软件所提供了一份RISC-V工具链镜像riscv-gnu-toolchain并实时同步submodule的更新,在终端中执行以下命令:

# 同时克隆子模块
curl https://mirror.iscas.ac.cn/riscv-toolchains/git/riscv-collab/riscv-gnu-toolchain.sh | bash

编译GCC和QEMU

cd riscv-gnu-toolchain

# 设置编译参数
# --enable-multilib:构建支持32位和64位的交叉编译器
# 支持的架构为 rv32i 或 rv64i 以及 MAFD 的标准扩展 (a)tomics、(m) 乘法和除法、(f)loat、(d)ouble 或 (g)general。
# 支持的 ABI 包括 ilp32(32 位软浮点)、ilp32d(32 位硬浮点)、ilp32f(寄存器中为单精度、内存中为双精度的 32 位,仅限利基使用)、lp64 lp64f lp64d(相同,但具有 64 位长和指针)。
./configure --prefix=/opt/riscv --enable-multilib

# 编译gcc
sudo make -j$(nproc)

# 编译qemu
sudo make -j$(nproc) build-sim SIM=qemu QEMU_TARGETS=riscv64-linux-user,riscv32-linux-user,riscv64-softmmu,riscv32-softmmu
  • -j: 是make命令的选项,用于指定并行构建的线程数。 -j 后面跟着的数字表示同时运行多少个构建任务,如:-j4 意味着要使用4个线程并行构建项目
  • $(nproc): 获取当前系统上可用的 CPU 核心数
  • build-sim: 构建模拟器
  • SIM=qemu: 使用qemu模拟器
  • riscv64-softmmu:表示要编译system mode的QEMU,riscv64-softmmu对应qemu-system-riscv64riscv32-softmmu对应qemu-system-riscv32
  • riscv64-linux-user:表示要编译user mode的QEMU,riscv64-linux-user对应qemu-riscv64riscv32-linux-user对应qemu-riscv32
  • ELF/Newlib工具链:是一个轻量级的C库,适用于嵌入式系统和裸机编程环境。它提供了C标准库函数的实现,适合用于没有标准操作系统的系统具有前缀riscv64-unknown-elf-使用make进行编译,支持32位、64位多架构,./config需要加上--enable-multilib参数。
  • Linux-ELF/glibc工具链:为支持运行在Linux操作系统上的应用程序而设计的工具链,适合于构建在Linux操作系统上运行的应用程序,包括服务器应用、应用程序开发、驱动程序开发,具有前缀riscv64-unknown-linux-gnu-使用make linux 进行编译,支持32位、64位多架构,./config需要加上--enable-multilib参数。
  • Linux musl工具链:Linux下的musl是一种C标准库(C library)的替代品,它提供了用于C和C++程序的标准函数和数据结构。与常见的GNU C库(glibc)不同,musl旨在提供更轻量级、可嵌入和高性能的C库,特别适用于嵌入式系统、小型设备和高效的应用程序具有前缀riscv64-unknown-linux-musl-使用make musl进行编译,由于上游 musl 架构支持的限制,musl 编译器 (riscv64-unknown-linux-musl-) 只能支持 64 位系统,即--enable-multilib参数实际上并没有起作用。

配置环境变量

echo 'export RISCV=/opt/riscv' >> /etc/profile && \
echo 'export PATH=$RISCV/bin:$PATH' >> /etc/profile && \
source /etc/profile

ubuntu要写在~/.bashrc中,要不然每次shell退出,就要重新source /etc/profile

# 追加内容
echo 'export RISCV=/opt/riscv' >> ~/.bashrc && \
echo 'export PATH=$RISCV/bin:$PATH' >> ~/.bashrc && \
source ~/.bashrc

查看版本信息

$ riscv64-unknown-elf-gcc -v
Using built-in specs.
COLLECT_GCC=riscv64-unknown-elf-gcc
COLLECT_LTO_WRAPPER=/opt/riscv/libexec/gcc/riscv64-unknown-elf/13.2.0/lto-wrapper
Target: riscv64-unknown-elf
Configured with: /opt/source/riscv-gnu-toolchain/gcc/configure --target=riscv64-unknown-elf --prefix=/opt/riscv --disable-shared --disable-threads --enable-languages=c,c++ --with-pkgversion=gc891d8dc23e --with-system-zlib --enable-tls --with-newlib --with-sysroot=/opt/riscv/riscv64-unknown-elf --with-native-system-header-dir=/include --disable-libmudflap --disable-libssp --disable-libquadmath --disable-libgomp --disable-nls --disable-tm-clone-registry --src=.././gcc --enable-multilib --with-abi=lp64d --with-arch=rv64imafdc --with-tune=rocket --with-isa-spec=20191213 'CFLAGS_FOR_TARGET=-Os -mcmodel=medlow' 'CXXFLAGS_FOR_TARGET=-Os -mcmodel=medlow'
Thread model: single
Supported LTO compression algorithms: zlib
gcc version 13.2.0 (gc891d8dc23e)
$ qemu-system-riscv64 -version
QEMU emulator version 8.1.1 (v8.1.1)
Copyright (c) 2003-2023 Fabrice Bellard and the QEMU Project developers

编译运行C程序(hello_world.c)

编写hello_world.c文件

echo '#include <stdio.h>' > hello_world.c && \
echo 'int main() {' >> hello_world.c && \
echo ' printf("Hello, world!\n");' >> hello_world.c && \
echo ' return 0;' >> hello_world.c && \
echo '}' >> hello_world.c

编译运行riscv64

# 编译
$ riscv64-unknown-elf-gcc -march=rv64imafdc -mabi=lp64 -o hello_world_64 hello_world.c

# 查看二进制文件格式,64-bit
$ file hello_world_64
hello_world_64: ELF 64-bit LSB executable, UCB RISC-V, RVC, soft-float ABI, version 1 (SYSV), statically linked, with debug_info, not stripped

# 使用qemu运行程序
# qemu-riscv64:user mode运行
# -L: 用于加载模拟器的体系结构支持文件的目录(risc-v的一些库都在$RISCV/sysroot目录下)
# qemu-riscv64 -L $RISCV/sysroot ./hello_world_64
$ qemu-riscv64 ./hello_world_64
hello world!

编译运行riscv32

# 编译
$ riscv64-unknown-elf-gcc -march=rv32imafdc -mabi=ilp32 -o hello_world_32 hello_world.c

# 查看二进制文件格式,32-bit
$ file hello_world_32
hello_world_32: ELF 32-bit LSB executable, UCB RISC-V, RVC, soft-float ABI, version 1 (SYSV), statically linked, with debug_info, not strippe

# 运行
$ qemu-riscv32 ./hello_world_32
hello world!

自动化脚本译安装riscv-gnu-toolchain

编写脚本

vim install_riscv-gun-toolchain_elf_gcc.sh
#!/bin/bash

set -e

# 标准库依赖
apt-get update && \
apt-get upgrade -y && \
apt-get install -y autoconf automake autotools-dev curl python3 python3-pip libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev ninja-build git cmake libglib2.0-dev libpixman-1-0 libpixman-1-dev

# clone riscv-gun-toolchain
curl https://mirror.iscas.ac.cn/riscv-toolchains/git/riscv-collab/riscv-gnu-toolchain.sh | bash

# 编译gcc和qemu
# --enable-multilib:构建支持32位和64位的交叉编译器
cd riscv-gnu-toolchain && \
./configure --prefix=/opt/riscv --enable-multilib && \
make -j$(nproc) && \
make -j$(nproc) build-sim SIM=qemu QEMU_TARGETS=riscv64-linux-user,riscv32-linux-user,riscv64-softmmu,riscv32-softmmu

# 配置环境变量
echo 'export RISCV=/opt/riscv' >> /etc/profile && \
echo 'export PATH=$RISCV/bin:$PATH' >> /etc/profile && \
source /etc/profile && \
echo 'export RISCV=/opt/riscv' >> ~/.bashrc && \
echo 'export PATH=$RISCV/bin:$PATH' >> ~/.bashrc && \
source ~/.bashrc

运行脚本

chmod +x install_riscv-gun-toolchain_elf_gcc.sh
# 要使用sudo权限
nohup sudo ./install_riscv-gun-toolchain_elf_gcc.sh &