这是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