Skip to content

Commit edfc2de

Browse files
authored
Merge pull request #1761 from DeusData/feat/nix-cross-dev-shell
feat(build): add a macOS cross-architecture Nix dev shell
2 parents 34d18ae + 3308f36 commit edfc2de

1 file changed

Lines changed: 52 additions & 1 deletion

File tree

‎flake.nix‎

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,57 @@
77
let
88
systems = [ "aarch64-darwin" "x86_64-darwin" "aarch64-linux" "x86_64-linux" ];
99
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+
};
1061
in
1162
{
1263
packages = forAllSystems (pkgs: {
@@ -45,6 +96,6 @@
4596
default = pkgs.mkShell {
4697
inputsFrom = [ self.packages.${pkgs.system}.default ];
4798
};
48-
});
99+
} // crossDevShells pkgs);
49100
};
50101
}

0 commit comments

Comments
 (0)