Skip to content

refactor!: rewrite zbuild as comptime library#7

Merged
wemeetagain merged 62 commits into
mainfrom
refactor/comptime-library-rewrite
May 11, 2026
Merged

refactor!: rewrite zbuild as comptime library#7
wemeetagain merged 62 commits into
mainfrom
refactor/comptime-library-rewrite

Conversation

@wemeetagain

@wemeetagain wemeetagain commented Mar 17, 2026

Copy link
Copy Markdown
Member

Summary

This PR rewrites zbuild from a CLI/codegen tool into a comptime Zig library that configures std.Build directly from build.zig.zon.

Major changes:

  • replaces the old CLI/runtime-parser/codegen flow with configureBuild(b, @import("build.zig.zon"), ...)
  • targets released Zig 0.16.0 and updates examples/docs to use direct @import("build.zig.zon")
  • removes the old CLI-era parser/serializer/IR command surface and makes zbuild a library-first package
  • returns a typed BuildResult from configureBuild
  • adds a built-in help step and richer docs/examples for the new library model
  • adds aliases for named aggregate top-level steps
  • adds fixture integration coverage and GitHub Actions CI

Semantics tightened in this branch

This branch also hardens the model substantially beyond the initial rewrite:

  • manifest-owned refs use enum literals, manual refs use bare strings, and dependency submodules use "dep:module"
  • options_modules now generate typed config modules, namespaced -Dmodule.option flags, real enum types, and explicit optional fields when no default is provided
  • depends_on is explicit: enum literals mean artifact install-step shorthand, strings mean exact top-level step names
  • named modules, options modules, and dependency default modules now share one reserved zbuild-owned import namespace
  • manual interop and dependency-backed refs now fail with targeted diagnostics instead of panics / silent shadowing
  • fixture runs are now uncached, so integration regressions actually get exercised

Breaking changes / migration notes

  • zbuild.zon and the old CLI workflow are gone; use standard build.zig.zon
  • Zig 0.16.0+ is now required
  • examples now use the released 0.16.0 package-import path directly; the pre-release workaround is removed
  • reference syntax is stricter and more explicit than before:
    • enum literals for zbuild-owned refs
    • bare strings for manual modules/steps
    • "dep:module" for dependency submodules

Test plan

  • zig build test --summary all
  • zig build test:fixtures --summary all
  • cd examples/simple && zig build
  • cd examples/full && zig build
  • cd examples/full && zig build info
  • cd test/fixtures/aliases_nested && zig build check

The fixture suite covers the examples plus targeted negative cases for namespace collisions, dependency import/lazy-path failures, manual interop errors, stdlib passthrough support, and alias validation.

wemeetagain and others added 30 commits March 13, 2026 21:31
Three-phase refactor: single ZON file, std.zon.parse-based Config,
static build.zig. See docs/superpowers/specs/ for details.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…e of truth

- Rename test fixtures from .zbuild.zon to .build.zig.zon
- Default zbuild_file to build.zig.zon
- Remove syncManifest from cmd_sync (no more manifest generation)
- Remove Manifest.zig dependency from cmd_init and cmd_fetch
- Delete sync_manifest.zig and Manifest.zig (parallel data model eliminated)
- Merge zbuild.zon content into build.zig.zon, delete zbuild.zon
- Simplify cmd_fetch to delegate entirely to zig fetch

Fixes: 2.9, 2.10, 2.12, 2.13, 4.5, 5.8

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Change fingerprint from []const u8 to u64 (matches ZON directly)
- Remove all deinit methods (arena handles cleanup)
- Replace hand-rolled if/else if parser with:
  - inline for over struct fields for typed values
  - fromZoirNode for standard types
  - Custom parsers only for Dependency, ModuleLink, Option
- parseHashMap replaces both parseHashMap and parseOptionalHashMap
- Ignore unknown top-level fields (enables single-file approach)
- Fix dependency parsing to include hash and lazy fields
- Fix parseRun to use parseString (Run = []const u8)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Create build_runner.zig with configureBuild() that reads build.zig.zon
  and configures the build graph via direct std.Build API calls
- Replace cmd_sync codegen with static build.zig template that imports
  zbuild and calls configureBuild
- Delete ConfigBuildgen.zig (~1280 lines) and sync_build_file.zig (~38 lines)
- Hand-write zbuild's own build.zig (can't self-reference)
- Expose configureBuild as public API via main.zig
- Update sync test to verify static template generation

