1+ #! /bin/bash
2+
3+ set -e
4+
5+ # ######################################
6+ # Variables
7+ # ######################################
8+ APP_NAME=" projectm_sdl"
9+ BUNDLE_ID=" projectM"
10+ DEVELOPER_ID=" Developer ID Application: Mischa Spiegelmock (5926VBQM6Y)"
11+ TEAM_ID=" 5926VBQM6Y"
12+ KEYCHAIN_PROFILE=" projectm"
13+
14+ BUILD_DIR=" target"
15+ OUTPUT_DIR=" ${PWD} /dist"
16+
17+ # Paths for universal binary
18+ UNIVERSAL_BINARY=" ${OUTPUT_DIR} /${APP_NAME} "
19+
20+ # .app bundle paths
21+ APP_BUNDLE_NAME=" ${APP_NAME} .app"
22+ APP_BUNDLE_PATH=" ${OUTPUT_DIR} /${APP_BUNDLE_NAME} "
23+ APP_EXECUTABLE_PATH=" ${APP_BUNDLE_PATH} /Contents/MacOS"
24+ INFO_PLIST_PATH=" ${APP_BUNDLE_PATH} /Contents/Info.plist"
25+ RESOURCES_PATH=" ${APP_BUNDLE_PATH} /Contents/Resources"
26+
27+ # Zip paths
28+ PRE_NOTARIZATION_ZIP=" ${OUTPUT_DIR} /${APP_NAME} -pre-notarization.zip"
29+ FINAL_ZIP=" ${OUTPUT_DIR} /${APP_NAME} .zip"
30+
31+ # ######################################
32+ # 1) Build Rust Binaries (x86_64 + arm64)
33+ # ######################################
34+ echo " ==> Building for x86_64"
35+ cargo build --release --target x86_64-apple-darwin
36+
37+ echo " ==> Building for arm64"
38+ cargo build --release --target aarch64-apple-darwin
39+
40+ # ######################################
41+ # 2) Create Universal Binary
42+ # ######################################
43+ mkdir -p " ${OUTPUT_DIR} "
44+ echo " ==> Creating universal binary"
45+ lipo -create -output " ${UNIVERSAL_BINARY} " \
46+ " ${BUILD_DIR} /x86_64-apple-darwin/release/${APP_NAME} " \
47+ " ${BUILD_DIR} /aarch64-apple-darwin/release/${APP_NAME} "
48+
49+ # ######################################
50+ # 3) Create .app Bundle Structure
51+ # ######################################
52+ echo " ==> Creating .app bundle structure"
53+ rm -rf " ${APP_BUNDLE_PATH} " || true
54+ mkdir -p " ${APP_EXECUTABLE_PATH} "
55+ mkdir -p " ${RESOURCES_PATH} "
56+
57+ # Move the universal binary into MacOS/
58+ mv " ${UNIVERSAL_BINARY} " " ${APP_EXECUTABLE_PATH} /${APP_NAME} "
59+
60+ # ######################################
61+ # 4) Create Info.plist
62+ # ######################################
63+ cat > " ${INFO_PLIST_PATH} " << EOL
64+ <?xml version="1.0" encoding="UTF-8"?>
65+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
66+ "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
67+ <plist version="1.0">
68+ <dict>
69+ <key>CFBundleName</key>
70+ <string>${APP_NAME} </string>
71+ <key>CFBundleIdentifier</key>
72+ <string>${BUNDLE_ID} </string>
73+ <key>CFBundleVersion</key>
74+ <string>1.0</string>
75+ <key>CFBundleExecutable</key>
76+ <string>${APP_NAME} </string>
77+ <key>CFBundlePackageType</key>
78+ <string>APPL</string>
79+ <key>LSMinimumSystemVersion</key>
80+ <string>10.12</string>
81+ </dict>
82+ </plist>
83+ EOL
84+
85+ # ######################################
86+ # 5) Clone and Copy Presets/Textures
87+ # ######################################
88+ echo " ==> Cloning preset repositories"
89+ TEMP_DIR=" $( mktemp -d) "
90+ pushd " $TEMP_DIR " > /dev/null
91+
92+ # cream-of-the-crop
93+ git clone
[email protected] :projectM-visualizer/presets-cream-of-the-crop.git
94+ mkdir -p " ${RESOURCES_PATH} /presets"
95+ cp -R presets-cream-of-the-crop/" ." " ${RESOURCES_PATH} /presets/"
96+
97+ # milkdrop-texture-pack
98+ git clone
[email protected] :projectM-visualizer/presets-milkdrop-texture-pack.git
99+ mkdir -p " ${RESOURCES_PATH} /textures"
100+ cp -R presets-milkdrop-texture-pack/textures/" ." " ${RESOURCES_PATH} /textures/"
101+
102+ popd > /dev/null
103+ rm -rf " $TEMP_DIR "
104+
105+ # ######################################
106+ # 6) Sign the .app Bundle
107+ # ######################################
108+ echo " ==> Signing the .app with hardened runtime"
109+ codesign --deep --verbose --force --options runtime \
110+ --sign " ${DEVELOPER_ID} " " ${APP_BUNDLE_PATH} "
111+
112+ # ######################################
113+ # 7) Zip the Signed .app for Notarization
114+ # ######################################
115+ echo " ==> Creating zip for notarization"
116+ rm -f " ${PRE_NOTARIZATION_ZIP} "
117+ ditto -c -k --sequesterRsrc --keepParent \
118+ " ${APP_BUNDLE_PATH} " \
119+ " ${PRE_NOTARIZATION_ZIP} "
120+
121+ # ######################################
122+ # 8) Submit the Zip File for Notarization
123+ # ######################################
124+ echo " ==> Submitting for notarization"
125+ xcrun notarytool submit " ${PRE_NOTARIZATION_ZIP} " \
126+ --keychain-profile " ${KEYCHAIN_PROFILE} " \
127+ --team-id " ${TEAM_ID} " \
128+ --wait
129+
130+ # ######################################
131+ # 9) Staple the Now-Notarized .app
132+ # ######################################
133+ echo " ==> Stapling notarization ticket to .app"
134+ xcrun stapler staple " ${APP_BUNDLE_PATH} "
135+
136+ # ######################################
137+ # 10) (Optional) Create Final Zip with Stapled .app
138+ # ######################################
139+ echo " ==> Creating final zip of stapled .app"
140+ rm -f " ${FINAL_ZIP} "
141+ ditto -c -k --sequesterRsrc --keepParent \
142+ " ${APP_BUNDLE_PATH} " \
143+ " ${FINAL_ZIP} "
144+
145+ # ######################################
146+ # 11) Verify with Gatekeeper
147+ # ######################################
148+ echo " ==> Verifying with spctl"
149+ spctl --assess --verbose=4 " ${APP_BUNDLE_PATH} "
150+
151+ echo " ✅ Build, sign, notarize, staple, and package completed successfully!"
0 commit comments