|
7 | 7 | let |
8 | 8 | systems = [ "aarch64-darwin" "x86_64-darwin" "aarch64-linux" "x86_64-linux" ]; |
9 | 9 | forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f nixpkgs.legacyPackages.${system}); |
| 10 | + |
| 11 | + # Cross dev shell (macOS only): build the *other* darwin arch locally. |
| 12 | + # The native clang already cross-emits object code via -arch (scripts/env.sh |
| 13 | + # exports ARCHFLAGS), so the only thing missing for a cross link is zlib: |
| 14 | + # it is the product's single link-time dependency (`-lz`), and the host-arch |
| 15 | + # copy cannot satisfy an x86_64 link on arm64 or vice versa. This shell puts |
| 16 | + # the TARGET-arch zlib on the include and link paths, and nothing else. |
| 17 | + # |
| 18 | + # Building needs no Rosetta; *running* an x86_64 binary on Apple Silicon |
| 19 | + # does. The target-arch libs come from prebuilt substitutes, so entering the |
| 20 | + # shell is a download rather than a cross-build of the dependency tree. |
| 21 | + # |
| 22 | + # Returns {} off macOS, where there is no second darwin arch to target. |
| 23 | + crossDevShells = pkgs: |
| 24 | + let |
| 25 | + inherit (nixpkgs) lib; |
| 26 | + crossTarget = |
| 27 | + { |
| 28 | + "aarch64-darwin" = "x86_64-darwin"; |
| 29 | + "x86_64-darwin" = "aarch64-darwin"; |
| 30 | + } |
| 31 | + .${pkgs.system} or null; |
| 32 | + mkCrossShell = |
| 33 | + targetSystem: |
| 34 | + let |
| 35 | + tpkgs = nixpkgs.legacyPackages.${targetSystem}; |
| 36 | + targetArch = if targetSystem == "x86_64-darwin" then "x86_64" else "arm64"; |
| 37 | + in |
| 38 | + pkgs.mkShell { |
| 39 | + # Host toolchain only — clang comes from the shell stdenv. Deliberately |
| 40 | + # NOT inputsFrom the default package: that would put the HOST-arch zlib |
| 41 | + # on the link path, which is exactly the wrong-arch copy this shell |
| 42 | + # exists to displace. |
| 43 | + nativeBuildInputs = [ pkgs.gnumake ]; |
| 44 | + shellHook = '' |
| 45 | + # zlib is consumed as a bare `-lz` / `#include <zlib.h>`, so its |
| 46 | + # include dir (the header is arch-independent) and lib dir are |
| 47 | + # supplied by hand. NIX_LDFLAGS is searched ahead of the link's own |
| 48 | + # -L, so the target-arch slice wins; a host-arch copy that still |
| 49 | + # reaches ld is skipped as "wrong architecture" rather than |
| 50 | + # producing a silently mislinked binary. |
| 51 | + export NIX_CFLAGS_COMPILE="-I${lib.getDev tpkgs.zlib}/include ''${NIX_CFLAGS_COMPILE:-}" |
| 52 | + export NIX_LDFLAGS="-L${lib.getLib tpkgs.zlib}/lib ''${NIX_LDFLAGS:-}" |
| 53 | + echo "[cross] target ${targetSystem} — build with: scripts/build.sh --arch ${targetArch}" |
| 54 | + ''; |
| 55 | + }; |
| 56 | + in |
| 57 | + lib.optionalAttrs (crossTarget != null) { |
| 58 | + # `nix develop .#cross` then `scripts/build.sh --arch <target>`. |
| 59 | + cross = mkCrossShell crossTarget; |
| 60 | + }; |
10 | 61 | in |
11 | 62 | { |
12 | 63 | packages = forAllSystems (pkgs: { |
|
45 | 96 | default = pkgs.mkShell { |
46 | 97 | inputsFrom = [ self.packages.${pkgs.system}.default ]; |
47 | 98 | }; |
48 | | - }); |
| 99 | + } // crossDevShells pkgs); |
49 | 100 | }; |
50 | 101 | } |
0 commit comments