Eliminates string-concatenation codegen, scratch buffers, and zig fmt
post-processing. Fixes bugs 1.6, 2.5, 2.6, 2.14, 3.7, 4.1, 4.3, 4.6,
5.5, 5.6, 5.10.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
16 inline tests covering: minimal config, modules, executables (inline
and named module refs), dependencies (with hash/lazy/args), libraries,
tests, runs, options, options_modules, fmts, module imports, description/
keywords, and error cases (missing required fields, invalid versions).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bug fixes:
- Implement serialization of libraries, objects, tests, fmts, runs
  sections (previously commented out, issue 2.7)
- Implement enum and enum_list option serialization (previously
  TODO stubs, issue 2.8)
- Add hash and lazy fields to dependency serialization (issue 2.10)

Tests:
- 8 round-trip tests that parse → serialize → re-parse and verify
  structural equivalence for each section type

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The depends_on field was parsed but never used in the build graph.
Now build_runner tracks install steps in a map and adds step
dependencies in a final pass after all artifacts are created.

Also adds parser + round-trip tests for depends_on.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bug fixes:
- ZigEnv: change 'and' to 'or' in exit code check so non-zero exits
  and signal terminations are properly detected (issue 1.3)
- GlobalOptions: add args.next() when consuming --no-sync flag to
  prevent infinite loop (issue 1.4)
- Config: implement write_files parser (was a stub that silently
  discarded all write_files entries) (issue 1.1)
- Args: fix test calling non-existent Args.parse, should be
  Args.initFromString (issue 3.9)

Tests:
- GlobalOptions: --no-sync flag consumption (verifies no infinite loop)
- Config: write_files parsing with file and dir items
- Config: write_files round-trip serialization

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- main.zig: add defer wip_bundle.deinit() so the error bundle's
  internal allocations are freed on the success path (issue 3.4)
- Config.zig: returnParseErrorFmt now sets .owned = true since
  the message is heap-allocated via allocPrint (issue 3.10)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
zbuild no longer ships a CLI binary. Users consume it as a standard Zig
dependency via build.zig.zon and call zbuild.configureBuild(b) from their
build.zig. This eliminates ~1,100 lines of CLI indirection that was just
wrapping zig build/fetch/init commands.

Deleted: Args, GlobalOptions, ZigEnv, Package, run_zig, cmd_build,
cmd_fetch, cmd_init, cmd_sync, test/sync, test/fixtures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Delete Config.zig entirely (2,112 lines — parser, serializer, IR types,
tests). The Zig compiler now parses build.zig.zon via @import, and
build_runner.zig walks the comptime anonymous struct directly using
inline for + @Hasfield.

This resolves the dependency args impedance mismatch: since the manifest
is comptime-known, dependency .args flow through to b.dependency()
naturally without needing a runtime→comptime bridge.

Project shrinks from ~2,630 to ~583 lines of source.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- #1: Clean stale build.zig.zon (remove deleted exe/test refs, bump to 0.3.0)
- #2: Remove @ptrCast for dest_sub_path (Zig coerces comptime strings)
- #3: Default modules to public (export to b.modules unless private = true)
- #4: @CompileError for unknown option types + validateManifest for unknown
  top-level fields
- #5: resolveImport returns error.ModuleNotFound instead of @Panic
- #6: Remove duplicate modules.put (createModule handles it, callers don't)
- #7: Add 8 comptime helper tests (toStringSlice, toEnumSlice, isIntType,
  isFloatType, isKnownField, validateManifest)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of rejecting unknown top-level fields (which breaks forward
compatibility with new Zig versions), validate semantic cross-references:
root_module refs point to declared modules, depends_on refs point to
declared artifacts, and imports reference modules/options_modules/deps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Dual-form syntax (bare tuple for simple commands, struct with cmd +
env/cwd/stdio/stdin/depends_on for complex ones), comptime validation,
and cmd: step prefix to avoid collision with executable run: steps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Three tasks: validation, createRun rewrite, and tests. Covers
dual-form syntax, stdin/stdin_file exclusion, depends_on wiring,
and cmd: step prefix to avoid executable collision.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cross-reference depends_on against declared artifacts and enforce
stdin/stdin_file mutual exclusion at compile time.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Short form (bare tuple) for simple commands, long form (struct with
cmd + cwd/env/inherit_stdio/stdin/stdin_file/depends_on) for complex
ones. Replaces runtime string splitting with comptime toStringSlice.
Step prefix changes from run: to cmd: to avoid executable collision.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Covers short-form tuples, long-form structs with depends_on/env/cwd,
run+executable name coexistence, and forward-compat unknown fields.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Merge three separate artifact-section loops in validateManifest into
a single pass that validates root_module refs, depends_on, and imports
per item. Extract the repeated install-artifact-and-register pattern
into installAndRegister helper used by all three artifact creators.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use toComptimeString consistently for extracting strings from ZON
tuples (wireDependsOnList, wireModuleImports). Have createRun reuse
wireDependsOnList instead of duplicating the depends_on logic inline.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace runtime splitScalar with comptime comptimeBaseName/comptimeAfterSep
for link_libraries colon syntax. Also use toComptimeString so link_libraries
accepts enum literals (consistent with imports and depends_on).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
configureBuild now takes a comptime Options struct with a help_step
field (default: "help"). When set, zig build help prints a formatted
overview of the project's modules, artifacts, tests, runs, options,
and dependencies — all derived from the manifest at comptime.

