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