Dagger
Search

zig

toolchain (build, build-exe, run, test, fmt, version, env, targets) so
downstream pipelines can build, test, format, and cross-compile Zig without
re-inventing toolchain pinning and container plumbing.

Toolchain version is pinned via New(version) or inferred from the source's
build.zig.zon `minimum_zig_version`; falls back to a module-pinned default.

There is no canonical official Zig image, so the base container downloads
the official release tarball from ziglang.org (via dag.HTTP, SHA256-verified
against download/index.json) and unpacks it onto a minimal alpine base with
`zig` on PATH and a shared zig-cache cache volume mounted.

Installation

dagger install github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3

Entrypoint

Return Type
Zig !
Arguments
NameTypeDefault ValueDescription
versionString -No description provided
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
func (m *MyModule) Example() *dagger.Zig  {
	return dag.
			Zig()
}
@function
def example() -> dagger.Zig:
	return (
		dag.zig()
	)
@func()
example(): Zig {
	return dag
		.zig()
}

Types

Zig 🔗

Zig wraps the Zig toolchain as Dagger functions. Construct via New(); call Container() for the prepared base container, or use the per-CLI helpers (Build, BuildExe, Run, Test, Fmt, …) which reuse the same backing container.

version() 🔗

Version is the pinned Zig toolchain version (e.g. “0.14.1”). Empty means infer from the supplied source’s build.zig.zon minimum_zig_version; falls back to a module-pinned default.

Return Type
String !
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 version
func (m *MyModule) Example(ctx context.Context) string  {
	return dag.
			Zig().
			Version(ctx)
}
@function
async def example() -> str:
	return await (
		dag.zig()
		.version()
	)
@func()
async example(): Promise<string> {
	return dag
		.zig()
		.version()
}

build() 🔗

Build runs zig build [-Doptimize=<optimize>] [-Dtarget=<target>] [steps...] [args...] against the supplied source and returns the zig-out install directory.

optimize, when non-empty, must be one of Debug, ReleaseSafe, ReleaseFast, ReleaseSmall and is rejected otherwise. Empty optimize and empty target build for the host.

steps and args are both appended to the zig build command line and are interpreted by the build system (steps name build steps; args are additional build-system arguments/options) — neither is forwarded to a built program. To pass arguments to the program itself, use Run, which inserts the -- separator zig build run expects.

Return Type
Directory !
Arguments
NameTypeDefault ValueDescription
sourceDirectory !-No description provided
optimizeString -No description provided
targetString -No description provided
steps[String ! ] -No description provided
args[String ! ] -No description provided
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 build --source DIR_PATH
func (m *MyModule) Example(source *dagger.Directory) *dagger.Directory  {
	return dag.
			Zig().
			Build(source)
}
@function
def example(source: dagger.Directory) -> dagger.Directory:
	return (
		dag.zig()
		.build(source)
	)
@func()
example(source: Directory): Directory {
	return dag
		.zig()
		.build(source)
}

buildExe() 🔗

BuildExe runs zig build-exe <root> [-O <optimize>] [-target <target>] --name <name> [args...] for a single entry file and returns the produced executable.

root is required (the single entry .zig file). optimize, when non-empty, must be one of Debug, ReleaseSafe, ReleaseFast, ReleaseSmall. name defaults to the basename of root with any trailing “.zig” stripped.

Note the flag spelling differs from Build: build-exe uses -O / -target / –name (compiler flags), not the -Doptimize= / -Dtarget= build-system options.

Return Type
File !
Arguments
NameTypeDefault ValueDescription
sourceDirectory !-No description provided
rootString !-No description provided
optimizeString -No description provided
targetString -No description provided
nameString -No description provided
args[String ! ] -No description provided
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 build-exe --source DIR_PATH --root string
func (m *MyModule) Example(source *dagger.Directory, root string) *dagger.File  {
	return dag.
			Zig().
			Buildexe(source, root)
}
@function
def example(source: dagger.Directory, root: str) -> dagger.File:
	return (
		dag.zig()
		.buildexe(source, root)
	)
@func()
example(source: Directory, root: string): File {
	return dag
		.zig()
		.buildExe(source, root)
}

cc() 🔗

