diff --git a/.gitea/workflows/macos-probe.yaml b/.gitea/workflows/macos-probe.yaml index 221b922..d338026 100644 --- a/.gitea/workflows/macos-probe.yaml +++ b/.gitea/workflows/macos-probe.yaml @@ -25,21 +25,36 @@ jobs: NIX_CONFIG: "experimental-features = nix-command flakes" steps: - uses: actions/checkout@v4 - - name: build both darwin targets through the flake + - name: build, de-nix, sign, verify both darwin targets run: | set -e for t in aarch64-apple-darwin x86_64-apple-darwin; do echo "==================== $t ====================" nix develop -c cargo build --release --target "$t" f="target/$t/release/rdbms-playground" - file "$f" - echo "--- linked libs (otool -L) ---" - otool -L "$f" - # Portability guard: a distributable macOS binary must link only - # system libs (/usr/lib, /System/Library) — never a /nix/store path. + + # The darwin stdenv bakes a /nix/store libiconv load path into the + # binary. Rewrite it to the system libiconv (every Mac has it, ABI- + # compatible), then re-sign ad-hoc — install_name_tool invalidates + # the signature and arm64 won't run an unsigned/broken-sig binary. + for l in $(otool -L "$f" | awk '/\/nix\/store.*libiconv.*dylib/ {print $1}'); do + echo "rewrite $l -> /usr/lib/libiconv.2.dylib" + install_name_tool -change "$l" /usr/lib/libiconv.2.dylib "$f" + done + codesign --force --sign - "$f" + + echo "--- linked libs ---"; otool -L "$f" if otool -L "$f" | grep -q /nix/store; then - echo "ERROR: $t binary links a /nix/store dylib — not portable"; exit 1 + echo "ERROR: $t still links a /nix/store dylib"; exit 1 fi - echo "OK: $t links only system libraries" + codesign --verify --verbose=2 "$f" && echo "signature OK" + + # Smoke-run the natively-runnable target (this VM is arm64). + if [ "$t" = "aarch64-apple-darwin" ]; then + echo "--- run --help ---"; "$f" --help | head -1 + else + echo "(skip run: $t needs Rosetta)" + fi + echo "OK: $t portable" done - echo "=== both darwin targets built + portable ===" + echo "=== both darwin targets built, de-nixed, signed, verified ===" diff --git a/flake.nix b/flake.nix index 741fa2b..cf5b968 100644 --- a/flake.nix +++ b/flake.nix @@ -63,11 +63,12 @@ buildInputs = buildInputs ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ # macOS release builds (aarch64/x86_64-apple-darwin) link AppKit # (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. + # system-lib stubs as *system* paths (/usr/lib, /System/Library). + # NOTE: the darwin stdenv still propagates a *nix-store* libiconv and + # links it regardless of inputs, so the release workflow rewrites that + # one load path to /usr/lib/libiconv.2.dylib (install_name_tool) and + # re-signs — see release-macos / the macOS smoke-test. Adding + # `pkgs.libiconv` here would only reinforce the wrong path, so don't. pkgs.apple-sdk ]; nativeBuildInputs = nativeBuildInputs ++ [