3 # Syntax: make_dmg.sh <environment> <builddir> <type> <apple-id> <apple-password>
4 # where <type> is universal or thin
6 # e.g. make_dmg.sh /Users/carl/osx-environment /Users/carl/cdist universal foo@bar.net opensesame
8 # Don't set -e here as egrep (used a few times) returns 1 if no matches
11 version=`git describe --tags --abbrev=0 | sed -e "s/v//"`
13 # DMG size in megabytes
21 if [ "$TYPE" != "universal" -a "$TYPE" != "thin" ]; then
22 echo "Syntax: $0 <builddir> <type>"
23 echo "where <type> is universal or thin"
27 # This is our work area for making up the .dmgs
28 mkdir -p build/platform/osx
36 ln -s $(readlink $f) "$3/`basename $f`"
38 g=`echo $f | sed -e "s/\/32\//\/64\//g"`
40 lipo -create $f $g -output "$3/`basename $f`"
46 ln -s $(readlink $1/$2) "$3/`basename $f`"
54 function copy_lib_root {
57 for f in $ROOT/32/lib/$1*.dylib; do
59 ln -s $(readlink $f) "$2/`basename $f`"
61 g=`echo $f | sed -e "s/\/32\//\/64\//g"`
63 lipo -create $f $g -output "$2/`basename $f`"
68 for f in $ROOT/lib/$1*.dylib; do
70 ln -s $(readlink $f) "$2/`basename $f`"
78 to_relink="$to_relink|$1"
81 function copy_lib_env {
84 for f in $ENV/32/lib/$1*.dylib; do
86 ln -s $(readlink $f) "$2/`basename $f`"
88 g=`echo $f | sed -e "s/\/32\//\/64\//g"`
90 lipo -create $f $g -output "$2/`basename $f`"
95 for f in $ENV/64/lib/$1*.dylib; do
97 ln -s $(readlink $f) "$2/`basename $f`"
105 to_relink="$to_relink|$1"
108 # @param #1 directory to copy to
111 copy_lib_root libcxml "$dest"
112 copy_lib_root libdcp-1.0 "$dest"
113 copy_lib_root libasdcp-carl "$dest"
114 copy_lib_root libkumu-carl "$dest"
115 copy_lib_root libsub "$dest"
116 copy_lib_root libopenjp2 "$dest"
117 copy_lib_root libavdevice "$dest"
118 copy_lib_root libavformat "$dest"
119 copy_lib_root libavfilter "$dest"
120 copy_lib_root libavutil "$dest"
121 copy_lib_root libavcodec "$dest"
122 copy_lib_root libswscale "$dest"
123 copy_lib_root libpostproc "$dest"
124 copy_lib_root libswresample "$dest"
125 copy_lib_root liblwext4 "$dest"
126 copy_lib_root libblockdev "$dest"
127 copy $ROOT src/dcpomatic/build/src/lib/libdcpomatic2.dylib "$dest"
128 copy $ROOT src/dcpomatic/build/src/wx/libdcpomatic2-wx.dylib "$dest"
129 copy_lib_env libboost_system "$dest"
130 copy_lib_env libboost_filesystem "$dest"
131 copy_lib_env libboost_thread "$dest"
132 copy_lib_env libboost_date_time "$dest"
133 copy_lib_env libboost_locale "$dest"
134 copy_lib_env libboost_regex "$dest"
135 copy_lib_env libxml++ "$dest"
136 copy_lib_env libxslt "$dest"
137 copy_lib_env libxml2 "$dest"
138 copy_lib_env libglibmm-2.4 "$dest"
139 copy_lib_env libgobject "$dest"
140 copy_lib_env libgthread "$dest"
141 copy_lib_env libgmodule "$dest"
142 copy_lib_env libsigc "$dest"
143 copy_lib_env libglib-2 "$dest"
144 copy_lib_env libintl "$dest"
145 copy_lib_env libsndfile "$dest"
146 copy_lib_env libssh "$dest"
147 copy_lib_env libwx "$dest"
148 copy_lib_env libfontconfig "$dest"
149 copy_lib_env libfreetype "$dest"
150 copy_lib_env libexpat "$dest"
151 copy_lib_env libltdl "$dest"
152 copy_lib_env libxmlsec1 "$dest"
153 copy_lib_env libcurl "$dest"
154 copy_lib_env libffi "$dest"
155 copy_lib_env libpango "$dest"
156 copy_lib_env libcairo "$dest"
157 copy_lib_env libpixman "$dest"
158 copy_lib_env libharfbuzz "$dest"
159 copy_lib_env libsamplerate "$dest"
160 copy_lib_env libicui18n "$dest"
161 copy_lib_env libicudata "$dest"
162 copy_lib_env libicuio "$dest"
163 copy_lib_env libicule "$dest"
164 copy_lib_env libiculx "$dest"
165 copy_lib_env libicutest "$dest"
166 copy_lib_env libicutu "$dest"
167 copy_lib_env libicuuc "$dest"
168 copy_lib_env libFLAC "$dest"
169 copy_lib_env libvorbis "$dest"
170 copy_lib_env libogg "$dest"
171 copy_lib_env libxerces-c "$dest"
174 # @param #1 directory to copy to
175 function copy_resources {
179 local prefix=$ROOT/32
185 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic_small.png "$dest"
186 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2.icns "$dest"
187 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2_kdm.icns "$dest"
188 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2_server.icns "$dest"
189 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2_player.icns "$dest"
190 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2_batch.icns "$dest"
191 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2_playlist.icns "$dest"
192 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2_disk.icns "$dest"
193 cp $prefix/src/dcpomatic/graphics/osx/preferences/colour_conversions.png "$dest"
194 cp $prefix/src/dcpomatic/graphics/osx/preferences/defaults.png "$dest"
195 cp $prefix/src/dcpomatic/graphics/osx/preferences/kdm_email.png "$dest"
196 cp $prefix/src/dcpomatic/graphics/osx/preferences/email.png "$dest"
197 cp $prefix/src/dcpomatic/graphics/osx/preferences/servers.png "$dest"
198 cp $prefix/src/dcpomatic/graphics/osx/preferences/tms.png "$dest"
199 cp $prefix/src/dcpomatic/graphics/osx/preferences/keys.png "$dest"
200 cp $prefix/src/dcpomatic/graphics/osx/preferences/cover_sheet.png "$dest"
201 cp $prefix/src/dcpomatic/graphics/osx/preferences/notifications.png "$dest"
202 cp $prefix/src/dcpomatic/graphics/osx/preferences/locations.png "$dest"
203 cp $prefix/src/dcpomatic/graphics/osx/preferences/sound.png "$dest"
204 cp $prefix/src/dcpomatic/fonts/LiberationSans-Regular.ttf "$dest"
205 cp $prefix/src/dcpomatic/fonts/LiberationSans-Italic.ttf "$dest"
206 cp $prefix/src/dcpomatic/fonts/LiberationSans-Bold.ttf "$dest"
207 cp $prefix/src/dcpomatic/fonts/fonts.conf.osx "$dest"/fonts.conf
208 cp $prefix/src/dcpomatic/graphics/splash.png "$dest"
209 cp $prefix/src/dcpomatic/graphics/zoom.png "$dest"
210 cp $prefix/src/dcpomatic/graphics/zoom_all.png "$dest"
211 cp $prefix/src/dcpomatic/graphics/select.png "$dest"
212 cp $prefix/src/dcpomatic/graphics/snap.png "$dest"
213 cp $prefix/src/dcpomatic/graphics/sequence.png "$dest"
214 cp $prefix/src/dcpomatic/graphics/me.jpg "$dest"
215 cp -r $prefix/share/libdcp/xsd "$dest"
217 # i18n: DCP-o-matic .mo files
218 for lang in de_DE es_ES fr_FR it_IT sv_SE nl_NL ru_RU pl_PL da_DK pt_PT pt_BR sk_SK cs_CZ uk_UA zh_CN tr_TR; do
219 mkdir -p "$dest/$lang/LC_MESSAGES"
220 cp $prefix/src/dcpomatic/build/src/lib/mo/$lang/*.mo "$dest/$lang/LC_MESSAGES"
221 cp $prefix/src/dcpomatic/build/src/wx/mo/$lang/*.mo "$dest/$lang/LC_MESSAGES"
222 cp $prefix/src/dcpomatic/build/src/tools/mo/$lang/*.mo "$dest/$lang/LC_MESSAGES"
225 # i18n: wxWidgets .mo files
226 for lang in de es fr it sv nl ru pl da cs; do
228 cp $ENV/64/share/locale/$lang/LC_MESSAGES/wxstd.mo "$dest/$lang"
232 # param $1 list of things that link to other things
234 to_relink=`echo $to_relink | sed -e "s/\+//g"`
237 for obj in "${linkers[@]}"; do
238 deps=`otool -L "$obj" | awk '{print $1}' | egrep "($to_relink)" | egrep "($ENV|$ROOT|boost|libicu)"`
242 if [ "$TYPE" == "universal" ]; then
243 # $dep will be a path within 64/; make a 32/ path too
244 dep32=`echo $dep | sed -e "s/\/64\//\/32\//g"`
245 changes="$changes -change $dep @executable_path/../Frameworks/$base -change $dep32 @executable_path/../Frameworks/$base"
247 changes="$changes -change $dep @executable_path/../Frameworks/$base"
250 if test "x$changes" != "x"; then
251 install_name_tool $changes -id `basename "$obj"` "$obj"
257 codesign --deep --force --verify --verbose --options runtime --sign "Developer ID Application: Carl Hetherington (R82DXSR997)" "$1"
258 if [ "$?" != "0" ]; then
259 echo "Failed to sign $1"
265 # @param #1 .app directory
266 # @param #2 .pkg or ""
267 # @param #3 full name e.g. DCP-o-matic Batch Converter
268 # @param #4 bundle id e.g. com.dcpomatic.batch
274 tmp_dmg=dcpomatic_tmp.dmg
275 dmg="$full_name $version.dmg"
276 vol_name=DCP-o-matic-$version
280 if [ "$pkg" != "" ]; then
281 productsign --sign "Developer ID Installer: Carl Hetherington (R82DXSR997)" "$pkg" "signed_temp.pkg"
282 if [ "$?" != "0" ]; then
283 echo "Failed to sign .pkg"
286 mv signed_temp.pkg "$pkg"
290 cp -a "$appdir" $vol_name
291 if [ "$pkg" != "" ]; then
292 cp -a "$pkg" $vol_name
294 ln -s /Applications "$vol_name/Applications"
295 cat<<EOF > "$vol_name/READ ME.txt"
296 Welcome to DCP-o-matic! The first time you run the program there may be
297 a long (several-minute) delay while OS X checks the code for viruses and
298 other malware. Please be patient!
300 cat<<EOF > "$vol_name/READ ME.de_DE.txt"
301 Beim erstmaligen Start der DCP-o-matic Anwendungen kann ein längerer
302 Verifikationsvorgang auftreten. Dies ist von der OS X Sicherheitsumgebung
303 'Gatekeeper' verursacht. Dieser je nach Rechner teils minutenlange
304 Verifikationsvorgang ist gegenwärtig normal und nicht zu umgehen,
305 es ist kein Programmfehler. Warten sie die Verifikation für jede der
306 DCP-o-matic Anwendungen ab, bei weiteren Programmstarts wird sie nicht
310 if [ "$pkg" != "" ]; then
311 cat<<EOF > "$vol_name/READ ME.txt"
313 To run this software successfully you must install $pkg before running
318 if [ "$pkg" != "" ]; then
319 cat<<EOF > "$vol_name/READ ME_de.DE.txt"
321 To run this software successfully you must install $pkg before running
326 rm -f $tmp_dmg "$dmg"
327 hdiutil create -srcfolder $vol_name -volname $vol_name -fs HFS+ -fsargs "-c c=64,a=16,e=16" -format UDRW -size $DMG_SIZE $tmp_dmg
328 attach=$(hdiutil attach -readwrite -noverify -noautoopen $tmp_dmg)
329 device=`echo $attach | egrep '^/dev/' | sed 1q | awk '{print $5}'`
333 tell application "Finder"
334 tell disk "'$vol_name'"
336 set current view of container window to icon view
337 set toolbar visible of container window to false
338 set statusbar visible of container window to false
339 set the bounds of container window to {400, 200, 940, 300}
340 set theViewOptions to the icon view options of container window
341 set arrangement of theViewOptions to not arranged
342 set icon size of theViewOptions to 64
343 set position of item "'$appdir'" of container window to {90, 80}
344 set position of item "Applications" of container window to {265, 80}
345 set position of item "READ ME.txt" of container window to {430, 80}
346 set position of item "READ ME.de_DE.txt" of container window to {595, 80}
347 set position of item "DCP-o-matic Disk Writer.pkg" of container window to {90, 255}
350 update without registering applications
356 chmod -Rf go-w /Volumes/"$vol_name"/"$appdir"
359 hdiutil eject $device
360 hdiutil convert -format UDZO $tmp_dmg -imagekey zlib-level=9 -o "$dmg"
361 sips -i "$appdir/Contents/Resources/dcpomatic2.icns"
362 DeRez -only icns "$appdir/Contents/Resources/dcpomatic2.icns" > "$appdir/Contents/Resources/DCP-o-matic.rsrc"
363 Rez -append "$appdir/Contents/Resources/DCP-o-matic.rsrc" -o "$dmg"
368 codesign --verify --verbose --options runtime --sign "Developer ID Application: Carl Hetherington (R82DXSR997)" "$dmg"
370 # We only notarize thin builds, as if we're building universal binaries we must be on an OS
371 # sufficiently old that it can't notarize anyway
372 if [ "$TYPE" == "thin" ]; then
374 id=$(xcrun altool --notarize-app -t osx -f "$dmg" --primary-bundle-id $bundle_id -u $APPLE_ID -p $APPLE_PASSWORD --output-format xml | grep -C1 RequestUUID | tail -n 1 | sed -e "s/<string>//g" | sed -e "s/<\/string>//g")
377 echo "Checking up on $id"
378 status=$(xcrun altool --notarization-info $id -u $APPLE_ID -p $APPLE_PASSWORD --output-format xml)
379 summary=$(echo "$status" | grep -C1 "<key>Status</key>" | tail -n 1 | sed -e "s/ .//g")
381 if [ "$summary" == "<string>invalid</string>" ]; then
382 echo "Notarization failed."
386 if [ "$summary" == "<string>success</string>" ]; then
391 if [ "$N" == "30" ]; then
392 echo "Timed out waiting for notarization"
397 xcrun stapler staple "$dmg"
408 approot="$appdir/Contents"
410 mkdir -p "$approot/MacOS"
411 mkdir -p "$approot/Frameworks"
412 mkdir -p "$approot/Resources"
414 to_relink="dcpomatic"
415 copy_libs "$approot/Frameworks"
416 copy_resources "$approot/Resources"
429 ##setup "DCP-o-matic 2.app"
430 ##copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2 "$approot/MacOS"
431 ##copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_cli "$approot/MacOS"
432 ##copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_create "$approot/MacOS"
433 ##copy $ROOT bin/ffprobe "$approot/MacOS"
434 ##copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
435 ##cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2.Info.plist "$approot/Info.plist"
436 ##rl=("$approot/MacOS/dcpomatic2" "$approot/MacOS/dcpomatic2_cli" "$approot/MacOS/dcpomatic2_create" "$approot/MacOS/ffprobe" "$approot/Frameworks/"*.dylib)
438 ##make_dmg "$appdir" "" "DCP-o-matic" com.dcpomatic
440 # DCP-o-matic KDM Creator
441 ##setup "DCP-o-matic 2 KDM Creator.app"
442 ##copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_kdm "$approot/MacOS"
443 ##copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_kdm_cli "$approot/MacOS"
444 ##copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
445 ##cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_kdm.Info.plist "$approot/Info.plist"
446 ##rl=("$approot/MacOS/dcpomatic2_kdm" "$approot/MacOS/dcpomatic2_kdm_cli" "$approot/Frameworks/"*.dylib)
448 ##make_dmg "$appdir" "" "DCP-o-matic KDM Creator" com.dcpomatic.kdm
450 # DCP-o-matic Encode Server
451 ##setup "DCP-o-matic 2 Encode Server.app"
452 ##copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_server "$approot/MacOS"
453 ##copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_server_cli "$approot/MacOS"
454 ##copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
455 ##cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_server.Info.plist "$approot/Info.plist"
456 ##rl=("$approot/MacOS/dcpomatic2_server" "$approot/MacOS/dcpomatic2_server_cli" "$approot/Frameworks/"*.dylib)
458 ##make_dmg "$appdir" "" "DCP-o-matic Encode Server" com.dcpomatic.server
460 # DCP-o-matic Batch Converter
461 ##setup "DCP-o-matic 2 Batch converter.app"
462 ##copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_batch "$approot/MacOS"
463 ##copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
464 ##cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_batch.Info.plist "$approot/Info.plist"
465 ##rl=("$approot/MacOS/dcpomatic2_batch" "$approot/Frameworks/"*.dylib)
467 ##make_dmg "$appdir" "" "DCP-o-matic Batch Converter" com.dcpomatic.batch
470 ##setup "DCP-o-matic 2 Player.app"
471 ##copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_player "$approot/MacOS"
472 ##copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
473 ##cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_player.Info.plist "$approot/Info.plist"
474 ##rl=("$approot/MacOS/dcpomatic2_player" "$approot/Frameworks/"*.dylib)
476 ##make_dmg "$appdir" "" "DCP-o-matic Player" com.dcpomatic.player
478 # DCP-o-matic Playlist Editor
479 ##setup "DCP-o-matic 2 Playlist Editor.app"
480 ##copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_playlist "$approot/MacOS"
481 ##copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
482 ##cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_playlist.Info.plist "$approot/Info.plist"
483 ##rl=("$approot/MacOS/dcpomatic2_playlist" "$approot/Frameworks/"*.dylib)
485 ##make_dmg "$appdir" "" "DCP-o-matic Playlist Editor" com.dcpomatic.playlist
487 # DCP-o-matic Disk Writer .app
488 setup "DCP-o-matic 2 Disk Writer.app"
489 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_disk "$approot/MacOS"
490 # XXX: this shouldn't really be necessary
491 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
492 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_disk.Info.plist "$approot/Info.plist"
493 rl=("$approot/MacOS/dcpomatic2_disk" "$approot/Frameworks/"*.dylib)
496 # DCP-o-matic Disk Writer daemon .pkg
497 pkgbase=tmp-disk-writer
500 pkgroot=$pkgbase/root
501 mkdir -p $pkgroot/Library/LaunchDaemons
502 cat > $pkgroot/Library/LaunchDaemons/com.dcpomatic.disk.writer.plist <<EOF
503 <?xml version="1.0" encoding="UTF-8"?>
504 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
505 <plist version="1.0">
508 <string>com.dcpomatic.disk.writer</string>
509 <key>ProgramArguments</key>
511 <string>/Library/Application Support/com.dcpomatic/dcpomatic2_disk_writer</string>
513 <key>EnvironmentVariables</key>
515 <key>DYLD_LIBRARY_PATH</key>
516 <string><![CDATA[/Library/Application Support/com.dcpomatic]]></string>
524 <key>StandardOutPath</key>
525 <string>/Users/carl/damon.out.log</string>
526 <key>StandardErrorPath</key>
527 <string>/Users/carl/damon.err.log</string>
532 mkdir -p "$pkgroot/Library/Application Support/com.dcpomatic"
533 target="$pkgroot/Library/Application Support/com.dcpomatic"
534 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_disk_writer "$target"
535 copy_lib_root libcxml "$target"
536 copy_lib_env libboost_system "$target"
537 copy_lib_env libboost_filesystem "$target"
538 copy_lib_env libboost_thread "$target"
539 copy_lib_env libboost_date_time "$target"
540 copy_lib_env libboost_locale "$target"
541 copy_lib_env libboost_regex "$target"
542 copy_lib_env libicui18n "$target"
543 copy_lib_env libicudata "$target"
544 copy_lib_env libicuio "$target"
545 copy_lib_env libicule "$target"
546 copy_lib_env libiculx "$target"
547 copy_lib_env libicutest "$target"
548 copy_lib_env libicutu "$target"
549 copy_lib_env libicuuc "$target"
551 rl=("$target/dcpomatic2_disk_writer" "$target/"*.dylib)
554 mkdir $pkgbase/scripts
555 cat > $pkgbase/scripts/postinstall <<EOF
557 /bin/launchctl load "/Library/LaunchDaemons/com.dcpomatic.disk.writer.plist"
560 chmod gou+x $pkgbase/scripts/postinstall
562 find "$target" -iname "*.dylib" -print0 | while IFS= read -r -d '' f; do
565 sign "$target/dcpomatic2_disk_writer"
567 pkgbuild --root $pkgroot --identifier com.dcpomatic.disk.writer --scripts $pkgbase/scripts "DCP-o-matic Disk Writer.pkg"
569 make_dmg "$appdir" "DCP-o-matic Disk Writer.pkg" "DCP-o-matic Disk Writer" com.dcpomatic.disk