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-riscv64
,riscv32-softmmu
对应qemu-system-riscv32
- riscv64-linux-user:表示要编译
user mode
的QEMU,riscv64-linux-user
对应qemu-riscv64
,riscv32-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 &