The Options struct provides a natural extension point for future
configuration without breaking the API.

Breaking: configureBuild signature changed to accept a third opts
parameter. Callers must add .{} as the third argument.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
B+C hybrid approach: README as landing page, docs/ for schema reference
and motivation, examples/ as compilable annotated projects. Nukes all
stale docs from the CLI tool era.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add missing fields: zig_lib_dir/win32_manifest for libraries, zig_lib_dir
for objects, passthrough/zig_lib_dir for tests, build-test step. Clarify
target/optimize value types, link_libraries vs LazyPath colon syntax,
LazyPath three-part form, inline module name override, help step metadata.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7 tasks: delete stale docs, write README/motivation/schema, create
simple and full compilable examples, delete superpowers working docs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Delete MOTIVATION.md, TODO.md, AdvancedFeatures.md, and
STRUCTURAL_ISSUES.md — all describe the old CLI tool architecture
that no longer exists.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pitch, before/after comparison, quickstart, feature list, and links
to schema reference and examples. Replaces the stale CLI tool README.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Covers the problem (build.zig verbosity), the insight (@import +
comptime), before/after comparison, and what zbuild is NOT.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Field tables for all manifest sections: modules, executables, libraries,
objects, tests, fmts, runs, options_modules, dependencies. Plus LazyPath
resolution, comptime validation, and configureBuild options.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
wemeetagain and others added 5 commits March 16, 2026 17:51
Fix bug where three BuildResult getters referenced self.result.X
instead of self.X. Propagate OOM errors consistently — createModule,
createRun, createFmt now return Error instead of panicking. Extract
~180 lines of help text generation into src/help.zig, keeping
build_runner.zig focused on build graph construction.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
depends_on entries can now reference any named step using colon syntax:
"test:unit", "build-test:unit", "cmd:deploy", "fmt:src", "run:myapp",
"build-exe:myapp", "build-lib:mylib", "build-obj:myobj".

Plain names (enum literals or strings without colons) continue to
reference artifact install steps as before.

Comptime validation maps step prefixes to manifest sections. Runtime
wiring looks up b.top_level_steps for colon-form references.

This makes tests, runs, and fmts valid depends_on targets — previously
only executables, libraries, and objects worked.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move buildHelpText, comptimePad, describeValue tests to help.zig
where the functions live. build_runner.zig keeps 20 tests, help.zig
has 4.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…r tests

- build.zig imports build_runner.zig directly (skip main.zig passthrough)
- Version bump to 0.4.0 (breaking API changes since 0.3.0)
- wireDependsOn now handles tests via top_level_steps lookup
- Delete leftover docs/specs/
- Update schema.md: depends_on step reference syntax, LazyPath collision note

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
main.zig was a pure passthrough with no added value. build_runner.zig
is now the root source file for both the zbuild module and tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request represents a fundamental shift in zbuild's architecture, transforming it from a CLI-driven code generator into a powerful, declarative comptime library for Zig projects. The change leverages Zig's @import("build.zig.zon") feature to process build manifests at compile time, drastically reducing boilerplate and improving type safety. The new design aims to streamline build configuration, making it more efficient and less error-prone by integrating directly with the native Zig build system.

