build.zig (addLib)
Contents
napi.addLib is the only build.zig API you need. It registers your addon as a Zig artifact, applies the right linker flags for each OS, sets up the .d.ts install, and (with -Dnpm=true) builds the cross-compile graph and generates the npm package skeleton.
You can call it more than once in the same build.zig to ship multiple addons from one repo. Each call writes its own zig-out/lib/<name>.node and its own npm/<name>/ tree, and the CLI (napikit build, napikit build --release, napikit bump, napikit publish, napikit npm-init) picks up every one. Every call needs a distinct .name. Per-platform package names are derived from .scope plus the platform suffix, so two addons may share a scope only when their configured platform sets do not overlap; a duplicate generated identity fails while configuring the build graph.
LibOptions
Import
Pass via .imports = &.{ .{ .name = "parser", .module = parser } }. See Project layout: where to put your code.
NpmConfig
.repository
npm requires a repository field on every published package for provenance to verify against the source tree, otherwise napikit publish fails in CI with "package must specify a repository". An addon ships as the main package plus one binding per platform (twelve package.json files with the default platform set), and setting .repository once in build.zig writes the field into every one of them on each release build, so you never have to keep them in sync by hand.
Two accepted forms:
Replace OWNER/REPO with the GitHub repository that contains the consumer addon, not the @teakit/napi source repository. The shorthand expands to git+https://github.com/owner/repo.git. It must contain exactly one slash, a valid GitHub owner, and a non-empty repository name; extra path segments, ./.., whitespace, and control characters are rejected. Full URLs may use git+https, git+ssh, ssh, git, http, or https; the git@host:path SCP form is also accepted. Each form must contain a DNS/IPv4-style host with valid labels and a non-empty repository path (IPv6 literals are intentionally not accepted)—transport-looking but incomplete values such as git+x, https://?, or git@host fail during build configuration. Non-GitHub URLs are usable only when you do not use the default GitHub trusted-publishing/provenance flow; napikit npm-init --repo and provenance publishing require the actual consumer GitHub OWNER/REPO. If .repository is empty, no field is emitted and any value already in the existing package.json is preserved.
.name follows npm's lowercase unscoped syntax and also has to be safe on every supported filesystem. Reserved names (node_modules, favicon.ico), trailing dots, and Windows device basenames such as con, con.txt, com1, and lpt9 fail before any artifact is written. A scope may use a value such as @con because the on-disk directory includes the leading @, but it may not end in a dot.
When .npm is present, its package name, scope, repository, and platform list are validated for ordinary development builds as well as release builds. Invalid publication metadata therefore cannot leave a seemingly usable local binary that only fails later during packaging.
Dts
See TypeScript declarations for what each mode produces.
With .none, the generated main package has no types field and does not list or contain index.d.ts. If a previously typed release package switches to .none, the release reconciler removes that build-owned declaration without deleting unrelated files.
Platform
A tagged enum of every supported (OS, architecture, libc) tuple. Used in .npm.platforms. Defaults are exposed as Platform.defaults:
Override the default set with:
What addLib does
- Creates a Zig module from
.rootand adds thenapiimport. - Adds any
.importsto the module. - Builds a dynamic library named
<name>.node. - Configures linker flags per OS:
- macOS:
linker_allow_shlib_undefined = true. - Linux/FreeBSD: links libc, restricts exports to N-API entry points via
exports.ld. - Windows: generates an import library from
node_api.defso the linker resolves N-API symbols against the host.exeat runtime.
- macOS:
- Drops red zone, unwind tables, and unreferenced sections (smaller binaries, no surprise symbols).
- If
.npmis set, installs the.d.tsnext to the binary in the right format. - If both
.npmis set and-Dnpm=trueis passed, generates the full cross-compile graph and thenpm/package tree.
napikit build --release is zig build -Dnpm=true --release=fast by default, with the selected optimization mode applied to every entry in .npm.platforms. --optimize=safe and --optimize=small select ReleaseSafe and ReleaseSmall for every generated binding. You can run the matching Zig command directly if you prefer.
Two build options narrow that loop, set for you by the matching CLI flags:
Under -Dnpm-host the main package.json still lists every configured platform in optionalDependencies, so a later full build stays complete. If the host is absent from .platforms, the build fails rather than creating an undeclared binding. See Building a subset.