这是PLCT实验室的一个公开课程,挺不错的,课程主页 或者 github.
搭建环境
docker run -u root --volume ~/build/go_ld:/code -it golang:bullseye 
上面这个命令就是快速使用docker搭建一个友好的开发环境,volume参数可以将宿主机的环境映射到docker中。
Digest: sha256:2a80cda19fac1972f4c8d69516372b452062631f84854c223f1a164ce77b06d3
Status: Downloaded newer image for golang:bullseye
root@57403975e64f:/go# cd /code/
root@57403975e64f:/code# ls
然后安装工具:
apt install gcc-10-riscv64-linux-gnu qemu-user
简化一下命令:
ln -sf /usr/bin/riscv64-linux-gnu-gcc-10 /usr/bin/riscv64-linux-gnu-gcc
exit退出容器。
docker补充知识
1.
docker ps -a
docker start names(容器名字)
2. 进入容器
A. docker attach name/id 使用“docker attach”命令进入container(容器)有一个缺点,那就是每次从container中退出到前台时,container也跟着退出了。
B. docker exec -it  (退出后台运行)
安装依赖
首先在容器中安装以下软件:
apt install gcc-10-riscv64-linux-gnu qemu-user
# 简化一下:
ln -sf /usr/bin/riscv64-linux-gnu-gcc-10 /usr/bin/riscv64-linux-gnu-gcc 
写一个简单的go文件测试下环境:
package main
func main()  {
	println("hello,world")
}
因为映射了嘛,所以可以直接在~/code下写go文件,然后在容器中运行。
go run rvld.go
hello,world
go mod 管理
root@57403975e64f:/code/rvld# go mod init github.com/yuzibo/go_ld 
go: creating new go.mod: module github.com/yuzibo/go_ld
go: to add module requirements and sums:
        go mod tidy
root@57403975e64f:/code/rvld# go mod tidy 
接下来写一个c程序,使用 -c只生成目标文件,不链接。
riscv64-linux-gnu-gcc main.c -c -o main.o 
不过这样可能不方便,所以我们需要新建一个tests的目录。
现在归纳一下环境就是,在宿主机上目前为~/build/go_ld而在docker里面为/code/
issue Error: EACCES: permission denied
如果vscode报告权限问题的话,可以参考这里看一下: here
chmod -R 777 dir # is ok
test case demo
在rvld/tests目录下,使用以下demo,就可以快速改写自己的测试文件。
#!/bin/bash
echo "$0"
test_name=$(basename "$0" .sh)
t=out/tests/$test_name
mkdir -p "$t"
cat <<EOF | riscv64-linux-gnu-gcc -o $t/a.o  -c -xc -
#include <stdio.h>
int main(){
    printf("hello,world");
    return 0;
}
EOF
./go_ld "$t/a.o"
# 在测试文件中直接调用rvld,因为一开始没有使用 go mod,这里导致go的可执行文件不一致
测试:
package main
import (
	"os";
	"fmt"
)
func main()  {
	fmt.Printf("%v\n", os.Args)
	if len(os.Args) < 2{
		println("wrong args")
		os.Exit(1)
	}
}
并执行测试脚本:
oot@57403975e64f:/code/rvld#  go build rvld.go 
root@57403975e64f:/code/rvld# ./tests/hello.sh 
./tests/hello.sh
[./rvld out/tests/hello/a.o]
下面写一个Makefile再次简化这个流程:
TESTS := $(wildcard tests/*.sh)
build:
        go build
test: build test_files
        @printf '\e[32mOKpassed all tests\e[0m\n'
test_files:
        @echo 'testing'
        @for file in $(TESTS); do \
                ./$$file ; \
        done
        @printf '\e[32mOK\e[0m\n'
clean:
        go clean
        rm -rf out/
.PHPNY: build clean test $(TESTS)
…
由于间隔时间比较远,所以有些混乱,目前的目录结构如下 :
vimer@dev:~/build/go_ld/rvld$ tree
.
├── go-ld.go
├── go.mod
├── Makefile
├── pkg
│   └── utils
│       └── utils.go # 抽象出来
└── tests
    ├── hello.sh
    └── world.sh
3 directories, 6 files