From 5ed7bed45af4d4fb6690396506fddd6456e10fcd Mon Sep 17 00:00:00 2001 From: Edgars Date: Tue, 21 Apr 2026 17:57:32 +0100 Subject: [PATCH 1/3] wip(flake): parameterise build host by system for darwin support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructures the flake so every genvm component is built under the current host system (aarch64-darwin, x86_64-linux, etc.) instead of the hardcoded x86_64-linux. On linux hosts the output is unchanged; on darwin hosts `nix build .#all-for-platform.arm64-macos` now advances past the gtt/glibc/wasi-sdk evaluation errors and successfully fetches + builds rust + zig toolchains natively. Changes: - flake.nix: wrap genvm-release in flake-utils.lib.eachSystem for x86_64-linux/aarch64-linux/aarch64-darwin/x86_64-darwin. Move all-for-platform + components under legacyPackages. so they thread per-system while keeping the shorthand `.#all-for-platform.X` working. Gate glibc in devShell packages and LD_LIBRARY_PATH on isLinux. - runners/default.nix + runners/support/all/head.nix: accept pkgs as an arg so runners evaluate under the caller's nixpkgs pin instead of creating their own x86_64-linux one. - support/rust.nix: default system to pkgs.stdenv.hostPlatform.system so the rust toolchain matches the build host. Gate glibc + patchelf fixupPhase behind isLinux. - support/compile-rust.nix: gate glibc in nativeBuildInputs behind isLinux. Replace hardcoded /build/libs with $TMPDIR/__libs so the staging path is writable on darwin sandboxes. - support/zig.nix: default system to host, add x86_64-darwin and aarch64-darwin (via name-mapping to zig's 'aarch64-macos' key). Replace /build/.zig-cache with $TMPDIR/.zig-cache. - runners/support/wasi-sdk.nix: per-host wasi-sdk tarball selection. Gate autoPatchelfHook behind isLinux; darwin Mach-O needs no ELF patching. STILL FAILING on darwin at link stage: the zig-cc wrapper filters Darwin-specific flags (-framework etc.) but strips `-Wl,-exported_symbols_list` which rustc emits for native aarch64-darwin builds. Likely fix: skip zig-cc when host == target (use the stdenv's native cc instead, since cross-compilation is only needed when host != target). Linux CI path is unaffected — eachSystem["x86_64-linux"] follows the same code path as before (same pkgs, same components). --- flake.nix | 320 ++++++++++++++++++----------------- runners/default.nix | 19 ++- runners/support/all/head.nix | 5 +- runners/support/wasi-sdk.nix | 47 ++++- support/compile-rust.nix | 24 ++- support/rust.nix | 21 ++- support/zig.nix | 38 ++++- 7 files changed, 286 insertions(+), 188 deletions(-) diff --git a/flake.nix b/flake.nix index 3b854c40..aa1e2f0b 100644 --- a/flake.nix +++ b/flake.nix @@ -22,167 +22,181 @@ }; outputs = { self, nixpkgs, flake-utils, systems }: - let - genvm-release = - let - pkgs = import nixpkgs { - system = "x86_64-linux"; - }; + flake-utils.lib.eachSystem [ + "x86_64-linux" + "aarch64-linux" + "aarch64-darwin" + "x86_64-darwin" + ] (system: + let + pkgs = import nixpkgs { + inherit system; + }; + + lib = pkgs.lib; - lib = pkgs.lib; + # Build inputs for devShells — only Linux has `glibc` as a + # separate package; on darwin the C library ships via + # stdenv.cc and doesn't need an explicit reference. + linuxOnly = x: lib.optional pkgs.stdenv.isLinux x; - args = import ./support { - inherit pkgs; - root-src = self; - } // { - inherit components; + custom-rust = import ./support/rust.nix { inherit pkgs system; withLinters = true; withZig = false; }; + custom-rust-builder = import ./support/compile-rust.nix { + inherit pkgs system; + zig = import ./support/zig.nix { inherit pkgs system; }; + }; - build-config = builtins.fromJSON (builtins.readFile ./flake-config.json); + custom-cargo-afl = custom-rust-builder rec { + name = "cargo-afl"; + version = "0.15.18"; + src = pkgs.fetchzip { + url = "https://crates.io/api/v1/crates/cargo-afl/0.15.18/download"; + hash = "sha256-6ti50bwE4bLwIyR76bMt/Vn6Nwqu9n0IKdVuDdYkiHg="; + extension = ".tar.gz"; + name = "cargo-afl-0.15.18.tar.gz"; }; - components = args.merge-components [ - (import ./libs args) - (import ./modules args) - (import ./executor args) - (import ./runners/release.nix args) - (import ./runners/support/all args) - ]; + target = system; - merge-all-for-platform = platform: - let - for-platform = components.${platform}; - names = builtins.attrNames for-platform; - just-derivations = builtins.attrValues for-platform; - in - pkgs.stdenvNoCC.mkDerivation { - name = "genvm-${platform}"; - - srcs = just-derivations; - - dontUnpack = true; - dontConfigure = true; - dontBuild = true; - dontFixup = true; - - installPhase = '' - mkdir -p $out - for src in $srcs; do - cp --no-preserve=ownership -r $src/. $out/. - chmod -R u+w $out - done - ''; - }; - in { - inherit components; + cargoLock.lockFile = "${src}/Cargo.lock"; - all-for-platform = builtins.mapAttrs (platform: sub: merge-all-for-platform platform) components; + nativeBuildInputs = [ pkgs.gnumake pkgs.makeWrapper ]; + + postBuild = '' + XDG_DATA_HOME="$out/data" ./target/*/release/cargo-afl afl config --build --verbose + ''; + + installPhase = '' + mkdir -p $out/bin + cp target/__out $out/bin/cargo-afl + wrapProgram $out/bin/cargo-afl \ + --set XDG_DATA_HOME "$out/data" + ''; + }; + + packages-0 = with pkgs; [ bash xz zlib git python312 coreutils which jq stdenv.cc nix ] ++ (linuxOnly pkgs.glibc); + packages-lint = with pkgs; [ pre-commit ]; + packages-rust = [ custom-rust ]; + packages-debug-test = with pkgs; [ + (pkgs.ninja.overrideAttrs (old: { + postPatch = old.postPatch + '' + substituteInPlace src/subprocess-posix.cc \ + --replace '"/bin/sh"' '"${pkgs.bash}/bin/bash"' + ''; + })) + ruby + gcc + + custom-cargo-afl + llvmPackages.libllvm + + python312Packages.jsonnet + pkgs.python312Packages.aiohttp + wabt + ]; + packages-py-test = with pkgs; [ + # aflplusplus # currently we don't run fuzzing on CI + python312 + poetry + ]; + shell-hook-base = '' + export PATH="$(pwd)/tools/git-third-party:$PATH" + export LD_LIBRARY_PATH="${toString pkgs.xz.out}/lib:${toString pkgs.zlib.out}/lib:${pkgs.stdenv.cc.cc.lib}/lib${lib.optionalString pkgs.stdenv.isLinux ":${toString pkgs.glibc}/lib"}:$LD_LIBRARY_PATH" + export LLVM_PROFILE_FILE=/dev/null + ''; + + # ──────────────────────────────────────────────────────── + # genvm release outputs — the platform-specific build + # artifacts (libs + modules + executor + runners + + # universal-manifest). Evaluated under the current build + # system; target platform is selected by attribute name + # (arm64-macos / amd64-linux / etc.) and cross-compiled + # via zig + wasi-sdk. + # ──────────────────────────────────────────────────────── + + args = import ./support { + inherit pkgs; + root-src = self; + } // { + inherit components; + build-config = builtins.fromJSON (builtins.readFile ./flake-config.json); }; - for-systems = - flake-utils.lib.eachDefaultSystem - (system: - let - pkgs = import nixpkgs { - inherit system; - }; - - custom-rust = import ./support/rust.nix { inherit pkgs system; withLinters = true; withZig = false; }; - custom-rust-builder = import ./support/compile-rust.nix { - inherit pkgs system; - zig = import ./support/zig.nix { inherit pkgs system; }; - }; - - custom-cargo-afl = custom-rust-builder rec { - name = "cargo-afl"; - version = "0.15.18"; - src = pkgs.fetchzip { - url = "https://crates.io/api/v1/crates/cargo-afl/0.15.18/download"; - hash = "sha256-6ti50bwE4bLwIyR76bMt/Vn6Nwqu9n0IKdVuDdYkiHg="; - extension = ".tar.gz"; - name = "cargo-afl-0.15.18.tar.gz"; - }; - - target = system; - - cargoLock.lockFile = "${src}/Cargo.lock"; - - nativeBuildInputs = [ pkgs.gnumake pkgs.makeWrapper ]; - - postBuild = '' - XDG_DATA_HOME="$out/data" ./target/*/release/cargo-afl afl config --build --verbose - ''; - - installPhase = '' - mkdir -p $out/bin - cp target/__out $out/bin/cargo-afl - wrapProgram $out/bin/cargo-afl \ - --set XDG_DATA_HOME "$out/data" - ''; - }; - - packages-0 = with pkgs; [ bash xz zlib git python312 coreutils which jq stdenv.cc glibc nix ]; - packages-lint = with pkgs; [ pre-commit ]; - packages-rust = [ custom-rust ]; - packages-debug-test = with pkgs; [ - (pkgs.ninja.overrideAttrs (old: { - postPatch = old.postPatch + '' - substituteInPlace src/subprocess-posix.cc \ - --replace '"/bin/sh"' '"${pkgs.bash}/bin/bash"' - ''; - })) - ruby - gcc - - custom-cargo-afl - llvmPackages.libllvm - - python312Packages.jsonnet - pkgs.python312Packages.aiohttp - wabt - ]; - packages-py-test = with pkgs; [ - # aflplusplus # currently we don't run fuzzing on CI - python312 - poetry - ]; - shell-hook-base = '' - export PATH="$(pwd)/tools/git-third-party:$PATH" - export LD_LIBRARY_PATH="${toString pkgs.xz.out}/lib:${toString pkgs.zlib.out}/lib:${pkgs.stdenv.cc.cc.lib}/lib:${toString pkgs.glibc}/lib:$LD_LIBRARY_PATH" - export LLVM_PROFILE_FILE=/dev/null - ''; - in - { - devShells.py-test = pkgs.mkShell { - packages = packages-py-test ++ [ pkgs.ruby ]; - shellHook = shell-hook-base; - }; - devShells.initial-check = pkgs.mkShell { - packages = packages-0 ++ packages-rust ++ packages-lint; - shellHook = shell-hook-base; - }; - devShells.rust-test = pkgs.mkShell { - packages = packages-0 ++ packages-debug-test ++ packages-rust; - shellHook = shell-hook-base; - }; - devShells.mock-tests = pkgs.mkShell { - packages = packages-0 ++ [ - pkgs.python312 - pkgs.python312Packages.jsonnet - pkgs.python312Packages.aiohttp - pkgs.wabt - ]; - shellHook = shell-hook-base; - }; - devShells.full = pkgs.mkShell { - packages = packages-0 ++ packages-debug-test ++ packages-py-test ++ packages-rust ++ packages-lint; - shellHook = shell-hook-base; - }; - devShells.check-qemu = pkgs.mkShell { - packages = packages-0 ++ [ pkgs.qemu ]; - shellHook = shell-hook-base; - }; - } - ); + components = args.merge-components [ + (import ./libs args) + (import ./modules args) + (import ./executor args) + (import ./runners/release.nix args) + (import ./runners/support/all args) + ]; + + merge-all-for-platform = platform: + let + for-platform = components.${platform}; + names = builtins.attrNames for-platform; + just-derivations = builtins.attrValues for-platform; + in + pkgs.stdenvNoCC.mkDerivation { + name = "genvm-${platform}"; + + srcs = just-derivations; + + dontUnpack = true; + dontConfigure = true; + dontBuild = true; + dontFixup = true; + + installPhase = '' + mkdir -p $out + for src in $srcs; do + cp --no-preserve=ownership -r $src/. $out/. + chmod -R u+w $out + done + ''; + }; + + all-for-platform = builtins.mapAttrs (platform: sub: merge-all-for-platform platform) components; in - for-systems // genvm-release; + { + devShells.py-test = pkgs.mkShell { + packages = packages-py-test ++ [ pkgs.ruby ]; + shellHook = shell-hook-base; + }; + devShells.initial-check = pkgs.mkShell { + packages = packages-0 ++ packages-rust ++ packages-lint; + shellHook = shell-hook-base; + }; + devShells.rust-test = pkgs.mkShell { + packages = packages-0 ++ packages-debug-test ++ packages-rust; + shellHook = shell-hook-base; + }; + devShells.mock-tests = pkgs.mkShell { + packages = packages-0 ++ [ + pkgs.python312 + pkgs.python312Packages.jsonnet + pkgs.python312Packages.aiohttp + pkgs.wabt + ]; + shellHook = shell-hook-base; + }; + devShells.full = pkgs.mkShell { + packages = packages-0 ++ packages-debug-test ++ packages-py-test ++ packages-rust ++ packages-lint; + shellHook = shell-hook-base; + }; + devShells.check-qemu = pkgs.mkShell { + packages = packages-0 ++ [ pkgs.qemu ]; + shellHook = shell-hook-base; + }; + + # `nix build .#all-for-platform.X` still works: Nix resolves + # the shorthand against `legacyPackages.` + # next (after `packages`). legacyPackages allows nested + # attrsets (packages does not, each entry must be a drv), + # which lets us keep the `all-for-platform.` shape. + legacyPackages = { + inherit components; + inherit all-for-platform; + }; + } + ); } diff --git a/runners/default.nix b/runners/default.nix index f66b79fd..36ca4f29 100644 --- a/runners/default.nix +++ b/runners/default.nix @@ -1,12 +1,19 @@ -# importing this file (no args) results in: +# importing this file results in: # [{ # id # hash # uid # derivation # tar file # }] +# +# Callers may pass `pkgs` to evaluate under their own nixpkgs + system; +# if omitted we fall back to a pinned x86_64-linux nixpkgs for legacy +# scripts that used to `import ./runners/default.nix` without args. +{ pkgs ? null +, ... +}: let - pkgs = import + default-pkgs = import (builtins.fetchGit { url = "https://github.com/NixOS/nixpkgs"; rev = "8b27c1239e5c421a2bbc2c65d52e4a6fbf2ff296"; @@ -15,11 +22,15 @@ let { system = "x86_64-linux"; }; + + effective-pkgs = if pkgs == null then default-pkgs else pkgs; + runnersLib = import ./support args; args = { - inherit pkgs runnersLib; - inherit (pkgs) lib stdenvNoCC; + pkgs = effective-pkgs; + inherit runnersLib; + inherit (effective-pkgs) lib stdenvNoCC; }; in (import ./py-libs args) ++ diff --git a/runners/support/all/head.nix b/runners/support/all/head.nix index 24ba0cda..65ba7fbf 100644 --- a/runners/support/all/head.nix +++ b/runners/support/all/head.nix @@ -1,6 +1,7 @@ -{ build-config +{ pkgs +, build-config , ... }: builtins.map (x: x // { rev = build-config.head-revision; }) - (import ../../default.nix) + (import ../../default.nix { inherit pkgs; }) diff --git a/runners/support/wasi-sdk.nix b/runners/support/wasi-sdk.nix index 8887aba7..0505e046 100644 --- a/runners/support/wasi-sdk.nix +++ b/runners/support/wasi-sdk.nix @@ -3,20 +3,51 @@ , ... }: let - wasi-sdk-raw = (pkgs.fetchzip { + # wasi-sdk ships binaries per host platform — linux x86_64/arm64 and + # macOS arm64/x86_64. The WASM output is platform-agnostic, but the + # toolchain itself is native to the build host. + tarballs = { + "x86_64-linux" = { + url = "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-24/wasi-sdk-24.0-x86_64-linux.tar.gz"; + hash = "sha256-/cyLxhFsfBBQxn4NrhLdbgHjU3YUjYhPnvquWJodcO8="; + }; + "aarch64-linux" = { + url = "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-24/wasi-sdk-24.0-arm64-linux.tar.gz"; + # Populate on first arm64-linux build: nix will report the correct + # sha256 and swap this placeholder in. + hash = lib.fakeHash; + }; + "aarch64-darwin" = { + url = "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-24/wasi-sdk-24.0-arm64-macos.tar.gz"; + hash = lib.fakeHash; + }; + "x86_64-darwin" = { + url = "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-24/wasi-sdk-24.0-x86_64-macos.tar.gz"; + hash = lib.fakeHash; + }; + }; + system = pkgs.stdenv.hostPlatform.system; + artifact = tarballs.${system} or + (throw "wasi-sdk: no packaged tarball for ${system}"); + + wasi-sdk-raw = pkgs.fetchzip { name = "wasi-sdk-raw"; - url = "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-24/wasi-sdk-24.0-x86_64-linux.tar.gz"; - hash = "sha256-/cyLxhFsfBBQxn4NrhLdbgHjU3YUjYhPnvquWJodcO8="; - }); + url = artifact.url; + hash = artifact.hash; + }; wasi-sdk = pkgs.stdenvNoCC.mkDerivation { name = "wasi-sdk"; version = "24.0"; src = wasi-sdk-raw; - buildInputs = [pkgs.libgcc pkgs.texinfo]; + # autoPatchelf is Linux-only; on darwin the toolchain ships as + # Mach-O binaries that don't need ELF patching. + buildInputs = + lib.optionals pkgs.stdenv.isLinux [ pkgs.libgcc pkgs.texinfo ]; - nativeBuildInputs = [pkgs.autoPatchelfHook]; + nativeBuildInputs = + lib.optional pkgs.stdenv.isLinux pkgs.autoPatchelfHook; dontConfigure = true; dontBuild = true; @@ -24,7 +55,9 @@ let installPhase = '' mkdir -p "$out" cp -r * "$out/" - autoPatchelf "$out" + ${lib.optionalString pkgs.stdenv.isLinux '' + autoPatchelf "$out" + ''} "$out/bin/clang" --version ''; diff --git a/support/compile-rust.nix b/support/compile-rust.nix index a04a3941..c62b6316 100644 --- a/support/compile-rust.nix +++ b/support/compile-rust.nix @@ -83,8 +83,11 @@ stdenv.mkDerivation ( cargoDeps = importCargoLock cargoLock; inherit buildAndTestSubdir; + # `/build` is hardcoded in the Linux sandbox layout; on darwin the + # equivalent write-root is set by the builder as TMPDIR. We resolve + # it at build time via a placeholder and substitute before cargo runs. RUSTFLAGS = - "-C target-feature=-crt-static -l dylib=c -L /build/libs -C link-arg=-dynamic " + "-C target-feature=-crt-static -l dylib=c -L @LIBS_DIR@ -C link-arg=-dynamic " + (args.RUSTFLAGS or ""); hardeningDisable = ["all"]; @@ -99,9 +102,11 @@ stdenv.mkDerivation ( cargoSetupHook rust-pkg zig - pkgs.glibc pkgs.libllvm - ]; + ] + # glibc on the host is Linux-only — zig vendors its own libc for + # cross-compiling to linux targets, so darwin hosts don't need it. + ++ lib.optional pkgs.stdenv.isLinux pkgs.glibc; buildInputs = buildInputs @@ -111,18 +116,23 @@ stdenv.mkDerivation ( PKG_CONFIG_ALLOW_CROSS = 1; + # `/build/libs` was the Linux-sandbox-specific staging dir for + # extraLibs. On darwin that path isn't writable — use TMPDIR and + # rewrite RUSTFLAGS's @LIBS_DIR@ placeholder at build time. postUnpack = '' eval "$cargoDepsHook" - mkdir -p /build/libs + LIBS_DIR="$TMPDIR/__libs" + mkdir -p "$LIBS_DIR" + export RUSTFLAGS="''${RUSTFLAGS//@LIBS_DIR@/$LIBS_DIR}" export RUST_LOG=${logLevel} '' + (args.postUnpack or "") + "\n" + builtins.concatStringsSep "\n" ( - builtins.map (x: "cp ${x}/lib/* /build/libs/") extraLibs + builtins.map (x: ''cp ${x}/lib/* "$LIBS_DIR/"'') extraLibs ); configurePhase = @@ -140,7 +150,7 @@ stdenv.mkDerivation ( buildPhase = '' runHook preBuild - ls -l /build/libs/ + ls -l "$LIBS_DIR/" echo "PATH=$PATH" echo "RUSTFLAGS=$RUSTFLAGS" @@ -162,7 +172,7 @@ stdenv.mkDerivation ( for i in $(patchelf --print-needed target/__out) do - if [[ "$i" == /build/libs/* ]] + if [[ "$i" == "$LIBS_DIR"/* ]] then echo "Replacing $i with $(basename $i)" patchelf --replace-needed "$i" "$(basename $i)" target/__out diff --git a/support/rust.nix b/support/rust.nix index d3168737..fd830648 100644 --- a/support/rust.nix +++ b/support/rust.nix @@ -1,5 +1,7 @@ { pkgs -, system ? "x86_64-linux" +# Default to the current build host so the rust toolchain matches — +# otherwise darwin hosts would try to exec an x86_64-linux cargo binary. +, system ? pkgs.stdenv.hostPlatform.system , withLinters ? false , withZig ? true , ... @@ -63,17 +65,21 @@ in pkgs.stdenvNoCC.mkDerivation rec { nativeBuildInputs = [ pkgs.makeWrapper ]; buildInputs = [ - pkgs.glibc pkgs.zlib pkgs.bash pkgs.gcc.cc.lib zig - ]; + ] ++ pkgs.lib.optional pkgs.stdenv.isLinux pkgs.glibc; dontAutoPatchelf = true; - fixupPhase = '' + # ELF-patching is Linux-only: the rust toolchain binaries on darwin + # are Mach-O and resolve dylibs via install names, not rpath. String + # interpolations like `${pkgs.glibc}/lib/ld-linux-x86-64.so.2` also + # force nix to realize glibc which doesn't exist on darwin, so we gate + # the whole block behind `isLinux`. + fixupPhase = if pkgs.stdenv.isLinux then '' SEARCH_DIRS="$out/bin" if [[ "${system}" == "x86_64-linux" ]] then @@ -83,10 +89,6 @@ in pkgs.stdenvNoCC.mkDerivation rec { then SEARCH_DIRS="$SEARCH_DIRS $out/lib/rustlib/aarch64-unknown-linux-gnu/bin" fi - if [[ "${system}" == "aarch64-darwin" ]] - then - SEARCH_DIRS="$SEARCH_DIRS $out/lib/rustlib/aarch64-apple-darwin/bin" - fi find $SEARCH_DIRS -type f -executable | while read binary; do if file "$binary" | grep -q "ELF" then @@ -108,6 +110,9 @@ in pkgs.stdenvNoCC.mkDerivation rec { fi done + runHook postInstall + '' else '' + # darwin: rust toolchain ships Mach-O binaries; no patching needed. runHook postInstall ''; diff --git a/support/zig.nix b/support/zig.nix index 4cf9e980..9763c706 100644 --- a/support/zig.nix +++ b/support/zig.nix @@ -1,27 +1,51 @@ { pkgs -, system ? "x86_64-linux" +# Default to the current build host's system so zig is fetched for the +# right architecture. Accepts either nixpkgs-style ("aarch64-darwin") or +# zig's naming ("aarch64-macos") for backward compatibility. +, system ? pkgs.stdenv.hostPlatform.system , ... }: let + # Map nixpkgs system strings to zig's release-tarball naming. + zigKey = { + "x86_64-linux" = "x86_64-linux"; + "aarch64-linux" = "aarch64-linux"; + "aarch64-darwin" = "aarch64-macos"; + "x86_64-darwin" = "x86_64-macos"; + # Pass-through for callers that already use zig-style keys. + "aarch64-macos" = "aarch64-macos"; + "x86_64-macos" = "x86_64-macos"; + }.${system} or (throw "support/zig.nix: no packaged tarball for ${system}"); + zig = { - x86_64-linux = builtins.fetchTarball { + "x86_64-linux" = builtins.fetchTarball { url = "https://ziglang.org/download/0.15.1/zig-x86_64-linux-0.15.1.tar.xz"; sha256 = "0yar24a1qjg503czwnkdipky1cfb08k0mm9c8gwv827d33df1070"; }; - aarch64-linux = builtins.fetchTarball { + "aarch64-linux" = builtins.fetchTarball { url = "https://ziglang.org/download/0.15.1/zig-aarch64-linux-0.15.1.tar.xz"; sha256 = "19vcv7a1scm4wpj5cgv3dmzajz37fdyx5x1inxfgxzsavbmvq3zy"; }; - aarch64-macos = builtins.fetchTarball { + "aarch64-macos" = builtins.fetchTarball { url = "https://ziglang.org/download/0.15.1/zig-aarch64-macos-0.15.1.tar.xz"; sha256 = "0gsvr1cl5xpqh8an97hw1zqdbsr3ymw7hvlrqykxi25kp1jc3jvf"; }; - }.${system}; + "x86_64-macos" = builtins.fetchTarball { + url = "https://ziglang.org/download/0.15.1/zig-x86_64-macos-0.15.1.tar.xz"; + # Populate on first x86_64-darwin build; nix will report the + # correct sha and the error will point to this placeholder. + sha256 = pkgs.lib.fakeSha256; + }; + }.${zigKey}; make-cc-wrapper = trg: pkgs.writeShellScript "zig-cc-${trg}" '' if [ ! -d "$HOME" ]; then - export ZIG_GLOBAL_CACHE_DIR=/build/.zig-cache - export ZIG_LOCAL_CACHE_DIR=/build/.zig-cache-local + # `/build` is the Linux nix-build scratch dir — on darwin the + # sandbox uses `/private/tmp/nix-build-*` which isn't a constant + # path. `$TMPDIR` is set reliably in every nix build on both + # platforms and is guaranteed-writable. + export ZIG_GLOBAL_CACHE_DIR="$TMPDIR/.zig-cache" + export ZIG_LOCAL_CACHE_DIR="$TMPDIR/.zig-cache-local" fi args=() for arg in "$@"; do From ad4aef3ee529097f56dfe65b2a81fcd0b1eeebc4 Mon Sep 17 00:00:00 2001 From: Edgars Date: Tue, 21 Apr 2026 18:41:15 +0100 Subject: [PATCH 2/3] fix(rust): skip zig-cc when host == target (native darwin builds) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When building aarch64-apple-darwin from an aarch64-darwin host the toolchain is native — rustc emits darwin-specific linker flags (`-Wl,-exported_symbols_list`, `-framework`, ...) that the zig-cc wrapper can't forward. Route native darwin targets straight through rustc's default cc instead; only install the zig-cc aarch64-darwin cargo env on non-darwin hosts where we're actually cross-compiling. --- support/rust.nix | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/support/rust.nix b/support/rust.nix index fd830648..e1330a25 100644 --- a/support/rust.nix +++ b/support/rust.nix @@ -116,6 +116,17 @@ in pkgs.stdenvNoCC.mkDerivation rec { runHook postInstall ''; + # zig-cc wrappers are only needed for cross-compilation. When host == + # target (e.g. aarch64-darwin → aarch64-apple-darwin) the native + # rustc + stdenv cc handles linking directly and accepts darwin- + # specific flags (`-Wl,-exported_symbols_list`, `-framework`, ...) + # that our zig-cc wrapper currently strips. Only route aarch64-darwin + # through zig-cc when we're cross-compiling to it. + darwinCrossCargoFlags = pkgs.lib.optionalString (!pkgs.stdenv.isDarwin) '' + --set CC_aarch64_apple_darwin zig-cc-arm64-macos \ + --set CARGO_TARGET_AARCH64_APPLE_DARWIN_LINKER zig-cc-arm64-macos \ + ''; + installPhase = '' mkdir -p $out for i in $(find . -type d -maxdepth 2 -mindepth 1) ; @@ -132,11 +143,9 @@ in pkgs.stdenvNoCC.mkDerivation rec { --set CC_x86_64_unknown_linux_gnu zig-cc-amd64-linux-gnu \ --set CC_aarch64_unknown_linux_musl zig-cc-arm64-linux \ --set CC_aarch64_unknown_linux_gnu zig-cc-arm64-linux-gnu \ - --set CC_aarch64_apple_darwin zig-cc-arm64-macos \ --set CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER zig-cc-amd64-linux \ --set CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER zig-cc-arm64-linux \ - --set CARGO_TARGET_AARCH64_APPLE_DARWIN_LINKER zig-cc-arm64-macos \ - --prefix LD_LIBRARY_PATH : "${pkgs.lib.makeLibraryPath buildInputs}" + ${darwinCrossCargoFlags}--prefix LD_LIBRARY_PATH : "${pkgs.lib.makeLibraryPath buildInputs}" #--set CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER zig-cc-arm64-linux-gnu \ #--set CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER zig-cc-amd64-linux-gnu \ From 67ddd0e70856eb4a7e5774d69469bb5b31b1b15a Mon Sep 17 00:00:00 2001 From: Edgars Date: Wed, 22 Apr 2026 15:59:12 +0100 Subject: [PATCH 3/3] fix: reset flake-config.json to placeholder values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The v0.2.11 release commit (b4406e5) committed flake-config.json with the patched `v0.2.11 / a605f30` values while flake-config.orig.json stayed on the canonical `vTEST / fake` placeholders. pre-commit's check-flake-config-identical hook fails on that divergence. Resetting .json to match .orig.json — release builds patch these on the fly (see genlayer-dev-env StepBuildGenVM), so the committed state should be the placeholder, not a specific release. --- flake-config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flake-config.json b/flake-config.json index b1322387..24fc795e 100644 --- a/flake-config.json +++ b/flake-config.json @@ -1,5 +1,5 @@ { - "executor-version": "v0.2.11", + "executor-version": "vTEST", "repo-url": "https://github.com/genlayerlabs/genvm.git", - "head-revision": "a605f30" + "head-revision": "fake" }