From ed9e48fc1a87dc9af004f825d7e3d84faed3f35b Mon Sep 17 00:00:00 2001 From: Bob Date: Thu, 9 Apr 2026 16:44:56 +0000 Subject: [PATCH] fix(build): sign all Mach-O files inside ambiguous framework bundles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous temp-copy fallback for non-standard framework bundles only signed $fw/$fw_name (e.g. Python.framework/Python). However, when cp -r assembles the .app bundle in build_app_tauri.sh, it dereferences symlinks — creating three physical copies of the Python binary at: - Python.framework/Python - Python.framework/Versions/Current/Python - Python.framework/Versions/3.9/Python Apple notarytool scans all three paths independently and rejects each unsigned copy with "The signature of the binary is invalid." Fix: in the ambiguous-bundle fallback, use `find + xargs file | grep Mach-O` to enumerate all Mach-O files inside the framework, then sign each one via the temp-copy approach (outside the .framework directory context to avoid the "bundle format is ambiguous" error from codesign). --- scripts/package/build_app_tauri.sh | 32 ++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/scripts/package/build_app_tauri.sh b/scripts/package/build_app_tauri.sh index e40f34148..1464e5858 100755 --- a/scripts/package/build_app_tauri.sh +++ b/scripts/package/build_app_tauri.sh @@ -153,22 +153,32 @@ if [ -n "$APPLE_PERSONALID" ]; then --sign "$APPLE_PERSONALID" \ "$fw" 2>&1) && echo " Signed bundle: $fw" || { if echo "$sign_output" | grep -q "bundle format is ambiguous"; then - echo " Note: $fw lacks standard bundle structure; signing main binary via temp copy" - fw_name="$(basename "${fw%.*}")" - fw_binary="$fw/$fw_name" - if [ -f "$fw_binary" ]; then - # codesign refuses to sign Python.framework/Python in-place because - # it sees the parent .framework dir and reports "bundle format is - # ambiguous". Copy to a temp path outside any bundle directory, - # sign there, then copy back. Code signatures are embedded in the - # binary (not path-dependent), so the result is identical. + echo " Note: $fw has non-standard structure (PyInstaller); signing all Mach-O files inside it via temp copy" + # PyInstaller-embedded Python.framework lacks the standard Versions/ symlink + # hierarchy. When cp -r assembles the .app bundle, it dereferences symlinks, + # creating multiple physical copies of the Python binary at all three paths: + # Python.framework/Python + # Python.framework/Versions/Current/Python + # Python.framework/Versions/3.9/Python + # codesign refuses to sign any of them in-place due to the ambiguous + # framework directory context. Signing only $fw/$fw_name (the top-level + # copy) leaves the Versions/ copies unsigned, and Apple notarytool rejects + # all three paths independently. + # Fix: find all Mach-O files inside the framework and sign each via a temp + # path outside any .framework directory. Signatures are embedded in the + # Mach-O binary (not path-dependent), so the signed binary is valid at + # its original location. + found=0 + while IFS= read -r fw_binary; do + found=1 tmp_binary=$(mktemp) cp "$fw_binary" "$tmp_binary" sign_binary "$tmp_binary" cp "$tmp_binary" "$fw_binary" rm -f "$tmp_binary" - else - echo "ERROR: Expected main binary not found at $fw_binary" >&2 + done < <(find "$fw" -type f | xargs file | grep "Mach-O" | cut -d: -f1) + if [ "$found" -eq 0 ]; then + echo "ERROR: No Mach-O binaries found inside $fw" >&2 echo " PyInstaller may have changed its output structure. Inspect $fw" >&2 exit 1 fi