Highlights

  • Architectural Rewrite: Rewrote zbuild from a standalone CLI tool with runtime parsing and codegen into a comptime Zig library that directly configures std.Build from a ZON manifest.
  • Codebase Reduction: Reduced the codebase significantly, eliminating approximately 6,400 lines of parser/serializer/IR code and replacing it with about 1,100 lines of comptime metaprogramming.
  • Enhanced Documentation: Overhauled documentation, including a new README, a comprehensive schema reference, a motivation document explaining the new approach, and two compilable examples (simple and full).
  • Typed BuildResult: configureBuild now returns a BuildResult struct with typed getters for all created entities, such as executables, libraries, modules, tests, runs, fmts, dependencies, and options modules.
  • Comptime Validation: Implemented comptime cross-reference validation to catch typos in module, artifact, import, and depends_on references at compile time, improving build reliability.
  • Flexible depends_on: Extended depends_on support to include explicit step references (e.g., "test:unit", "cmd:deploy") in addition to plain artifact names.
  • Built-in Help Step: Added a built-in zig build help step that prints a formatted project overview derived from the manifest metadata.
  • Improved runs Syntax: Introduced dual-form syntax for runs, allowing bare tuples for simple commands and a structured format with cmd, cwd, env, stdin, and depends_on for complex scenarios.
  • Options Modules Update: Updated options modules to accept enum literals for type fields (e.g., .bool instead of "bool"), enhancing type safety and readability.
  • Version Bump: Bumped the project version to 0.4.0 to reflect the significant changes and new features.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • README.md
    • Rewrote the introduction to reflect the new library-based approach.
    • Updated the 'Before and after' section with examples of the new declarative ZON configuration.
    • Replaced installation and usage instructions with a quickstart guide for the library.
    • Added a new 'Features' section detailing the library's capabilities.
    • Updated the 'Documentation' section with links to new schema and motivation documents.
  • build.zig
    • Transformed the file from a CLI tool's build script to a library's build script.
    • Exposed configureBuild, Options, and BuildResult for external use.
    • Updated the zbuild_module to point to src/build_runner.zig.
    • Removed all CLI-specific executable and installation steps.
    • Simplified test setup to only include tests for the zbuild_module.
  • build.zig.zon
    • Updated the project version from 0.2.0 to 0.4.0.
    • Modified the description to 'Declarative build configuration for Zig projects'.
  • docs/AdvancedFeatures.md
    • Removed the file, as its content is no longer relevant to the new library architecture.
  • docs/MOTIVATION.md
    • Removed the old motivation document.
  • docs/TODO.md
    • Removed the old TODO list.
  • docs/motivation.md
    • Added a new motivation document explaining the rationale behind the comptime library approach, its benefits, and inspirations.
  • docs/schema.md
    • Added a comprehensive schema reference for all zbuild manifest fields, including details on modules, executables, libraries, objects, tests, fmts, runs, options modules, dependencies, LazyPath resolution, and comptime validation.
  • examples/full/build.zig
    • Added a new build file demonstrating a full example project using the zbuild library, including modules, executables, libraries, tests, fmts, runs, and options modules.
  • examples/full/build.zig.zon
    • Added a new manifest file for the full example project, defining its metadata and a dependency on zbuild.
  • examples/full/src/lib.zig
    • Added a new example library source file for the full example.
  • examples/full/src/main.zig
    • Added a new example main executable source file for the full example.
  • examples/full/src/test.zig
    • Added a new example test source file for the full example.
  • examples/simple/build.zig
    • Added a new build file demonstrating a minimal example project using the zbuild library.
  • examples/simple/build.zig.zon
    • Added a new manifest file for the simple example project, defining its metadata and a dependency on zbuild.
  • examples/simple/src/main.zig
    • Added a new example main executable source file for the simple example.
  • src/Args.zig
    • Removed the file, as command-line argument parsing is no longer needed for the library.
  • src/Config.zig
    • Removed the file, as the old configuration parsing and serialization logic is replaced by comptime processing.
  • src/ConfigBuildgen.zig
    • Removed the file, as the old build file generation logic is replaced by direct std.Build configuration at comptime.
  • src/GlobalOptions.zig
    • Removed the file, as global CLI options are no longer applicable.
  • src/Manifest.zig
    • Removed the file, as the old manifest parsing logic is replaced by direct @import("build.zig.zon").
  • src/Package.zig
    • Removed the file, as old package handling is no longer directly used.
  • src/ZigEnv.zig
    • Removed the file, as the old Zig environment detection is no longer directly used.
  • src/build_runner.zig
    • Added the core build_runner.zig file, which contains the configureBuild function and all comptime logic for processing the ZON manifest and configuring the std.Build graph.
  • src/cmd_build.zig
    • Removed the file, as the old CLI build command is no longer needed.
  • src/cmd_fetch.zig
    • Removed the file, as the old CLI fetch command is no longer needed.
  • src/cmd_init.zig
    • Removed the file, as the old CLI init command is no longer needed.
  • src/cmd_sync.zig
    • Removed the file, as the old CLI sync command is no longer needed.
  • src/help.zig
    • Added the help.zig file, which provides comptime functions to generate formatted help text for the built-in zig build help step.
  • src/main.zig
    • Removed the file, as the old CLI entry point is no longer needed.
  • src/run_zig.zig
    • Removed the file, as the old Zig command runner is no longer needed.
  • src/sync_build_file.zig
    • Removed the file, as the old build file synchronization logic is no longer needed.
  • src/sync_manifest.zig
    • Removed the file, as the old manifest synchronization logic is no longer needed.
  • test/fixtures/basic1.zbuild.zon
    • Removed the old test fixture.
  • test/fixtures/basic2.zbuild.zon
    • Removed the old test fixture.
  • test/fixtures/basic3.zbuild.zon
    • Removed the old test fixture.
  • test/fixtures/basic4.zbuild.zon
    • Removed the old test fixture.
  • test/fixtures/basic5.zbuild.zon
    • Removed the old test fixture.
  • test/fixtures/basic6.zbuild.zon
    • Removed the old test fixture.
  • test/sync.zig
    • Removed the old synchronization tests.
  • zbuild.zon
    • Removed the project's own zbuild.zon file, as it is now configured via build.zig.zon and the new library.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@wemeetagain wemeetagain changed the title Rewrite zbuild as comptime library refactor!: rewrite zbuild as comptime library Mar 17, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This is an excellent and significant rewrite of zbuild. The move from a CLI tool with codegen to a comptime library is a huge architectural improvement, leveraging Zig's comptime capabilities to provide a more robust, declarative, and user-friendly build configuration experience. The code quality is high, and the new documentation is thorough and clear. I have one suggestion to improve the internal structure by centralizing some logic, but overall this is a fantastic contribution.

