在ubuntu上构建riscv64编译运行环境

3 篇文章 0 订阅
3 篇文章 0 订阅

Ubuntu && LLVM && RISC-V

主要参考:

https://risc-v-getting-started-guide.readthedocs.io/en/latest/linux-qemu.html

https://zhuanlan.zhihu.com/p/263550372

https://zhuanlan.zhihu.com/p/258394849

1 LLVM构建

1.1 LLVM 源码下载

建议下载LLVM release版本:https://releases.llvm.org/

当前版本:11.0.0

下载:Sources --> llvm-project monorepo source code (.sig)选项

1.2 编译前配置 & 编译安装

创建build,然后使用cmake配置;或者使用clion等IDE配置,参考https://blog.csdn.net/qq_21746331/article/details/110198265#t8

推荐先了解cmake,再使用IDE

$ cmake -G <generator> [options] SRC_ROOT

其中:

  • generator 表示用于最终驱动 gcc 执行编译生成 llvm 的工具,是用双引号括起来的字符串,cmake 支持跨平台开发,有以下四种选项:

    • Unix Makefiles: 即采用 Unix 上传统的 Make,指定该选项后 cmake 负责生成用于 Make 的 makefile 文件。
    • Ninja: 采用 Ninja,指定该选项后 cmake 负责生成用于 Ninja 的 build.ninja 文件。这是 LLVM 的开发社区推荐采用的方式,因为对于像 LLVM 这样的大型软件来说,采用 Ninja 会大大加速编译的速度。
    • Visual Studio: 指示 cmake 产生用于 Visual Studio 的项目构造文件。
    • Xcode: 指示 cmake 产生用于 Xcode 的项目构造文件, Xcode 是运行在操作系统 MacOS X 上的集成开发工具(IDE)。
  • SRC_ROOT: LLVM 的官方定义是 the top level directory of the LLVM source tree, 在这里指的就是我们下载的仓库根目录 llvm-project 下的 llvm 子目录,在 LLVM 项目中 llvm 子目录存放的是这个项目的主框架代码,是必须要编译的对象。

  • options,以 -D 开头定义的选项宏,如果超过一个则用空格分隔。这些选项会影响 cmake 生成的构造配置文件并进而影响整个编译构造过程,针对 LLVM 常用的有以下这些,更多选项请参阅 【参考 1】:

    • CMAKE_BUILD_TYPE=type: 指定生成的应用程序(这里当然指的是 LLVM)的类型,type 包括 DebugReleaseRelWithDebInfo 或者 MinSizeRel。如果不指定缺省为 Debug
    • CMAKE_INSTALL_PREFIX=directory: 用于指定编译完后安装 LLVM 工具和库的路径,如果不指定,默认安装在 /usr/local
    • LLVM_TARGETS_TO_BUILD: 用于指定生成的 LLVM 可以支持的体系架构(这里称为 target),LLVM 和 GCC 有个很大的不同点是, GCC 需要为每个特定的体系架构,譬如 arm/x86 独立生成一套交叉工具链套件,而 LLVM 是在一个工具链套件中就可以支持多个体系架构。如果不指定,默认会编译所有的 targets,具体的 targets 有哪些,可以看源码 llvm-project/llvm/CMakeLists.txtLLVM_ALL_TARGETS 的定义。具体制作时可以自己指定需要的 targets,通过以分号(semicolon)分隔方式给出,譬如 -DLLVM_TARGETS_TO_BUILD="ARM;PowerPC;X86"
    • LLVM_DEFAULT_TARGET_TRIPLE: 可以通过该选项修改默认的 target 的 triple 组合,不指定默认是 x86_64-unknown-linux-gnu
    • LLVM_ENABLE_PROJECTS='...': LLVM 是整个工具链套件的总称,LLVM 下包括了很多个子项目,譬如 clang, clang-tools-extra, libcxx, libcxxabi, libunwind, lldb, compiler-rt, lld, polly, or debuginfo-tests 等。如果不指定该选项,默认只编译 llvm 这个主框架。如果要选择并指定编译哪些子项目,可以通过分号分隔方式给出,譬如我们在编译 llvm 之外还想编译 Clang, libcxx, 和 libcxxabi, 那么可以写成这样:-DLLVM_ENABLE_PROJECTS="clang;libcxx;libcxxabi"
