Files
RetroArch/pkg/apple/make-frameworks.sh
T
LibretroAdmin e5fc0a50e4 apple: the App Store builds compile without warnings, and their uploads stop failing on one bad core
Built the way Xcode builds them - the App Store floors (macOS 12,
iOS/tvOS 15), the projects' warnings, every translation unit - the
tree still warned:

- Delegate methods the SDK deprecates that an older OS still calls
  are no longer implemented in source.  apple_rt_add_method() gives
  the class each one at run time, from +initialize and only on the
  releases that call it: -locationManager:didChangeAuthorizationStatus:
  before macOS 11 / iOS 14 (-locationManagerDidChangeAuthorization:
  from there), -documentPicker:didPickDocumentAtURL: before iOS 11
  (the URL-array method from there), -shouldAutorotateTo-
  InterfaceOrientation: before iOS 6, and NSView's
  -layer:shouldInheritContentsScale:fromWindow: from 10.7.
  class_addMethod is looked up by name, as the 10.4 binary may not
  import it.  CocoaView no longer declares UIDocumentPickerDelegate,
  whose pre-11 SDKs require the method it now adds at run time, and
  -prefersPointerLocked is not built for tvOS, where it is
  unavailable.
- The open panel's file types, the companion's folder icon and the
  cores folder's open are -setAllowedContentTypes:, -iconForContent-
  Type: and -openURL: from macOS 11, the 10.x methods before it, by
  selector where they are not on every release.
- The alert's end selector is looked up by name, and on SDKs older
  than the selectors ui_cocoa.m names (10.6, 10.7, 10.9) they are
  declared in an unimplemented NSObject category, so @selector()
  stays a constant.
- size_t and 64-bit values narrowed without a cast in configuration.c,
  gl3.c, cdrom.c, media_detect_cd.c and vfs_implementation_cdrom.c;
  rchd_read_extent() rejects an extent past the last 32-bit frame
  instead of wrapping into the wrong track.

App Store uploads: one iOS or tvOS core without an unencrypted
LC_ENCRYPTION_INFO_64 - written by Apple's ld, not by other linkers -
fails the whole upload (ITMS-90125).  make-frameworks.sh leaves such a
core out of an App Store build with a warning naming it.  The
Fastfile's check for a build already in TestFlight review passed
Build.all a filter it does not take, so it always failed and the
upload went on to external distribution and stopped there; it asks
App Store Connect for the newest five builds of the platform with
their review submissions instead.
2026-10-07 09:38:29 +02:00

167 lines
7.6 KiB
Bash
Executable File

#!/bin/bash
# Prefer the expanded name, if available.
CODE_SIGN_IDENTITY_FOR_ITEMS="${EXPANDED_CODE_SIGN_IDENTITY}"
if [ "${CODE_SIGN_IDENTITY_FOR_ITEMS}" = "" ] ; then
# Fall back to old behavior.
CODE_SIGN_IDENTITY_FOR_ITEMS="${CODE_SIGN_IDENTITY}"
fi
echo "Identity:"
echo "${CODE_SIGN_IDENTITY_FOR_ITEMS}"
if [ "$PLATFORM_FAMILY_NAME" = "tvOS" ] ; then
BASE_DIR="tvOS"
SUFFIX="_tvos"
PLATFORM="tvos"
DEPLOYMENT_TARGET="${TVOS_DEPLOYMENT_TARGET}"
elif [ "$PLATFORM_FAMILY_NAME" = "iOS" ] ; then
BASE_DIR="iOS"
SUFFIX="_ios"
PLATFORM="ios"
DEPLOYMENT_TARGET="${IPHONEOS_DEPLOYMENT_TARGET}"
elif [ "$PLATFORM_FAMILY_NAME" = "macOS" ] ; then
BASE_DIR="OSX"
SUFFIX=
PLATFORM=
DEPLOYMENT_TARGET="${MACOSX_DEPLOYMENT_TARGET}"
fi
if [ -n "$BUILT_PRODUCTS_DIR" -a -n "$FRAMEWORKS_FOLDER_PATH" ] ; then
OUTDIR="$BUILT_PRODUCTS_DIR"/"$FRAMEWORKS_FOLDER_PATH"
DSYM_OUTDIR="$BUILT_PRODUCTS_DIR"
else
OUTDIR="$BASE_DIR"/Frameworks
DSYM_OUTDIR="$BASE_DIR"/Frameworks
fi
mkdir -p "$OUTDIR"
process_one() {
set -e
local dylib="$1"
local intermediate fwName fwDir build_sdk dSYMDir dylibName
intermediate=$(basename "$dylib")
intermediate="${intermediate/%.dylib/}"
if [ -n "$SUFFIX" ] ; then
intermediate="${intermediate/%$SUFFIX/}"
fi
fwName="${intermediate//_/.}"
# App Store Connect takes an iOS/tvOS binary only with an
# LC_ENCRYPTION_INFO_64 that is not yet encrypted (cryptid 0), which
# Apple's ld writes and other linkers do not; one core without it
# fails the whole upload (ITMS-90125). Leave such a core out of an
# App Store build and name it, rather than lose every other core.
if [ -n "$APPSTORE_BUILD" ] && [ "$PLATFORM_FAMILY_NAME" = "iOS" -o "$PLATFORM_FAMILY_NAME" = "tvOS" ] ; then
cryptid=$(otool -l "$dylib" | awk '/cmd LC_ENCRYPTION_INFO/ { f = 1 } f && $1 == "cryptid" { print $2; exit }')
if [ -z "$cryptid" ] ; then
echo "warning: leaving $fwName out of the App Store build: $(basename "$dylib") has no LC_ENCRYPTION_INFO_64 (not linked by Apple's ld)"
return 0
elif [ "$cryptid" != "0" ] ; then
echo "warning: leaving $fwName out of the App Store build: $(basename "$dylib") is already encrypted (cryptid $cryptid)"
return 0
fi
fi
echo Making framework $fwName from $dylib
fwDir="${OUTDIR}/${fwName}.framework"
mkdir -p "$fwDir"
if [ "$PLATFORM_FAMILY_NAME" = "iOS" -o "$PLATFORM_FAMILY_NAME" = "tvOS" ] ; then
build_sdk=$(vtool -show-build "$dylib" | grep sdk | awk '{print $2}')
vtool -set-build-version "${PLATFORM}" "${DEPLOYMENT_TARGET}" "${build_sdk}" -set-build-tool "$PLATFORM" ld 1115.7.3 -set-source-version 0.0 -replace -output "$dylib" "$dylib"
fi
lipo -create "$dylib" -output "$fwDir/$fwName"
sed -e "s,%CORE%,$fwName," -e "s,%BUNDLE%,$fwName," -e "s,%IDENTIFIER%,$fwName," -e "s,%OSVER%,$DEPLOYMENT_TARGET," iOS/fw.tmpl > "$fwDir/Info.plist"
if [ "$PLATFORM_FAMILY_NAME" = "macOS" ] ; then
mkdir -p "$fwDir"/Versions/A/Resources
mv "$fwDir/$fwName" "$fwDir"/Versions/A
mv "$fwDir"/Info.plist "$fwDir"/Versions/A/Resources
ln -sf A "$fwDir"/Versions/Current
ln -sf Versions/Current/Resources "$fwDir"/Resources
ln -sf "Versions/Current/$fwName" "$fwDir/$fwName"
fi
echo "signing $fwName"
codesign --force --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" "$fwDir"
# Create framework dSYM if dylib dSYM exists
if [ -d "$dylib.dSYM" ] ; then
echo "Creating dSYM for framework $fwName"
dSYMDir="${DSYM_OUTDIR}/${fwName}.framework.dSYM"
# Copy entire dSYM structure to preserve all metadata and future additions
cp -R "$dylib.dSYM" "$dSYMDir"
# Rename DWARF binary to match framework name
dylibName=$(basename "$dylib")
mv "$dSYMDir/Contents/Resources/DWARF/$dylibName" "$dSYMDir/Contents/Resources/DWARF/$fwName"
# Update binary-path in Relocations yml files if they exist
if [ -d "$dSYMDir/Contents/Resources/Relocations" ] ; then
find "$dSYMDir/Contents/Resources/Relocations" -name "*.yml" -type f | while read -r ymlfile ; do
sed -i '' "s/binary-path: *$dylibName/binary-path: $fwName/" "$ymlfile"
done
fi
# Update Info.plist with framework identifier
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier com.apple.xcode.dsym.$fwName" "$dSYMDir/Contents/Info.plist"
fi
}
export -f process_one
export OUTDIR DSYM_OUTDIR SUFFIX PLATFORM_FAMILY_NAME PLATFORM \
DEPLOYMENT_TARGET CODE_SIGN_IDENTITY_FOR_ITEMS APPSTORE_BUILD
JOBS=$(sysctl -n hw.ncpu)
if [ "$JOBS" -gt 8 ] ; then JOBS=8 ; fi
find "$BASE_DIR"/modules -maxdepth 1 -type f -regex '.*libretro.*\.dylib$' -print0 \
| xargs -0 -n1 -P"$JOBS" bash -c 'process_one "$0"' || exit 1
# Copy in MoltenVK as an embedded library manually instead of having
# Xcode do it. This makes it potentially easier to substitute out
# MoltenVK, have it provided outside the repo, or have different
# MoltenVK builds for different OS versions.
if [ -z "${MOLTENVK_XCFRAMEWORK}" ] ; then
MOLTENVK_XCFRAMEWORK="${SRCROOT}/Frameworks/MoltenVK.xcframework"
fi
MVK_PLATFORM_SUBDIR="${SWIFT_PLATFORM_TARGET_PREFIX}-$(echo $ARCHS_STANDARD_64_BIT | sed -e 's/ /_/g')${LLVM_TARGET_TRIPLE_SUFFIX}"
if [ -d "${MOLTENVK_XCFRAMEWORK}/${MVK_PLATFORM_SUBDIR}/MoltenVK.framework" ] ; then
echo copying moltenvk from "${MOLTENVK_XCFRAMEWORK}/${MVK_PLATFORM_SUBDIR}/MoltenVK.framework"
cp -R "${MOLTENVK_XCFRAMEWORK}/${MVK_PLATFORM_SUBDIR}/MoltenVK.framework" "${OUTDIR}"
# tvOS App Store rejects arm64e; strip it from the fat MoltenVK binary
if [ "$PLATFORM_FAMILY_NAME" = "tvOS" -a "$APPSTORE_BUILD" = "1" ] ; then
MVK_BIN="${OUTDIR}/MoltenVK.framework/MoltenVK"
if lipo -info "$MVK_BIN" 2>/dev/null | grep -q arm64e ; then
echo "stripping arm64e from MoltenVK for tvOS App Store build"
lipo -remove arm64e "$MVK_BIN" -output "$MVK_BIN"
fi
fi
codesign --force --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" "${OUTDIR}/MoltenVK.framework"
fi
# iOS 12 needs an older version of MoltenVK
if [ -n "$MOLTENVK_LEGACY_XCFRAMEWORK_PATH" -a -d "${MOLTENVK_LEGACY_XCFRAMEWORK_PATH}/${MVK_PLATFORM_SUBDIR}/MoltenVK-${MOLTENVK_LEGACY_VERSION}.framework" ] ; then
echo copying legacy moltenvk from "${MOLTENVK_LEGACY_XCFRAMEWORK_PATH}/${MVK_PLATFORM_SUBDIR}/MoltenVK-${MOLTENVK_LEGACY_VERSION}.framework"
cp -R "${MOLTENVK_LEGACY_XCFRAMEWORK_PATH}/${MVK_PLATFORM_SUBDIR}/MoltenVK-${MOLTENVK_LEGACY_VERSION}.framework" "${OUTDIR}"
codesign --force --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" "${OUTDIR}/MoltenVK-${MOLTENVK_LEGACY_VERSION}.framework/MoltenVK-${MOLTENVK_LEGACY_VERSION}"
codesign --force --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" "${OUTDIR}/MoltenVK-${MOLTENVK_LEGACY_VERSION}.framework"
fi
# Copy Vulkan ICD file for loader discovery (macOS only)
# This allows the Vulkan loader to find MoltenVK when using validation layers
# Only include current MoltenVK - legacy version is for old OS support, not validation
if [ "$PLATFORM_FAMILY_NAME" = "macOS" ] ; then
RESOURCES_DIR="$(dirname "$OUTDIR")/Resources"
ICD_DIR="$RESOURCES_DIR/vulkan/icd.d"
mkdir -p "$ICD_DIR"
if [ -f "${OUTDIR}/MoltenVK.framework/Versions/A/Resources/MoltenVK_icd.json" ] ; then
sed 's|\.\./MoltenVK|../../../Frameworks/MoltenVK.framework/Versions/A/MoltenVK|' \
"${OUTDIR}/MoltenVK.framework/Versions/A/Resources/MoltenVK_icd.json" \
> "$ICD_DIR/MoltenVK_icd.json"
fi
fi