纯Go代码

举例:
frp的交叉编译配置:
env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frpc_darwin_amd64 ./cmd/frpc

  • GOOS: Target Operating System
  • GOARCH:Target Platform
  • GOMIPS,GOARM,GO386(仅在对应的系统架构体系相关)
  • CGO_ENABLED=0:交叉编译不支持 CGO 所以禁用了CGO

Go,C混合代码

代码中import "C"或者比如你的程序中使用了sqlite数据库,在编译go-sqlite驱动时按照上面的做法是编译不通过的

启用CGO支持(根据情况修改):

export CGO_ENABLED=1
export CC=arm-linux-gnueabi-gcc
  • 设置静态链接(如果是.a库):export CGO_LDFLAGS=”-g -O2 -static”
  • 如果是so动态库,在运行时会缺少库ld-linux.so.3ln -s /usr/arm-linux-gnueabi/lib/ld-linux.so.3 /lib/ld-linux.so.3
  • 运行时如果缺少其它库,如libc.so.6,libpthread.so.0,可查找系统,找到/usr/arm-linux-gnueabi/lib/下对应的库,然后拷贝到当前目录.然后,将当前目录设置为库搜索路径export LD_LIBRARY_PATH=.

xgo

最原始版本karalabe/xgo,但是不支持go mod,也很久没有更新了。
新版本的techknowlogick/xgo推荐使用。

使用方法

举例一个启用go mod的go项目目录mt-shell

go语言 交叉编译 xgo交叉编译_go语言 交叉编译


先拉去docker镜像:docker pull techknowlogick/xgo:latest 然后在项目目录执行:go get src.techknowlogick.com/xgo

此时xgo的可执行文件会默认安装在~/go/bin/xgo,可以设置环境变量,这样输入xgo就可以直接执行

编译所有平台你想要的项目:xgo ~/mt-shell/mt-server

更详细的使用方法可以参考github上的readme

事实上上面肯定是跑不通的

原因:golang.org是上不去的,因为某些你懂得的原因。
症状:

  • net/http: TLS handshake timeout
  • dial tcp 172.217.27.145:443: i/o timeout
  • no Go files in /source(这个大概率是当前所在目录的问题,我运行xgo的时候保证目录下有go.mod并且有要编译的程序就可以了,具体怎么回事不太清楚)

解决方案1(最简单):

修改了本地机器的环境变量,手动加上了export GOPROXY=https://goproxy.io,direct,然后source ~/.zshrc刷新一下

go语言 交叉编译 xgo交叉编译_go_02

解决方案2

借鉴kevinho/xgo这个项目的思路,向xgo添加了goproxy配置选项。

修改techknowlogick/xgo项目的xgo.go文件,原始文件:

go语言 交叉编译 xgo交叉编译_交叉编译_03

修改后:

go语言 交叉编译 xgo交叉编译_go语言 交叉编译_04


编译xgo(我这目录都随便扔的):go build -o ~/xgo ~/test/xgo go.mod项目出了各种问题(目录结构见之前的图),假如go.mod在mt-shell里面,我们要编译的可执行文件是mt-shell/mt-server,这样总是出错:

  1. 执行:~/xgo ~/mt-shell/mt-server/main.go,报错:Requested path invalid.
  2. 执行:~/xgo ~/mt-shell/mt-server或者~/xgo ~/mt-shell,报错:No $GOPATH is set or forwarded to xgo,记得要切到项目目录里再xgo

然后我也不懂就随便试,最后是在mt-server这个目录里执行了go mod init server,再执行~/xgo ~/mt-shell/mt-server就可以使用xgo编译啦!

go语言 交叉编译 xgo交叉编译_交叉编译_05


编译成功!

go语言 交叉编译 xgo交叉编译_golang_06

参考与致谢

使用xgo一键编译多个发行版本再谈Go语言的交叉编译kevinho/xgo - enable goproxy environment variable