Rul1an/zig-cross-compile-action
Zig based cross compilation for C, C++, Rust and Go. No Docker.
Docker-free cross-compilation for C, C++, Rust, and Go using Zig’s cc / c++ toolchain.
Turn a standard GitHub Actions runner into a cross-compiling build host — no containers, sysroots, or system headers required.
# Example: Go + CGO to linux-arm64 using Zig as cross-compiler
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.23'
- name: Cross-compile with Zig
uses: Rul1an/zig-cross-compile-action@v2
with:
target: linux-arm64 # → aarch64-linux-musl
project-type: go
cmd: |
go build -o dist/app-go-arm64 ./cmd
This Action configures Zig as a drop-in cross-compiler:
goto-bus-stop/setup-zig).CC, CXX, AR, RANLIB to use zig cc / zig c++ with the requested target.CGO_ENABLED, GOOS, GOARCHCARGO_TARGET_..._LINKER + CC_<TRIPLE>, CXX_<TRIPLE>file scan.This Action is infrastructure, not a helper script:
go build, cargo build, make, or modify your project files.You stay in control of your build commands; the Action guarantees the compiler side is correct.
No Docker required
Avoids nested Docker, slow volume mounts, permission issues, and platform quirks. Runs directly on ubuntu-latest and macos-latest.
Opinionated environment The Action unconditionally overwrites:
CC, CXX, AR, RANLIBZIG_TARGETCGO_ENABLED, GOOS, GOARCH (for Go)CARGO_TARGET_<TRIPLE>_LINKER, CC_<TRIPLE>, CXX_<TRIPLE> (for Rust)Simple target aliases Human-friendly targets mapped to Zig triples:
linux-arm64 → aarch64-linux-musl (static, musl)linux-x64 → x86_64-linux-muslmacos-arm64 → aarch64-macosmacos-x64 → x86_64-macoswindows-x64 → x86_64-windows-gnuStrict Rust+Musl policy Rust’s bundled Musl CRT and Zig’s Musl can conflict. This Action denies Musl Rust targets by default, with an explicit opt-out:
rust-musl-mode: deny # default
# or: warn / allow
Debug mode
Set ZIG_ACTION_DEBUG: 1 to get extra logging about the configured environment.
| Input | Required | Default | Description |
|---|---|---|---|
version |
no | 0.13.0 |
Zig version to install via setup-zig. |
target |
yes | — | Target architecture / triple or alias (e.g. linux-arm64). |
project-type |
no | auto |
Preset: auto, go, rust, c, custom. |
rust-musl-mode |
no | deny |
Rust+Musl policy: deny, warn, or allow. |
verify-level |
no | basic |
Post-build verification: basic (file check) or none. |
cmd |
yes | — | Build command to run in the configured environment. |
project-type presetsauto: Detects language based on files in the repository root:Cargo.toml → Rustgo.mod → Gogo: Configure Go + CGO only.rust: Configure Rust linker/wrappers only.c: Pure C/C++: set CC, CXX, explicitly CGO_ENABLED=0.custom: Only injects compiler-related env vars; no language-specific tweaks.Host Runners (where the Action runs):
ubuntu-latest (Tier 1)macos-latest (Tier 1)RUNNER_OS == Windows).Verified Target Examples:
x86_64-linux-musl, aarch64-linux-muslaarch64-unknown-linux-gnux86_64-windows-gnuaarch64-macos, x86_64-macosFor a full and up-to-date list of Tier 1/2/3 targets, see TARGETS.md.
jobs:
build-go:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.23'
- name: Build Go (CGO) for linux-arm64
uses: Rul1an/zig-cross-compile-action@v2
with:
target: linux-arm64 # → aarch64-linux-musl
project-type: go
cmd: |
go build -o dist/app-go-arm64 ./cmd
jobs:
build-rust:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
targets: aarch64-unknown-linux-gnu
- name: Build Rust with Zig linker
uses: Rul1an/zig-cross-compile-action@v2
with:
target: aarch64-unknown-linux-gnu
project-type: rust
rust-musl-mode: deny
cmd: |
cargo build --release --target aarch64-unknown-linux-gnu
jobs:
build-c-win:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build C for Windows
uses: Rul1an/zig-cross-compile-action@v2
with:
target: windows-x64 # → x86_64-windows-gnu
project-type: c
cmd: $CC src/main.c -o dist/app.exe
jobs:
build-c-macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Build C for macOS ARM64
uses: Rul1an/zig-cross-compile-action@v2
with:
target: aarch64-macos
project-type: c
cmd: $CC src/main.c -o dist/app-macos
You can combine this Action with common build systems by reusing $CC, $CXX:
CMake:
cmake -DCMAKE_C_COMPILER="$CC" -DCMAKE_CXX_COMPILER="$CXX" .
cmake --build .
Autotools:
./configure CC="$CC" CXX="$CXX" --host="$ZIG_TARGET"
make
Make:
make CC="$CC" CXX="$CXX"
project-type: auto only inspects the current working directory (typically repo root):
If your Go/Rust project lives in a subdirectory (e.g. services/api), either:
project-type explicitly (go / rust / c), orworking-directory and cmd accordingly.Example:
defaults:
run:
working-directory: services/rust-api
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Rul1an/zig-cross-compile-action@v2
with:
target: aarch64-unknown-linux-gnu
project-type: rust
cmd: cargo build --release --target aarch64-unknown-linux-gnu
The Action itself is cache-agnostic, but you can speed up CI by caching Zig’s local data:
- uses: actions/cache@v4
with:
path: ~/.cache/zig
key: zig-${{ inputs.version }}-${{ runner.os }}-${{ runner.arch }}
restore-keys: |
zig-${{ inputs.version }}-${{ runner.os }}-
zig-${{ inputs.version }}-
Set ZIG_ACTION_DEBUG: 1 to enable verbose logging:
ZIG_*, GO*, CARGO_*, CC, CXX).ZIG_TARGET.CARGO_TARGET_*_LINKER (when applicable).This makes it easier to diagnose misconfigured targets or unexpected toolchain behavior.
If you want deterministic, Docker-free cross-compilation with minimal configuration, this Action gives you a clean, opinionated foundation for your CI pipelines.
Read the story behind this Action: Cross-compile anything to anywhere with one GitHub Action on Dev.to.