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
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_lib_root libleqm_nrt "$dest"
128 copy $ROOT src/dcpomatic/build/src/lib/libdcpomatic2.dylib "$dest"
129 copy $ROOT src/dcpomatic/build/src/wx/libdcpomatic2-wx.dylib "$dest"
130 copy_lib_env libboost_system "$dest"
131 copy_lib_env libboost_filesystem "$dest"
132 copy_lib_env libboost_thread "$dest"
133 copy_lib_env libboost_date_time "$dest"
134 copy_lib_env libboost_locale "$dest"
135 copy_lib_env libboost_regex "$dest"
136 copy_lib_env libxml++ "$dest"
137 copy_lib_env libxslt "$dest"
138 copy_lib_env libxml2 "$dest"
139 copy_lib_env libglibmm-2.4 "$dest"
140 copy_lib_env libgobject "$dest"
141 copy_lib_env libgthread "$dest"
142 copy_lib_env libgmodule "$dest"
143 copy_lib_env libsigc "$dest"
144 copy_lib_env libglib-2 "$dest"
145 copy_lib_env libintl "$dest"
146 copy_lib_env libsndfile "$dest"
147 copy_lib_env libssh "$dest"
148 copy_lib_env libwx "$dest"
149 copy_lib_env libfontconfig "$dest"
150 copy_lib_env libfreetype "$dest"
151 copy_lib_env libexpat "$dest"
152 copy_lib_env libltdl "$dest"
153 copy_lib_env libxmlsec1 "$dest"
154 copy_lib_env libcurl "$dest"
155 copy_lib_env libffi "$dest"
156 copy_lib_env libpango "$dest"
157 copy_lib_env libcairo "$dest"
158 copy_lib_env libpixman "$dest"
159 copy_lib_env libharfbuzz "$dest"
160 copy_lib_env libsamplerate "$dest"
161 copy_lib_env libicui18n "$dest"
162 copy_lib_env libicudata "$dest"
163 copy_lib_env libicuio "$dest"
164 copy_lib_env libicule "$dest"
165 copy_lib_env libiculx "$dest"
166 copy_lib_env libicutest "$dest"
167 copy_lib_env libicutu "$dest"
168 copy_lib_env libicuuc "$dest"
169 copy_lib_env libFLAC "$dest"
170 copy_lib_env libvorbis "$dest"
171 copy_lib_env libogg "$dest"
172 copy_lib_env libxerces-c "$dest"
175 # @param #1 directory to copy to
176 function copy_resources {
180 local prefix=$ROOT/32
186 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic_small.png "$dest"
187 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2.icns "$dest"
188 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2_kdm.icns "$dest"
189 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2_server.icns "$dest"
190 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2_player.icns "$dest"
191 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2_batch.icns "$dest"
192 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2_playlist.icns "$dest"
193 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2_disk.icns "$dest"
194 cp $prefix/src/dcpomatic/graphics/osx/preferences/colour_conversions.png "$dest"
195 cp $prefix/src/dcpomatic/graphics/osx/preferences/defaults.png "$dest"
196 cp $prefix/src/dcpomatic/graphics/osx/preferences/kdm_email.png "$dest"
197 cp $prefix/src/dcpomatic/graphics/osx/preferences/email.png "$dest"
198 cp $prefix/src/dcpomatic/graphics/osx/preferences/servers.png "$dest"
199 cp $prefix/src/dcpomatic/graphics/osx/preferences/tms.png "$dest"
200 cp $prefix/src/dcpomatic/graphics/osx/preferences/keys.png "$dest"
201 cp $prefix/src/dcpomatic/graphics/osx/preferences/cover_sheet.png "$dest"
202 cp $prefix/src/dcpomatic/graphics/osx/preferences/notifications.png "$dest"
203 cp $prefix/src/dcpomatic/graphics/osx/preferences/locations.png "$dest"
204 cp $prefix/src/dcpomatic/graphics/osx/preferences/sound.png "$dest"
205 cp $prefix/src/dcpomatic/graphics/osx/preferences/identifiers.png "$dest"
206 cp $prefix/src/dcpomatic/fonts/LiberationSans-Regular.ttf "$dest"
207 cp $prefix/src/dcpomatic/fonts/LiberationSans-Italic.ttf "$dest"
208 cp $prefix/src/dcpomatic/fonts/LiberationSans-Bold.ttf "$dest"
209 cp $prefix/src/dcpomatic/fonts/fonts.conf.osx "$dest"/fonts.conf
210 cp $prefix/src/dcpomatic/graphics/splash.png "$dest"
211 cp $prefix/src/dcpomatic/graphics/zoom.png "$dest"
212 cp $prefix/src/dcpomatic/graphics/zoom_all.png "$dest"
213 cp $prefix/src/dcpomatic/graphics/select.png "$dest"
214 cp $prefix/src/dcpomatic/graphics/snap.png "$dest"
215 cp $prefix/src/dcpomatic/graphics/sequence.png "$dest"
216 cp $prefix/src/dcpomatic/graphics/me.jpg "$dest"
217 cp $prefix/src/dcpomatic/graphics/link.png "$dest"
218 cp -r $prefix/src/dcpomatic/graphics/help "$dest"
219 cp -r $prefix/share/libdcp/xsd "$dest"
221 # i18n: DCP-o-matic .mo files
222 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
223 mkdir -p "$dest/$lang/LC_MESSAGES"
224 cp $prefix/src/dcpomatic/build/src/lib/mo/$lang/*.mo "$dest/$lang/LC_MESSAGES"
225 cp $prefix/src/dcpomatic/build/src/wx/mo/$lang/*.mo "$dest/$lang/LC_MESSAGES"
226 cp $prefix/src/dcpomatic/build/src/tools/mo/$lang/*.mo "$dest/$lang/LC_MESSAGES"
229 # i18n: wxWidgets .mo files
230 for lang in de es fr it sv nl ru pl da cs; do
232 cp $ENV/64/share/locale/$lang/LC_MESSAGES/wxstd.mo "$dest/$lang"
236 # param $1 list of things that link to other things
237 function relink_relative {
238 to_relink=`echo $to_relink | sed -e "s/\+//g"`
241 for obj in "${linkers[@]}"; do
242 deps=`otool -L "$obj" | awk '{print $1}' | egrep "($to_relink)" | egrep "($ENV|$ROOT|boost|libicu)"`
246 if [ "$TYPE" == "universal" ]; then
247 # $dep will be a path within 64/; make a 32/ path too
248 dep32=`echo $dep | sed -e "s/\/64\//\/32\//g"`
249 changes="$changes -change $dep @executable_path/../Frameworks/$base -change $dep32 @executable_path/../Frameworks/$base"
251 changes="$changes -change $dep @executable_path/../Frameworks/$base"
254 if test "x$changes" != "x"; then
255 install_name_tool $changes -id `basename "$obj"` "$obj"
260 # param $1 directory things should be relinked into
261 # $2 list of things that link to other things
262 function relink_absolute {
263 to_relink=`echo $to_relink | sed -e "s/\+//g"`
268 for obj in "${linkers[@]}"; do
269 deps=`otool -L "$obj" | awk '{print $1}' | egrep "($to_relink)" | egrep "($ENV|$ROOT|boost|libicu)"`
272 install_name_tool -change "$dep" "$target"/$base -id `basename "$obj"` "$obj"
278 codesign --deep --force --verify --verbose --options runtime --sign "Developer ID Application: Carl Hetherington (R82DXSR997)" "$1"
279 if [ "$?" != "0" ]; then
280 echo "Failed to sign $1"
286 # @param #1 .app directory
287 # @param #2 .pkg or ""
288 # @param #3 full name e.g. DCP-o-matic Batch Converter
289 # @param #4 bundle id e.g. com.dcpomatic.batch
295 tmp_dmg=dcpomatic_tmp.dmg
296 dmg="$full_name $version.dmg"
297 vol_name=DCP-o-matic-$version
301 if [ "$pkg" != "" ]; then
302 productsign --sign "Developer ID Installer: Carl Hetherington (R82DXSR997)" "$pkg" "signed_temp.pkg"
303 if [ "$?" != "0" ]; then
304 echo "Failed to sign .pkg"
307 mv signed_temp.pkg "$pkg"
311 cp -a "$appdir" $vol_name
312 if [ "$pkg" != "" ]; then
313 cp -a "$pkg" $vol_name
315 ln -s /Applications "$vol_name/Applications"
316 cat<<EOF > "$vol_name/READ ME.txt"
317 Welcome to DCP-o-matic! The first time you run the program there may be
318 a long (several-minute) delay while OS X checks the code for viruses and
319 other malware. Please be patient!
321 cat<<EOF > "$vol_name/READ ME.de_DE.txt"
322 Beim erstmaligen Start der DCP-o-matic Anwendungen kann ein längerer
323 Verifikationsvorgang auftreten. Dies ist von der OS X Sicherheitsumgebung
324 'Gatekeeper' verursacht. Dieser je nach Rechner teils minutenlange
325 Verifikationsvorgang ist gegenwärtig normal und nicht zu umgehen,
326 es ist kein Programmfehler. Warten sie die Verifikation für jede der
327 DCP-o-matic Anwendungen ab, bei weiteren Programmstarts wird sie nicht
331 if [ "$pkg" != "" ]; then
332 cat<<EOF > "$vol_name/READ ME.txt"
334 To run this software successfully you must install $pkg before running
339 if [ "$pkg" != "" ]; then
340 cat<<EOF > "$vol_name/READ ME.de_DE.txt"
342 To run this software successfully you must install $pkg before running
347 rm -f $tmp_dmg "$dmg"
348 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
349 attach=$(hdiutil attach -readwrite -noverify -noautoopen $tmp_dmg)
350 device=`echo $attach | egrep '^/dev/' | sed 1q | awk '{print $5}'`
354 tell application "Finder"
355 tell disk "'$vol_name'"
357 set current view of container window to icon view
358 set toolbar visible of container window to false
359 set statusbar visible of container window to false
360 set the bounds of container window to {400, 200, 1160, 600}
361 set the bounds of container window to {400, 200, 1160, 600}
362 set the bounds of container window to {400, 200, 1160, 600}
363 set theViewOptions to the icon view options of container window
364 set arrangement of theViewOptions to not arranged
365 set icon size of theViewOptions to 64
366 set position of item "'$appdir'" of container window to {90, 80}
367 set position of item "Applications" of container window to {265, 80}
368 set position of item "READ ME.txt" of container window to {430, 80}
369 set position of item "READ ME.de_DE.txt" of container window to {595, 80}
370 set position of item "DCP-o-matic Disk Writer.pkg" of container window to {90, 255}
373 update without registering applications
379 chmod -Rf go-w /Volumes/"$vol_name"/"$appdir"
382 hdiutil eject $device
383 hdiutil convert -format UDZO $tmp_dmg -imagekey zlib-level=9 -o "$dmg"
384 sips -i "$appdir/Contents/Resources/dcpomatic2.icns"
385 DeRez -only icns "$appdir/Contents/Resources/dcpomatic2.icns" > "$appdir/Contents/Resources/DCP-o-matic.rsrc"
386 Rez -append "$appdir/Contents/Resources/DCP-o-matic.rsrc" -o "$dmg"
391 codesign --verify --verbose --options runtime --sign "Developer ID Application: Carl Hetherington (R82DXSR997)" "$dmg"
393 # We only notarize thin builds, as if we're building universal binaries we must be on an OS
394 # sufficiently old that it can't notarize anyway
395 if [ "$TYPE" == "thin" ]; then
397 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")
400 echo "Checking up on $id"
402 status=$(xcrun altool --notarization-info $id -u $APPLE_ID -p $APPLE_PASSWORD --output-format xml)
404 summary=$(echo "$status" | grep -C1 "<key>Status</key>" | tail -n 1 | sed -e "s/ .//g")
406 if [ "$summary" == "<string>invalid</string>" ]; then
407 echo "Notarization failed."
411 if [ "$summary" == "<string>success</string>" ]; then
416 if [ "$N" == "30" ]; then
417 echo "Timed out waiting for notarization"
422 xcrun stapler staple "$dmg"
433 approot="$appdir/Contents"
435 mkdir -p "$approot/MacOS"
436 mkdir -p "$approot/Frameworks"
437 mkdir -p "$approot/Resources"
439 to_relink="dcpomatic"
440 copy_libs "$approot/Frameworks"
441 copy_resources "$approot/Resources"
454 setup "DCP-o-matic 2.app"
455 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2 "$approot/MacOS"
456 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_cli "$approot/MacOS"
457 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_create "$approot/MacOS"
458 copy $ROOT bin/ffprobe "$approot/MacOS"
459 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
460 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2.Info.plist "$approot/Info.plist"
461 rl=("$approot/MacOS/dcpomatic2" "$approot/MacOS/dcpomatic2_cli" "$approot/MacOS/dcpomatic2_create" "$approot/MacOS/ffprobe" "$approot/Frameworks/"*.dylib)
462 relink_relative "${rl[@]}"
463 make_dmg "$appdir" "" "DCP-o-matic" com.dcpomatic
465 # DCP-o-matic KDM Creator
466 setup "DCP-o-matic 2 KDM Creator.app"
467 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_kdm "$approot/MacOS"
468 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_kdm_cli "$approot/MacOS"
469 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
470 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_kdm.Info.plist "$approot/Info.plist"
471 rl=("$approot/MacOS/dcpomatic2_kdm" "$approot/MacOS/dcpomatic2_kdm_cli" "$approot/Frameworks/"*.dylib)
472 relink_relative "${rl[@]}"
473 make_dmg "$appdir" "" "DCP-o-matic KDM Creator" com.dcpomatic.kdm
475 # DCP-o-matic Encode Server
476 setup "DCP-o-matic 2 Encode Server.app"
477 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_server "$approot/MacOS"
478 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_server_cli "$approot/MacOS"
479 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
480 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_server.Info.plist "$approot/Info.plist"
481 rl=("$approot/MacOS/dcpomatic2_server" "$approot/MacOS/dcpomatic2_server_cli" "$approot/Frameworks/"*.dylib)
482 relink_relative "${rl[@]}"
483 make_dmg "$appdir" "" "DCP-o-matic Encode Server" com.dcpomatic.server
485 # DCP-o-matic Batch Converter
486 setup "DCP-o-matic 2 Batch converter.app"
487 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_batch "$approot/MacOS"
488 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
489 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_batch.Info.plist "$approot/Info.plist"
490 rl=("$approot/MacOS/dcpomatic2_batch" "$approot/Frameworks/"*.dylib)
491 relink_relative "${rl[@]}"
492 make_dmg "$appdir" "" "DCP-o-matic Batch Converter" com.dcpomatic.batch
495 setup "DCP-o-matic 2 Player.app"
496 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_player "$approot/MacOS"
497 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
498 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_player.Info.plist "$approot/Info.plist"
499 rl=("$approot/MacOS/dcpomatic2_player" "$approot/Frameworks/"*.dylib)
500 relink_relative "${rl[@]}"
501 make_dmg "$appdir" "" "DCP-o-matic Player" com.dcpomatic.player
503 # DCP-o-matic Playlist Editor
504 setup "DCP-o-matic 2 Playlist Editor.app"
505 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_playlist "$approot/MacOS"
506 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
507 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_playlist.Info.plist "$approot/Info.plist"
508 rl=("$approot/MacOS/dcpomatic2_playlist" "$approot/Frameworks/"*.dylib)
509 relink_relative "${rl[@]}"
510 make_dmg "$appdir" "" "DCP-o-matic Playlist Editor" com.dcpomatic.playlist
512 # DCP-o-matic Disk Writer .app
513 setup "DCP-o-matic 2 Disk Writer.app"
514 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_disk "$approot/MacOS"
515 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
516 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_disk.Info.plist "$approot/Info.plist"
517 rl=("$approot/MacOS/dcpomatic2_disk" "$approot/Frameworks/"*.dylib)
518 relink_relative "${rl[@]}"
520 # DCP-o-matic Disk Writer daemon .pkg
522 pkgbase=tmp-disk-writer
526 pkgroot=$pkgbase/root
528 mkdir -p $pkgroot/Library/LaunchDaemons
529 cat > $pkgroot/Library/LaunchDaemons/com.dcpomatic.disk.writer.plist <<EOF
530 <?xml version="1.0" encoding="UTF-8"?>
531 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
532 <plist version="1.0">
535 <string>com.dcpomatic.disk.writer</string>
536 <key>ProgramArguments</key>
538 <string>/Library/Application Support/com.dcpomatic/dcpomatic2_disk_writer</string>
540 <key>EnvironmentVariables</key>
542 <key>DYLD_LIBRARY_PATH</key>
543 <string><![CDATA[/Library/Application Support/com.dcpomatic]]></string>
545 <key>StandardOutPath</key>
546 <string>/var/log/dcpomatic_disk_writer_out.log</string>
547 <key>StandardErrorPath</key>
548 <string>/var/log/dcpomatic_disk_writer_err.log</string>
549 <key>LaunchEvents</key>
551 <key>com.apple.notifyd.matching</key>
553 <key>com.dcpomatic.disk.writer.start</key>
555 <key>Notification</key>
556 <string>com.dcpomatic.disk.writer.start</string>
564 # Get the binaries together in $pkgbin then move them to the
565 # place with spaces in the filename to avoid some of the pain of escaping
568 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_disk_writer "$pkgbin"
571 rl=("$pkgbin/dcpomatic2_disk_writer" "$pkgbin/"*.dylib)
572 relink_absolute "/Library/Application Support/com.dcpomatic" "${rl[@]}"
574 mkdir $pkgbase/scripts
575 cat > $pkgbase/scripts/postinstall <<EOF
577 /bin/launchctl unload "/Library/LaunchDaemons/com.dcpomatic.disk.writer.plist"
578 /bin/launchctl load "/Library/LaunchDaemons/com.dcpomatic.disk.writer.plist"
581 chmod gou+x $pkgbase/scripts/postinstall
583 find "$pkgbin" -iname "*.dylib" -print0 | while IFS= read -r -d '' f; do
586 sign "$pkgbin/dcpomatic2_disk_writer"
588 mkdir -p "$pkgroot/Library/Application Support/com.dcpomatic"
589 mv $pkgbin/* "$pkgroot/Library/Application Support/com.dcpomatic/"
590 pkgbuild --root $pkgroot --identifier com.dcpomatic.disk.writer --scripts $pkgbase/scripts "DCP-o-matic Disk Writer.pkg"
592 make_dmg "$appdir" "DCP-o-matic Disk Writer.pkg" "DCP-o-matic Disk Writer" com.dcpomatic.disk