3 SYNTAX="make_dmg.sh <environment> <builddir> <type> <disk> <apple-id> <apple-password>"
4 # where <type> is universal or thin
7 # e.g. make_dmg.sh /Users/carl/osx-environment /Users/carl/cdist universal yes foo@bar.net opensesame
9 # Don't set -e here as egrep (used a few times) returns 1 if no matches
12 version=`git describe --tags --abbrev=0 | sed -e "s/v//"`
14 # DMG size in megabytes
23 if [ "$TYPE" != "universal" -a "$TYPE" != "thin" ]; then
25 echo "where <type> is universal or thin"
29 if [ "$DISK" != "yes" -a "$DISK" != "no" ]; then
31 echo "where <disk> is yes or no"
35 # This is our work area for making up the .dmgs
36 mkdir -p build/platform/osx
44 ln -s $(readlink $f) "$3/`basename $f`"
46 g=`echo $f | sed -e "s/\/32\//\/64\//g"`
48 lipo -create $f $g -output "$3/`basename $f`"
54 ln -s $(readlink $1/$2) "$3/`basename $f`"
62 function copy_lib_root {
65 for f in $ROOT/32/lib/$1*.dylib; do
67 ln -s $(readlink $f) "$2/`basename $f`"
69 g=`echo $f | sed -e "s/\/32\//\/64\//g"`
71 lipo -create $f $g -output "$2/`basename $f`"
76 for f in $ROOT/lib/$1*.dylib; do
78 ln -s $(readlink $f) "$2/`basename $f`"
86 to_relink="$to_relink|$1"
89 function copy_lib_env {
92 for f in $ENV/32/lib/$1*.dylib; do
94 ln -s $(readlink $f) "$2/`basename $f`"
96 g=`echo $f | sed -e "s/\/32\//\/64\//g"`
98 lipo -create $f $g -output "$2/`basename $f`"
103 for f in $ENV/64/lib/$1*.dylib; do
105 ln -s $(readlink $f) "$2/`basename $f`"
113 to_relink="$to_relink|$1"
116 # @param #1 directory to copy to
119 copy_lib_root libcxml "$dest"
120 copy_lib_root libdcp-1.0 "$dest"
121 copy_lib_root libasdcp-carl "$dest"
122 copy_lib_root libkumu-carl "$dest"
123 copy_lib_root libsub "$dest"
124 copy_lib_root libopenjp2 "$dest"
125 copy_lib_root libavdevice "$dest"
126 copy_lib_root libavformat "$dest"
127 copy_lib_root libavfilter "$dest"
128 copy_lib_root libavutil "$dest"
129 copy_lib_root libavcodec "$dest"
130 copy_lib_root libswscale "$dest"
131 copy_lib_root libpostproc "$dest"
132 copy_lib_root libswresample "$dest"
133 copy_lib_root liblwext4 "$dest"
134 copy_lib_root libblockdev "$dest"
135 copy $ROOT src/dcpomatic/build/src/lib/libdcpomatic2.dylib "$dest"
136 copy $ROOT src/dcpomatic/build/src/wx/libdcpomatic2-wx.dylib "$dest"
137 copy_lib_env libboost_system "$dest"
138 copy_lib_env libboost_filesystem "$dest"
139 copy_lib_env libboost_thread "$dest"
140 copy_lib_env libboost_date_time "$dest"
141 copy_lib_env libboost_locale "$dest"
142 copy_lib_env libboost_regex "$dest"
143 copy_lib_env libxml++ "$dest"
144 copy_lib_env libxslt "$dest"
145 copy_lib_env libxml2 "$dest"
146 copy_lib_env libglibmm-2.4 "$dest"
147 copy_lib_env libgobject "$dest"
148 copy_lib_env libgthread "$dest"
149 copy_lib_env libgmodule "$dest"
150 copy_lib_env libsigc "$dest"
151 copy_lib_env libglib-2 "$dest"
152 copy_lib_env libintl "$dest"
153 copy_lib_env libsndfile "$dest"
154 copy_lib_env libssh "$dest"
155 copy_lib_env libwx "$dest"
156 copy_lib_env libfontconfig "$dest"
157 copy_lib_env libfreetype "$dest"
158 copy_lib_env libexpat "$dest"
159 copy_lib_env libltdl "$dest"
160 copy_lib_env libxmlsec1 "$dest"
161 copy_lib_env libcurl "$dest"
162 copy_lib_env libffi "$dest"
163 copy_lib_env libpango "$dest"
164 copy_lib_env libcairo "$dest"
165 copy_lib_env libpixman "$dest"
166 copy_lib_env libharfbuzz "$dest"
167 copy_lib_env libsamplerate "$dest"
168 copy_lib_env libicui18n "$dest"
169 copy_lib_env libicudata "$dest"
170 copy_lib_env libicuio "$dest"
171 copy_lib_env libicule "$dest"
172 copy_lib_env libiculx "$dest"
173 copy_lib_env libicutest "$dest"
174 copy_lib_env libicutu "$dest"
175 copy_lib_env libicuuc "$dest"
176 copy_lib_env libFLAC "$dest"
177 copy_lib_env libvorbis "$dest"
178 copy_lib_env libogg "$dest"
179 copy_lib_env libxerces-c "$dest"
182 # @param #1 directory to copy to
183 function copy_resources {
187 local prefix=$ROOT/32
193 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic_small.png "$dest"
194 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2.icns "$dest"
195 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2_kdm.icns "$dest"
196 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2_server.icns "$dest"
197 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2_player.icns "$dest"
198 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2_batch.icns "$dest"
199 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2_playlist.icns "$dest"
200 cp $prefix/src/dcpomatic/graphics/osx/dcpomatic2_disk.icns "$dest"
201 cp $prefix/src/dcpomatic/graphics/osx/preferences/colour_conversions.png "$dest"
202 cp $prefix/src/dcpomatic/graphics/osx/preferences/defaults.png "$dest"
203 cp $prefix/src/dcpomatic/graphics/osx/preferences/kdm_email.png "$dest"
204 cp $prefix/src/dcpomatic/graphics/osx/preferences/email.png "$dest"
205 cp $prefix/src/dcpomatic/graphics/osx/preferences/servers.png "$dest"
206 cp $prefix/src/dcpomatic/graphics/osx/preferences/tms.png "$dest"
207 cp $prefix/src/dcpomatic/graphics/osx/preferences/keys.png "$dest"
208 cp $prefix/src/dcpomatic/graphics/osx/preferences/cover_sheet.png "$dest"
209 cp $prefix/src/dcpomatic/graphics/osx/preferences/notifications.png "$dest"
210 cp $prefix/src/dcpomatic/graphics/osx/preferences/locations.png "$dest"
211 cp $prefix/src/dcpomatic/graphics/osx/preferences/sound.png "$dest"
212 cp $prefix/src/dcpomatic/fonts/LiberationSans-Regular.ttf "$dest"
213 cp $prefix/src/dcpomatic/fonts/LiberationSans-Italic.ttf "$dest"
214 cp $prefix/src/dcpomatic/fonts/LiberationSans-Bold.ttf "$dest"
215 cp $prefix/src/dcpomatic/fonts/fonts.conf.osx "$dest"/fonts.conf
216 cp $prefix/src/dcpomatic/graphics/splash.png "$dest"
217 cp $prefix/src/dcpomatic/graphics/zoom.png "$dest"
218 cp $prefix/src/dcpomatic/graphics/zoom_all.png "$dest"
219 cp $prefix/src/dcpomatic/graphics/select.png "$dest"
220 cp $prefix/src/dcpomatic/graphics/snap.png "$dest"
221 cp $prefix/src/dcpomatic/graphics/sequence.png "$dest"
222 cp $prefix/src/dcpomatic/graphics/me.jpg "$dest"
223 cp -r $prefix/share/libdcp/xsd "$dest"
225 # i18n: DCP-o-matic .mo files
226 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
227 mkdir -p "$dest/$lang/LC_MESSAGES"
228 cp $prefix/src/dcpomatic/build/src/lib/mo/$lang/*.mo "$dest/$lang/LC_MESSAGES"
229 cp $prefix/src/dcpomatic/build/src/wx/mo/$lang/*.mo "$dest/$lang/LC_MESSAGES"
230 cp $prefix/src/dcpomatic/build/src/tools/mo/$lang/*.mo "$dest/$lang/LC_MESSAGES"
233 # i18n: wxWidgets .mo files
234 for lang in de es fr it sv nl ru pl da cs; do
236 cp $ENV/64/share/locale/$lang/LC_MESSAGES/wxstd.mo "$dest/$lang"
240 # param $1 list of things that link to other things
241 function relink_relative {
242 to_relink=`echo $to_relink | sed -e "s/\+//g"`
245 for obj in "${linkers[@]}"; do
246 deps=`otool -L "$obj" | awk '{print $1}' | egrep "($to_relink)" | egrep "($ENV|$ROOT|boost|libicu)"`
250 if [ "$TYPE" == "universal" ]; then
251 # $dep will be a path within 64/; make a 32/ path too
252 dep32=`echo $dep | sed -e "s/\/64\//\/32\//g"`
253 changes="$changes -change $dep @executable_path/../Frameworks/$base -change $dep32 @executable_path/../Frameworks/$base"
255 changes="$changes -change $dep @executable_path/../Frameworks/$base"
258 if test "x$changes" != "x"; then
259 install_name_tool $changes -id `basename "$obj"` "$obj"
264 # param $1 directory things should be relinked into
265 # $2 list of things that link to other things
266 function relink_absolute {
267 to_relink=`echo $to_relink | sed -e "s/\+//g"`
272 for obj in "${linkers[@]}"; do
273 deps=`otool -L "$obj" | awk '{print $1}' | egrep "($to_relink)" | egrep "($ENV|$ROOT|boost|libicu)"`
276 install_name_tool -change "$dep" "$target"/$base -id `basename "$obj"` "$obj"
282 codesign --deep --force --verify --verbose --options runtime --sign "Developer ID Application: Carl Hetherington (R82DXSR997)" "$1"
283 if [ "$?" != "0" ]; then
284 echo "Failed to sign $1"
290 # @param #1 .app directory
291 # @param #2 .pkg or ""
292 # @param #3 full name e.g. DCP-o-matic Batch Converter
293 # @param #4 bundle id e.g. com.dcpomatic.batch
299 tmp_dmg=dcpomatic_tmp.dmg
300 dmg="$full_name $version.dmg"
301 vol_name=DCP-o-matic-$version
305 if [ "$pkg" != "" ]; then
306 productsign --sign "Developer ID Installer: Carl Hetherington (R82DXSR997)" "$pkg" "signed_temp.pkg"
307 if [ "$?" != "0" ]; then
308 echo "Failed to sign .pkg"
311 mv signed_temp.pkg "$pkg"
315 cp -a "$appdir" $vol_name
316 if [ "$pkg" != "" ]; then
317 cp -a "$pkg" $vol_name
319 ln -s /Applications "$vol_name/Applications"
320 cat<<EOF > "$vol_name/READ ME.txt"
321 Welcome to DCP-o-matic! The first time you run the program there may be
322 a long (several-minute) delay while OS X checks the code for viruses and
323 other malware. Please be patient!
325 cat<<EOF > "$vol_name/READ ME.de_DE.txt"
326 Beim erstmaligen Start der DCP-o-matic Anwendungen kann ein längerer
327 Verifikationsvorgang auftreten. Dies ist von der OS X Sicherheitsumgebung
328 'Gatekeeper' verursacht. Dieser je nach Rechner teils minutenlange
329 Verifikationsvorgang ist gegenwärtig normal und nicht zu umgehen,
330 es ist kein Programmfehler. Warten sie die Verifikation für jede der
331 DCP-o-matic Anwendungen ab, bei weiteren Programmstarts wird sie nicht
335 if [ "$pkg" != "" ]; then
336 cat<<EOF > "$vol_name/READ ME.txt"
338 To run this software successfully you must install $pkg before running
343 if [ "$pkg" != "" ]; then
344 cat<<EOF > "$vol_name/READ ME.de_DE.txt"
346 To run this software successfully you must install $pkg before running
351 rm -f $tmp_dmg "$dmg"
352 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
353 attach=$(hdiutil attach -readwrite -noverify -noautoopen $tmp_dmg)
354 device=`echo $attach | egrep '^/dev/' | sed 1q | awk '{print $5}'`
358 tell application "Finder"
359 tell disk "'$vol_name'"
361 set current view of container window to icon view
362 set toolbar visible of container window to false
363 set statusbar visible of container window to false
364 set the bounds of container window to {400, 200, 1160, 600}
365 set the bounds of container window to {400, 200, 1160, 600}
366 set the bounds of container window to {400, 200, 1160, 600}
367 set theViewOptions to the icon view options of container window
368 set arrangement of theViewOptions to not arranged
369 set icon size of theViewOptions to 64
370 set position of item "'$appdir'" of container window to {90, 80}
371 set position of item "Applications" of container window to {265, 80}
372 set position of item "READ ME.txt" of container window to {430, 80}
373 set position of item "READ ME.de_DE.txt" of container window to {595, 80}
374 set position of item "DCP-o-matic Disk Writer.pkg" of container window to {90, 255}
377 update without registering applications
383 chmod -Rf go-w /Volumes/"$vol_name"/"$appdir"
386 hdiutil eject $device
387 hdiutil convert -format UDZO $tmp_dmg -imagekey zlib-level=9 -o "$dmg"
388 sips -i "$appdir/Contents/Resources/dcpomatic2.icns"
389 DeRez -only icns "$appdir/Contents/Resources/dcpomatic2.icns" > "$appdir/Contents/Resources/DCP-o-matic.rsrc"
390 Rez -append "$appdir/Contents/Resources/DCP-o-matic.rsrc" -o "$dmg"
395 codesign --verify --verbose --options runtime --sign "Developer ID Application: Carl Hetherington (R82DXSR997)" "$dmg"
397 # We only notarize thin builds, as if we're building universal binaries we must be on an OS
398 # sufficiently old that it can't notarize anyway
399 if [ "$TYPE" == "thin" ]; then
401 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")
404 echo "Checking up on $id"
405 status=$(xcrun altool --notarization-info $id -u $APPLE_ID -p $APPLE_PASSWORD --output-format xml)
406 summary=$(echo "$status" | grep -C1 "<key>Status</key>" | tail -n 1 | sed -e "s/ .//g")
408 if [ "$summary" == "<string>invalid</string>" ]; then
409 echo "Notarization failed."
413 if [ "$summary" == "<string>success</string>" ]; then
418 if [ "$N" == "30" ]; then
419 echo "Timed out waiting for notarization"
424 xcrun stapler staple "$dmg"
435 approot="$appdir/Contents"
437 mkdir -p "$approot/MacOS"
438 mkdir -p "$approot/Frameworks"
439 mkdir -p "$approot/Resources"
441 to_relink="dcpomatic"
442 copy_libs "$approot/Frameworks"
443 copy_resources "$approot/Resources"
456 setup "DCP-o-matic 2.app"
457 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2 "$approot/MacOS"
458 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_cli "$approot/MacOS"
459 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_create "$approot/MacOS"
460 copy $ROOT bin/ffprobe "$approot/MacOS"
461 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
462 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2.Info.plist "$approot/Info.plist"
463 rl=("$approot/MacOS/dcpomatic2" "$approot/MacOS/dcpomatic2_cli" "$approot/MacOS/dcpomatic2_create" "$approot/MacOS/ffprobe" "$approot/Frameworks/"*.dylib)
464 relink_relative "${rl[@]}"
465 make_dmg "$appdir" "" "DCP-o-matic" com.dcpomatic
467 # DCP-o-matic KDM Creator
468 setup "DCP-o-matic 2 KDM Creator.app"
469 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_kdm "$approot/MacOS"
470 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_kdm_cli "$approot/MacOS"
471 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
472 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_kdm.Info.plist "$approot/Info.plist"
473 rl=("$approot/MacOS/dcpomatic2_kdm" "$approot/MacOS/dcpomatic2_kdm_cli" "$approot/Frameworks/"*.dylib)
474 relink_relative "${rl[@]}"
475 make_dmg "$appdir" "" "DCP-o-matic KDM Creator" com.dcpomatic.kdm
477 # DCP-o-matic Encode Server
478 setup "DCP-o-matic 2 Encode Server.app"
479 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_server "$approot/MacOS"
480 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_server_cli "$approot/MacOS"
481 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
482 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_server.Info.plist "$approot/Info.plist"
483 rl=("$approot/MacOS/dcpomatic2_server" "$approot/MacOS/dcpomatic2_server_cli" "$approot/Frameworks/"*.dylib)
484 relink_relative "${rl[@]}"
485 make_dmg "$appdir" "" "DCP-o-matic Encode Server" com.dcpomatic.server
487 # DCP-o-matic Batch Converter
488 setup "DCP-o-matic 2 Batch converter.app"
489 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_batch "$approot/MacOS"
490 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
491 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_batch.Info.plist "$approot/Info.plist"
492 rl=("$approot/MacOS/dcpomatic2_batch" "$approot/Frameworks/"*.dylib)
493 relink_relative "${rl[@]}"
494 make_dmg "$appdir" "" "DCP-o-matic Batch Converter" com.dcpomatic.batch
497 setup "DCP-o-matic 2 Player.app"
498 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_player "$approot/MacOS"
499 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
500 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_player.Info.plist "$approot/Info.plist"
501 rl=("$approot/MacOS/dcpomatic2_player" "$approot/Frameworks/"*.dylib)
502 relink_relative "${rl[@]}"
503 make_dmg "$appdir" "" "DCP-o-matic Player" com.dcpomatic.player
505 # DCP-o-matic Playlist Editor
506 setup "DCP-o-matic 2 Playlist Editor.app"
507 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_playlist "$approot/MacOS"
508 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
509 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_playlist.Info.plist "$approot/Info.plist"
510 rl=("$approot/MacOS/dcpomatic2_playlist" "$approot/Frameworks/"*.dylib)
511 relink_relative "${rl[@]}"
512 make_dmg "$appdir" "" "DCP-o-matic Playlist Editor" com.dcpomatic.playlist
514 if [ "$DISK" == "yes" ]; then
516 # DCP-o-matic Disk Writer .app
517 setup "DCP-o-matic 2 Disk Writer.app"
518 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_disk "$approot/MacOS"
519 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_disk.Info.plist "$approot/Info.plist"
520 rl=("$approot/MacOS/dcpomatic2_disk" "$approot/Frameworks/"*.dylib)
521 relink_relative "${rl[@]}"
523 # DCP-o-matic Disk Writer daemon .pkg
525 pkgbase=tmp-disk-writer
529 pkgroot=$pkgbase/root
531 mkdir -p $pkgroot/Library/LaunchDaemons
532 cat > $pkgroot/Library/LaunchDaemons/com.dcpomatic.disk.writer.plist <<EOF
533 <?xml version="1.0" encoding="UTF-8"?>
534 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
535 <plist version="1.0">
538 <string>com.dcpomatic.disk.writer</string>
539 <key>ProgramArguments</key>
541 <string>/Library/Application Support/com.dcpomatic/dcpomatic2_disk_writer</string>
543 <key>EnvironmentVariables</key>
545 <key>DYLD_LIBRARY_PATH</key>
546 <string><![CDATA[/Library/Application Support/com.dcpomatic]]></string>
554 <key>StandardOutPath</key>
555 <string>/Users/carl/damon.out.log</string>
556 <key>StandardErrorPath</key>
557 <string>/Users/carl/damon.err.log</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 load "/Library/LaunchDaemons/com.dcpomatic.disk.writer.plist"
578 chmod gou+x $pkgbase/scripts/postinstall
580 find "$pkgbin" -iname "*.dylib" -print0 | while IFS= read -r -d '' f; do
583 sign "$pkgbin/dcpomatic2_disk_writer"
585 mkdir -p "$pkgroot/Library/Application Support/com.dcpomatic"
586 mv $pkgbin/* "$pkgroot/Library/Application Support/com.dcpomatic/"
587 pkgbuild --root $pkgroot --identifier com.dcpomatic.disk.writer --scripts $pkgbase/scripts "DCP-o-matic Disk Writer.pkg"
589 make_dmg "$appdir" "DCP-o-matic Disk Writer.pkg" "DCP-o-matic Disk Writer" com.dcpomatic.disk