Zig 0.16 · v0.0.2 preview

Extraction and module resolution

ArchUnitZig validates Zig source with Zig's own AST parser, scans literal dependency builtins, resolves project paths, and normalizes the results into stable project-relative graph identifiers.

Project discovery and enumeration

Pass an explicit project directory or marker, or let discovery walk upward to the nearest build.zig.zon and then build.zig. Enumeration returns sorted lowercase .zig and .zon paths. Cache, VCS, output, dependency, and nested-project directories are excluded by default; custom exclusions are additive.

Symlinks and Windows reparse points are not followed. This keeps traversal bounded and makes an external target's classification independent of filesystem aliases.

Project-wide source exclusions

An optional .archignore beside the located root marker applies to direct enumeration and every fluent architecture check. It uses ArchUnitZig globs: * stays in one segment, ** crosses segments, a leading / anchors at the root, separator-free patterns match basenames at any depth, and Windows separators are accepted. Blank lines and full-line # comments are ignored.

Only the root file is authoritative. Nested files do not override it, and its patterns are additive with explicit and built-in exclusions. Gitignore negation is intentionally unsupported; a line beginning with ! is an InvalidPattern error rather than an inert policy.

Workspaces and nested packages

The compatible default analyzes only the located package. Workspace mode can instead select an explicit list of package ids and root-relative paths, or discover every build.zig.zon below a repository root. Discovery prunes dependency, vendor, cache, VCS, output, documentation, symlink, and reparse-point trees.

Workspace identifiers are package_id::package-relative/path. Discovered ids are manifest-directory paths (. for the root); explicit ids are caller supplied. Compilation units name their package, root stays in that package, and project-origin aliases may deliberately target another selected package. The workspace root ignore file matches physical repository paths, package ignore files match package-relative paths, and explicit exclusions match qualified identifiers.

Dependency syntax

The extractor recognizes literal @import, @embedFile, and deprecated @cImport/@cInclude forms without evaluating code. Comments, ordinary string contents, and multiline strings cannot become false dependencies.

Strict parsing

Malformed syntax, invalid literals, and non-literal operands return a technical parser failure with located context.

Permissive parsing

Broken files contribute owned syntax diagnostics and no partial dependency edges, allowing editor-style callers to continue.

Relative files and resources

Relative Zig, ZON, and embedded-resource paths resolve from the importing file. Resolution collapses . and .., checks the canonical project boundary, and distinguishes resolved, missing, and outside_project. A resolved resource stays project-owned while retaining its resource target class.

Named modules need compilation-unit context

An import such as @import("domain") cannot be resolved correctly from its string alone. build.zig is an arbitrary program, and the same alias may point to a different module for each executable or test root. Configure explicit CompilationUnitOverride values with an optional root source and exact alias table.

Module resultGraph meaning
resolved_projectThe alias maps to a project-relative source root and becomes internal.
resolved_packageAn explicitly package-origin mapping remains external, even if its checkout is inside the repository.
compiler_providedstd and builtin; root resolves only from the selected unit.
unresolvedThe raw alias stays visible as a stable external graph target.
missing / outside_projectThe configured path is unavailable or crosses the project boundary.

Production graphs and colocated tests

Zig test declarations live beside production code, so their imports are visible by default. Set ExtractionOptions.include_test_imports = false when enforcing a production-only architecture. Ordinary comptime dependencies remain included.

Deterministic cache identity

Graph-cache keys encode the canonical project root and every extraction option, including workspace selection, ordered compilation-unit mappings, and test-import behavior. They also encode root/package ignore fingerprints plus every selected manifest's canonical path and exact-content fingerprint, so edits or newly discovered packages invalidate prior results. Caller-owned caches are unsynchronized; the optional process cache is mutex-protected. Reads return clones, so clearing a cache cannot invalidate a graph already returned to a caller.

Local dependency suppressions

// archunit: ignore may suppress one intentional dependency occurrence. A trailing directive applies to calls on that line; a standalone directive applies only to the builtin on the next physical line. Optional target names are exact after Zig string decoding. Malformed directives are reported instead of silently changing the graph.

Automatic build-graph discovery is not implemented The default resolver does not execute or partially interpret build.zig. Explicit compilation-unit mappings are the honest current contract; see limitations.
Next: Files