0%

cgo 跨平台编辑

最近的项目有用到 sqlite3,自从项目引入了盖依赖,再也不能愉快的跨平台编译了。
虽然这个项目不用跨平台部署,不过我还是花了一点时间研究 cgo 跨平台编译。
cgo 跨平台编译使用了 zig,需要安装 zig 编译器。
本次演示在 ubuntu20 下进行,因为我现在的电脑使用的是 ubuntu。

前往 zig 官网 https://ziglang.org/download/ 下载最新版 zip

1
wget https://ziglang.org/builds/zig-linux-x86_64-0.10.0-dev.3394+1a1b7a3af.tar.xz

安装 zig(我喜欢放用户变量环境,你喜欢放那里都可以)

1
2
3
tar -xvf zig-linux-x86_64*.tar.xz
mv zig-linux-x86_64* ~/.local/zig
echo "PATH=\"\$HOME/.local/zig:\$PATH\"" >> ~/.profile

到这里 zig 就安装好了

下面新建 main.go 写入以下包括了c代码的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
package main

//CGO_ENABLED=1 GOOS=linux GOARCH=amd64 CC="zig cc -target x86_64-linux" CXX="zig c++ -target x86_64-linux" go build -v
//CGO_ENABLED=1 GOOS=windows GOARCH=amd64 CC="zig cc -target x86_64-windows" CXX="zig c++ -target x86_64-windows" go build -v

//int add(int x, int y){
// return x + y;
//}
import "C"
import (
"fmt"
"os"
"strconv"
)

func main() {
x := 0
y := 0
if len(os.Args) > 1 {
x, _ = strconv.Atoi(os.Args[1])
}
if len(os.Args) > 2 {
y, _ = strconv.Atoi(os.Args[2])
}
z := C.add(C.int(x), C.int(y))

fmt.Printf("%d\n", int(z))
}

然后运行以下命令即可在 linux 上编译出 windows 的可执行文件

1
CGO_ENABLED=1 GOOS=windows GOARCH=amd64 CC="zig cc -target x86_64-windows" CXX="zig c++ -target x86_64-windows" go build -v

本程序的使用方式类似于这样

1
.\main.exe 1 2

输出是 3

不出意外的的话到这里演示就结束了。
说点其它东西,如果一个 go 程序使用了 cgo,在 ubuntu20 上编译的程序无法在 centos7 上运行。那么有两种解决方案,一种是去目标平台编译,一种是使用 zig 后端进行编译,使用方式类似于下面这样。

1
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 CC="zig cc -target x86_64-linux" CXX="zig c++ -target x86_64-linux" go build -v

参考资料

https://dev.to/kristoff/zig-makes-go-cross-compilation-just-work-29ho

https://ziglang.org/documentation/master/#Targets