$ cmake -G "Unix Makefiles" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=../install \
-DLLVM_TARGETS_TO_BUILD="RISCV" \
-DLLVM_ENABLE_PROJECTS="clang;libcxx;libcxxabi" \
-DLLVM_DEFAULT_TARGET_TRIPLE="riscv64-unknown-linux-gnu" \
../llvm
$ make -j $(nproc)
$ make install
$ ../install/bin/clang -v
clang version 10.0.1 (https://gitee.com/mirrors/llvm-project.git ef32c611aa214dea855364efd7ba451ec5ec3f74)
Target: riscv64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/u/ws/llvm-project/test/../install/bin

2 构建RISCV交叉编译工具链

2.1 环境准备

$ sudo apt install 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 git \
                 libglib2.0-dev libfdt-dev libpixman-1-dev \
                 libncurses5-dev libncursesw5-dev
$ mkdir riscv64-linux
$ cd riscv64-linux

2.2 从国内镜像git riscv-gnu-toolchain 并移除qemu并下载其他子库

$ git clone https://gitee.com/mirrors/riscv-gnu-toolchain
$ cd riscv-gnu-toolchain
$ git rm qemu
$ git submodule update --init --recursive

2.3 编译交叉工具链

$ ./configure --prefix=/opt/riscv64 
$ sudo make linux -j $(nproc)

2.4 export

export PATH="$PATH:/opt/riscv64/bin"

2.5 验证

$ riscv64-unknown-linux-gnu-gcc -v
Using built-in specs.
COLLECT_GCC=riscv64-unknown-linux-gnu-gcc
COLLECT_LTO_WRAPPER=/opt/riscv64/libexec/gcc/riscv64-unknown-linux-gnu/10.1.0/lto-wrapper
Target: riscv64-unknown-linux-gnu
Configured with: /home/u/ws/riscv64-linux/riscv-gnu-toolchain/riscv-gcc/configure --target=riscv64-unknown-linux-gnu --prefix=/opt/riscv64 --with-sysroot=/opt/riscv64/sysroot --with-system-zlib --enable-shared --enable-tls --enable-languages=c,c++,fortran --disable-libmudflap --disable-libssp --disable-libquadmath --disable-libsanitizer --disable-nls --disable-bootstrap --src=.././riscv-gcc --disable-multilib --with-abi=lp64d --with-arch=rv64imafdc --with-tune=rocket 'CFLAGS_FOR_TARGET=-O2   -mcmodel=medlow' 'CXXFLAGS_FOR_TARGET=-O2   -mcmodel=medlow'
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 10.1.0 (GCC)

3 构建RISCV运行环境:QEMU

3.1 下载qemu源码

$ cd riscv64-linux
#回到根目录
$ wget https://download.qemu.org/qemu-5.2.0.tar.xz
$ tar xvJf qemu-5.2.0.tar.xz

3.2 编译和安装qemu

$ cd qemu-5.1.0/
$ ./configure --target-list=riscv64-softmmu --prefix=/opt/qemu
$ make -j $(nproc)
$ sudo make install

3.3 export

export PATH=$PATH:/opt/riscv64/bin:/opt/qemu/bin

3.4 验证qemu

$ qemu-system-riscv64 --version
QEMU emulator version 5.1.0
Copyright (c) 2003-2020 Fabrice Bellard and the QEMU Project developers

3.5 下载内核源码

$ cd riscv64-linux
#回到根目录
$ git clone https://gitee.com/mirrors/linux.git

如果出现“过早的文件结束符”,尝试扩大缓存

3.6 配置和编译内核

$ git checkout v5.4
$ make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- defconfig
$ make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- -j $(nproc)

3.7 下载busybox源码

$ cd riscv64-linux
#回到根目录
$ git clone https://gitee.com/mirrors/busyboxsource.git
$ cd busyboxsource

3.8 配置编译安装busybox

$ CROSS_COMPILE=riscv64-unknown-linux-gnu- make menuconfig
#打开配置菜单后进入第一行的 "Settings",在"Build Options"节中,选中 “Build static binary (no shared libs)”,设置好后退出保存配置。

$ CROSS_COMPILE=riscv64-unknown-linux-gnu- make -j $(nproc)
$ CROSS_COMPILE=riscv64-unknown-linux-gnu- make install
$ ls _install
bin  linuxrc  sbin  usr

3.9 制作一个最小的文件系统

$ cd riscv64-linux
#回到根目录
$ qemu-img create rootfs.img  1g
$ mkfs.ext4 rootfs.img
$ mkdir rootfs
$ sudo mount -o loop rootfs.img  rootfs
$ cd rootfs
$ sudo cp -r ../busyboxsource/_install/* .
$ sudo mkdir proc sys dev etc etc/init.d
$ cd etc/init.d/
$ sudo touch rcS
$ sudo vi rcS
#编辑该文件如下
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
/sbin/mdev -s

$ sudo chmod +x rcS
$ sudo umount rootfs

4 编译并启动运行

4.1 编译

编辑一个简单的 c 文件 test.c

$ vim test.c 
#include <stdio.h>

int main(int argc, char *argv[])
{
 printf("Hello, world!\n");
 return 0;
}

受限于 LLVM 自身链接器和 C 库的不完善,clang 目前需要使用 GNU 的链接器和 C 库来生成 RISC-V 的可执行程序。

运行 clang 编译程序,通过 --sysroot 选项来指定 gnu 工具链的 sysroot,通过 --gcc-toolchain 来指定 gcc 工具链的位置。

使用 2 中制作的交叉编译工具链,生成riscv上的可执行文件

$ clang --target=riscv64-unknown-linux-gnu --gcc-toolchain=/opt/riscv64 --sysroot=/opt/riscv64/sysroot/ --static test.c

验证文件格式

$ file a.out
a.out: ELF 64-bit LSB executable, UCB RISC-V, version 1 (SYSV), statically linked, for GNU/Linux 4.15.0, with debug_info, not stripped

4.2 启动qemu并运行riscv可执行文件

将文件复制到3中构建的文件系统中

$ cd riscv64-linux
#回到根目录
$ sudo mount -o loop rootfs.img  rootfs
$ sudo cp <the path of the a.out> rootfs/root/
$ sudo umount rootfs

启动qemu并运行

$ qemu-system-riscv64 -M virt -m 256M -nographic -kernel linux/arch/riscv/boot/Image -drive file=rootfs.img,format=raw,id=hd0  -device virtio-blk-device,drive=hd0 -append "root=/dev/vda rw console=ttyS0"

/ # cd root/
/root # ./a.out 
Hello, world!
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值