纯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.3
ln -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
:
先拉去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
刷新一下
解决方案2
借鉴kevinho/xgo这个项目的思路,向xgo添加了goproxy配置选项。
修改techknowlogick/xgo项目的xgo.go文件,原始文件:
修改后:
编译xgo(我这目录都随便扔的):go build -o ~/xgo ~/test/xgo
go.mod项目出了各种问题(目录结构见之前的图),假如go.mod在mt-shell里面,我们要编译的可执行文件是mt-shell/mt-server,这样总是出错:
- 执行:
~/xgo ~/mt-shell/mt-server/main.go
,报错:Requested path invalid.
- 执行:
~/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编译啦!
编译成功!
参考与致谢
使用xgo一键编译多个发行版本再谈Go语言的交叉编译kevinho/xgo - enable goproxy environment variable