Some checks failed
Build / Build openSUSE (leap:15.6) (push) Has been cancelled
Build / Build openSUSE (leap:16.0) (push) Has been cancelled
Build / Build openSUSE (tumbleweed) (push) Has been cancelled
Build / Build Fedora (42) (push) Has been cancelled
Build / Build Fedora (43) (push) Has been cancelled
Build / Build Fedora (44) (push) Has been cancelled
Build / Build OpenMandriva (cooker) (push) Has been cancelled
Build / Build Mageia (9) (push) Has been cancelled
Build / Build Debian (bookworm) (push) Has been cancelled
Build / Build Debian (forky) (push) Has been cancelled
Build / Build Debian (trixie) (push) Has been cancelled
Build / Build Ubuntu (noble) (push) Has been cancelled
Build / Build Ubuntu (questing) (push) Has been cancelled
Build / Build Ubuntu (resolute) (push) Has been cancelled
Build / Upload Ubuntu PPA (noble) (push) Has been cancelled
Build / Upload Ubuntu PPA (questing) (push) Has been cancelled
Build / Upload Ubuntu PPA (resolute) (push) Has been cancelled
Build / Build FreeBSD (push) Has been cancelled
Build / Build OpenBSD (push) Has been cancelled
Build / Build macOS Public (release, macos-15) (push) Has been cancelled
Build / Build macOS Public (release, macos-15-intel) (push) Has been cancelled
Build / Build macOS Private (release, macos-arm64) (push) Has been cancelled
Build / Build Windows MinGW (i686, debug) (push) Has been cancelled
Build / Build Windows MinGW (i686, release) (push) Has been cancelled
Build / Build Windows MinGW (x86_64, debug) (push) Has been cancelled
Build / Build Windows MinGW (x86_64, release) (push) Has been cancelled
Build / Build Windows MSVC (arm64, debug, arm64 debug, windows-11-arm) (push) Has been cancelled
Build / Build Windows MSVC (arm64, release, arm64 release, windows-11-arm) (push) Has been cancelled
Build / Build Windows MSVC (x86, debug, x86 debug, windows-2022) (push) Has been cancelled
Build / Build Windows MSVC (x86, release, x86 release, windows-2022) (push) Has been cancelled
Build / Build Windows MSVC (x86_64, debug, x86_64 debug, windows-2022) (push) Has been cancelled
Build / Build Windows MSVC (x86_64, release, x86_64 release, windows-2022) (push) Has been cancelled
Build / Upload (push) Has been cancelled
Build / Attach to release (push) Has been cancelled
This commit enhances the `README_MAS.md` by providing detailed information on the differences between arm64-only, universal, and x86_64-only app architectures for Mac App Store uploads. It includes recommendations for achieving broad compatibility and clarifies the limitations of submitting multiple builds. This update aims to assist developers in making informed decisions regarding app architecture for their submissions.
171 lines
4.8 KiB
Bash
171 lines
4.8 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# Create a universal (arm64+x86_64) .app by merging two already-deployed app bundles
|
|
# that have identical layouts, one built on Apple Silicon and one built on Intel.
|
|
#
|
|
# Usage:
|
|
# ./build_tools/macos/make_universal_app.sh \
|
|
# --arm-app /path/to/arm64/strawberry.app \
|
|
# --x86-app /path/to/x86_64/strawberry.app \
|
|
# --out-app /path/to/output/strawberry.app \
|
|
# [--clean]
|
|
#
|
|
# Notes:
|
|
# - Do NOT sign the per-arch apps first; signatures will be invalidated by lipo anyway.
|
|
# - Both inputs must be the same app version/config with the same enabled features,
|
|
# so the file lists match.
|
|
|
|
ts() { date +"%H:%M:%S"; }
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage:
|
|
./build_tools/macos/make_universal_app.sh --arm-app <path> --x86-app <path> --out-app <path> [--clean]
|
|
|
|
What it does:
|
|
- Copies the arm64 app to --out-app
|
|
- For every Mach-O file in the copied app, finds the corresponding file in the x86_64 app
|
|
- Uses lipo to combine the two slices into a universal binary at the same relative path
|
|
|
|
Required:
|
|
--arm-app <path> Path to arm64 Strawberry.app (built+deployed on Apple Silicon)
|
|
--x86-app <path> Path to x86_64 Strawberry.app (built+deployed on Intel)
|
|
--out-app <path> Output path for universal Strawberry.app
|
|
|
|
Optional:
|
|
--clean Delete --out-app if it already exists
|
|
EOF
|
|
}
|
|
|
|
if [[ "$(uname -s)" != "Darwin" ]]; then
|
|
echo "Error: This script is for macOS only." >&2
|
|
exit 1
|
|
fi
|
|
|
|
arm_app=""
|
|
x86_app=""
|
|
out_app=""
|
|
do_clean=0
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--arm-app) arm_app="${2:-}"; shift 2 ;;
|
|
--x86-app) x86_app="${2:-}"; shift 2 ;;
|
|
--out-app) out_app="${2:-}"; shift 2 ;;
|
|
--clean) do_clean=1; shift ;;
|
|
-h|--help) usage; exit 0 ;;
|
|
*) echo "Unknown arg: $1" >&2; usage; exit 2 ;;
|
|
esac
|
|
done
|
|
|
|
if [[ -z "$arm_app" || -z "$x86_app" || -z "$out_app" ]]; then
|
|
echo "Error: missing required args." >&2
|
|
usage
|
|
exit 2
|
|
fi
|
|
if [[ ! -d "$arm_app" ]]; then
|
|
echo "Error: --arm-app not found: $arm_app" >&2
|
|
exit 2
|
|
fi
|
|
if [[ ! -d "$x86_app" ]]; then
|
|
echo "Error: --x86-app not found: $x86_app" >&2
|
|
exit 2
|
|
fi
|
|
|
|
for cmd in /usr/bin/file /usr/bin/lipo /usr/bin/ditto; do
|
|
if [[ ! -x "$cmd" ]]; then
|
|
echo "Error: required tool not found: $cmd" >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
out_parent="$(cd -- "$(dirname -- "$out_app")" && pwd)"
|
|
out_name="$(basename -- "$out_app")"
|
|
out_app="${out_parent}/${out_name}"
|
|
|
|
if [[ -e "$out_app" && "$do_clean" -eq 1 ]]; then
|
|
echo "==> [$(ts)] Removing existing output app: $out_app"
|
|
rm -rf "$out_app"
|
|
fi
|
|
if [[ -e "$out_app" ]]; then
|
|
echo "Error: output already exists: $out_app (use --clean to overwrite)" >&2
|
|
exit 2
|
|
fi
|
|
|
|
echo "==> [$(ts)] Copying arm64 app to output"
|
|
/usr/bin/ditto "$arm_app" "$out_app"
|
|
|
|
# Remove any existing signatures in the copied app; we'll re-sign after creating universal binaries.
|
|
echo "==> [$(ts)] Removing existing code signature metadata (will be re-signed later)"
|
|
find "$out_app" -type d -name "_CodeSignature" -print0 2>/dev/null | while IFS= read -r -d '' d; do
|
|
rm -rf "$d" || true
|
|
done
|
|
|
|
echo "==> [$(ts)] Merging Mach-O files with lipo"
|
|
|
|
merged=0
|
|
skipped=0
|
|
|
|
# Traverse output app and lipo-merge any Mach-O file with its counterpart in the x86 app.
|
|
while IFS= read -r -d '' f; do
|
|
# Only operate on regular files.
|
|
if [[ ! -f "$f" ]]; then
|
|
continue
|
|
fi
|
|
|
|
ft="$(/usr/bin/file -b "$f" 2>/dev/null || true)"
|
|
if [[ "$ft" != *"Mach-O"* ]]; then
|
|
skipped=$((skipped + 1))
|
|
continue
|
|
fi
|
|
|
|
rel="${f#"$out_app"/}"
|
|
other="${x86_app}/${rel}"
|
|
if [[ ! -f "$other" ]]; then
|
|
echo "Error: missing matching file in x86 app for:" >&2
|
|
echo " $rel" >&2
|
|
echo "Expected at:" >&2
|
|
echo " $other" >&2
|
|
exit 1
|
|
fi
|
|
|
|
other_ft="$(/usr/bin/file -b "$other" 2>/dev/null || true)"
|
|
if [[ "$other_ft" != *"Mach-O"* ]]; then
|
|
echo "Error: file is Mach-O in arm app but not Mach-O in x86 app:" >&2
|
|
echo " $rel" >&2
|
|
echo "arm64: $ft" >&2
|
|
echo "x86_64: $other_ft" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Validate architectures.
|
|
arm_archs="$(/usr/bin/lipo -archs "$f" 2>/dev/null || true)"
|
|
x86_archs="$(/usr/bin/lipo -archs "$other" 2>/dev/null || true)"
|
|
if [[ "$arm_archs" != *"arm64"* ]]; then
|
|
echo "Error: expected arm64 slice in arm app file:" >&2
|
|
echo " $rel" >&2
|
|
echo " archs: $arm_archs" >&2
|
|
exit 1
|
|
fi
|
|
if [[ "$x86_archs" != *"x86_64"* ]]; then
|
|
echo "Error: expected x86_64 slice in x86 app file:" >&2
|
|
echo " $rel" >&2
|
|
echo " archs: $x86_archs" >&2
|
|
exit 1
|
|
fi
|
|
|
|
tmp="$(mktemp -t strawberry-universal.XXXXXX)"
|
|
/usr/bin/lipo -create "$f" "$other" -output "$tmp"
|
|
chmod --reference="$f" "$tmp" 2>/dev/null || true
|
|
mv -f "$tmp" "$f"
|
|
merged=$((merged + 1))
|
|
done < <(find "$out_app" -type f -print0 2>/dev/null)
|
|
|
|
echo "==> [$(ts)] Done"
|
|
echo "Merged Mach-O files: $merged"
|
|
echo "Non-Mach-O files skipped: $skipped"
|
|
echo "Output app:"
|
|
echo " $out_app"
|
|
|