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/fonts/LiberationSans-Regular.ttf "$dest"
206 cp $prefix/src/dcpomatic/fonts/LiberationSans-Italic.ttf "$dest"
207 cp $prefix/src/dcpomatic/fonts/LiberationSans-Bold.ttf "$dest"
208 cp $prefix/src/dcpomatic/fonts/fonts.conf.osx "$dest"/fonts.conf
209 cp $prefix/src/dcpomatic/graphics/splash.png "$dest"
210 cp $prefix/src/dcpomatic/graphics/zoom.png "$dest"
211 cp $prefix/src/dcpomatic/graphics/zoom_all.png "$dest"
212 cp $prefix/src/dcpomatic/graphics/select.png "$dest"
213 cp $prefix/src/dcpomatic/graphics/snap.png "$dest"
214 cp $prefix/src/dcpomatic/graphics/sequence.png "$dest"
215 cp $prefix/src/dcpomatic/graphics/me.jpg "$dest"
216 cp $prefix/src/dcpomatic/graphics/link.png "$dest"
217 cp -r $prefix/share/libdcp/xsd "$dest"
219 # i18n: DCP-o-matic .mo files
220 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
221 mkdir -p "$dest/$lang/LC_MESSAGES"
222 cp $prefix/src/dcpomatic/build/src/lib/mo/$lang/*.mo "$dest/$lang/LC_MESSAGES"
223 cp $prefix/src/dcpomatic/build/src/wx/mo/$lang/*.mo "$dest/$lang/LC_MESSAGES"
224 cp $prefix/src/dcpomatic/build/src/tools/mo/$lang/*.mo "$dest/$lang/LC_MESSAGES"
227 # i18n: wxWidgets .mo files
228 for lang in de es fr it sv nl ru pl da cs; do
230 cp $ENV/64/share/locale/$lang/LC_MESSAGES/wxstd.mo "$dest/$lang"
234 # param $1 list of things that link to other things
235 function relink_relative {
236 to_relink=`echo $to_relink | sed -e "s/\+//g"`
239 for obj in "${linkers[@]}"; do
240 deps=`otool -L "$obj" | awk '{print $1}' | egrep "($to_relink)" | egrep "($ENV|$ROOT|boost|libicu)"`
244 if [ "$TYPE" == "universal" ]; then
245 # $dep will be a path within 64/; make a 32/ path too
246 dep32=`echo $dep | sed -e "s/\/64\//\/32\//g"`
247 changes="$changes -change $dep @executable_path/../Frameworks/$base -change $dep32 @executable_path/../Frameworks/$base"
249 changes="$changes -change $dep @executable_path/../Frameworks/$base"
252 if test "x$changes" != "x"; then
253 install_name_tool $changes -id `basename "$obj"` "$obj"
258 # param $1 directory things should be relinked into
259 # $2 list of things that link to other things
260 function relink_absolute {
261 to_relink=`echo $to_relink | sed -e "s/\+//g"`
266 for obj in "${linkers[@]}"; do
267 deps=`otool -L "$obj" | awk '{print $1}' | egrep "($to_relink)" | egrep "($ENV|$ROOT|boost|libicu)"`
270 install_name_tool -change "$dep" "$target"/$base -id `basename "$obj"` "$obj"
276 codesign --deep --force --verify --verbose --options runtime --sign "Developer ID Application: Carl Hetherington (R82DXSR997)" "$1"
277 if [ "$?" != "0" ]; then
278 echo "Failed to sign $1"
284 # @param #1 .app directory
285 # @param #2 .pkg or ""
286 # @param #3 full name e.g. DCP-o-matic Batch Converter
287 # @param #4 bundle id e.g. com.dcpomatic.batch
293 tmp_dmg=dcpomatic_tmp.dmg
294 dmg="$full_name $version.dmg"
295 vol_name=DCP-o-matic-$version
299 if [ "$pkg" != "" ]; then
300 productsign --sign "Developer ID Installer: Carl Hetherington (R82DXSR997)" "$pkg" "signed_temp.pkg"
301 if [ "$?" != "0" ]; then
302 echo "Failed to sign .pkg"
305 mv signed_temp.pkg "$pkg"
309 cp -a "$appdir" $vol_name
310 if [ "$pkg" != "" ]; then
311 cp -a "$pkg" $vol_name
313 ln -s /Applications "$vol_name/Applications"
314 cat<<EOF > "$vol_name/READ ME.txt"
315 Welcome to DCP-o-matic! The first time you run the program there may be
316 a long (several-minute) delay while OS X checks the code for viruses and
317 other malware. Please be patient!
319 cat<<EOF > "$vol_name/READ ME.de_DE.txt"
320 Beim erstmaligen Start der DCP-o-matic Anwendungen kann ein längerer
321 Verifikationsvorgang auftreten. Dies ist von der OS X Sicherheitsumgebung
322 'Gatekeeper' verursacht. Dieser je nach Rechner teils minutenlange
323 Verifikationsvorgang ist gegenwärtig normal und nicht zu umgehen,
324 es ist kein Programmfehler. Warten sie die Verifikation für jede der
325 DCP-o-matic Anwendungen ab, bei weiteren Programmstarts wird sie nicht
329 if [ "$pkg" != "" ]; then
330 cat<<EOF > "$vol_name/READ ME.txt"
332 To run this software successfully you must install $pkg before running
337 if [ "$pkg" != "" ]; then
338 cat<<EOF > "$vol_name/READ ME.de_DE.txt"
340 To run this software successfully you must install $pkg before running
345 rm -f $tmp_dmg "$dmg"
346 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
347 attach=$(hdiutil attach -readwrite -noverify -noautoopen $tmp_dmg)
348 device=`echo $attach | egrep '^/dev/' | sed 1q | awk '{print $5}'`
352 tell application "Finder"
353 tell disk "'$vol_name'"
355 set current view of container window to icon view
356 set toolbar visible of container window to false
357 set statusbar visible of container window to false
358 set the bounds of container window to {400, 200, 1160, 600}
359 set the bounds of container window to {400, 200, 1160, 600}
360 set the bounds of container window to {400, 200, 1160, 600}
361 set theViewOptions to the icon view options of container window
362 set arrangement of theViewOptions to not arranged
363 set icon size of theViewOptions to 64
364 set position of item "'$appdir'" of container window to {90, 80}
365 set position of item "Applications" of container window to {265, 80}
366 set position of item "READ ME.txt" of container window to {430, 80}
367 set position of item "READ ME.de_DE.txt" of container window to {595, 80}
368 set position of item "DCP-o-matic Disk Writer.pkg" of container window to {90, 255}
371 update without registering applications
377 chmod -Rf go-w /Volumes/"$vol_name"/"$appdir"
380 hdiutil eject $device
381 hdiutil convert -format UDZO $tmp_dmg -imagekey zlib-level=9 -o "$dmg"
382 sips -i "$appdir/Contents/Resources/dcpomatic2.icns"
383 DeRez -only icns "$appdir/Contents/Resources/dcpomatic2.icns" > "$appdir/Contents/Resources/DCP-o-matic.rsrc"
384 Rez -append "$appdir/Contents/Resources/DCP-o-matic.rsrc" -o "$dmg"
389 codesign --verify --verbose --options runtime --sign "Developer ID Application: Carl Hetherington (R82DXSR997)" "$dmg"
391 # We only notarize thin builds, as if we're building universal binaries we must be on an OS
392 # sufficiently old that it can't notarize anyway
393 if [ "$TYPE" == "thin" ]; then
395 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")
398 echo "Checking up on $id"
400 status=$(xcrun altool --notarization-info $id -u $APPLE_ID -p $APPLE_PASSWORD --output-format xml)
402 summary=$(echo "$status" | grep -C1 "<key>Status</key>" | tail -n 1 | sed -e "s/ .//g")
404 if [ "$summary" == "<string>invalid</string>" ]; then
405 echo "Notarization failed."
409 if [ "$summary" == "<string>success</string>" ]; then
414 if [ "$N" == "30" ]; then
415 echo "Timed out waiting for notarization"
420 xcrun stapler staple "$dmg"
431 approot="$appdir/Contents"
433 mkdir -p "$approot/MacOS"
434 mkdir -p "$approot/Frameworks"
435 mkdir -p "$approot/Resources"
437 to_relink="dcpomatic"
438 copy_libs "$approot/Frameworks"
439 copy_resources "$approot/Resources"
452 setup "DCP-o-matic 2.app"
453 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2 "$approot/MacOS"
454 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_cli "$approot/MacOS"
455 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_create "$approot/MacOS"
456 copy $ROOT bin/ffprobe "$approot/MacOS"
457 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
458 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2.Info.plist "$approot/Info.plist"
459 rl=("$approot/MacOS/dcpomatic2" "$approot/MacOS/dcpomatic2_cli" "$approot/MacOS/dcpomatic2_create" "$approot/MacOS/ffprobe" "$approot/Frameworks/"*.dylib)
460 relink_relative "${rl[@]}"
461 make_dmg "$appdir" "" "DCP-o-matic" com.dcpomatic
463 # DCP-o-matic KDM Creator
464 setup "DCP-o-matic 2 KDM Creator.app"
465 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_kdm "$approot/MacOS"
466 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_kdm_cli "$approot/MacOS"
467 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
468 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_kdm.Info.plist "$approot/Info.plist"
469 rl=("$approot/MacOS/dcpomatic2_kdm" "$approot/MacOS/dcpomatic2_kdm_cli" "$approot/Frameworks/"*.dylib)
470 relink_relative "${rl[@]}"
471 make_dmg "$appdir" "" "DCP-o-matic KDM Creator" com.dcpomatic.kdm
473 # DCP-o-matic Encode Server
474 setup "DCP-o-matic 2 Encode Server.app"
475 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_server "$approot/MacOS"
476 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_server_cli "$approot/MacOS"
477 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
478 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_server.Info.plist "$approot/Info.plist"
479 rl=("$approot/MacOS/dcpomatic2_server" "$approot/MacOS/dcpomatic2_server_cli" "$approot/Frameworks/"*.dylib)
480 relink_relative "${rl[@]}"
481 make_dmg "$appdir" "" "DCP-o-matic Encode Server" com.dcpomatic.server
483 # DCP-o-matic Batch Converter
484 setup "DCP-o-matic 2 Batch converter.app"
485 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_batch "$approot/MacOS"
486 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
487 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_batch.Info.plist "$approot/Info.plist"
488 rl=("$approot/MacOS/dcpomatic2_batch" "$approot/Frameworks/"*.dylib)
489 relink_relative "${rl[@]}"
490 make_dmg "$appdir" "" "DCP-o-matic Batch Converter" com.dcpomatic.batch
493 setup "DCP-o-matic 2 Player.app"
494 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_player "$approot/MacOS"
495 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
496 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_player.Info.plist "$approot/Info.plist"
497 rl=("$approot/MacOS/dcpomatic2_player" "$approot/Frameworks/"*.dylib)
498 relink_relative "${rl[@]}"
499 make_dmg "$appdir" "" "DCP-o-matic Player" com.dcpomatic.player
501 # DCP-o-matic Playlist Editor
502 setup "DCP-o-matic 2 Playlist Editor.app"
503 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_playlist "$approot/MacOS"
504 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
505 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_playlist.Info.plist "$approot/Info.plist"
506 rl=("$approot/MacOS/dcpomatic2_playlist" "$approot/Frameworks/"*.dylib)
507 relink_relative "${rl[@]}"
508 make_dmg "$appdir" "" "DCP-o-matic Playlist Editor" com.dcpomatic.playlist
510 # DCP-o-matic Disk Writer .app
511 setup "DCP-o-matic 2 Disk Writer.app"
512 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_disk "$approot/MacOS"
513 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
514 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_disk.Info.plist "$approot/Info.plist"
515 rl=("$approot/MacOS/dcpomatic2_disk" "$approot/Frameworks/"*.dylib)
516 relink_relative "${rl[@]}"
518 # DCP-o-matic Disk Writer daemon .pkg
520 pkgbase=tmp-disk-writer
524 pkgroot=$pkgbase/root
526 mkdir -p $pkgroot/Library/LaunchDaemons
527 cat > $pkgroot/Library/LaunchDaemons/com.dcpomatic.disk.writer.plist <<EOF
528 <?xml version="1.0" encoding="UTF-8"?>
529 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
530 <plist version="1.0">
533 <string>com.dcpomatic.disk.writer</string>
534 <key>ProgramArguments</key>
536 <string>/Library/Application Support/com.dcpomatic/dcpomatic2_disk_writer</string>
538 <key>EnvironmentVariables</key>
540 <key>DYLD_LIBRARY_PATH</key>
541 <string><![CDATA[/Library/Application Support/com.dcpomatic]]></string>
543 <key>StandardOutPath</key>
544 <string>/var/log/dcpomatic_disk_writer_out.log</string>
545 <key>StandardErrorPath</key>
546 <string>/var/log/dcpomatic_disk_writer_err.log</string>
547 <key>LaunchEvents</key>
549 <key>com.apple.notifyd.matching</key>
551 <key>com.dcpomatic.disk.writer.start</key>
553 <key>Notification</key>
554 <string>com.dcpomatic.disk.writer.start</string>
562 # Get the binaries together in $pkgbin then move them to the
563 # place with spaces in the filename to avoid some of the pain of escaping
566 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_disk_writer "$pkgbin"
569 rl=("$pkgbin/dcpomatic2_disk_writer" "$pkgbin/"*.dylib)
570 relink_absolute "/Library/Application Support/com.dcpomatic" "${rl[@]}"
572 mkdir $pkgbase/scripts
573 cat > $pkgbase/scripts/postinstall <<EOF
575 /bin/launchctl unload "/Library/LaunchDaemons/com.dcpomatic.disk.writer.plist"
576 /bin/launchctl load "/Library/LaunchDaemons/com.dcpomatic.disk.writer.plist"
579 chmod gou+x $pkgbase/scripts/postinstall
581 find "$pkgbin" -iname "*.dylib" -print0 | while IFS= read -r -d '' f; do
584 sign "$pkgbin/dcpomatic2_disk_writer"
586 mkdir -p "$pkgroot/Library/Application Support/com.dcpomatic"
587 mv $pkgbin/* "$pkgroot/Library/Application Support/com.dcpomatic/"
588 pkgbuild --root $pkgroot --identifier com.dcpomatic.disk.writer --scripts $pkgbase/scripts "DCP-o-matic Disk Writer.pkg"
590 make_dmg "$appdir" "DCP-o-matic Disk Writer.pkg" "DCP-o-matic Disk Writer" com.dcpomatic.disk