Search docsSearch this language
Using C2Go
Release candidatev0.20260809.0-rc.5

These docs describe the current coordinated release candidate.

Using C2Go

Multi-file projects

Compile several translation units, use C2Go LTO, and bind archives safely.

For a real library, all translation units that contribute to one generated package must agree on package path, target, manifest schema, and both contract epochs. Their minimum Go versions and validation snapshots are merged conservatively.

One driver invocation

The simplest multi-file build passes every source to 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

The driver compiles each source to bitcode, invokes c2go-lto, and emits one merged assembly/manifest pair. Cross-translation-unit inlining is enabled at optimization levels of 2 or higher.

Bind the merged output normally:

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

Drive c2go-lto directly

Advanced build systems can produce bitcode first and call the linker explicitly:

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

Despite their .o suffix, the compile outputs are pre-link LLVM bitcode. They are inputs to c2go-lto, not native objects for the system linker.

Useful options include:

Option Use
--c2go-emit-archive=engine.a Package assembly and manifest members in one ar archive
--c2go-lto-inline=0 Disable cross-unit inlining for diagnosis
--c2go-escape-nonfatal Suppress the escape report and return success; diagnosis only
--c2go-print-stats Print pipeline statistics

Without the nonfatal option, exit status 0 is clean, 1 means the escape audit found stack-to-heap escape, 2 is a tool/input error, and 3 is a cross-TU attribute conflict. The Clang driver passes the nonfatal policy for its normal pipeline, so a successful driver build is not an escape-safety gate. Follow the standalone stack escape audit for release builds.

Bind multiple inputs or an archive

c2go-bind can also merge multiple assembly inputs or accept a C2Go archive:

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

The binder performs exact duplicate elimination and rejects conflicts across symbols, types, globals, linknames, GC masks, callbacks, targets, manifest generations, and contract epochs.

Build-system rule

Treat each .s and its manifest as an inseparable pair. Cache keys must include the target triple, package path, optimization level, and coordinated toolchain release. Never combine artifacts produced for different operating systems into one package without the target-specific structure generated by c2go-bind.

For copyable Makefile rules, the limited AR=c2go-lto compatibility boundary, and a CMake custom target, continue with Existing build systems.

With the project build coordinated, continue with calling Go from C.