这个教程是PLCT推出的,强烈推荐。在这篇文章中,我们就简单记录下这个学习过程。
https://gist.github.com/sunshaoce/90216c19591581f8997df0109b65c154 这个是RISC-V环境的构建脚本,需要先下载有相应的代码仓库。
riscv elfapi url: https://github.com/riscv-non-isa/riscv-elf-psabi-doc
Docker 环境也有了:
大家好,RVCC 开发环境的 Docker 镜像已经配置好,欢迎大家使用。详情可以参考:https://github.com/ksco/rvcc-env-docker。
提供的是国内阿里云的 registry,下载飞快!
[完结] 循序渐进,学习开发一个RISC-V上的操作系统 - 汪辰 - 2021春
https://www.bilibili.com/video/BV1Q5411w7z5
可以看看前面一部分的公共知识课,包含了RISC-V的基础指令集的详细的介绍和一些程序执行堆栈的知识
01视频地址 首先我是在rv硬件上执行这个程序的,所以命令稍微不同,但是效果是一样的。我只是没用交叉编译器嘛。
#cat tmp.s
.global main # 声明一个main的段,程序的入口
main: # 段开始的标志
li a0, 42 # a0寄存器就是 返回值
ret
# compiler cmd:
gcc -s tmp.s
./a.out
vimer@unmatched:~/build/rvcc$ echo $?
42
接下来,我们再进一步,使用一个 .c 文件:
vimer@unmatched:~/build/rvcc/02$ cat main.c
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char ** argv){
if (argc != 2){
// argc is right
fprintf(stderr, "%s: invalid number of argcs\n", argv[0]);
return 1;
}
printf(" .global main\n");
printf("main:\n");
printf(" li a0, %d\n", atoi(argv[1]));
printf(" ret\n");
}
然后Makefile:
vimer@unmatched:~/build/rvcc/02$ cat Makefile
# C编译器参数:使用C11标准,生成debug信息,禁止将未初始化的全局变量放入到common段
CFLAGS=-std=c11 -g -fno-common
# 指定C编译器,来构建项目
CC=clang
# rvcc标签,表示如何构建最终的二进制文件,依赖于main.o文件
rvcc: main.o
# 将多个*.o文件编译为rvcc
$(CC) -o rvcc $(CFLAGS) main.o
# 测试标签,运行测试脚本
test: rvcc
./test.sh
# 清理标签,清理所有非源代码文件
clean:
rm -f rvcc *.o *.s tmp* a.out
# 伪目标,没有实际的依赖文件
.PHONY: test clean
这里还有一个test.sh:
#!/bin/bash
# 声明一个函数
assert() {
# 程序运行的 期待值 为参数1
expected="$1"
# 输入值 为参数2
input="$2"
# 运行程序,传入期待值,将生成结果写入tmp.s汇编文件。
# 如果运行不成功,则会执行exit退出。成功时会短路exit操作
./rvcc "$input" > tmp.s || exit
# 编译rvcc产生的汇编文件
clang -o tmp tmp.s
# $RISCV/bin/riscv64-unknown-linux-gnu-gcc -static -o tmp tmp.s
# 运行生成出来目标文件
./tmp
# $RISCV/bin/qemu-riscv64 -L $RISCV/sysroot ./tmp
# $RISCV/bin/spike --isa=rv64gc $RISCV/riscv64-unknown-linux-gnu/bin/pk ./tmp
# 获取程序返回值,存入 实际值
actual="$?"
# 判断实际值,是否为预期值
if [ "$actual" = "$expected" ]; then
echo "$input => $actual"
else
echo "$input => $expected expected, but got $actual"
exit 1
fi
}
# assert 期待值 输入值
# [1] 返回指定数值
assert 0 0
assert 42 42
# 如果运行正常未提前退出,程序将显示OK
echo OK
执行 make test:
vimer@unmatched:~/build/rvcc/02$ make test
clang -std=c11 -g -fno-common -c -o main.o main.c
clang -o rvcc -std=c11 -g -fno-common main.o
./test.sh
0 => 0
42 => 42
OK
其实,程序的注释已经非常清晰明了,除了一些特性,基本的流程我们总结一下。
首先,项目的主程序是main.c,也就是我们通过c程序把目前的汇编代码重定向输出到汇编文件,这个过程转换完成之后, 再利用一个简易的脚本把汇编文件编译成可执行文件,基本上模拟了一个编译器的整体流程。
徒手写一个RISC-V编译器 - 第002课
https://www.bilibili.com/video/BV1KS4y1E79u
#!/usr/bin/make -f
%:
dh $@ --buildsystem=makefile
override_dh_auto_build:
cd Platform/Linux/CreateRedist && ./RedistMaker
override_dh_clean:
dh_clean -X Platform/Win32/CreateRedist/EE_NI/Includes/EENIVariables.wxi.bak
rm -rf -- Platform/Linux/Bin/
rm -rf -- Platform/Linux/Build/Utils/XnSensorServer/*-Release/
rm -rf -- Platform/Linux/Build/XnCore/*-Release/
rm -rf -- Platform/Linux/Build/XnDDK/*-Release/
rm -rf -- Platform/Linux/Build/XnDeviceFile/*-Release/
rm -rf -- Platform/Linux/Build/XnDeviceSensorV2/*-Release/
rm -rf -- Platform/Linux/Build/XnFormats/*-Release/
rm -rf -- Platform/Linux/CreateRedist/Final/
rm -rf -- Platform/Linux/Redist/
# cat Platform/Linux/CreateRedist/RedistMaker
# Build Engine
echo "Building..."
make -C ../Build clean > /dev/null
make -C ../Build
点评: 针对makefile的rules编写。
目前因为处理一个s390的ftbfs issue,所以需要一台s390的机器,当然,这是在不考虑qemu的前提下。
参考这里 会给1-2 mothes的时间登陆相关的机器。
hardware list这里有很多机器,目前还没有riscv的,需要我们在后面完善。
可以参考这篇文章: https://etbe.coker.com.au/2020/07/05/debian-s390x-emulation/
我最终借用dqib创建了一个s390x的虚拟机。
如果因为有symbols file的影响导致ftbfs,可以尝试着更新xx.symbols文件,具体的方法如下:
最根本的教程是here。
首先安装 pkg-kde-tools 依赖包。
然后要把源码下载下来,可以使用 apt source xx的方法。
pkgkde-getbuildlogs
pkgkde-symbolshelper batchpatch -v 1.6.1 *_unstable_logs/*.build
有可能需要多次的更新symbols文件。
It means that packages depending on a library can relax their version dependencies on that library to the oldest version that supports all the symbols they use. Until the symbols mechanism was invented, whenever a library added a symbol, it bumped its shlibs and after that packages built against the library would require the new version. That made it harder to do (partial) upgrades, testing migration etc.
https://wiki.debian.org/Projects/ImprovedDpkgShlibdeps