golang 开发的代码只需要针对运行平台进行编译就可以实现可以跨平台独立运行,这一点可不像java那样半变异半解释型的语言,Java的运行依赖jvm,但编译后的golang则不需要。
golang在编译的时候比较重要的两个参数是:“目标平台GOOS” 和 “目标架构 GOARCH”
例如:
# 编译目标平台linux 64位
GOOS=linux GOARCH=amd64 go build main.go
# 编译目标平台windows 64位
GOOS=windows GOARCH=amd64 go build main.go
当然针对不同的平台和架构会涉及各种编译参数,另外,在不同的开发环境和go版本下也许还会有各类的编译问题,遇到的时候再查找解决方案。以下只是一些交叉编译的常用信息。
一、参数说明和常用参数
参数 | 说明 |
GOROOT_FINAL | go语言根目录(可不设置) |
GOHOSTARCH | 主机编译器系统架构 |
GOARCH | 主机系统架构 |
GOOS | 主机操作系统 |
GO_GCFLAGS | 构建软件包和命令时go工具编译参数 |
GO_LDFLAGS | 构建命令时go工具编译参数 |
CGO_ENABLED | 允许C编译 |
CC | 主机C编译器 |
CC_FOR_TARGET | 目标系统C编译器 |
CXX_FOR_TARGET | 目标系统C++编译器 |
PKG_CONFIG | pkg-config工具的路径 |
GOROOT_BOOTSTRAP | 安装目录 |
GOARM | 使用的浮点运算协处理器版本号,只对arm平台有用,可选值有5,6,7 |
其中GOOS、GOARCH参数的常用类型如下:
GOOS | GOARCH |
darwin | 386/amd64 |
linux | 386/amd64/arm |
windows | 386/amd64 |
freebsd | 386/amd64/arm |
solaris | amd64 |
openbsd | 386/amd64 |
dragonfly | 386/amd64 |
netbsd | 386/amd64/arm |
plan9 | 386/amd64 |
二、包含有C的编译
如果go中包含有C代码(例如:sqlite数据库),那么编译需要设置参数 CGO_ENABLED=1(默认情况下CGO_ENABLED=0),指定C编译器参数CC 或者C++编译器参数CXX。举几个栗子:
1、在linux上编译arm平台程序
需要先安装C编译器
sudo apt-get install libc6-armel-cross libc6-dev-armel-cross binutils-arm-linux-gnueabi libncurses5-dev
sudo apt-get install gcc-arm-linux-gnueabi g++-arm-linux-gnueabi
CGO_ENABLED=1 GOOS=linux GOARCH=arm go build
2、在linux上编译arm64平台程序
sudo apt-get install gcc-aarch64-linux-gnu
CGO_ENABLED=1 GOOS=linux GOARCH=arm64 go build
3、在linux上编译windows64程序
sudo apt-get update
sudo apt-get install mingw-w64
CGO_ENABLED=1 CXX=x86_64-w64-mingw32-g++ CC=x86_64-w64-mingw32-gcc GOOS=windows GOARCH=amd64 go build
4、linux上编译windows32程序
CGO_ENABLED=1 GOOS=windows GOARCH=386 CC=i686-w64-mingw32-gcc go build
windows程序运行总是黑色的cmd窗口,实在太难看,可以增加编译参数去掉:-ldflags "-H=windowsgui"
5、linux上编译 32位的arm
sudo apt-get update
sudo apt-get install gcc-arm-linux-gnueabihf
CGO_ENABLED=1 GOOS=linux GOARCH=arm CC=arm-linux-gnueabihf-gcc go build
6、mac 上编译windows64
(1)编译可执行文件
brew install mingw-w64
CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ GOOS=windows GOARCH=amd64 go build -x -v -ldflags "-s -w" -o hello_x64.exe
(2)编译静态库
CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ GOOS=windows GOARCH=amd64 go build -buildmode=c-archive -x -v -ldflags "-s -w" -o bin/x64/x64.a main.go
(3)编译动态库
CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ GOOS=windows GOARCH=amd64 go build -buildmode=c-shared -x -v -ldflags "-s -w" -o bin/x64/x64.a main.go
动态库和静态库的区别是将-buildmode=c-archive
改为-buildmode=c-shared
7、mac 上编译windows x86
(1)可执行文件
CGO_ENABLED=1 CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-g++ GOOS=windows GOARCH=386 go build -x -v -ldflags "-s -w" -o hello_x86.exe
(2)编译静态库
CGO_ENABLED=1 CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-g++ GOOS=windows GOARCH=386 go build -buildmode=c-archive -x -v -ldflags "-s -w" -o bin/x86/x86.a main.go
(3)编译动态库
和静态库类似,只需要修改参数:-buildmode=c-archive
为 -buildmode=c-shared
三、其他
除了自己写编译命令外,还有一种方法是借助docker进行交叉编译。在github里有一个Golang跨平台编译工具karalabe/xgo, 可以一条命令生成windows、linux、mac下的bin文件。
go虽然很强大,但他的优势更多用于后端应用,在我接触的大大小小平台里面linux平台AMD64环境更多一些,也不乏一些在arm平台的场景,例如:移动端、树莓派或者其他物联网终端设备。