Package macOS releases as a universal binary.
* Minimum macOS version is raised to 10.11. * App bundles ship 3 versions of the runtime and engine binaries, and a fat launcher that selects the appropriate runtime/apphost. * Mono is used for macOS 10.11 - 10.14, or if OPENRA_PREFER_MONO environment variable has been set.
This commit is contained in:
@@ -21,8 +21,10 @@ if [[ "${OSTYPE}" != "darwin"* ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $# -ne "4" ]; then
|
||||
echo "Usage: $(basename "$0") tag outputdir platform dmg"
|
||||
command -v clang >/dev/null 2>&1 || { echo >&2 "macOS packaging requires clang."; exit 1; }
|
||||
|
||||
if [ $# -ne "2" ]; then
|
||||
echo "Usage: $(basename "$0") tag outputdir"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -45,6 +47,7 @@ fi
|
||||
|
||||
TAG="${1}"
|
||||
OUTPUTDIR="${2}"
|
||||
|
||||
SRCDIR="$(pwd)/../.."
|
||||
BUILTDIR="$(pwd)/build"
|
||||
ARTWORK_DIR="$(pwd)/../artwork/"
|
||||
@@ -55,15 +58,13 @@ modify_plist() {
|
||||
|
||||
# Copies the game files and sets metadata
|
||||
build_app() {
|
||||
PLATFORM="${1}"
|
||||
TEMPLATE_DIR="${2}"
|
||||
LAUNCHER_DIR="${3}"
|
||||
MOD_ID="${4}"
|
||||
MOD_NAME="${5}"
|
||||
DISCORD_APPID="${6}"
|
||||
TEMPLATE_DIR="${1}"
|
||||
LAUNCHER_DIR="${2}"
|
||||
MOD_ID="${3}"
|
||||
MOD_NAME="${4}"
|
||||
DISCORD_APPID="${5}"
|
||||
|
||||
LAUNCHER_CONTENTS_DIR="${LAUNCHER_DIR}/Contents"
|
||||
LAUNCHER_ASSEMBLY_DIR="${LAUNCHER_CONTENTS_DIR}/MacOS"
|
||||
LAUNCHER_RESOURCES_DIR="${LAUNCHER_CONTENTS_DIR}/Resources"
|
||||
|
||||
cp -r "${TEMPLATE_DIR}" "${LAUNCHER_DIR}"
|
||||
@@ -74,12 +75,10 @@ build_app() {
|
||||
fi
|
||||
|
||||
# Install engine and mod files
|
||||
RUNTIME="net6"
|
||||
if [ "${PLATFORM}" = "mono" ]; then
|
||||
RUNTIME="mono"
|
||||
fi
|
||||
install_assemblies "${SRCDIR}" "${LAUNCHER_CONTENTS_DIR}/MacOS/x86_64" "osx-x64" "net6" "True" "True" "${IS_D2K}"
|
||||
install_assemblies "${SRCDIR}" "${LAUNCHER_CONTENTS_DIR}/MacOS/arm64" "osx-arm64" "net6" "True" "True" "${IS_D2K}"
|
||||
install_assemblies "${SRCDIR}" "${LAUNCHER_CONTENTS_DIR}/MacOS/mono" "osx-x64" "mono" "True" "True" "${IS_D2K}"
|
||||
|
||||
install_assemblies "${SRCDIR}" "${LAUNCHER_ASSEMBLY_DIR}" "osx-x64" "${RUNTIME}" "True" "True" "${IS_D2K}"
|
||||
install_data "${SRCDIR}" "${LAUNCHER_RESOURCES_DIR}" "${MOD_ID}"
|
||||
set_engine_version "${TAG}" "${LAUNCHER_RESOURCES_DIR}"
|
||||
set_mod_version "${TAG}" "${LAUNCHER_RESOURCES_DIR}/mods/${MOD_ID}/mod.yaml" "${LAUNCHER_RESOURCES_DIR}/mods/modcontent/mod.yaml"
|
||||
@@ -110,82 +109,101 @@ build_app() {
|
||||
fi
|
||||
}
|
||||
|
||||
build_platform() {
|
||||
PLATFORM="${1}"
|
||||
DMG_PATH="${2}"
|
||||
echo "Building launchers (${PLATFORM})"
|
||||
echo "Building launchers"
|
||||
|
||||
# Prepare generic template for the mods to duplicate and customize
|
||||
TEMPLATE_DIR="${BUILTDIR}/template.app"
|
||||
mkdir -p "${TEMPLATE_DIR}/Contents/Resources"
|
||||
mkdir -p "${TEMPLATE_DIR}/Contents/MacOS"
|
||||
echo "APPL????" > "${TEMPLATE_DIR}/Contents/PkgInfo"
|
||||
cp Info.plist.in "${TEMPLATE_DIR}/Contents/Info.plist"
|
||||
modify_plist "{DEV_VERSION}" "${TAG}" "${TEMPLATE_DIR}/Contents/Info.plist"
|
||||
modify_plist "{FAQ_URL}" "http://wiki.openra.net/FAQ" "${TEMPLATE_DIR}/Contents/Info.plist"
|
||||
# Prepare generic template for the mods to duplicate and customize
|
||||
TEMPLATE_DIR="${BUILTDIR}/template.app"
|
||||
mkdir -p "${TEMPLATE_DIR}/Contents/Resources"
|
||||
mkdir -p "${TEMPLATE_DIR}/Contents/MacOS/mono"
|
||||
mkdir -p "${TEMPLATE_DIR}/Contents/MacOS/x86_64"
|
||||
mkdir -p "${TEMPLATE_DIR}/Contents/MacOS/arm64"
|
||||
|
||||
if [ "${PLATFORM}" = "mono" ]; then
|
||||
modify_plist "{MINIMUM_SYSTEM_VERSION}" "10.9" "${TEMPLATE_DIR}/Contents/Info.plist"
|
||||
clang -m64 launcher-mono.m -o "${TEMPLATE_DIR}/Contents/MacOS/Launcher" -framework AppKit -mmacosx-version-min=10.9
|
||||
else
|
||||
modify_plist "{MINIMUM_SYSTEM_VERSION}" "10.14" "${TEMPLATE_DIR}/Contents/Info.plist"
|
||||
clang -m64 launcher.m -o "${TEMPLATE_DIR}/Contents/MacOS/Launcher" -framework AppKit -mmacosx-version-min=10.14
|
||||
fi
|
||||
echo "APPL????" > "${TEMPLATE_DIR}/Contents/PkgInfo"
|
||||
cp Info.plist.in "${TEMPLATE_DIR}/Contents/Info.plist"
|
||||
modify_plist "{DEV_VERSION}" "${TAG}" "${TEMPLATE_DIR}/Contents/Info.plist"
|
||||
modify_plist "{FAQ_URL}" "http://wiki.openra.net/FAQ" "${TEMPLATE_DIR}/Contents/Info.plist"
|
||||
modify_plist "{MINIMUM_SYSTEM_VERSION}" "10.11" "${TEMPLATE_DIR}/Contents/Info.plist"
|
||||
|
||||
build_app "${PLATFORM}" "${TEMPLATE_DIR}" "${BUILTDIR}/OpenRA - Red Alert.app" "ra" "Red Alert" "699222659766026240"
|
||||
build_app "${PLATFORM}" "${TEMPLATE_DIR}" "${BUILTDIR}/OpenRA - Tiberian Dawn.app" "cnc" "Tiberian Dawn" "699223250181292033"
|
||||
build_app "${PLATFORM}" "${TEMPLATE_DIR}" "${BUILTDIR}/OpenRA - Dune 2000.app" "d2k" "Dune 2000" "712711732770111550"
|
||||
# Compile universal (x86_64 + arm64) Launcher and arch-specific apphosts
|
||||
clang apphost.c -o "${TEMPLATE_DIR}/Contents/MacOS/apphost-x86_64" -framework AppKit -target x86_64-apple-macos10.15
|
||||
clang apphost.c -o "${TEMPLATE_DIR}/Contents/MacOS/apphost-arm64" -framework AppKit -target arm64-apple-macos10.15
|
||||
clang apphost-mono.c -o "${TEMPLATE_DIR}/Contents/MacOS/apphost-mono" -framework AppKit -target x86_64-apple-macos10.11
|
||||
clang checkmono.c -o "${TEMPLATE_DIR}/Contents/MacOS/checkmono" -framework AppKit -target x86_64-apple-macos10.11
|
||||
clang launcher.m -o "${TEMPLATE_DIR}/Contents/MacOS/Launcher-x86_64" -framework AppKit -target x86_64-apple-macos10.11
|
||||
clang launcher.m -o "${TEMPLATE_DIR}/Contents/MacOS/Launcher-arm64" -framework AppKit -target arm64-apple-macos10.15
|
||||
lipo -create -output "${TEMPLATE_DIR}/Contents/MacOS/Launcher" "${TEMPLATE_DIR}/Contents/MacOS/Launcher-x86_64" "${TEMPLATE_DIR}/Contents/MacOS/Launcher-arm64"
|
||||
rm "${TEMPLATE_DIR}/Contents/MacOS/Launcher-x86_64" "${TEMPLATE_DIR}/Contents/MacOS/Launcher-arm64"
|
||||
|
||||
rm -rf "${TEMPLATE_DIR}"
|
||||
build_app "${TEMPLATE_DIR}" "${BUILTDIR}/OpenRA - Red Alert.app" "ra" "Red Alert" "699222659766026240"
|
||||
build_app "${TEMPLATE_DIR}" "${BUILTDIR}/OpenRA - Tiberian Dawn.app" "cnc" "Tiberian Dawn" "699223250181292033"
|
||||
build_app "${TEMPLATE_DIR}" "${BUILTDIR}/OpenRA - Dune 2000.app" "d2k" "Dune 2000" "712711732770111550"
|
||||
|
||||
echo "Packaging disk image"
|
||||
hdiutil create "${DMG_PATH}" -format UDRW -volname "OpenRA" -fs HFS+ -srcfolder build
|
||||
DMG_DEVICE=$(hdiutil attach -readwrite -noverify -noautoopen "${DMG_PATH}" | egrep '^/dev/' | sed 1q | awk '{print $1}')
|
||||
sleep 2
|
||||
rm -rf "${TEMPLATE_DIR}"
|
||||
|
||||
# Background image is created from source svg in artsrc repository
|
||||
mkdir "/Volumes/OpenRA/.background/"
|
||||
tiffutil -cathidpicheck "${ARTWORK_DIR}/macos-background.png" "${ARTWORK_DIR}/macos-background-2x.png" -out "/Volumes/OpenRA/.background/background.tiff"
|
||||
echo "Packaging disk image"
|
||||
hdiutil create "build.dmg" -format UDRW -volname "OpenRA" -fs HFS+ -srcfolder build
|
||||
DMG_DEVICE=$(hdiutil attach -readwrite -noverify -noautoopen "build.dmg" | egrep '^/dev/' | sed 1q | awk '{print $1}')
|
||||
sleep 2
|
||||
|
||||
cp "${BUILTDIR}/OpenRA - Red Alert.app/Contents/Resources/ra.icns" "/Volumes/OpenRA/.VolumeIcon.icns"
|
||||
# Background image is created from source svg in artsrc repository
|
||||
mkdir "/Volumes/OpenRA/.background/"
|
||||
tiffutil -cathidpicheck "${ARTWORK_DIR}/macos-background.png" "${ARTWORK_DIR}/macos-background-2x.png" -out "/Volumes/OpenRA/.background/background.tiff"
|
||||
|
||||
echo '
|
||||
tell application "Finder"
|
||||
tell disk "'OpenRA'"
|
||||
open
|
||||
set current view of container window to icon view
|
||||
set toolbar visible of container window to false
|
||||
set statusbar visible of container window to false
|
||||
set the bounds of container window to {400, 100, 1040, 580}
|
||||
set theViewOptions to the icon view options of container window
|
||||
set arrangement of theViewOptions to not arranged
|
||||
set icon size of theViewOptions to 72
|
||||
set background picture of theViewOptions to file ".background:background.tiff"
|
||||
make new alias file at container window to POSIX file "/Applications" with properties {name:"Applications"}
|
||||
set position of item "'OpenRA - Tiberian Dawn.app'" of container window to {160, 106}
|
||||
set position of item "'OpenRA - Red Alert.app'" of container window to {320, 106}
|
||||
set position of item "'OpenRA - Dune 2000.app'" of container window to {480, 106}
|
||||
set position of item "Applications" of container window to {320, 298}
|
||||
set position of item ".background" of container window to {160, 298}
|
||||
set position of item ".fseventsd" of container window to {160, 298}
|
||||
set position of item ".VolumeIcon.icns" of container window to {160, 298}
|
||||
update without registering applications
|
||||
delay 5
|
||||
close
|
||||
end tell
|
||||
end tell
|
||||
' | osascript
|
||||
cp "${BUILTDIR}/OpenRA - Red Alert.app/Contents/Resources/ra.icns" "/Volumes/OpenRA/.VolumeIcon.icns"
|
||||
|
||||
# HACK: Copy the volume icon again - something in the previous step seems to delete it...?
|
||||
cp "${BUILTDIR}/OpenRA - Red Alert.app/Contents/Resources/ra.icns" "/Volumes/OpenRA/.VolumeIcon.icns"
|
||||
SetFile -c icnC "/Volumes/OpenRA/.VolumeIcon.icns"
|
||||
SetFile -a C "/Volumes/OpenRA"
|
||||
echo '
|
||||
tell application "Finder"
|
||||
tell disk "'OpenRA'"
|
||||
open
|
||||
set current view of container window to icon view
|
||||
set toolbar visible of container window to false
|
||||
set statusbar visible of container window to false
|
||||
set the bounds of container window to {400, 100, 1040, 580}
|
||||
set theViewOptions to the icon view options of container window
|
||||
set arrangement of theViewOptions to not arranged
|
||||
set icon size of theViewOptions to 72
|
||||
set background picture of theViewOptions to file ".background:background.tiff"
|
||||
make new alias file at container window to POSIX file "/Applications" with properties {name:"Applications"}
|
||||
set position of item "'OpenRA - Tiberian Dawn.app'" of container window to {160, 106}
|
||||
set position of item "'OpenRA - Red Alert.app'" of container window to {320, 106}
|
||||
set position of item "'OpenRA - Dune 2000.app'" of container window to {480, 106}
|
||||
set position of item "Applications" of container window to {320, 298}
|
||||
set position of item ".background" of container window to {160, 298}
|
||||
set position of item ".fseventsd" of container window to {160, 298}
|
||||
set position of item ".VolumeIcon.icns" of container window to {160, 298}
|
||||
update without registering applications
|
||||
delay 5
|
||||
close
|
||||
end tell
|
||||
end tell
|
||||
' | osascript
|
||||
|
||||
# Replace duplicate .NET runtime files with hard links to improve compression
|
||||
if [ "${PLATFORM}" != "mono" ]; then
|
||||
for MOD in "Red Alert" "Tiberian Dawn"; do
|
||||
for f in "/Volumes/OpenRA/OpenRA - ${MOD}.app/Contents/MacOS"/*; do
|
||||
g="/Volumes/OpenRA/OpenRA - Dune 2000.app/Contents/MacOS/"$(basename "${f}")
|
||||
# HACK: Copy the volume icon again - something in the previous step seems to delete it...?
|
||||
cp "${BUILTDIR}/OpenRA - Red Alert.app/Contents/Resources/ra.icns" "/Volumes/OpenRA/.VolumeIcon.icns"
|
||||
SetFile -c icnC "/Volumes/OpenRA/.VolumeIcon.icns"
|
||||
SetFile -a C "/Volumes/OpenRA"
|
||||
|
||||
# Replace duplicate .NET runtime files with hard links to improve compression
|
||||
for MOD in "Red Alert" "Tiberian Dawn"; do
|
||||
for p in "x86_64" "arm64" "mono"; do
|
||||
for f in "/Volumes/OpenRA/OpenRA - ${MOD}.app/Contents/MacOS/${p}"/*; do
|
||||
g="/Volumes/OpenRA/OpenRA - Dune 2000.app/Contents/MacOS/${p}/"$(basename "${f}")
|
||||
hashf=$(shasum "${f}" | awk '{ print $1 }') || :
|
||||
hashg=$(shasum "${g}" | awk '{ print $1 }') || :
|
||||
if [ -n "${hashf}" ] && [ "${hashf}" = "${hashg}" ]; then
|
||||
echo "Deduplicating ${f}"
|
||||
rm "${f}"
|
||||
ln "${g}" "${f}"
|
||||
fi
|
||||
done
|
||||
done
|
||||
done
|
||||
|
||||
for MOD in "Red Alert" "Tiberian Dawn" "Dune 2000"; do
|
||||
for p in "arm64" "mono"; do
|
||||
for f in "/Volumes/OpenRA/OpenRA - ${MOD}.app/Contents/MacOS/x86_64"/*; do
|
||||
g="/Volumes/OpenRA/OpenRA - ${MOD}.app/Contents/MacOS/${p}/"$(basename "${f}")
|
||||
if [ -e "${g}" ]; then
|
||||
hashf=$(shasum "${f}" | awk '{ print $1 }') || :
|
||||
hashg=$(shasum "${g}" | awk '{ print $1 }') || :
|
||||
if [ -n "${hashf}" ] && [ "${hashf}" = "${hashg}" ]; then
|
||||
@@ -193,35 +211,37 @@ build_platform() {
|
||||
rm "${f}"
|
||||
ln "${g}" "${f}"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
chmod -Rf go-w /Volumes/OpenRA
|
||||
sync
|
||||
sync
|
||||
chmod -Rf go-w /Volumes/OpenRA
|
||||
sync
|
||||
sync
|
||||
|
||||
hdiutil detach "${DMG_DEVICE}"
|
||||
rm -rf "${BUILTDIR}"
|
||||
}
|
||||
hdiutil detach "${DMG_DEVICE}"
|
||||
rm -rf "${BUILTDIR}"
|
||||
|
||||
notarize_package() {
|
||||
DMG_PATH="${1}"
|
||||
NOTARIZE_DMG_PATH="${DMG_PATH%.*}"-notarization.dmg
|
||||
echo "Submitting ${DMG_PATH} for notarization"
|
||||
if [ -n "${MACOS_DEVELOPER_CERTIFICATE_BASE64}" ] && [ -n "${MACOS_DEVELOPER_CERTIFICATE_PASSWORD}" ] && [ -n "${MACOS_DEVELOPER_IDENTITY}" ]; then
|
||||
security delete-keychain build.keychain
|
||||
fi
|
||||
|
||||
if [ -n "${MACOS_DEVELOPER_USERNAME}" ] && [ -n "${MACOS_DEVELOPER_PASSWORD}" ] && [ -n "${MACOS_DEVELOPER_IDENTITY}" ]; then
|
||||
echo "Submitting build for notarization"
|
||||
|
||||
# Reset xcode search path to fix xcrun not finding altool
|
||||
sudo xcode-select -r
|
||||
|
||||
# Create a temporary read-only dmg for submission (notarization service rejects read/write images)
|
||||
hdiutil convert "${DMG_PATH}" -format ULFO -ov -o "${NOTARIZE_DMG_PATH}"
|
||||
hdiutil convert "build.dmg" -format ULFO -ov -o "build-notarization.dmg"
|
||||
|
||||
xcrun notarytool submit "${NOTARIZE_DMG_PATH}" --wait --apple-id "${MACOS_DEVELOPER_USERNAME}" --password "${MACOS_DEVELOPER_PASSWORD}" --team-id "${MACOS_DEVELOPER_IDENTITY}"
|
||||
xcrun notarytool submit "build-notarization.dmg" --wait --apple-id "${MACOS_DEVELOPER_USERNAME}" --password "${MACOS_DEVELOPER_PASSWORD}" --team-id "${MACOS_DEVELOPER_IDENTITY}"
|
||||
|
||||
rm "${NOTARIZE_DMG_PATH}"
|
||||
rm "build-notarization.dmg"
|
||||
|
||||
echo "${DMG_PATH}: Stapling tickets"
|
||||
DMG_DEVICE=$(hdiutil attach -readwrite -noverify -noautoopen "${DMG_PATH}" | egrep '^/dev/' | sed 1q | awk '{print $1}')
|
||||
echo "Stapling tickets"
|
||||
DMG_DEVICE=$(hdiutil attach -readwrite -noverify -noautoopen "build.dmg" | egrep '^/dev/' | sed 1q | awk '{print $1}')
|
||||
sleep 2
|
||||
|
||||
xcrun stapler staple "/Volumes/OpenRA/OpenRA - Red Alert.app"
|
||||
@@ -232,35 +252,7 @@ notarize_package() {
|
||||
sync
|
||||
|
||||
hdiutil detach "${DMG_DEVICE}"
|
||||
break
|
||||
}
|
||||
|
||||
finalize_package() {
|
||||
PLATFORM="${1}"
|
||||
INPUT_PATH="${2}"
|
||||
OUTPUT_PATH="${3}"
|
||||
|
||||
if [ "${PLATFORM}" = "mono" ]; then
|
||||
hdiutil convert "${INPUT_PATH}" -format UDZO -imagekey zlib-level=9 -ov -o "${OUTPUT_PATH}-mono.dmg"
|
||||
else
|
||||
# ULFO offers better compression and faster decompression speeds, but is only supported by 10.11+
|
||||
hdiutil convert "${INPUT_PATH}" -format ULFO -ov -o "${OUTPUT_PATH}.dmg"
|
||||
fi
|
||||
|
||||
rm "${INPUT_PATH}"
|
||||
}
|
||||
|
||||
PLATFORM="$3"
|
||||
DISK_IMAGE="$4"
|
||||
|
||||
build_platform "${PLATFORM}" "${DISK_IMAGE}"
|
||||
|
||||
if [ -n "${MACOS_DEVELOPER_CERTIFICATE_BASE64}" ] && [ -n "${MACOS_DEVELOPER_CERTIFICATE_PASSWORD}" ] && [ -n "${MACOS_DEVELOPER_IDENTITY}" ]; then
|
||||
security delete-keychain build.keychain
|
||||
fi
|
||||
|
||||
if [ -n "${MACOS_DEVELOPER_USERNAME}" ] && [ -n "${MACOS_DEVELOPER_PASSWORD}" ] && [ -n "${MACOS_DEVELOPER_IDENTITY}" ]; then
|
||||
notarize_package "${DISK_IMAGE}"
|
||||
fi
|
||||
|
||||
finalize_package "${PLATFORM}" "${DISK_IMAGE}" "${OUTPUTDIR}/OpenRA-${TAG}"
|
||||
hdiutil convert "build.dmg" -format ULFO -ov -o "${OUTPUTDIR}/OpenRA-${TAG}.dmg"
|
||||
rm "build.dmg"
|
||||
|
||||
Reference in New Issue
Block a user