ci: de-nix macOS binary libiconv via install_name_tool + re-sign
libiconv is the only /nix/store dep the darwin stdenv bakes in (everything else is system frameworks + libSystem/libobjc). The smoke-test now rewrites that load path to /usr/lib/libiconv.2.dylib (ABI-compatible, present on every Mac), re-signs ad-hoc (install_name_tool breaks the sig; arm64 requires a valid one), then verifies no /nix/store paths remain, the signature is valid, and the native binary launches. Flake comment updated to reflect the propagated-libiconv reality.
This commit is contained in:
@@ -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.
|
||||
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"
|
||||
|
||||
# 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
|
||||
echo "=== both darwin targets built + portable ==="
|
||||
codesign --force --sign - "$f"
|
||||
|
||||
echo "--- linked libs ---"; otool -L "$f"
|
||||
if otool -L "$f" | grep -q /nix/store; then
|
||||
echo "ERROR: $t still links a /nix/store dylib"; exit 1
|
||||
fi
|
||||
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, de-nixed, signed, verified ==="
|
||||
|
||||
@@ -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 ++ [
|
||||
|
||||
Reference in New Issue
Block a user