Cc cross-compiles C source with zig cc, a clang frontend that bundles libc and headers for every supported target, so cross-compilation needs no sysroot setup. files is required (the C source files, relative to source). target, when non-empty, sets clang’s -target triple (e.g. “x86_64-windows-gnu”). outputName names the produced artifact (default “a.out”); extra clang flags pass through via args. Returns the artifact as a *dagger.File.

outputName (CLI: –output-name) is named so to avoid colliding with the Dagger CLI’s top-level –output/-o flag — same precedent as go’s Ci.WithBuild.

Return Type
File !
Arguments
NameTypeDefault ValueDescription
sourceDirectory !-No description provided
files[String ! ] !-No description provided
targetString -No description provided
outputNameString !"a.out"No description provided
args[String ! ] -No description provided
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 cc --source DIR_PATH --files string1 --files string2 --output-name string
func (m *MyModule) Example(source *dagger.Directory, files []string, outputName string) *dagger.File  {
	return dag.
			Zig().
			Cc(source, files, outputName)
}
@function
def example(source: dagger.Directory, files: List[str], outputname: str) -> dagger.File:
	return (
		dag.zig()
		.cc(source, files, outputname)
	)
@func()
example(source: Directory, files: string[], outputName: string): File {
	return dag
		.zig()
		.cc(source, files, outputName)
}

ci() 🔗

Ci returns a new pipeline builder bound to the supplied source.

Return Type
Ci !
Arguments
NameTypeDefault ValueDescription
sourceDirectory !-No description provided
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 ci --source DIR_PATH
func (m *MyModule) Example(source *dagger.Directory) *dagger.ZigCi  {
	return dag.
			Zig().
			Ci(source)
}
@function
def example(source: dagger.Directory) -> dagger.ZigCi:
	return (
		dag.zig()
		.ci(source)
	)
@func()
example(source: Directory): ZigCi {
	return dag
		.zig()
		.ci(source)
}

container() 🔗

Container returns the prepared base container with the zig toolchain on PATH, the shared zig-cache cache volume mounted, source mounted at /src, and the working directory set to /src. Use this as an escape hatch when a Zig command isn’t covered by the typed helpers.

The toolchain is downloaded from ziglang.org at the version from New() or, when New(“”) was used, from source/build.zig.zon’s minimum_zig_version (falling back to the module-pinned default). The signature takes ctx + returns error because version inference and the tarball download require async I/O.

Return Type
Container !
Arguments
NameTypeDefault ValueDescription
sourceDirectory !-No description provided
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 container --source DIR_PATH
func (m *MyModule) Example(source *dagger.Directory) *dagger.Container  {
	return dag.
			Zig().
			Container(source)
}
@function
def example(source: dagger.Directory) -> dagger.Container:
	return (
		dag.zig()
		.container(source)
	)
@func()
example(source: Directory): Container {
	return dag
		.zig()
		.container(source)
}

cxx() 🔗

Cxx cross-compiles C++ source with zig c++ (the C++ frontend; bundles libc++). Same parameters and semantics as Cc.

Return Type
File !
Arguments
NameTypeDefault ValueDescription
sourceDirectory !-No description provided
files[String ! ] !-No description provided
targetString -No description provided
outputNameString !"a.out"No description provided
args[String ! ] -No description provided
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 cxx --source DIR_PATH --files string1 --files string2 --output-name string
func (m *MyModule) Example(source *dagger.Directory, files []string, outputName string) *dagger.File  {
	return dag.
			Zig().
			Cxx(source, files, outputName)
}
@function
def example(source: dagger.Directory, files: List[str], outputname: str) -> dagger.File:
	return (
		dag.zig()
		.cxx(source, files, outputname)
	)
@func()
example(source: Directory, files: string[], outputName: string): File {
	return dag
		.zig()
		.cxx(source, files, outputName)
}

env() 🔗

Env runs zig env in a source-less base container and returns its stdout (JSON).

Return Type
String !
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 env
func (m *MyModule) Example(ctx context.Context) string  {
	return dag.
			Zig().
			Env(ctx)
}
@function
async def example() -> str:
	return await (
		dag.zig()
		.env()
	)
@func()
async example(): Promise<string> {
	return dag
		.zig()
		.env()
}

fmt() 🔗

