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 版本支持的编译平台
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
➜ 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
对应关系补充
1 2 3 4 5 6 7 8 |
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
1 2 3 4 5 6 7 8 9 |
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 二进制
1 |
go build -ldflags "-w -s" main.go |
macOS 下编译 Windows .dll
1 2 3 4 5 6 7 8 9 10 11 |
//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
1 2 3 4 5 6 |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
//安装 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
1 2 3 4 5 6 |
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 位程序:
1 2 3 4 5 6 7 8 9 10 11 |
# 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 位程序:
1 2 3 4 5 |
# 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交叉编译多平台二进制文件一文搞定
所有媒体,可在保留署名、
原文连接
的情况下转载,若非则不得使用我方内容。