主要参考了这几篇文章:
总纲:RISCV仿真环境搭建:riscv-tools_Like_ai的博客-CSDN博客
riscv-gnu-toolchain:搭建RISC-V编译环境与运行环境 - 知乎 (zhihu.com)
riscv-gnu-toolchain代码下载:riscv-gnu-toolchain工具链-从下载到运行_limanjihe的博客-CSDN博客_riscv-gnu-toolchain
riscv-gnu-toolchain是交叉工具链,利用这个工具链对C/C++文件进行编译,生成一个输出文件(file.o或者file.elf),riscv-tools是仿真工具(模拟目标机器),对前面输出的可执行文件进行仿真。
环境准备:centos7
RISCV环境变量设置为RISC-V工具链安装路径,可以写在/etc/profile或者~/.bashrc中
export RISCV="/tools/riscv/toolchain" #工具链的安装链接路径 export PATH=$PATH:$RISCV/bin # $RISCV/bin链接工具的位置
安装软件包:对于centos在装过riscv-gnu-toolchain交叉编译器情况下,主要查看device-tree-compiler(即dtc工具)是否拥有。
yum install dtc
在编译时,会要求更高版本的gcc版本:(g++: error: unrecognized command line option '-std=c++17')
在编译环境上安装高版本gcc,或者拷贝一个源码安装的gcc目录,设置PATH export PATH=/tools/misc/gcc/7.4.0/bin:$PATH export LD_LIBRARY_PATH=/tools/misc/gcc/7.4.0/lib:$LD_LIBRARY_PATH
github源码:https://github.com/riscv-collab/riscv-gnu-toolchain
下载代码算是环境安装中的一个比较耗时的一步了,想要在GitHub上拿到源码编译非常困难,即使使用了科学上网网络也不是很好。比较庆幸的是Gitee上有镜像源,每天同步一次。但是注意子仓的下载才是最难的,要把子仓一个个换成Gitee仓库。(子仓需要在Gitee上搜索仓库是否同步正确,对应分支是否存在:Gitee 极速下载 - Gitee.com)子仓中还有几个开源软件,用到的是清华的开源软件源:清华大学开源软件镜像站 | Tsinghua Open Source Mirror
步骤如下:
下载主仓:
git clone https://gitee.com/mirrors/riscv-gnu-toolchain.git cd riscv-gnu-toolchain
2. 修改子仓url:
原.gitmodules
cat .gitmodules [submodule "binutils"] path = binutils url = https://sourceware.org/git/binutils-gdb.git branch = binutils-2_39-branch [submodule "gcc"] path = gcc url = https://gcc.gnu.org/git/gcc.git branch = releases/gcc-12.1.0 [submodule "glibc"] path = glibc url = https://sourceware.org/git/glibc.git [submodule "riscv-dejagnu"] path = riscv-dejagnu url = https://github.com/riscv-collab/riscv-dejagnu.git branch = riscv-dejagnu-1.6 [submodule "newlib"] path = newlib url = https://sourceware.org/git/newlib-cygwin.git branch = master [submodule "riscv-gdb"] path = riscv-gdb url = https://github.com/riscv-collab/riscv-binutils-gdb.git branch = fsf-gdb-10.1-with-sim [submodule "qemu"] path = qemu url = https://gitlab.com/qemu-project/qemu.git [submodule "musl"] path = musl url = git://git.musl-libc.org/musl branch = master [submodule "spike"] path = spike url = https://github.com/riscv-software-src/riscv-isa-sim.git branch = master [submodule "pk"] path = pk url = https://github.com/riscv-software-src/riscv-pk.git branch = master
修改后,其中用到了清华的开源软件源,以及Gitee源:
[submodule "binutils"] path = binutils url = https://mirrors.tuna.tsinghua.edu.cn/git/binutils-gdb.git branch = binutils-2_39-branch [submodule "gcc"] path = gcc url = https://mirrors.tuna.tsinghua.edu.cn/git/gcc.git branch = releases/gcc-12.1.0 [submodule "glibc"] path = glibc url = https://mirrors.tuna.tsinghua.edu.cn/git/glibc.git [submodule "riscv-dejagnu"] path = riscv-dejagnu url = https://gitee.com/mirrors/riscv-dejagnu branch = riscv-dejagnu-1.6 [submodule "newlib"] path = newlib url = https://gitee.com/mirrors/riscv-newlib branch = master [submodule "riscv-gdb"] path = riscv-gdb url = https://gitee.com/mirrors/riscv-binutils-gdb.git branch = fsf-gdb-10.1-with-sim [submodule "qemu"] path = qemu url = https://mirrors.tuna.tsinghua.edu.cn/git/qemu.git [submodule "musl"] path = musl url = https://gitee.com/mirrors/musl.git branch = master [submodule "spike"] path = spike url = https://gitee.com/mirrors/riscv-isa-sim.git branch = master [submodule "pk"] path = pk url = https://github.com/riscv-software-src/riscv-pk.git branch = master
3. 更新子仓:
git submodule update --init --recursive
sudo yum install autoconf automake python3 libmpc-devel mpfr-devel gmp-devel gawk bison flex texinfo patchutils gcc gcc-c++ zlib-devel expat-devel
编译riscv64-unknown-elf-gcc
: (本文只编译了这个gcc)
./configure --prefix=$RISCV sudo make # 可以用make -j$(nproc) 来加速编译
编译64-bitriscv64-unknown-linux-gnu-gcc
:
./configure --prefix=/opt/riscv sudo make linux
编译32-bit:
./configure --prefix=/opt/riscv --with-arch=rv32gc --with-abi=ilp32d sudo make linux
编译32-bit和64-bit:
./configure --prefix=/opt/riscv --enable-multilib sudo make linux
这两个gcc的区别在于,elf-gcc是静态链接,linux-gnu-gcc是动态链接。
编译完可以去$RISCV/bin目录下检查下生成的二进制文件:
[root@gerrit-backup bin]# ls -lt total 815924 -rwxr-xr-x. 1 root root 3804552 Aug 30 11:30 riscv64-unknown-elf-gcov-dump -rwxr-xr-x. 1 root root 4073824 Aug 30 11:30 riscv64-unknown-elf-gcov-tool -rwxr-xr-x. 1 root root 5760744 Aug 30 11:30 riscv64-unknown-elf-gcov -rwxr-xr-x. 1 root root 152912 Aug 30 11:30 riscv64-unknown-elf-gcc-ranlib -rwxr-xr-x. 1 root root 152896 Aug 30 11:30 riscv64-unknown-elf-gcc-nm -rwxr-xr-x. 1 root root 153008 Aug 30 11:30 riscv64-unknown-elf-gcc-ar -rwxr-xr-x. 1 root root 13760048 Aug 30 11:30 riscv64-unknown-elf-cpp -rwxr-xr-x. 2 root root 13739832 Aug 30 11:30 riscv64-unknown-elf-gcc -rwxr-xr-x. 2 root root 13739832 Aug 30 11:30 riscv64-unknown-elf-gcc-12.1.0 -rwxr-xr-x. 1 root root 198479896 Aug 30 11:30 riscv64-unknown-elf-lto-dump -rwxr-xr-x. 2 root root 13762680 Aug 30 11:30 riscv64-unknown-elf-c++ -rwxr-xr-x. 2 root root 13762680 Aug 30 11:30 riscv64-unknown-elf-g++ -rwxr-xr-x. 1 root root 4045 Aug 30 11:16 riscv64-unknown-elf-gdb-add-index -rwxr-xr-x. 1 root root 104069296 Aug 30 11:16 riscv64-unknown-elf-gdb -rwxr-xr-x. 1 root root 7847096 Aug 30 11:16 riscv64-unknown-elf-run -rwxr-xr-x. 1 root root 5162208 Aug 30 11:12 riscv64-unknown-elf-c++filt -rwxr-xr-x. 2 root root 6060840 Aug 30 11:12 riscv64-unknown-elf-strip -rwxr-xr-x. 2 root root 5276296 Aug 30 11:12 riscv64-unknown-elf-nm -rwxr-xr-x. 1 root root 271312 Aug 30 11:12 riscv64-unknown-elf-elfedit -rwxr-xr-x. 2 root root 4080960 Aug 30 11:12 riscv64-unknown-elf-readelf -rwxr-xr-x. 1 root root 5219200 Aug 30 11:12 riscv64-unknown-elf-addr2line -rwxr-xr-x. 2 root root 6060848 Aug 30 11:12 riscv64-unknown-elf-objcopy -rwxr-xr-x. 2 root root 5442872 Aug 30 11:12 riscv64-unknown-elf-ranlib -rwxr-xr-x. 4 root root 8526168 Aug 30 11:12 riscv64-unknown-elf-ld -rwxr-xr-x. 4 root root 8526168 Aug 30 11:12 riscv64-unknown-elf-ld.bfd -rwxr-xr-x. 1 root root 5226056 Aug 30 11:12 riscv64-unknown-elf-strings -rwxr-xr-x. 2 root root 5442872 Aug 30 11:12 riscv64-unknown-elf-ar -rwxr-xr-x. 2 root root 8672264 Aug 30 11:12 riscv64-unknown-elf-objdump -rwxr-xr-x. 1 root root 5204520 Aug 30 11:12 riscv64-unknown-elf-size -rwxr-xr-x. 1 root root 5862048 Aug 30 11:12 riscv64-unknown-elf-gprof -rwxr-xr-x. 2 root root 7632544 Aug 30 11:12 riscv64-unknown-elf-as
这一步一定要检查是否已经生成riscv64-unknown-elf-cpp并且$RISCV/bin路径已经加入PATH,否则后续编译riscv-tools会报错:
gcc: error: unrecognized argument in option ‘-mcmodel=medany’ gcc: note: valid arguments to ‘-mcmodel=’ are: 32 kernel large medium small; did you mean ‘medium’? make: *** [file.o] Error 1
git clone https://github.com/riscv/riscv-fesvr.git cd riscv-fesvr #克隆完成进入克隆下来的目录 mkdir build && cd build #创建并进入build文件夹 ../configure --prefix=$RISCV --target=riscv64-unknown-elf #检查环境并生成当前环境使用的Makefile,如果需要指定编译链的输出目录,就可以把R I S C V 改 为 相 应 目 录 或 者 配 置 RISCV改为相应目录或者配置RISCV改为相应目录或者配置RISCV环境变量为相应的目录。 如果没有配置就默认为/bin --target=为你的编译链的路径 [sudo] make install #编译安装,[sudo]代表sudo可选,安装输出目录的读写全写的实际情况选择
具体细节见:GitHub - riscvarchive/riscv-fesvr: RISC-V Frontend Server
git clone --recursive https://github.com/riscv/riscv-tools.git
会下载下面的几个模块
Spike, the ISA simulator
riscv-tests, a battery of ISA-level tests
riscv-opcodes, the enumeration of all RISC-V
opcodes executable by the simulator
riscv-pk, which contains bbl, a boot loader for Linux and similar OS kernels, and pk, a proxy kernel that services system calls for a target-machine application by forwarding them to the host machine
由于网络环境不好,而且需求清单中只需要安装:riscv isa simulator和riscv proxy kernel
笔者选择下载这两个库并分别安装:
参考:https://github.com/riscv-software-src/riscv-isa-sim 和 GitHub - riscv-software-src/riscv-pk: RISC-V Proxy Kernel
riscv-isa-sim:
$ git clone https://github.com/riscv-software-src/riscv-isa-sim.git $ cd riscv-isa-sim $ mkdir build $ cd build $ ../configure --prefix=$RISCV $ make $ make install
riscv-pk
$ git clone https://github.com/riscv-software-src/riscv-pk.git $ cd riscv-pk $ mkdir build $ cd build $ ../configure --prefix=$RISCV --host=riscv64-unknown-elf #此处指定了编译器为riscv64-unknown-elf,需确保该文件能在PATH中被找到。 $ make $ make install
自此,安装完成,$RISCV/目录结构一览:
[root@gerrit-backup bin]# cd /tools/riscv/toolchain/ [root@gerrit-backup toolchain]# ls bin include lib lib64 libexec riscv64-unknown-elf share [root@gerrit-backup toolchain]# cd bin/ [root@gerrit-backup bin]# ls elf2hex riscv64-unknown-elf-cpp riscv64-unknown-elf-gcc-nm riscv64-unknown-elf-gdb-add-index riscv64-unknown-elf-objcopy riscv64-unknown-elf-strings xspike riscv64-unknown-elf-addr2line riscv64-unknown-elf-elfedit riscv64-unknown-elf-gcc-ranlib riscv64-unknown-elf-gprof riscv64-unknown-elf-objdump riscv64-unknown-elf-strip riscv64-unknown-elf-ar riscv64-unknown-elf-g++ riscv64-unknown-elf-gcov riscv64-unknown-elf-ld riscv64-unknown-elf-ranlib spike riscv64-unknown-elf-as riscv64-unknown-elf-gcc riscv64-unknown-elf-gcov-dump riscv64-unknown-elf-ld.bfd riscv64-unknown-elf-readelf spike-dasm riscv64-unknown-elf-c++ riscv64-unknown-elf-gcc-12.1.0 riscv64-unknown-elf-gcov-tool riscv64-unknown-elf-lto-dump riscv64-unknown-elf-run spike-log-parser riscv64-unknown-elf-c++filt riscv64-unknown-elf-gcc-ar riscv64-unknown-elf-gdb riscv64-unknown-elf-nm riscv64-unknown-elf-size termios-xspike
创建hello.c
#include <stdio.h> int main(void) { printf("Hello Word!\n"); return 0; }
编译执行(如果$RISCV/bin已经加入PATH,则不用指定绝对路径)
riscv64-unknown-elf-gcc hello.c -o hello.o spike pk hello.o
2. 执行结果
bbl loader hello, word
此外,在验证时出现报错:
[root@gerrit-backup local]# /tools/riscv/toolchain/bin/spike pk hello.o /tools/riscv/toolchain/bin/spike: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by /tools/riscv/toolchain/bin/spike) /tools/riscv/toolchain/bin/spike: /lib64/libstdc++.so.6: version `CXXABI_1.3.8' not found (required by /tools/riscv/toolchain/bin/spike) /tools/riscv/toolchain/bin/spike: /lib64/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by /tools/riscv/toolchain/bin/spike) /tools/riscv/toolchain/bin/spike: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by /tools/riscv/toolchain/bin/spike) [root@gerrit-backup local]# strings /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | grep GLIBCXX strings: '/usr/lib/x86_64-linux-gnu/libstdc++.so.6': No such file
这是因为环境上的libstdc++版本太低了,升级到libstdc++.so.6.0.26就可以了。
# 将libstdc++.so.6.0.26放到/usr/lib64目录下 scp -r root@10.2***:/usr/local/share/libstdc++.so.6.0.26 ./ ls -al libstdc++* mv libstdc++.so.6 libstdc++.so.6.bak ln -s libstdc++.so.6.0.26 libstdc++.so.6