Build Zig with Nix

Network operations are not possible when building a Nix package, therefore Zig fetching the package dependencies to build your program or application will not work and instead you need to store your pre-downloaded dependencies in the cache Zig is gonna use. Here are a couple ways to do so.

Zon2Nix

Zon2Nix is a program that will convert the dependencies in build.zig.zon to a Nix expression.

Basic build file

Our most basic default.nix for our Zig application must look like this:

# default.nix
{
  pkgs ? import <nixpkgs> {},
  # unstable channel to build with the latest Zig release
  unstable ? import (fetchTarball "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz") {},
}:
pkgs.stdenv.mkDerivation {
  pname = "my-program";
  version = "0.0.0";
  
  src = ./.;
  
  buildInputs = [
    unstable.zig
  ];
  
  patchPhase = ''
    export HOME="$TMPDIR"
    export ZIG_GLOBAL_CACHE_DIR="$HOME/.cache/zig"
    mkdir -p "$ZIG_GLOBAL_CACHE_DIR"
  '';
  
  buildPhase = ''
    zig build --prefix $out --release=fast
  '';
  
  installPhase = ''
    zig build --prefix $out --release=fast install
  '';
  
  meta = {
    homepage = "https://my-project.com";
    description = "My project description";
    license = pkgs.lib.licenses.my-license;
    mainProgram = "my-program";
  };
}

Generate dependencies file

Run:

zon2nix > deps.nix

Which generates a deps.nix file like this:

{ linkFarm, fetchzip }:
linkFarm "zig-packages" [
  {
    name = "<HASH>";
    path = fetchzip {
      url = "<URL>";
      hash = "<NIX-HASH>";
    };
  }
  # ...
]

The we import it into our default.nix file with pkgs.callPackage ./deps.nix {}

# default.nix
{
  pkgs ? import <nixpkgs> {},
  # unstable channel to build with the latest Zig release
  unstable ? import (fetchTarball "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz") {},
+ # our dependencies link farm import
+ deps ? pkgs.callPackage ./deps.nix {};
}:
pkgs.stdenv.mkDerivation {

...

  patchPhase = ''
    export HOME="$TMPDIR"
    export ZIG_GLOBAL_CACHE_DIR="$HOME/.cache/zig"
    mkdir -p "$ZIG_GLOBAL_CACHE_DIR"
+   
+   ln -s ${deps} "$ZIG_GLOBAL_CACHE_DIR/p"
  '';

...

And done!