搜索文档搜索当前语言
使用 C2Go
候选版本v0.20260809.0-rc.5

本文档对应当前协同发布候选版本。

使用 C2Go

多文件项目

编译多个 translation unit,使用 C2Go LTO,并安全绑定 archive。

真实项目中,构成同一个生成 package 的所有 translation unit,必须使用一致的 package path、target、manifest schema 和两个 contract epoch。它们的最低 Go 版本与验证快照会按保守方式合并。

一次 driver 调用

最简单的多文件构建是把所有源码交给一次 c2go-clang 调用:

c2go-clang --target="$C2GO_TARGET" \
  -fc2go \
  -fc2go-package=example.com/acme/engine \
  -O2 \
  -fc2go-emit-plan9-asm=engine.s \
  -fc2go-emit-manifest=engine.json \
  parser.c runtime.c storage.c

driver 将每个源码编译为 bitcode,调用 c2go-lto,然后输出一对合并的汇编与 manifest。优化级别 2 及以上会启用跨 translation unit 内联。

正常绑定合并产物:

mkdir -p engine
c2go-bind \
  --out=engine \
  --sidecar=engine.json \
  engine.s

直接驱动 c2go-lto

高级构建系统可以先生成 bitcode,再显式调用 linker:

c2go-clang --target="$C2GO_TARGET" \
  -fc2go -fc2go-package=example.com/acme/engine -O2 -c \
  parser.c runtime.c storage.c

c2go-lto parser.o runtime.o storage.o \
  --c2go-emit-asm=engine.s \
  --c2go-emit-manifest=engine.json

这些编译产物虽然使用 .o 后缀,内容却是 pre-link LLVM bitcode;它们属于 c2go-lto 输入,不能交给系统 linker。

常用选项:

选项 用途
--c2go-emit-archive=engine.a 把汇编与 manifest member 打包进一个 ar archive
--c2go-lto-inline=0 诊断时关闭跨单元内联
--c2go-escape-nonfatal 抑制逃逸报告并返回成功;只用于受控诊断
--c2go-print-stats 打印管线统计

不使用 nonfatal 选项时,退出码 0 表示干净,1 表示发现 stack-to-heap escape,2 表示工具或输入错误,3 表示跨 TU 属性冲突。Clang driver 的普通管线会传入 nonfatal 策略,因此 driver 构建成功不是逃逸安全门禁。发布构建必须执行独立的栈指针逃逸审计。

绑定多个输入或 archive

c2go-bind 也可以合并多个汇编输入,或直接读取 C2Go archive:

c2go-bind --out=engine a.s b.s
c2go-bind --out=engine engine.a

binder 会精确去重,并拒绝符号、类型、全局变量、linkname、GC mask、callback、target、manifest generation 或 contract epoch 冲突。

构建系统规则

把每个 .s 与其 manifest 视为不可拆分的一对。cache key 必须包含 target triple、package path、优化级别和协同工具链版本。不要在未经过 c2go-bind 生成目标选择结构的情况下,把不同 OS 产物塞进同一个 package。

可直接采用的 Makefile 规则、有限的 AR=c2go-lto 兼容边界以及 CMake custom target,见接入现有构建系统。

项目构建协调完成后,继续学习从 C 调用 Go。