Fmt runs zig fmt --check . against the supplied source, returning a non-nil error that lists the offending files when any are unformatted, and nil when the tree is clean — so CI fails fast on formatting violations.

zig fmt --check exits non-zero and prints the offending paths to stdout, so the exec is run allowing any exit code and the paths are surfaced in the returned error. Fmt returns only error (not the file list as a string) because a Dagger function’s non-error return value is dropped at the GraphQL boundary whenever it also returns a non-nil error: a (string, error) signature would leave the file list unreachable on exactly the failure path that needs it.

Return Type
Void !
Arguments
NameTypeDefault ValueDescription
sourceDirectory !-No description provided
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 fmt --source DIR_PATH
func (m *MyModule) Example(ctx context.Context, source *dagger.Directory)   {
	return dag.
			Zig().
			Fmt(ctx, source)
}
@function
async def example(source: dagger.Directory) -> None:
	return await (
		dag.zig()
		.fmt(source)
	)
@func()
async example(source: Directory): Promise<void> {
	return dag
		.zig()
		.fmt(source)
}

objCopy() 🔗

ObjCopy runs zig objcopy -O <format> <input> <output> in the toolchain container, converting an ELF (e.g. from BuildExe) into a flashable artifact, and returns the result as a *dagger.File. This is the post-build step every embedded flow needs before flashing.

format selects the output target: “binary” (a raw .bin image) or “hex” (Intel HEX). Any other value is rejected with a clear error — notably UF2 is out of scope here, since zig objcopy can’t emit it.

outputName names the produced artifact and defaults to the input’s basename with its extension replaced by the format’s (.bin or .hex). Extra flags (e.g. –only-section, –pad-to) pass through via args.

outputName (CLI: –output-name) is named so to avoid colliding with the Dagger CLI’s top-level –output/-o flag — same precedent as Cc/Cxx.

Return Type
File !
Arguments
NameTypeDefault ValueDescription
inputFile !-No description provided
formatString !"binary"No description provided
outputNameString !""No description provided
args[String ! ] -No description provided
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 obj-copy --input file:path --format string --output-name string
func (m *MyModule) Example(input *dagger.File, format string, outputName string) *dagger.File  {
	return dag.
			Zig().
			Objcopy(input, format, outputName)
}
@function
def example(input: dagger.File, format: str, outputname: str) -> dagger.File:
	return (
		dag.zig()
		.objcopy(input, format, outputname)
	)
@func()
example(input: File, format: string, outputName: string): File {
	return dag
		.zig()
		.objCopy(input, format, outputName)
}

run() 🔗

Run runs zig build run [-- args...] against the supplied source and returns the program’s stdout.

Return Type
String !
Arguments
NameTypeDefault ValueDescription
sourceDirectory !-No description provided
args[String ! ] -No description provided
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 run --source DIR_PATH
func (m *MyModule) Example(ctx context.Context, source *dagger.Directory) string  {
	return dag.
			Zig().
			Run(ctx, source)
}
@function
async def example(source: dagger.Directory) -> str:
	return await (
		dag.zig()
		.run(source)
	)
@func()
async example(source: Directory): Promise<string> {
	return dag
		.zig()
		.run(source)
}

size() 🔗

Size reports the per-section byte totals of an ELF input (e.g. a freestanding BuildExe output) so CI can gate Flash/Ram against a target’s budget.

Zig ships no size subcommand, so this is computed in pure Go via debug/elf: the input is exported and its section headers are read directly — no helper container (per the established runtime-I/O pattern). A non-ELF input returns a clear error.

Return Type
SectionSizes !
Arguments
NameTypeDefault ValueDescription
inputFile !-No description provided
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 size --input file:path
func (m *MyModule) Example(input *dagger.File) *dagger.ZigSectionSizes  {
	return dag.
			Zig().
			Size(input)
}
@function
def example(input: dagger.File) -> dagger.ZigSectionSizes:
	return (
		dag.zig()
		.size(input)
	)
@func()
example(input: File): ZigSectionSizes {
	return dag
		.zig()
		.size(input)
}

targets() 🔗

Targets runs zig targets in a source-less base container and returns its stdout (the supported architecture/OS/ABI matrix).

Return Type
String !
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 targets
func (m *MyModule) Example(ctx context.Context) string  {
	return dag.
			Zig().
			Targets(ctx)
}
@function
async def example() -> str:
	return await (
		dag.zig()
		.targets()
	)
