diff --git a/.gitea/workflows/macos-probe.yaml b/.gitea/workflows/macos-probe.yaml index 58d31bd..221b922 100644 --- a/.gitea/workflows/macos-probe.yaml +++ b/.gitea/workflows/macos-probe.yaml @@ -34,6 +34,12 @@ jobs: f="target/$t/release/rdbms-playground" file "$f" echo "--- linked libs (otool -L) ---" - otool -L "$f" 2>/dev/null | head -8 || true + otool -L "$f" + # Portability guard: a distributable macOS binary must link only + # system libs (/usr/lib, /System/Library) — never a /nix/store path. + if otool -L "$f" | grep -q /nix/store; then + echo "ERROR: $t binary links a /nix/store dylib — not portable"; exit 1 + fi + echo "OK: $t links only system libraries" done - echo "=== both darwin targets built ===" + echo "=== both darwin targets built + portable ===" diff --git a/flake.nix b/flake.nix index c0b5bb6..741fa2b 100644 --- a/flake.nix +++ b/flake.nix @@ -62,12 +62,13 @@ devShells.default = pkgs.mkShell { buildInputs = buildInputs ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ # macOS release builds (aarch64/x86_64-apple-darwin) link AppKit - # (arboard) + libSystem; the nix toolchain's own clang resolves the - # frameworks via the Apple SDK provided here. (The Mac runner also - # has full Xcode, but the devShell stays self-contained.) `libiconv` - # is linked by several crates on darwin. + # (arboard) + libSystem; the Apple SDK provides those framework/ + # system-lib stubs as *system* paths (/usr/lib, /System/Library), so + # the resulting binary is portable. NOTE: do NOT add `pkgs.libiconv` + # — it makes the linker prefer the nix-store libiconv.dylib, baking a + # /nix/store path into the binary (non-portable). The SDK's own + # libiconv stub resolves `-liconv` to /usr/lib/libiconv instead. pkgs.apple-sdk - pkgs.libiconv ]; nativeBuildInputs = nativeBuildInputs ++ [ rust