原文链接:搭建 golang mips 容器测试环境 | Akkuman 的技术博客
需要golang 编译 mips 程序,然后本地做测试
注意 mips 架构分为很多,以下是名词和对应的含义区别:
- mips:32 位大端
- mipsel/mipsle:32 位小端
- mips64:64 位大端
- mips64el/mips64le: 64 位小端
编译 golang程序
1
| GOOS=linux GOARCH=mips GOMIPS=softfloat go build
|
mips 环境
1
2
3
4
| docker run --rm --privileged multiarch/qemu-user-static:register --reset
# https://github.com/multiarch/qemu-user-static/issues/15
find /proc/sys/fs/binfmt_misc -type f -name "*mipsn32*" -exec sh -c 'echo -1 > {}' \;
docker run -it --rm multiarch/debian-debootstrap:mips-buster-slim
|
经过测试
multiarch/qemu-user-static 的环境太老,对 mips 32 bit 的支持有问题
会报错
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| fatal error: sigaction failed
runtime stack:
runtime.throw({0xfd03e, 0x10})
runtime/panic.go:1101 +0x48 fp=0x7ffff074 sp=0x7ffff060 pc=0xa3e00
runtime.sysSigaction.func1()
runtime/os_linux.go:553 +0x4c fp=0x7ffff080 sp=0x7ffff074 pc=0x9ef14
runtime.sysSigaction(0x41, 0x7ffff0a8, 0x0)
runtime/os_linux.go:552 +0x7c fp=0x7ffff098 sp=0x7ffff080 pc=0x5b114
runtime.sigaction(...)
runtime/sigaction.go:15
runtime.setsig(0x41, 0x7dba4)
runtime/os_linux.go:500 +0xbc fp=0x7ffff0c4 sp=0x7ffff098 pc=0x5afe0
runtime.initsig(0x0)
runtime/signal_unix.go:148 +0x2c0 fp=0x7ffff100 sp=0x7ffff0c4 pc=0x7d23c
runtime.mstartm0()
runtime/proc.go:1879 +0x70 fp=0x7ffff108 sp=0x7ffff100 pc=0x66508
runtime.mstart1()
runtime/proc.go:1847 +0x94 fp=0x7ffff118 sp=0x7ffff108 pc=0x66400
runtime.mstart0()
runtime/proc.go:1808 +0x7c fp=0x7ffff12c sp=0x7ffff118 pc=0x6634c
runtime.mstart()
runtime/asm_mipsx.s:89 +0x14 fp=0x7ffff130 sp=0x7ffff12c pc=0xa8894
goroutine 1 gp=0x400128 m=nil [runnable]:
runtime.main()
runtime/proc.go:147 fp=0x43e7ec sp=0x43e7ec pc=0x615f0
runtime.goexit({})
runtime/asm_mipsx.s:664 +0x4 fp=0x43e7ec sp=0x43e7ec pc=0xaad14
|
和 https://github.com/golang/go/issues/33746#issuecomment-588066863 中的报错类似
尝试去 pkgs.org 找了个 arch linux 上最新版本的 qemu-user-static,把里面的 qemu-mips-static 拿出来,qemu-mips-static ./helloworld
可以正常运行
说明新版本 qemu 有修复
根据 Issues · multiarch/qemu-user-static 来看,tonistiigi/binfmt: Cross-platform emulator collection distributed with Docker images. 有新版本的 qemu
但是下载看了下,支持的平台不包括 mips 32 位
提了个 support mips 32 bit · Issue #255 · tonistiigi/binfmt
希望作者能早日支持
不过弄出来一个另外的解决方案,就是结合新版本的 qemu-user-static 来使用,主要灵感来自于 使用 qemu-user-static 在 Docker 中生成容器异构 - 编程进阶之路 - SegmentFault 思否 中提到的将 qemu-user-static 挂载进去
首先我们去 Search Results for qemu-user-static 找到 arch linux 的 qemu-user-static 包,比如我这里访问 qemu-user-static-10.0.2-1-x86_64.pkg.tar.zst Arch Linux Download ,得到包的下载地址,解压出来找到 qemu-mipsel-static(小端) 或 qemu-mips-static (大端)
然后放到机器上,添加可执行权限
然后按照如下
1
2
3
4
| docker run --rm --privileged multiarch/qemu-user-static:register --reset
# https://github.com/multiarch/qemu-user-static/issues/15
find /proc/sys/fs/binfmt_misc -type f -name "*mipsn32*" -exec sh -c 'echo -1 > {}' \;
docker run -it --rm -v ./qemu-mips-static:/usr/bin/qemu-mips-static multiarch/debian-debootstrap:mips-buster-slim
|
前两步的主要目的是预先把环境配置起来
剩下的唯一的区别就是将 qemu-mips-static 挂载进去了
这样 golang 编译产物就能正常执行,没有报错
注意事项#
如果你使用 garble,可能新版本会有问题,我提了个 mipsle arch broken · Issue #963 · burrowers/garble
目前可降版本 go1.21.13+garble v0.12.1 来解决