@func()
async example(): Promise<string> {
	return dag
		.zig()
		.targets()
}

test() 🔗

Test runs zig build test when root is empty, else zig test <root>, against the supplied source and returns the combined stdout.

Return Type
String !
Arguments
NameTypeDefault ValueDescription
sourceDirectory !-No description provided
rootString -No description provided
args[String ! ] -No description provided
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 test --source DIR_PATH
func (m *MyModule) Example(ctx context.Context, source *dagger.Directory) string  {
	return dag.
			Zig().
			Test(ctx, source)
}
@function
async def example(source: dagger.Directory) -> str:
	return await (
		dag.zig()
		.test(source)
	)
@func()
async example(source: Directory): Promise<string> {
	return dag
		.zig()
		.test(source)
}

toolVersion() 🔗

ToolVersion runs zig version in a source-less base container and returns the trimmed output (e.g. “0.14.1”).

Return Type
String !
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 tool-version
func (m *MyModule) Example(ctx context.Context) string  {
	return dag.
			Zig().
			Toolversion(ctx)
}
@function
async def example() -> str:
	return await (
		dag.zig()
		.toolversion()
	)
@func()
async example(): Promise<string> {
	return dag
		.zig()
		.toolVersion()
}

Ci 🔗

Ci is a chained builder for a standardized Zig CI pipeline. Construct via Zig.Ci(source); enable check stages via the With* methods; call Run to execute checks-then-build, or Check to run only the parallel checks.

Stage 1 runs the enabled static checks in parallel (Fmt, Test); errors are aggregated. Stage 2 builds the source and Run returns the produced zig-out directory. Downstream consumers compose that directory into their own pipelines (package, sign, publish, …).

check() 🔗

Check runs the enabled check stages (Fmt, Test) in parallel via github.com/dagger/dagger/util/parallel and returns the aggregated error. Use when callers want to run the checks independently of the build (for example multi-target pipelines that share one check run across N target builds).

Return Type
Void !
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 ci --source DIR_PATH \
 check
func (m *MyModule) Example(ctx context.Context, source *dagger.Directory)   {
	return dag.
			Zig().
			Ci(source).
			Check(ctx)
}
@function
async def example(source: dagger.Directory) -> None:
	return await (
		dag.zig()
		.ci(source)
		.check()
	)
@func()
async example(source: Directory): Promise<void> {
	return dag
		.zig()
		.ci(source)
		.check()
}

run() 🔗

Run executes the pipeline: stage 1 (Check) → stage 2 (build). Returns the produced zig-out directory. On stage-1 failure, returns the aggregated error from Check and a nil directory (stage 2 is skipped).

Return Type
Directory !
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 ci --source DIR_PATH \
 run
func (m *MyModule) Example(source *dagger.Directory) *dagger.Directory  {
	return dag.
			Zig().
			Ci(source).
			Run()
}
@function
def example(source: dagger.Directory) -> dagger.Directory:
	return (
		dag.zig()
		.ci(source)
		.run()
	)
@func()
example(source: Directory): Directory {
	return dag
		.zig()
		.ci(source)
		.run()
}

withBuild() 🔗

WithBuild configures the build stage parameters (forwarded to Zig.Build). optimize, when non-empty, must be one of Debug, ReleaseSafe, ReleaseFast, ReleaseSmall; target sets -Dtarget; steps names build steps. Build is always executed by Run regardless of whether this method is called.

Return Type
Ci !
Arguments
NameTypeDefault ValueDescription
optimizeString -No description provided
targetString -No description provided
steps[String ! ] -No description provided
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 ci --source DIR_PATH \
 with-build
func (m *MyModule) Example(source *dagger.Directory) *dagger.ZigCi  {
	return dag.
			Zig().
			Ci(source).
			Withbuild()
}
@function
def example(source: dagger.Directory) -> dagger.ZigCi:
	return (
		dag.zig()
		.ci(source)
		.withbuild()
	)
@func()
example(source: Directory): ZigCi {
	return dag
		.zig()
		.ci(source)
		.withBuild()
}

withFmt() 🔗

WithFmt enables the zig fmt --check check stage.

