Golang交叉编译多平台二进制文件一文搞定
- 发表于
- go
Go跨平台交叉编译介绍
golang
依托语言特性跨平台、性能效率、周边都还算不错,有不少开发者把Go做为跨平台SDK来封装,起到了不错的效果,今天写篇Go如何交叉编译多平台二进制文件的文章,以达到跨平台调用的目的。
从Golang 1.5
开始,交叉编译变得非常便捷:
- 对于没有使用
CGO
的程序,只需设置GOOS
、GOARCH
、CGO_ENABLED
这几个环境变量,即可直接利用编译器自带的跨平台特性实现跨平台编译 - 对于使用
CGO
的程序,大部分情况下可以通过配置CC
环境变量使用自行准备的交叉编译工具进行编译
首先当然是安装go的脚手架,这部分自行补充,我们看一下go支持的跨平台交叉编译支持列表:
GOOS - Target Operating System | GOARCH - Target Platform |
---|---|
系统 | 平台 |
查看当前 Go 版本支持的编译平台
➜root ✗ go version
go version go1.18.2 darwin/amd64
➜root ✗ go tool dist list
aix/ppc64
android/386
android/amd64
android/arm
android/arm64
darwin/amd64
darwin/arm64
dragonfly/amd64
freebsd/386
freebsd/amd64
freebsd/arm
freebsd/arm64
illumos/amd64
ios/amd64
ios/arm64
js/wasm
linux/386
linux/amd64
linux/arm
linux/arm64
linux/mips
linux/mips64
linux/mips64le
linux/mipsle
linux/ppc64
linux/ppc64le
linux/riscv64
linux/s390x
netbsd/386
netbsd/amd64
netbsd/arm
netbsd/arm64
openbsd/386
openbsd/amd64
openbsd/arm
openbsd/arm64
openbsd/mips64
plan9/386
plan9/amd64
plan9/arm
solaris/amd64
windows/386
windows/amd64
windows/arm
windows/arm64
支持非常广泛,最常用的大概是x86
和amd64
架构:
darwin/386
:对应 Mac x86darwin/amd64
:对应 Mac amd64linux/386
:对应 Linux x86linux/amd64
:对应 Linux amd64Windows/386
:对应 Windows x86Windows/amd64
:对应 Windows amd64
对应关系补充
arm -> armv7
arm64 -> arm64
386 -> i386=i686
amd64 -> x86_64
armeabi-v7a -> armv7a-linux-androideabi
arm64-v8a -> aarch64-linux-android
x86 -> i686-linux-android
x86-64 -> x86_64-linux-android
Go多平台交叉编译示例 macOS
以下示例是Mac下go交叉编译跨平台的 动态库与静态库 .so .a .dll
这里有几点要注意
package
一定要是main
(强制规定)- 一定要包含
main 函数
(强制规定) import ""
, 不能少, 因为要编译出 c(c++)的头文件- 每个方法前要加
//export 方法名
, 这里要注意//
和export
间不能有空格- 方法名和 go 的方法名必须完全一样
- 方法名不能是 c 内置的方法名, 比如
remove
就不行
main.go
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello Gophers")
}
注意:下面的 -ldflags "-w -s"
参数很多时候并不需要,自行调整。
编译变量说明
GOOS
=目标平台(编译后要运行的目标平台)的操作系统(darwin、freebsd、linux、windows、android、IOS)GOARCH
=目标平台(编译后要运行的目标平台)的体系架构(386、amd64、arm)分别对应(32位、64位、ARM平台)的架构CGO_ENABLED
=1 是否开启CGO编译,0关闭CGOCC
=ndk 里的 clang,需要是对应 CPU 版本的, API 呢建议是最低- 这里单独说明一下, 高版本的 ndk 用的是 clang, 低版本用的是 gcc, 这个根据你情况来, 个人建议直接用
21.0.6113669
版本, 这个我测试过, 没有问题, ndk20 我也试过, 也是 ok 的
- 这里单独说明一下, 高版本的 ndk 用的是 clang, 低版本用的是 gcc, 这个根据你情况来, 个人建议直接用
go build
命令-buildmode=c-shared
构建类型, 使用go help buildmode
查看, 安卓一般用c-shared
就可以了, 意思就是 c 类型的共享库(动态库)- -o 后面跟输出的位置, 一般建议使用 libxxx.so 的格式, 相对的, 头文件也会被生成在同一目录下, xxx 就是库的名字, 对应到 Java 里加载库的方法就是
System.loadLibrary("xxx")
而不是System.loadLibrary("libxxx")
- 最后一个是需要编译的 go 文件
CPU 类型和设备类型可以使用go tool dist list
查看
macOS 下编译 macos 二进制
go build -ldflags "-w -s" main.go
macOS 下编译 Windows .dll
//64位使用 x86_64-w64-mingw32-gcc
//可能需要mac 安装 brew install mingw-w64
//32位
GOOS=windows GOARCH=386 CGO_ENABLED=1 CC=i686-w64-mingw32-gcc go build -buildmode=c-shared -ldflags "-w -s" -o cShareDll.dll cShareDll.go
//64位
GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc go build -buildmode=c-shared -ldflags "-w -s" -o cShareDll.dll cShareDll.go
//编译macos 64位 so 或者 dylib delphi C/C++ 可以调用
GOOS=darwin GOARCH=amd64 CGO_ENABLED=1 go build -buildmode=c-shared -ldflags "-w -s" -o cShareDll.so cShareDll.go
//默认参数是 debug 版,加编译参数 -ldflags "-w -s" 才是 release. -w 为去掉调试信息,-s 为去掉符号表,文件大小会减小
macOS 下编译 Linux .so
brew install FiloSottile/musl-cross/musl-cross
//为了交叉编译基于cgo的项目,需要设置CC或CCX环境变量标志来构建到 x86_64-linux-musl-gcc和x86_64-linux-musl-g++(或其他相关架构)。
//该环境变量标志应放在GOOS和GOARCH两个环境变量标志之前。
//64位
CC=x86_64-linux-musl-gcc GOOS=linux GOARCH=amd64 CGO_ENABLED=1 go build -buildmode=c-shared -o cShareDll.so cShareDll.g
macOS 下编译 Android .so
//安装 NDK 环境设置
//编辑.zshrc 添加以下变量
export ANDROID_HOME="/Users/M2Macbook/Library/Android"
export ANDROID_NDK_HOME="$ANDROID_HOME/android-ndk-r21b"
export PATH="$PATH:/Users/M2Macbook/Library/Android/android-ndk-r21b/toolchains/llvm/prebuilt/darwin-x86_64/bin"
//编译命令
//armeabi-v7a
GOOS=android GOARCH=arm CGO_ENABLED=1 CC=armv7a-linux-androideabi21-clang go build -buildmode=c-shared -ldflags "-w -s" -o output/android/armeabi-v7a/cShareDll.so cShareDll.go
//arm64-v8a
GOOS=android GOARCH=arm64 CGO_ENABLED=1 CC=aarch64-linux-android21-clang go build -buildmode=c-shared -ldflags "-w -s" -o output/android/arm64-v8a/cShareDll.so cShareDll.go
//利用strip 工具来减少Android 的 so的大小
//strip 工具会去掉debug和符号信息
//测试可以减少到原来的 60%左右工具在 android-ndk 的目录中
//类似
cd android-ndk/android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/arm-linux-androideabi/bin
./strip [yourOSFile
macOS 下编译 iOS .a
brew install FiloSottile/musl-cross/musl-cross
//为了交叉编译基于cgo的项目,需要设置CC或CCX环境变量标志来构建到 x86_64-linux-musl-gcc和x86_64-linux-musl-g++(或其他相关架构)。
//该环境变量标志应放在GOOS和GOARCH两个环境变量标志之前。
//64位
CC=x86_64-linux-musl-gcc GOOS=linux GOARCH=amd64 CGO_ENABLED=1 go build -buildmode=c-shared -o cShareDll.so cShareDll.
下面补充其它平台下编译示例
Go多平台交叉编译示例 Windows
在 Windows 下编译 MacOS 和 Linux 的 64 位程序:
# For MacOS/amd64
set CGO_ENABLED=0
set GOOS=darwin
set GOARCH=amd64
go build main.go
# For Linux/amd64
set CGO_ENABLED=0
set GOOS=linux
set GOARCH=amd64
go build main.go
Go多平台交叉编译示例 Linux
在 Linux 下编译 MacOS 和 Windows 的 64 位程序:
# For MacOS/amd64
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build main.go
# For Windows/amd64
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go
参考文章
原文连接:Golang交叉编译多平台二进制文件一文搞定
所有媒体,可在保留署名、
原文连接
的情况下转载,若非则不得使用我方内容。