zig: write and cross-compile maintainable robust, optimal, and reusable software.

To update or switch versions, run webi zig@stable (or @v0.9, @beta, etc).

Files

These are the files / directories that are created and/or modified with this install:

~/.config/envman/PATH.env
~/.local/opt/zig

Cheat Sheet

zig is two things:

  1. A drop-in cross-compiling toolchain for C and C++ (and Rust and CGo for that matter).
  2. A general purpose systems programming language, like C, but intentional, and with benefit of hindsight.

(and also a nod to Zero Wing)

Philosophy:

The Zen of Zig

  • Communicate intent precisely.
  • Edge cases matter.
  • Favor reading code over writing code.
  • Only one obvious way to do things.
  • Runtime crashes are better than bugs.
  • Compile errors are better than runtime crashes.
  • Incremental improvements.
  • Avoid local maximums.
  • Reduce the amount one must remember.
  • Focus on code rather than style.
  • Resource allocation may fail; resource deallocation must succeed.
  • Memory is a resource.
  • Together we serve the users.

How to compile C/C++ with Zig

You can use Zig as a drop-in C compiler.

zig cc -o ./hello main.c
zig c++ -o ./hello++ main.cpp

And you can cross-compile effortlessly:

zig cc -o ./hello.exe main.c -target x86_64-windows-gnu
zig c++ -o ./hello.exe main.cpp -target x86_64-windows-gnu

How to create and compile Zig programs

  1. Create a new project directory:
    mkdir -p ./zig-hello/
    pushd ./zig-hello/
    
  2. Initialize the project with a new build.zig
    zig init-exe
    
  3. Build hello.exe for Windows from MacOS or Linux
    zig build-exe src/main.zig --name hello -target x86_64-windows-gnu
    zig build-exe src/main.zig --name hello -target x86_64-linux-musl
    zig build-exe src/main.zig --name hello-arm -target aarch64-linux-musl
    zig build-exe src/main.zig --name hello-macos -target x86_64-macos-gnu
    zig build-exe src/main.zig --name hello-m1 -target aarch64-macos-gnu
    

How to list and use Zig's cross-compile targets

zig targets | jq -r '.libc[]'

Here's a few of the common targets:

aarch64-linux-musl
aarch64-windows-gnu
aarch64-macos-gnu
thumb-linux-musleabihf
wasm32-wasi-musl
x86_64-linux-musl
x86_64-windows-gnu
x86_64-macos-gnu

How to cross-compile Rust with Zig

  1. Create a zig-cc-{ARCH-OS} and zig-cpp-{ARCH-OS} wrappers:

    cat << EOF >> ~/.local/bin/zig-cc-x86_64-windows-gnu
    #!/bin/sh
    set -e
    set -u
    "\${HOME}/.local/opt/zig/zig" cc -target x86_64-windows-gnu \$@
    EOF
    
    chmod a+x ~/.local/bin/zig-cc
    
    cat << EOF >> ~/.local/bin/zig-cpp-x86_64-windows-gnu
    #!/bin/sh
    set -e
    set -u
    "\${HOME}/.local/opt/zig/zig" c++ -target x86_64-windows-gnu \$@
    EOF
    
    chmod a+x ~/.local/bin/zig-cpp
    
  2. Set the CC, CPP and ZIGTARGET ENVs. For example:

    #export ZIGTARGET="x86_64-windows-gnu"
    export CC="zig-cc-x86_64-windows-gnu"
    export CPP="zig-cpp-x86_64-windows-gnu"
    
  3. Install the correpsonding Rust toolchains:

    rustup target install x86_64-apple-darwin
    rustup target install x86_64-unknown-linux-musl
    rustup target install aarch64-unknown-linux-musl
    rustup target install x86_64-pc-windows-gnu
    
  4. You may need to also specifically set the linker. For example, with Rust's ~/.cargo/config.toml:

    [target.x86_64-apple-darwin]
    linker = "zig-cc-x86_64-macos-gnu"
    
    [target.x86_64-unknown-linux-musl]
    linker = "zig-cc-x86_64-unknown-linux-musl"
    
    [target.aarch64-unknown-linux-musl]
    linker = "zig-cc-aarch64-unknown-linux-musl"
    
    [target.x86_64-pc-windows-gnu]
    linker = "zig-cc-x86_64-windows-gnu"
    

~/.local/bin/zig-create-crossies:

#!/bin/bash
set -e
set -u

my_targets="$(zig targets | jq -r '.libc[]' | sort -u)"

for my_target in $my_targets; do
   cat << EOF >> "${HOME}/.local/bin/zig-cc-${my_target}"
#!/bin/sh
set -e
set -u

"\${HOME}/.local/opt/zig/zig" cc -target ${my_target} \$@
EOF

   chmod a+x "${HOME}/.local/bin/zig-cc-${my_target}"
done

for my_target in $my_targets; do
   cat << EOF >> "${HOME}/.local/bin/zig-cpp-${my_target}"
#!/bin/sh
set -e
set -u

"\${HOME}/.local/opt/zig/zig" c++ -target ${my_target} \$@
EOF

   chmod a+x "${HOME}/.local/bin/zig-cpp-${my_target}"
done

See also:

How to cross-compile CGo (Golang) with Zig

See the section above about Rust.

It's almost exactly the same.

See also:

Contribute

Report an Issue Submit Installer Star on GitHub