Return Type
Ci !
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 ci --source DIR_PATH \
 with-fmt
func (m *MyModule) Example(source *dagger.Directory) *dagger.ZigCi  {
	return dag.
			Zig().
			Ci(source).
			Withfmt()
}
@function
def example(source: dagger.Directory) -> dagger.ZigCi:
	return (
		dag.zig()
		.ci(source)
		.withfmt()
	)
@func()
example(source: Directory): ZigCi {
	return dag
		.zig()
		.ci(source)
		.withFmt()
}

withTest() 🔗

WithTest enables the test check stage. root maps onto Zig.Test’s optional root: empty runs zig build test; non-empty runs zig test <root>.

Return Type
Ci !
Arguments
NameTypeDefault ValueDescription
rootString -No description provided
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 ci --source DIR_PATH \
 with-test
func (m *MyModule) Example(source *dagger.Directory) *dagger.ZigCi  {
	return dag.
			Zig().
			Ci(source).
			Withtest()
}
@function
def example(source: dagger.Directory) -> dagger.ZigCi:
	return (
		dag.zig()
		.ci(source)
		.withtest()
	)
@func()
example(source: Directory): ZigCi {
	return dag
		.zig()
		.ci(source)
		.withTest()
}

SectionSizes 🔗

SectionSizes is the per-section footprint of an ELF, in bytes. Flash and Ram are the budget-relevant rollups: Flash is what the image occupies in flash, Ram what it claims at runtime.

text() 🔗

SHF_ALLOC, read-only: code (.text) + constants (.rodata)

Return Type
Integer !
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 size --input file:path \
 text
func (m *MyModule) Example(ctx context.Context, input *dagger.File) int  {
	return dag.
			Zig().
			Size(input).
			Text(ctx)
}
@function
async def example(input: dagger.File) -> int:
	return await (
		dag.zig()
		.size(input)
		.text()
	)
@func()
async example(input: File): Promise<number> {
	return dag
		.zig()
		.size(input)
		.text()
}

data() 🔗

SHF_ALLOC|SHF_WRITE, PROGBITS (initialized data)

Return Type
Integer !
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 size --input file:path \
 data
func (m *MyModule) Example(ctx context.Context, input *dagger.File) int  {
	return dag.
			Zig().
			Size(input).
			Data(ctx)
}
@function
async def example(input: dagger.File) -> int:
	return await (
		dag.zig()
		.size(input)
		.data()
	)
@func()
async example(input: File): Promise<number> {
	return dag
		.zig()
		.size(input)
		.data()
}

bss() 🔗

SHF_ALLOC|SHF_WRITE, NOBITS (zero-init data)

Return Type
Integer !
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 size --input file:path \
 bss
func (m *MyModule) Example(ctx context.Context, input *dagger.File) int  {
	return dag.
			Zig().
			Size(input).
			Bss(ctx)
}
@function
async def example(input: dagger.File) -> int:
	return await (
		dag.zig()
		.size(input)
		.bss()
	)
@func()
async example(input: File): Promise<number> {
	return dag
		.zig()
		.size(input)
		.bss()
}

flash() 🔗

Text + Data (consumes flash)

Return Type
Integer !
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 size --input file:path \
 flash
func (m *MyModule) Example(ctx context.Context, input *dagger.File) int  {
	return dag.
			Zig().
			Size(input).
			Flash(ctx)
}
@function
async def example(input: dagger.File) -> int:
	return await (
		dag.zig()
		.size(input)
		.flash()
	)
@func()
async example(input: File): Promise<number> {
	return dag
		.zig()
		.size(input)
		.flash()
}

ram() 🔗

Data + Bss (consumes RAM)

Return Type
Integer !
Example
dagger -m github.com/z5labs/devex/daggerverse/zig@bc5cee36080549722c6d3bf02152aa7d46d2dcf3 call \
 size --input file:path \
 ram
func (m *MyModule) Example(ctx context.Context, input *dagger.File) int  {
	return dag.
			Zig().
			Size(input).
			Ram(ctx)
}
@function
async def example(input: dagger.File) -> int:
	return await (
		dag.zig()
		.size(input)
		.ram()
	)
@func()
async example(input: File): Promise<number> {
	return dag
		.zig()
		.size(input)
		.ram()
}