GO语言交叉编译

现在用GO语言写的项目越来越多了,有许多很实用的项目我们如果想要在路由器上运行就需要交叉编译,文章主要就介绍一下交叉编译GO语言的基本方法。

确定编译参数

我们可以通过查看/proc/cpuinfo来确定cpu的基本信息,比如我使用的小米路由器3G

system type		: MediaTek MT7621 ver:1 eco:3
machine : Xiaomi Mi Router 3G
processor : 0
cpu model : MIPS 1004Kc V2.15
BogoMIPS : 584.90
wait instruction : yes
microsecond timers : yes
tlb_entries : 32
extra interrupt vector : yes
hardware watchpoint : yes, count: 4, address/irw mask: [0x0ffc, 0x0ffc, 0x0ffb, 0x0ffb]
isa : mips1 mips2 mips32r1 mips32r2
ASEs implemented : mips16 dsp mt
shadow register sets : 1
kscratch registers : 0
package : 0
core : 0
VPE : 0
VCED exceptions : not available
VCEI exceptions : not available

然后我们可以通过file命令来查看一个路由器上可执行文件的文件类型,比如/bin/sh

/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分为大端序和小端序两种,一定要注意区分清楚。所以我们可以确定我们的编译参数为

export GOOS=linux
export GOARCH=mipsle

这里GOOS是宿主机的架构,GOARCH是目标架构。如果是大端序的CPU则GOARCH=mips,注意需要GO版本在1.8以上才能够支持mips架构。

在确定好编译参数之后就可以

go build

但是这时编译出来的程序很有可能执行的时候出现错误

root@OpenWrt:~# ./v2ray-plugin
Illegal instruction

出现这个情况的主要原因是因为我所使用的MT7621A处理器没有默认支持浮点运算。

MIPS架构软浮点的支持

这里有两种办法解决这个问题,一个是重新编译openwrt的内核使其模拟FPU的运算,另一种方法是在GO编译的时候指定使用软浮点,这样GO会使用其他的指令来模拟浮点运算。第一种方法操作起来稍显麻烦,这里主要介绍第二种办法。

在编译参数中加上

export GOMIPS=softfloat

然后

go build

压缩可执行文件以节省空间

在嵌入式设备中,存储空间都非常受限,所以如何缩减可执行文件的大小显得至关重要。

原始可执行文件的大小,接近14M

-rwxrwxrwx 1 kevin kevin 13866969 Aug 20 14:00 v2ray-plugin
  1. 添加编译参数

    go build -ldflags '-w -s'

    这样可以去掉可执行文件中的一些不重要的符号和调试信息

    -rwxrwxrwx 1 kevin kevin 10127136 Aug 20 14:26 v2ray-plugin

    可以看到这里大小已经减小了3M

  2. 使用upx进行进一步的压缩

    upx的原理是对二进制文件进行压缩然后再运行时解压后再执行

    upx -9 ./v2ray-plugin

    这里-9指追求最高的压缩率,-1指更快地压缩

                           Ultimate 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多一点。