GO语言交叉编译
现在用GO语言写的项目越来越多了,有许多很实用的项目我们如果想要在路由器上运行就需要交叉编译,文章主要就介绍一下交叉编译GO语言的基本方法。
确定编译参数
我们可以通过查看/proc/cpuinfo
来确定cpu
的基本信息,比如我使用的小米路由器3G
1 | system type : MediaTek MT7621 ver:1 eco:3 |
然后我们可以通过file
命令来查看一个路由器上可执行文件的文件类型,比如/bin/sh
1 | /bin/sh: ELF 32-bit LSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld-, corrupted section header size |
这里我们可以看到这个可执行文件是LSB,也就是小端序的,MIPS架构的CPU分为大端序和小端序两种,一定要注意区分清楚。所以我们可以确定我们的编译参数为
1 | export GOOS=linux |
这里GOOS
是宿主机的架构,GOARCH
是目标架构。如果是大端序的CPU则GOARCH=mips
,注意需要GO版本在1.8以上才能够支持mips
架构。
在确定好编译参数之后就可以
1 | go build |
但是这时编译出来的程序很有可能执行的时候出现错误
1 | root@OpenWrt:~# ./v2ray-plugin |
出现这个情况的主要原因是因为我所使用的MT7621A处理器没有默认支持浮点运算。
MIPS架构软浮点的支持
这里有两种办法解决这个问题,一个是重新编译openwrt
的内核使其模拟FPU的运算,另一种方法是在GO编译的时候指定使用软浮点,这样GO会使用其他的指令来模拟浮点运算。第一种方法操作起来稍显麻烦,这里主要介绍第二种办法。
在编译参数中加上
1 | export GOMIPS=softfloat |
然后
1 | go build |
压缩可执行文件以节省空间
在嵌入式设备中,存储空间都非常受限,所以如何缩减可执行文件的大小显得至关重要。
原始可执行文件的大小,接近14M
1 | -rwxrwxrwx 1 kevin kevin 13866969 Aug 20 14:00 v2ray-plugin |
添加编译参数
1
go build -ldflags '-w -s'
这样可以去掉可执行文件中的一些不重要的符号和调试信息
1
-rwxrwxrwx 1 kevin kevin 10127136 Aug 20 14:26 v2ray-plugin
可以看到这里大小已经减小了3M
使用
upx
进行进一步的压缩upx
的原理是对二进制文件进行压缩然后再运行时解压后再执行1
upx -9 ./v2ray-plugin
这里
-9
指追求最高的压缩率,-1
指更快地压缩1
2
3
4
5
6
7
8
9Ultimate Packer for eXecutables
Copyright (C) 1996 - 2017
UPX 3.94 Markus Oberhumer, Laszlo Molnar & John Reiser May 12th 2017
File size Ratio Format Name
-------------------- ------ ----------- -----------
10127136 -> 3494172 34.50% linux/mipsel v2ray-plugin
Packed 1 file.我们可以看到
upx
的压缩率很高,最后的可执行文件只有3M多一点。