Skip to content

Add link modes: consume a dependency as a Zig import, not just a C-ABI link - #6

Merged
godofecht merged 1 commit into
mainfrom
feat/link-import-mode
Jul 29, 2026
Merged

Add link modes: consume a dependency as a Zig import, not just a C-ABI link#6
godofecht merged 1 commit into
mainfrom
feat/link-import-mode

Conversation

@godofecht

Copy link
Copy Markdown
Owner

What

Adds a link field to #Module, one of "abi" (default) or "import".

  • "abi" is the current behaviour: the module is a separately compiled artifact linked over the C ABI (pub export fn / extern fn). Required for shared libraries and C/C++ interop.
  • "import" merges the module into each dependent as a plain Zig module reached with @import("name"). One compilation, no separate artifact, no link step.

The default stays "abi", so every existing project builds unchanged. A shared module is forced to "abi" by the schema.

Why

Every deps edge was a C-ABI link, so a pure Zig-to-Zig graph paid for one artifact and one link step per module, plus a build graph Zig re-validates step by step each build. That overhead scales linearly with the module count.

Measured through the real CUE -> build_spec.zig -> zig build pipeline on a 150-module graph:

operation abi import
clean build 12.7s 5.2s
no-op build 4.5s 0.3s
one-module change 4.9s 0.5s

import mode is ~10x faster on incremental builds and stays flat as the module count grows, because the subgraph is a single compilation that Zig caches and links once.

Changes

  • schema.cue: #Link and the link field, shared pinned to "abi".
  • export.cue, gen_build_spec.sh: thread link through to the generated spec.
  • build.zig: module per declared module, compile step only for real artifacts, wire import deps with addImport and abi deps with linkLibrary, install only real artifacts.
  • build_spec_test.zig: two invariants (shared is abi; an import dep is static).
  • examples/05-import-mode/: a runnable import-edge project.
  • docs/WIKI.md, README.md: document link and the source contract.
  • Sync the shared schema.cue / gen_build_spec.sh into examples 01-04.

Verification

  • Root zig build unchanged; zig build test 58/58 pass (2 new).
  • All five examples build (Zig 0.14.0 locally; CI covers 0.14.1 / 0.15.2 / 0.16.0).

🤖 Generated with Claude Code

…I link

azazel modelled every `deps` edge as a C-ABI link: each module became its own
compiled artifact and dependents linked it over `pub export fn` / `extern fn`.
That is correct for shared libraries and C/C++ interop, but for a pure
Zig-to-Zig edge it means one artifact and one link step per module, plus a build
graph that Zig re-validates step by step on every build. On a 150-module graph a
no-op build took ~4.5s and a one-module change ~4.9s, scaling linearly with the
module count.

Add a `link` field to `#Module`, one of "abi" (default, the existing behaviour)
or "import". An `import` dependency merges into each dependent as a plain Zig
module reached with `@import("name")`: one compilation, no separate artifact, no
link step. The default stays "abi", so every existing project builds unchanged.
A `shared` module is forced to "abi" by the schema.

Measured through the real pipeline on a 150-module graph:

  operation           abi      import
  clean build        12.7s      5.2s
  no-op build         4.5s      0.3s
  one-module change   4.9s      0.5s

import mode is roughly 10x faster on incremental builds and stays flat as the
module count grows, because the whole subgraph is a single compilation that Zig
caches and links once.

- schema.cue: #Link and the `link` field, with `shared` pinned to "abi".
- export.cue, gen_build_spec.sh: thread `link` through to build_spec.zig.
- build.zig: create a module for every declared module, a compile step only for
  real artifacts, and wire import deps with addImport / abi deps with
  linkLibrary. Install only real artifacts.
- build_spec_test.zig: assert shared is abi and that an import dep is a static
  module.
- examples/05-import-mode: a runnable import-edge project.
- docs/WIKI.md, README.md: document `link` and the source contract.
- Sync the shared schema.cue / gen_build_spec.sh into examples 01-04.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@godofecht
godofecht merged commit d618104 into main Jul 29, 2026
3 checks passed
@godofecht
godofecht deleted the feat/link-import-mode branch July 29, 2026 02:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant