Jan 02
2024 更新:
最快的方法还是在虚拟机中交叉编译, 而且最新的 1.2x 版本如果在路由器编译会很容易内存溢出。
下载源码,解压后在 Alpine/Debian 虚拟机中执行:
cd /root/src/go/src
GOARCH=arm GOARM=5 GOOS=linux ./make.bash -v
完成后用 go/bin/linux_arm/ 下的文件替换 go/bin/ 下面的 go 和 gofmt 两个同名文件;删除 go/pkg/tool/linux_amd64 目录,然后打包:
cd ../bin
mv linux_arm/* ./
rm -rf linux_arm/
cd ../pkg
rm -rf tool/linux_amd64/
tar --numeric-owner -czf /root/src/go1.22.5.linux-armv7.tar.gz -C /root/src go
复制到路由器上:
rm -fr /mnt/data/go
tar -xzf /mnt/data/go1.22.5.linux-armv7.tar.gz -C /mnt/data
export PATH=/mnt/data/go/bin:$PATH
go version
------------------------------------------------------------------------------------------------------------------------------
可以不看
一. 预备工作:
首先请建立一个足够大的 SWAP 分区/文件,建议 512M 以上。通过源码编译 Go 的时候路由器的 256M 内存很快就会被耗尽。如下是建立一个 1G 的 swapfile 并且挂载为交换区:
dd if=/dev/zero of=/mnt/swap/swapfile bs=1024 count=1048576
mkswap /mnt/swap/swapfile
swapon /mnt/swap/swapfile
然后你需要指定一个临时文件存放目录 TMPDIR,在编译 Go 时,Tomatoware 内置的 TMP 和 TEMP 环境变量不能被编译过程识别,它会把临时文件全部丢去 /tmp 目录,而 /tmp 目录是用内存虚拟的,空间瞬间就会被耗尽。
export TMPDIR=/mmc/tmp
二. 开始编译:(安装目标目录为 /mmc/usr/go,你可以修改为你自己的)
下载解压源码:
rm -fr /mmc/usr/go
curl -sSL https://storage.googleapis.com/golang/go1.4.3.src.tar.gz | tar -xz -C /mmc/usr
#或者:
rm -fr /mmc/usr/go
curl -O https://storage.googleapis.com/golang/go1.4.3.src.tar.gz
tar -xzf go1.4.3.src.tar.gz -C /mmc/usr
编译:
cd /mmc/usr/go/src
./make.bash
这里耗时约 20分钟(ASUS RT-AC68P 1000MHz);
测试:
export PATH=/mmc/usr/go/bin:$PATH
go version
#应该显示:
go version go1.4.3 linux/arm
打包:
为了在其他路由器上也能直接使用,我们可以压缩打包这个编译好的 Go:
tar --numeric-owner -czf /mnt/data/go1.4.3.linux-armv7.tar.gz -C /mmc/usr go
保存这个压缩包,今后在其他路由器上,只需:
rm -fr /mmc/usr/go
tar -xzf /mnt/data/go1.4.3.linux-armv7.tar.gz -C /mmc/usr
export PATH=/mmc/usr/go/bin:$PATH
go version
#应该显示:
go version go1.4.3 linux/arm
即可。
三. 升级为 Go 1.5.2:
Go 1.5.2 并不能直接编译,它需要 1.4.3 版本的支持,还好,我们上面已经编译好 1.4.3 版本的 Go 了。那么开始编译 1.5.2:
mv /mmc/usr/go /mmc/usr/go1.4
rm -fr /mmc/usr/go
curl -sSL https://storage.googleapis.com/golang/go1.5.2.src.tar.gz | tar -xz -C /mmc/usr
#或者解压已下载好的包:
tar -xzf ./go1.11.4.src.tar.gz -C /mmc/usr
cd /mmc/usr/go/src
#替换证书位置为 Tomato 默认位置 (避免这个问题:Tomato 下运行 Golang 程序的 SSL/TLS 证书问题 )
sed -i 's#/etc/pki/tls#/rom#g' ./crypto/x509/root_linux.go
GOROOT_BOOTSTRAP=/mmc/usr/go1.4 ./make.bash
这个时间很长,你可以去做点别的,大约 30 分钟到 1 小时不等;编译好后你一样可以用上面的方法打包好以便今后使用。
四. 编译实战:
我们以 https://github.com/cyfdecyf/cow 为例来静态编译一下 COW 程序:
export GOPATH=/mnt/data/compile/go
cd /mnt/data/compile/go
go get github.com/cyfdecyf/cow
这里可能会提示出错:
package golang.org/x/crypto/blowfish: unrecognized import path "golang.org/x/crypto/blowfish"
package golang.org/x/crypto/cast5: unrecognized import path "golang.org/x/crypto/cast5"
package golang.org/x/crypto/salsa20/salsa: unrecognized import path "golang.org/x/crypto/salsa20/salsa"
因为 golang.org 被 X 了;使用设置 http_proxy 以及 https_proxy 环境变量的办法在我这不行,所以我们曲线救国:
mkdir -p $GOPATH/src/golang.org/x
cd $GOPATH/src/golang.org/x
git clone https://go.googlesource.com/crypto
这样再编译就没问题了:
cd /mnt/data/compile/go/src/github.com/cyfdecyf/cow
go build
不过这样编译出来的不是静态文件,静态编译要这样:
CGO_ENABLED=0 go build
下载链接是基于 go 11.4 源码编译的成品。 编译环境:
Buffalo WZR-1750DHP:1G/512MB
DD-WRT v3.0-r29875M kongac (06/11/16),内核版本的 Linux 3.10.101;
不在 Asus RT-AC68P 上面编译的原因是: Golang 1.9 之后 ARMv5 已经不支持内核版本低于 3.1 以下升级编译(参考链接)。而 Tomato 固件的内核是 2.6 的。
编译后的版本在 Tomato 这种老内核上运行没问题,支持(基于博通 BCM 4708/4709 的 Asus RT-AC68U/P/Netgear R7000/6300v2/6250/小米) 等路由器。
参考: How to compile Go on any ARM device