使用 CGO 和 Zig 构建静态链接的 Go 可执行文件

这是一篇关于如何使用 Zig 创建静态链接的 Go 可执行文件并调用 CGO 依赖的短文。完整代码在此仓库中。

  • 默认使用 CGO 时生成的可执行文件是动态链接的,常希望静态链接以避免运行时错误。
  • 步骤如下:

    • 通过zig init创建 zig 库,然后删除src/main.zig,只保留简单的静态库。
    • 修剪build.zig为:
    const std = @import("std");
    
    pub fn build(b: *std.Build) void {
      const target = b.standardTargetOptions(.{});
      const optimize = b.standardOptimizeOption(.{});
    
      const lib_mod = b.createModule(.{
         .root_source_file = b.path("src/root.zig"),
         .target = target,
         .optimize = optimize,
      });
    
      const lib = b.addLibrary(.{
         .linkage =.static,
         .name = "cgo_static_linking",
         .root_module = lib_mod,
      });
      b.installArtifact(lib);
    }
    • src/root.zig中编写使用 C ABI 的简单库函数:
    const std = @import("std");
    
    pub export fn my_zig_function() void {
      std.debug.print("Hello from zig!\n",.{});
    }
    • 编写对应的 C 头文件zig_lib.h
    #pragma once
    
    void my_zig_function();
    • 构建库:运行zig build
    • 编写 Go 程序调用:
    package main
    
    /*
    #cgo LDFLAGS: -L./zig-out/lib -lcgo_static_linking -static
    #include "zig_lib.h"
    */
    import "C"
    import "fmt"
    
    func main() {
      fmt.Println("starting program")
      defer fmt.Println("done")
    
      C.my_zig_function()
    }
    • 构建 Go 可执行文件并静态链接:使用CC="zig cc -target x86_64-linux-musl" CGO_ENABLED=1 CGO_LDFLAGS="-static" GOOS=linux GOARCH=amd64 go build -a -ldflags '-extldflags "-static"' main.go
    • 检查工作:可执行文件不是动态可执行文件,说明静态链接成功。

    最后作者表示对当前工具的发展感到感激,Go 和 Zig 都很出色,若觉得有用可向Zig Software Foundation捐赠。

阅读 9
0 条评论