macOS script to build the universal app bundle.
1. Build TuxPaint.app on Intel macOS, rename it TuxPaint-x86_64.app.
2. Build TuxPaint.app on Apple Silicon macOS, rename it TuxPaint-arm64.app.
3. Copy TuxPaint-x86_64.app to the same directory as TuxPaint-arm64.app
on the Apple Silicon macOS, then run:
macos/build-universal.sh TuxPaint-x86_64.app TuxPaint-arm64.app
... to produce TuxPaint.app that's universal.
4. `make TuxPaint.dmg` to produce TuxPaint.dmg from the universal
TuxPaint.app.
This commit is contained in:
parent
c239e849cb
commit
e5faf36d5d
1 changed files with 142 additions and 0 deletions
142
macos/build-universal.sh
Executable file
142
macos/build-universal.sh
Executable file
|
|
@ -0,0 +1,142 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
function usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Build a macOS universal application bundle from one or more application
|
||||||
|
bundles.
|
||||||
|
|
||||||
|
Usage: ${SCRIPTNAME} [OPTIONS] TuxPaint-1.app TuxPaint-2.app ...
|
||||||
|
|
||||||
|
TuxPaint-N.app Bundle(s) to read. If no bundles are specified, the
|
||||||
|
following files are read:
|
||||||
|
$(
|
||||||
|
for bundle in "${BUNDLES[@]}"; do
|
||||||
|
printf "\n%26s%s" "" "$bundle"
|
||||||
|
done
|
||||||
|
)
|
||||||
|
|
||||||
|
-o OUTBUNDLE Bundle to create. [Default=${OUTBUNDLE}]
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# CONFIG
|
||||||
|
|
||||||
|
ARCHS=( arm64 x86_64 )
|
||||||
|
BUNDLES=( $(printf "TuxPaint-%s.app\n" "${ARCHS[@]}") )
|
||||||
|
OUTBUNDLE=TuxPaint.app
|
||||||
|
FORCE=0
|
||||||
|
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# PROGRAM BEGINS HERE
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
local OPTIND OPTARG OPTERR opt
|
||||||
|
local bundle
|
||||||
|
local isok=1
|
||||||
|
|
||||||
|
# Process arguments
|
||||||
|
while getopts "fo:h" opt; do
|
||||||
|
case "$opt" in
|
||||||
|
f) FORCE=1 ;;
|
||||||
|
o) OUTBUNDLE=$OPTARG ;;
|
||||||
|
h) usage && exit 0 ;;
|
||||||
|
*) isok=0
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
shift $((OPTIND-1))
|
||||||
|
|
||||||
|
# Use the specified bundles
|
||||||
|
if (( $# )); then
|
||||||
|
BUNDLES=( "$@" )
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Sanity check
|
||||||
|
if (( ! isok )); then
|
||||||
|
usage 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Status
|
||||||
|
echo " * Creating universal app bundle $OUTBUNDLE by combining ${BUNDLES[*]}..."
|
||||||
|
|
||||||
|
# Validate input
|
||||||
|
for bundle in "${BUNDLES[@]}"; do
|
||||||
|
if ! [[ -d "$bundle" ]]; then
|
||||||
|
printf " -> FAILED: No such input bundle named %s exists\n" "$bundle" 1>&2
|
||||||
|
isok=0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
(( isok)) || exit 1
|
||||||
|
|
||||||
|
# Validate output
|
||||||
|
if [[ -d "$OUTBUNDLE" ]] && (( FORCE )); then
|
||||||
|
printf " -> Deleting %s...\n" "$OUTBUNDLE"
|
||||||
|
rm -rf "$OUTBUNDLE" || exitcode=1
|
||||||
|
elif [[ -d "$OUTBUNDLE" ]]; then
|
||||||
|
printf " -> FAILED: Output bundled named %s already exists, use -f option to recreate.\n" "$OUTBUNDLE" 1>&2
|
||||||
|
isok=0
|
||||||
|
fi
|
||||||
|
(( isok )) || exit 1
|
||||||
|
|
||||||
|
build-universal
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function build-universal() {
|
||||||
|
local isok=1
|
||||||
|
local i j
|
||||||
|
|
||||||
|
# Create the base package without binaries or libraries
|
||||||
|
echo " -> Create skeleton app bundle ${OUTBUNDLE}..." \
|
||||||
|
&& cp -a "${BUNDLES[0]}" "$OUTBUNDLE" \
|
||||||
|
&& rm -f "${OUTBUNDLE}/Contents/MacOS"/* \
|
||||||
|
&& find "$OUTBUNDLE" -name '*.dylib' -print0 | xargs -0 rm -f \
|
||||||
|
|| return 1
|
||||||
|
|
||||||
|
# Create the universal binary for each binary and library
|
||||||
|
for (( i=0; i < ${#BUNDLES[@]}; i++ )); do
|
||||||
|
local filelist=()
|
||||||
|
local file
|
||||||
|
|
||||||
|
# Binaries
|
||||||
|
for file in "${BUNDLES[i]}/Contents/MacOS"/*; do
|
||||||
|
filelist+=( "${file#${BUNDLES[i]}/}" )
|
||||||
|
done
|
||||||
|
|
||||||
|
# Dynamic Libraries
|
||||||
|
while IFS= read -r file; do
|
||||||
|
filelist+=( "${file#${BUNDLES[i]}/}" )
|
||||||
|
done < <(find "${BUNDLES[i]}" -name '*.dylib')
|
||||||
|
|
||||||
|
# Build each as universal
|
||||||
|
for file in "${filelist[@]}"; do
|
||||||
|
local instances=()
|
||||||
|
|
||||||
|
# Skip if already built
|
||||||
|
[[ -e "${OUTBUNDLE}/${file}" ]] && continue
|
||||||
|
|
||||||
|
# Get this file's instances in all bundles
|
||||||
|
for (( j=i; j < ${#BUNDLES[@]}; j++ )); do
|
||||||
|
if [[ -e "${BUNDLES[j]}/${file}" ]]; then
|
||||||
|
instances+=( "${BUNDLES[j]}/${file}" )
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Build into $OUTBUNDLE
|
||||||
|
echo " -> Combine ${file}..."
|
||||||
|
lipo -create -output "${OUTBUNDLE}/${file}" "${instances[@]}" || isok=0
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
(( isok ))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# ENTRY POINT
|
||||||
|
|
||||||
|
main "$@"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue