Skip to content

Instantly share code, notes, and snippets.

@Benitoite
Created June 22, 2024 19:17
Show Gist options
  • Save Benitoite/f803a2c15daf93c706aa0339065f50bc to your computer and use it in GitHub Desktop.
Save Benitoite/f803a2c15daf93c706aa0339065f50bc to your computer and use it in GitHub Desktop.
WIP: builds a MAX/MSP 8 application for App Store / Test Flight
# Convert a standalone maxmsp8 application to a mac app store application
#
# USAGE: sudo CODESIGNID="Apple Distribution: DOCTOR WHO (ABCDE12345)" TEAMID=ABCDE12345 DOM=com.mycompanyname APP=myappname sh buildmaxapp.sh
#
# Prerequisites on ~/Desktop:
# custom Max.icns
# Info.plist
# objects.txt list of objects from maxmsp
# main.entitlements
# profile.entitlements
# main.entitlements
# helper.entitlements
# myappname.app from Max/MSP
date
cd ~/Desktop
team=${TEAMID}
iden=${DOM}.${APP}
appid="$team"."$iden"
echo -f script -w 256 "$appid"
sudo xattr -cr "${APP}".app
# Prepare some resources
LC_ALL=C sed -i '' -e '/<key>com.apple.application-identifier<\/key>/ {' -e 'n; s/<string>.*<\/string>/<string>'$appid'<\/string>/' -e '}' helper.entitlements
LC_ALL=C sed -i '' -e '/<key>com.apple.developer.team-identifier<\/key>/ {' -e 'n; s/<string>.*<\/string>/<string>'$team'<\/string>/' -e '}' helper.entitlements
LC_ALL=C sed -i '' -e '/<key>com.apple.application-identifier<\/key>/ {' -e 'n; s/<string>.*<\/string>/<string>'$appid'<\/string>/' -e '}' main.entitlements
LC_ALL=C sed -i '' -e '/<key>com.apple.developer.team-identifier<\/key>/ {' -e 'n; s/<string>.*<\/string>/<string>'$team'<\/string>/' -e '}' main.entitlements
LC_ALL=C sed -i '' -e '/<key>com.apple.application-identifier<\/key>/ {' -e 'n; s/<string>.*<\/string>/<string>'$appid'<\/string>/' -e '}' profile.entitlements
LC_ALL=C sed -i '' -e '/<key>com.apple.developer.team-identifier<\/key>/ {' -e 'n; s/<string>.*<\/string>/<string>'$team'<\/string>/' -e '}' profile.entitlements
LC_ALL=C sed -i '' -e '/<key>com.apple.application-identifier<\/key>/ {' -e 'n; s/<string>.*<\/string>/<string>'$appid'<\/string>/' -e '}' inherit.entitlements
LC_ALL=C sed -i '' -e '/<key>com.apple.developer.team-identifier<\/key>/ {' -e 'n; s/<string>.*<\/string>/<string>'$team'<\/string>/' -e '}' inherit.entitlements
iconv -f UTF-8 -t ASCII inherit.entitlements > "${APP}".entitlements
plutil -convert xml1 "${APP}".entitlements
iconv -f UTF-8 -t ASCII main.entitlements > main"${APP}".entitlements
plutil -convert xml1 main"${APP}".entitlements
iconv -f UTF-8 -t ASCII profile.entitlements > profile"${APP}".entitlements
plutil -convert xml1 profile"${APP}".entitlements
iconv -f UTF-8 -t ASCII helper.entitlements > helper"${APP}".entitlements
plutil -convert xml1 helper"${APP}".entitlements
cp Info.plist "${APP}".app/Contents
cp Max.icns "${APP}".app/Contents/Resources
cp "${APP}".provisionprofile "${APP}".app/Contents/embedded.provisionprofile
cp "${APP}".provisionprofile "${APP}".app/Contents/Frameworks/"${APP}"\ Helper.app/Contents/embedded.provisionprofile
cp "${APP}".provisionprofile "${APP}".app/Contents/Frameworks/"${APP}"\ Helper\ \(GPU\).app/Contents/embedded.provisionprofile
cp "${APP}".provisionprofile "${APP}".app/Contents/Frameworks/"${APP}"\ Helper\ \(Plugin\).app/Contents/embedded.provisionprofile
cp "${APP}".provisionprofile "${APP}".app/Contents/Frameworks/"${APP}"\ Helper\ \(Renderer\).app/Contents/embedded.provisionprofile
rm -r "${APP}".app/Contents/Resources/C74/extensions/max/*
rm -r "${APP}".app/Contents/Resources/C74/media/jitter
for mxo in "${APP}".app/Contents/Resources/C74/*/*/*mxo ; do
cp "${APP}".provisionprofile "$mxo"/Contents/embedded.provisionprofile
done
for framework in "${APP}".app/Contents/Frameworks/*framework ; do
cp "${APP}".provisionprofile "$framework"/Versions/Current/Resources/embedded.provisionprofile
done
rm "${APP}".app/Contents/Resources/MaxPlugInScanner
# Clean up the externals folders
for objects in $(cat /Users/rb/Desktop/objects.txt | tail -n +2 | sed 's/^.\{15\}//g' | sed 's#[[:space:]].*##' | grep "~") ; do cp -r "${APP}".app/Contents/Resources/C74/externals/msp/$objects ./mspobj ; done
for objects in $(cat /Users/rb/Desktop/objects.txt | tail -n +2 | sed 's/^.\{15\}//g' | sed 's#[[:space:]].*##' | grep -v "~") ; do cp -r "${APP}".app/Contents/Resources/C74/externals/max/$objects ./maxobj ; done
rm -r "${APP}".app/Contents/Resources/C74/externals/msp/*
rm -r "${APP}".app/Contents/Resources/C74/externals/max/*
cp -r ./mspobj/* "${APP}".app/Contents/Resources/C74/externals/msp
cp -r ./maxobj/* "${APP}".app/Contents/Resources/C74/externals/max
rm -r "${APP}".app/Contents/Resources/C74/externals/jitter/*
rm -r "${APP}".app/Contents/Resources/C74/externals/m4l/*
rm "${APP}".app/Contents/PkgInfo
rm "${APP}".app/Contents/Frameworks/*app/Contents/PkgInfo
rm "${APP}".app/Contents/Resources/C74/*/*/*mxo/Contents/PkgInfo
rm -r "${APP}".app/Contents/Frameworks/Chromium\ Embedded\ Framework.framework/_CodeSignature
# Fix the Chromium bundle structure
mkdir "${APP}".app/Contents/Frameworks/Chromium\ Embedded\ Framework.framework/Versions
mkdir "${APP}".app/Contents/Frameworks/Chromium\ Embedded\ Framework.framework/Versions/A
mv "${APP}".app/Contents/Frameworks/Chromium*/Resources "${APP}".app/Contents/Frameworks/Chromium\ Embedded\ Framework.framework/Versions/A
mv "${APP}".app/Contents/Frameworks/Chromium*/Libraries "${APP}".app/Contents/Frameworks/Chromium\ Embedded\ Framework.framework/Versions/A
mv "${APP}".app/Contents/Frameworks/Chromium\ Embedded\ Framework.framework/Chromium\ Embedded\ Framework "${APP}".app/Contents/Frameworks/Chromium\ Embedded\ Framework.framework/Versions/A
mv "${APP}".app/Contents/Frameworks/Chromium*/embedded.provisionprofile "${APP}".app/Contents/Frameworks/Chromium\ Embedded\ Framework.framework/Versions/A/Resources
cd ~/Desktop/"${APP}".app/Contents/Frameworks/Chromium\ Embedded\ Framework.framework/Versions
ln -s A Current
cd ~/Desktop/"${APP}".app/Contents/Frameworks/Chromium\ Embedded\ Framework.framework
ln -s Versions/Current/Chromium\ Embedded\ Framework Chromium\ Embedded\ Framework
ln -s Versions/Current/Resources Resources
ln -s Versions/Current/Libraries Libraries
cd ~/Desktop
rm -r ${APP}.app/Contents/Frameworks/Chromium\ Embedded\ Framework.framework/Versions/A/A
#mv "${APP}".app/Contents/Frameworks/Chromium\ Embedded\ Framework.framework/Versions/A/Libraries/* "${APP}".app/Contents/Frameworks
#rm -r "${APP}".app/Contents/Frameworks/Chromium\ Embedded\ Framework.framework/Versions/A/Libraries
rm -r "${APP}".app/Contents/Frameworks/Chromium\ Embedded\ Framework.framework/Versions/A/Resources/Resources
# Point the helper app executables to the new chromium location
mv /Users/rb/Desktop/"${APP}".app/Contents/Frameworks/"${APP}"\ Helper\ \(GPU\).app/Contents/MacOS/"${APP}"\ Helper\ \(GPU\) /Users/rb/Desktop/"${APP}".app/Contents/Frameworks/"${APP}"\ Helper\ \(GPU\).app/Contents/MacOS/"${APP}"\ Helpergpu
install_name_tool -change "@executable_path/../Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework" "@executable_path/../Frameworks/Chromium Embedded Framework.framework/Versions/A/Chromium Embedded Framework" "${APP}".app/Contents/Frameworks/"${APP}"\ Helper\ \(GPU\).app/Contents/MacOS/"${APP}" Helpergpu
mv "${APP}".app/Contents/Frameworks/"${APP}"\ Helper\ \(GPU\).app/Contents/MacOS/"${APP}"\ Helpergpu /Users/rb/Desktop/"${APP}".app/Contents/Frameworks/"${APP}"\ Helper\ \(GPU\).app/Contents/MacOS/"${APP}"\ Helper\ \(GPU\)
mv /Users/rb/Desktop/"${APP}".app/Contents/Frameworks/"${APP}"\ Helper\ \(Renderer\).app/Contents/MacOS/"${APP}"\ Helper\ \(Renderer\) "${APP}".app/Contents/Frameworks/"${APP}"\ Helper\ \(Renderer\).app/Contents/MacOS/"${APP}"\ Helperrenderer
install_name_tool -change "@executable_path/../Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework" "@executable_path/../Frameworks/Chromium Embedded Framework.framework/Versions/A/Chromium Embedded Framework" "${APP}".app/Contents/Frameworks/"${APP}"\ Helper\ \(Renderer\).app/Contents/MacOS/"${APP}"\ Helperrenderer
mv "${APP}".app/Contents/Frameworks/"${APP}"\ Helper\ \(Renderer\).app/Contents/MacOS/"${APP}"\ Helperrenderer "${APP}".app/Contents/Frameworks/"${APP}"\ Helper\ \(Renderer\).app/Contents/MacOS/"${APP}"\ Helper\ \(Renderer\)
mv /Users/rb/Desktop/"${APP}".app/Contents/Frameworks/"${APP}"\ Helper\ \(Plugin\).app/Contents/MacOS/"${APP}"\ Helper\ \(Plugin\) "${APP}".app/Contents/Frameworks/"${APP}"\ Helper\ \(Plugin\).app/Contents/MacOS/"${APP}"\ Helperplugin
install_name_tool -change "@executable_path/../Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework" "@executable_path/../Frameworks/Chromium Embedded Framework.framework/Versions/A/Chromium Embedded Framework" "${APP}".app/Contents/Frameworks/"${APP}"\ Helper\ \(Plugin\).app/Contents/MacOS/"${APP}"\ Helperplugin
mv ${APP}.app/Contents/Frameworks/"${APP}"\ Helper\ \(Plugin\).app/Contents/MacOS/"${APP}"\ Helperplugin "${APP}".app/Contents/Frameworks/"${APP}"\ Helper\ \(Plugin\).app/Contents/MacOS/"${APP}"\ Helper\ \(Plugin\)
install_name_tool -change "@executable_path/../Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework" "@executable_path/../Frameworks/Chromium Embedded Framework.framework/Versions/A/Chromium Embedded Framework" "${APP}".app/Contents/Frameworks/"${APP}"\ Helper.app/Contents/MacOS/"${APP}"\ Helper
# Point the main executable to the new chromium location
install_name_tool -change "@executable_path/../Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework" "@executable_path/../Frameworks/Chromium Embedded Framework.framework/Versions/A/Chromium Embedded Framework" "${APP}".app/Contents/MacOS/"${APP}"
for xec in "${APP}".app/Contents/Frameworks/*app/Contents/MacOS/* ; do install_name_tool -change @executable_path/../Frameworks/Chromium\ Embedded\ Framework.framework/Chromium\ Embedded\ Framework @executable_path/../Frameworks/Chromium\ Embedded\ Framework.framework/Versions/A/Chromium\ Embedded\ Framework "$xec" ; done
# Codesign the app, first inner, outer last
echo "Codesigning Application."
LC_ALL=C sed -i '' -e '/<key>CFBundleIdentifier<\/key>/ {' -e 'n; s/<string>.*<\/string>/<string>'$team'.'$iden'<\/string>/' -e '}' "${APP}".app/Contents/Frameworks/Chromium\ Embedded\ Framework.framework/Versions/A/Resources/Info.plist
for list in "${APP}".app/Contents/Frameworks/*framework/Resources/Info.plist ; do
LC_ALL=C sed -i '' -e '/<key>CFBundleIdentifier<\/key>/ {' -e 'n; s/<string>.*<\/string>/<string>'$team'.'$iden'<\/string>/' -e '}' "$list"
done
for framework in "${APP}".app/Contents/Frameworks/*framework/Versions/Current/* ; do
LC_ALL=C sed -i '' -e '/<key>CFBundleIdentifier<\/key>/ {' -e 'n; s/<string>.*<\/string>/<string>'$team'.'$iden'<\/string>/' -e '}' ''$(dirname ''$framework'')/Resources/Info.plist''
done
for help in "${APP}".app/Contents/Frameworks/*app/Contents/Info.plist ; do
LC_ALL=C sed -i '' -e '/<key>CFBundleIdentifier<\/key>/ {' -e 'n; s/<string>.*<\/string>/<string>'$iden'<\/string>/' -e '}' "$help"
done
for mxo in "${APP}".app/Contents/Resources/C74/*/*/*mxo/Contents/MacOS/* ; do
LC_ALL=C sed -i '' -e '/<key>CFBundleIdentifier<\/key>/ {' -e 'n; s/<string>.*<\/string>/<string>'$team'.'$iden'<\/string>/' -e '}' ''$(dirname ''$mxo'')/../Info.plist''
done
for framework in "${APP}".app/Contents/Frameworks/*framework/Versions/A/* ; do
codesign --timestamp --entitlements "${APP}".entitlements -f -v -s "${CODESIGNID}" -i "$team"."$iden" "$framework"
done
for frameworklib in "${APP}".app/Contents/Frameworks/*framework/Resources/*/* ; do
codesign --timestamp --entitlements "${APP}".entitlements -f -v -s "${CODESIGNID}" -i "$team"."$iden" "$frameworklib"
done
for frameworklib in "${APP}".app/Contents/Frameworks/*framework/Resources/* ; do
codesign --timestamp --entitlements "${APP}".entitlements -f -v -s "${CODESIGNID}" -i "$team"."$iden" "$frameworklib"
done
for mxo in "${APP}".app/Contents/Resources/C74/*/*/*mxo/Contents/MacOS/* ; do
lipo -extract arm64 $mxo -o $mxo.1 ; mv $mxo.1 $mxo
codesign --timestamp --entitlements "${APP}".entitlements -f -v -s "${CODESIGNID}" -i "$team"."$iden" "$mxo"
done
for subsub in "${APP}".app/Contents/Resources/C74/*/*/*mxo ; do
codesign --timestamp --entitlements "${APP}".entitlements -f -v -s "${CODESIGNID}" -i "$team"."$iden" "$subsub"
done
#for sub in "${APP}".app/Contents/Resources/C74/*/* ; do
# codesign --timestamp --entitlements "${APP}".entitlements -f -v -s "${CODESIGNID}" -i "$team"."$iden" "$sub"
#done
for resource in "${APP}".app/Contents/Resources/* ; do
if [ ! -d "$resource" ]; then
codesign --timestamp -f -v -s "${CODESIGNID}" --entitlements ${APP}.entitlements -i "$team"."$iden" "$resource"
fi
done
lipo -extract arm64 "${APP}".app/Contents/Frameworks/Chromium\ Embedded\ Framework.framework/Versions/A/Chromium\ Embedded\ Framework -o "${APP}".app/Contents/Frameworks/Chromium\ Embedded\ Framework.framework/Versions/A/Chromium\ Embedded\ Framework1 ; mv "${APP}".app/Contents/Frameworks/Chromium\ Embedded\ Framework.framework/Versions/A/Chromium\ Embedded\ Framework1 "${APP}".app/Contents/Frameworks/Chromium\ Embedded\ Framework.framework/Versions/A/Chromium\ Embedded\ Framework
codesign --timestamp -f -v -s "${CODESIGNID}" -i "$team"."$iden" --entitlements "${APP}".entitlements ''''${APP}''.app/Contents/Frameworks/Chromium Embedded Framework.framework/Versions/A/Chromium Embedded Framework''
for frame in "${APP}".app/Contents/Frameworks/* ; do
lipo -extract arm64 $frame -o $frame.1 ; mv $frame.1 $frame
codesign --timestamp --entitlements "${APP}".entitlements -f -v -s "${CODESIGNID}" -i "$team"."$iden" "$frame"
done
for helper in "${APP}".app/Contents/Frameworks/*app ; do
codesign --timestamp --entitlements helper"${APP}".entitlements -f -v -s "${CODESIGNID}" -i "$iden" "$helper"
done
lipo -arch arm64 "${APP}".app/Contents/Resources/C74/interfaces/search/sqlite3_darwin-arm64.node -arch x86_64 "${APP}".app/Contents/Resources/C74/interfaces/search/sqlite3_darwin-x64.node -create -output lipped
cp lipped "${APP}".app/Contents/Resources/C74/interfaces/search/sqlite3_darwin-arm64.node
cp lipped "${APP}".app/Contents/Resources/C74/interfaces/search/sqlite3_darwin-x64.node
rm lipped
codesign --timestamp -f -v -s "${CODESIGNID}" -i "$team"."$iden" --entitlements "${APP}".entitlements "${APP}".app/Contents/Resources/C74/interfaces/search/sqlite3_darwin-arm64.node
codesign --timestamp -f -v -s "${CODESIGNID}" -i "$team"."$iden" --entitlements "${APP}".entitlements "${APP}".app/Contents/Resources/C74/interfaces/search/sqlite3_darwin-x64.node
#codesign --timestamp -f -v -s "${CODESIGNID}" -i "$team"."$iden" --entitlements "${APP}".entitlements ''''${APP}''.app/Contents/Frameworks/Chromium Embedded Framework.framework''
codesign --timestamp --entitlements profile"${APP}".entitlements -f -v -s "${CODESIGNID}" -i "$team"."$iden" "${APP}".app/Contents/embedded.provisionprofile
lipo -extract arm64 "${APP}".app/Contents/MacOS/"${APP}" -o "${APP}".app/Contents/MacOS/"${APP}".1 ; mv "${APP}".app/Contents/MacOS/"${APP}".1 "${APP}".app/Contents/MacOS/"${APP}"
codesign --timestamp --entitlements main"${APP}".entitlements -f -v -s "${CODESIGNID}" -i "$iden" "${APP}".app/Contents/MacOS/"${APP}"
codesign --timestamp -f -v -s "${CODESIGNID}" --preserve-metadata=identifier,entitlements "${APP}".app
spctl -a -vvvv "${APP}".app
# End of Script
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment