Strip foreign-architecture code from the macOS bundle (#10063) (#10064)

The macOS app is built for a single architecture (matching the build
machine, via ${ARCH}), but relocatable-python pulls the python.org
universal2 installer, so the entire Python.framework ships both arm64
and x86_64 slices. PostgreSQL-sourced dylibs may be universal too. The
foreign slice is dead weight that bloats the bundle and DMG.

Add a _strip_architecture step, run after _complete_bundle and before
code-signing (lipo invalidates signatures, so the existing sign passes
re-sign the thinned binaries). It removes the universal2 stragglers
(python*-intel64 launcher, config-*-darwin/python.o) and lipo-thins
every fat Mach-O in the bundle to the build arch, preserving file modes
and warning on anything lacking the target slice. Already single-arch
inputs (Electron and its helpers) are skipped.
This commit is contained in:
Dave Page
2026-06-12 15:57:09 +05:30
committed by GitHub
parent 255550e981
commit 922f06c7d2
3 changed files with 65 additions and 0 deletions
+1
View File
@@ -36,6 +36,7 @@ Housekeeping
| `Issue #9981 <https://github.com/pgadmin-org/pgadmin4/issues/9981>`_ - Clarify the SSH tunnel "Prompt for identity file password?" switch label and help text to indicate it applies only to identity-file authentication.
| `Issue #10018 <https://github.com/pgadmin-org/pgadmin4/issues/10018>`_ - Remove the EDB BigAnimal cloud deployment support.
| `Issue #10049 <https://github.com/pgadmin-org/pgadmin4/issues/10049>`_ - Bump vulnerable transitive dependencies (tar, flatted) to clear security advisories.
| `Issue #10063 <https://github.com/pgadmin-org/pgadmin4/issues/10063>`_ - Strip the foreign-architecture slice from the macOS bundle so single-arch builds no longer ship the universal2 Python framework's unused arm64/x86_64 code.
Bug fixes
*********
+63
View File
@@ -364,6 +364,69 @@ _complete_bundle() {
chmod -R og-w "${BUNDLE_DIR}"
}
_strip_architecture() {
# We only ship a single architecture (matching the build machine, via
# ${ARCH}), but some inputs arrive as fat/universal2 Mach-O binaries.
# In particular relocatable-python pulls the python.org *universal2*
# installer, so the entire Python.framework carries both arm64 and
# x86_64 slices; PostgreSQL-sourced dylibs (libpq, libssl, ...) may be
# universal too. Strip the foreign slice from every fat Mach-O so the
# bundle ships lean. Electron and its helpers are downloaded
# single-arch already, so the loop simply skips them.
#
# NB: lipo invalidates code signatures, so this MUST run before
# _codesign_binaries / _codesign_bundle.
# Map the build ARCH ("arm64"/"x64") to the lipo/Mach-O arch name.
local LIPO_ARCH="arm64"
if [ "${ARCH}" == "x64" ]; then
LIPO_ARCH="x86_64"
fi
echo "Stripping foreign architectures, keeping ${LIPO_ARCH}..."
# Remove arch-specific stragglers shipped by the universal2 Python
# installer: a pure-x86_64 launcher and a stray, never-executed build
# object file. Globs keep this independent of the Python version.
find "${BUNDLE_DIR}/Contents/Frameworks/Python.framework" \
-name 'python*-intel64' -type f -delete
find "${BUNDLE_DIR}/Contents/Frameworks/Python.framework" \
-path '*/config-*-darwin/python.o' -type f -delete
# Thin every fat Mach-O in the bundle in place. -type f skips symlinks,
# so versioned dylib aliases are left alone and only the real file is
# thinned once.
local f archs perms
while IFS= read -r f; do
archs=$(lipo -archs "${f}" 2>/dev/null) || continue # not Mach-O
case " ${archs} " in
*" ${LIPO_ARCH} "*) ;; # has our slice
*)
# No slice for our target arch — thinning can't help; this
# would need a rebuild from the right arch. Warn loudly.
echo "WARNING: ${f} lacks a ${LIPO_ARCH} slice (${archs}); leaving as-is" >&2
continue
;;
esac
# Already single-arch (our arch) — nothing to strip.
if [ "$(echo "${archs}" | wc -w)" -le 1 ]; then
continue
fi
echo "Thinning ${f} (${archs} -> ${LIPO_ARCH})"
# lipo writes to a separate file, which loses the original mode
# (notably the +x bit the signing pass relies on), so capture and
# restore the permissions across the swap.
perms=$(stat -f '%Lp' "${f}")
if lipo -thin "${LIPO_ARCH}" "${f}" -output "${f}.thin"; then
chmod "${perms}" "${f}.thin"
mv -f "${f}.thin" "${f}"
else
rm -f "${f}.thin"
echo "WARNING: failed to thin ${f}" >&2
fi
done < <(find "${BUNDLE_DIR}" -type f)
}
_generate_sbom() {
echo "Generating SBOM..."
syft "${BUNDLE_DIR}/Contents/" -o cyclonedx-json > "${BUNDLE_DIR}/Contents/sbom.json"
+1
View File
@@ -92,6 +92,7 @@ _build_runtime
_create_python_env
_build_docs
_complete_bundle
_strip_architecture
_generate_sbom
_codesign_binaries
_codesign_bundle