Comment thread src/build_runner.zig Outdated
wemeetagain and others added 20 commits March 17, 2026 16:36
Move runs depends_on wiring from createRun into wireDependsOn,
alongside artifacts and tests. All dependency wiring now happens
in Phase 11, keeping creation phases focused on creation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
`configureBuild` previously resolved every dependency that lacked an
explicit `.args` field via `b.dependency(name, .{})`. Empty args mean
the child build's `b.standardOptimizeOption` and `b.standardTargetOptions`
fall back to their own defaults (host target, Debug) regardless of the
parent's CLI flags.

For C-heavy deps this is a real footgun: in Debug, Zig's default
`sanitize_c=.full` emits `__ubsan_handle_*` external calls into the
dep's object files. When the parent links those objects into a shared
library (e.g. a Node NAPI `.node`), the symbols stay unresolved and the
library fails to dlopen at runtime despite `-Doptimize=ReleaseSafe`
being passed to the top-level `zig build`.

Forward `runner.target` and `runner.optimize` by default so child
builds inherit the parent's CLI resolution. Users who need full control
(e.g. pin a dep to a specific optimize) can still supply `.args`
explicitly; in that case zbuild passes their args through unchanged
without injecting anything.

Tested with:
- zig build test (26/26)
- zig build test:fixtures (all passing)
Tests that link against C symbols which the runtime resolves at dlopen
time (e.g. napi C symbols Node provides when loading a `.node` file)
need this flag so the linker doesn't fail standalone test binaries.

Previously the option was only allowed for libraries; mirror the same
behaviour for tests:

- `isKnownArtifactField`: accept `linker_allow_shlib_undefined` in
  `tests` in addition to `libraries`.
- `createTest`: copy the field onto the resulting Compile artifact
  post-create, mirroring `createLibrary`.
- Extend the `stdlib_passthrough` fixture to set the field on both
  the library and the test entry, exercising both code paths.
- Document the field on the `tests` schema table.
@wemeetagain wemeetagain merged commit 5761c5c into main May 11, 2026
2 checks passed
@wemeetagain wemeetagain deleted the refactor/comptime-library-rewrite branch May 11, 2026 18:29
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.

2 participants