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 -r $prefix/share/libdcp/xsd "$dest"
218 # i18n: DCP-o-matic .mo files
219 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
220 mkdir -p "$dest/$lang/LC_MESSAGES"
221 cp $prefix/src/dcpomatic/build/src/lib/mo/$lang/*.mo "$dest/$lang/LC_MESSAGES"
222 cp $prefix/src/dcpomatic/build/src/wx/mo/$lang/*.mo "$dest/$lang/LC_MESSAGES"
223 cp $prefix/src/dcpomatic/build/src/tools/mo/$lang/*.mo "$dest/$lang/LC_MESSAGES"
226 # i18n: wxWidgets .mo files
227 for lang in de es fr it sv nl ru pl da cs; do
229 cp $ENV/64/share/locale/$lang/LC_MESSAGES/wxstd.mo "$dest/$lang"
233 # param $1 list of things that link to other things
234 function relink_relative {
235 to_relink=`echo $to_relink | sed -e "s/\+//g"`
238 for obj in "${linkers[@]}"; do
239 deps=`otool -L "$obj" | awk '{print $1}' | egrep "($to_relink)" | egrep "($ENV|$ROOT|boost|libicu)"`
243 if [ "$TYPE" == "universal" ]; then
244 # $dep will be a path within 64/; make a 32/ path too
245 dep32=`echo $dep | sed -e "s/\/64\//\/32\//g"`
246 changes="$changes -change $dep @executable_path/../Frameworks/$base -change $dep32 @executable_path/../Frameworks/$base"
248 changes="$changes -change $dep @executable_path/../Frameworks/$base"
251 if test "x$changes" != "x"; then
252 install_name_tool $changes -id `basename "$obj"` "$obj"
257 # param $1 directory things should be relinked into
258 # $2 list of things that link to other things
259 function relink_absolute {
260 to_relink=`echo $to_relink | sed -e "s/\+//g"`
265 for obj in "${linkers[@]}"; do
266 deps=`otool -L "$obj" | awk '{print $1}' | egrep "($to_relink)" | egrep "($ENV|$ROOT|boost|libicu)"`
269 install_name_tool -change "$dep" "$target"/$base -id `basename "$obj"` "$obj"
275 codesign --deep --force --verify --verbose --options runtime --sign "Developer ID Application: Carl Hetherington (R82DXSR997)" "$1"
276 if [ "$?" != "0" ]; then
277 echo "Failed to sign $1"
283 # @param #1 .app directory
284 # @param #2 .pkg or ""
285 # @param #3 full name e.g. DCP-o-matic Batch Converter
286 # @param #4 bundle id e.g. com.dcpomatic.batch
292 tmp_dmg=dcpomatic_tmp.dmg
293 dmg="$full_name $version.dmg"
294 vol_name=DCP-o-matic-$version
298 if [ "$pkg" != "" ]; then
299 productsign --sign "Developer ID Installer: Carl Hetherington (R82DXSR997)" "$pkg" "signed_temp.pkg"
300 if [ "$?" != "0" ]; then
301 echo "Failed to sign .pkg"
304 mv signed_temp.pkg "$pkg"
308 cp -a "$appdir" $vol_name
309 if [ "$pkg" != "" ]; then
310 cp -a "$pkg" $vol_name
312 ln -s /Applications "$vol_name/Applications"
313 cat<<EOF > "$vol_name/READ ME.txt"
314 Welcome to DCP-o-matic! The first time you run the program there may be
315 a long (several-minute) delay while OS X checks the code for viruses and
316 other malware. Please be patient!
318 cat<<EOF > "$vol_name/READ ME.de_DE.txt"
319 Beim erstmaligen Start der DCP-o-matic Anwendungen kann ein längerer
320 Verifikationsvorgang auftreten. Dies ist von der OS X Sicherheitsumgebung
321 'Gatekeeper' verursacht. Dieser je nach Rechner teils minutenlange
322 Verifikationsvorgang ist gegenwärtig normal und nicht zu umgehen,
323 es ist kein Programmfehler. Warten sie die Verifikation für jede der
324 DCP-o-matic Anwendungen ab, bei weiteren Programmstarts wird sie nicht
328 if [ "$pkg" != "" ]; then
329 cat<<EOF > "$vol_name/READ ME.txt"
331 To run this software successfully you must install $pkg before running
336 if [ "$pkg" != "" ]; then
337 cat<<EOF > "$vol_name/READ ME.de_DE.txt"
339 To run this software successfully you must install $pkg before running
344 rm -f $tmp_dmg "$dmg"
345 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
346 attach=$(hdiutil attach -readwrite -noverify -noautoopen $tmp_dmg)
347 device=`echo $attach | egrep '^/dev/' | sed 1q | awk '{print $5}'`
351 tell application "Finder"
352 tell disk "'$vol_name'"
354 set current view of container window to icon view
355 set toolbar visible of container window to false
356 set statusbar visible of container window to false
357 set the bounds of container window to {400, 200, 1160, 600}
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 theViewOptions to the icon view options of container window
361 set arrangement of theViewOptions to not arranged
362 set icon size of theViewOptions to 64
363 set position of item "'$appdir'" of container window to {90, 80}
364 set position of item "Applications" of container window to {265, 80}
365 set position of item "READ ME.txt" of container window to {430, 80}
366 set position of item "READ ME.de_DE.txt" of container window to {595, 80}
367 set position of item "DCP-o-matic Disk Writer.pkg" of container window to {90, 255}
370 update without registering applications
376 chmod -Rf go-w /Volumes/"$vol_name"/"$appdir"
379 hdiutil eject $device
380 hdiutil convert -format UDZO $tmp_dmg -imagekey zlib-level=9 -o "$dmg"
381 sips -i "$appdir/Contents/Resources/dcpomatic2.icns"
382 DeRez -only icns "$appdir/Contents/Resources/dcpomatic2.icns" > "$appdir/Contents/Resources/DCP-o-matic.rsrc"
383 Rez -append "$appdir/Contents/Resources/DCP-o-matic.rsrc" -o "$dmg"
388 codesign --verify --verbose --options runtime --sign "Developer ID Application: Carl Hetherington (R82DXSR997)" "$dmg"
390 # We only notarize thin builds, as if we're building universal binaries we must be on an OS
391 # sufficiently old that it can't notarize anyway
392 if [ "$TYPE" == "thin" ]; then
394 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")
397 echo "Checking up on $id"
398 status=$(xcrun altool --notarization-info $id -u $APPLE_ID -p $APPLE_PASSWORD --output-format xml)
399 summary=$(echo "$status" | grep -C1 "<key>Status</key>" | tail -n 1 | sed -e "s/ .//g")
401 if [ "$summary" == "<string>invalid</string>" ]; then
402 echo "Notarization failed."
406 if [ "$summary" == "<string>success</string>" ]; then
411 if [ "$N" == "30" ]; then
412 echo "Timed out waiting for notarization"
417 xcrun stapler staple "$dmg"
428 approot="$appdir/Contents"
430 mkdir -p "$approot/MacOS"
431 mkdir -p "$approot/Frameworks"
432 mkdir -p "$approot/Resources"
434 to_relink="dcpomatic"
435 copy_libs "$approot/Frameworks"
436 copy_resources "$approot/Resources"
449 setup "DCP-o-matic 2.app"
450 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2 "$approot/MacOS"
451 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_cli "$approot/MacOS"
452 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_create "$approot/MacOS"
453 copy $ROOT bin/ffprobe "$approot/MacOS"
454 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
455 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2.Info.plist "$approot/Info.plist"
456 rl=("$approot/MacOS/dcpomatic2" "$approot/MacOS/dcpomatic2_cli" "$approot/MacOS/dcpomatic2_create" "$approot/MacOS/ffprobe" "$approot/Frameworks/"*.dylib)
457 relink_relative "${rl[@]}"
458 make_dmg "$appdir" "" "DCP-o-matic" com.dcpomatic
460 # DCP-o-matic KDM Creator
461 setup "DCP-o-matic 2 KDM Creator.app"
462 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_kdm "$approot/MacOS"
463 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_kdm_cli "$approot/MacOS"
464 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
465 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_kdm.Info.plist "$approot/Info.plist"
466 rl=("$approot/MacOS/dcpomatic2_kdm" "$approot/MacOS/dcpomatic2_kdm_cli" "$approot/Frameworks/"*.dylib)
467 relink_relative "${rl[@]}"
468 make_dmg "$appdir" "" "DCP-o-matic KDM Creator" com.dcpomatic.kdm
470 # DCP-o-matic Encode Server
471 setup "DCP-o-matic 2 Encode Server.app"
472 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_server "$approot/MacOS"
473 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_server_cli "$approot/MacOS"
474 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
475 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_server.Info.plist "$approot/Info.plist"
476 rl=("$approot/MacOS/dcpomatic2_server" "$approot/MacOS/dcpomatic2_server_cli" "$approot/Frameworks/"*.dylib)
477 relink_relative "${rl[@]}"
478 make_dmg "$appdir" "" "DCP-o-matic Encode Server" com.dcpomatic.server
480 # DCP-o-matic Batch Converter
481 setup "DCP-o-matic 2 Batch converter.app"
482 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_batch "$approot/MacOS"
483 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
484 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_batch.Info.plist "$approot/Info.plist"
485 rl=("$approot/MacOS/dcpomatic2_batch" "$approot/Frameworks/"*.dylib)
486 relink_relative "${rl[@]}"
487 make_dmg "$appdir" "" "DCP-o-matic Batch Converter" com.dcpomatic.batch
490 setup "DCP-o-matic 2 Player.app"
491 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_player "$approot/MacOS"
492 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
493 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_player.Info.plist "$approot/Info.plist"
494 rl=("$approot/MacOS/dcpomatic2_player" "$approot/Frameworks/"*.dylib)
495 relink_relative "${rl[@]}"
496 make_dmg "$appdir" "" "DCP-o-matic Player" com.dcpomatic.player
498 # DCP-o-matic Playlist Editor
499 setup "DCP-o-matic 2 Playlist Editor.app"
500 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_playlist "$approot/MacOS"
501 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
502 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_playlist.Info.plist "$approot/Info.plist"
503 rl=("$approot/MacOS/dcpomatic2_playlist" "$approot/Frameworks/"*.dylib)
504 relink_relative "${rl[@]}"
505 make_dmg "$appdir" "" "DCP-o-matic Playlist Editor" com.dcpomatic.playlist
507 # DCP-o-matic Disk Writer .app
508 setup "DCP-o-matic 2 Disk Writer.app"
509 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_disk "$approot/MacOS"
510 copy $ROOT src/openssl/apps/openssl "$approot/MacOS"
511 cp $prefix/src/dcpomatic/build/platform/osx/dcpomatic2_disk.Info.plist "$approot/Info.plist"
512 rl=("$approot/MacOS/dcpomatic2_disk" "$approot/Frameworks/"*.dylib)
513 relink_relative "${rl[@]}"
515 # DCP-o-matic Disk Writer daemon .pkg
517 pkgbase=tmp-disk-writer
521 pkgroot=$pkgbase/root
523 mkdir -p $pkgroot/Library/LaunchDaemons
524 cat > $pkgroot/Library/LaunchDaemons/com.dcpomatic.disk.writer.plist <<EOF
525 <?xml version="1.0" encoding="UTF-8"?>
526 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
527 <plist version="1.0">
530 <string>com.dcpomatic.disk.writer</string>
531 <key>ProgramArguments</key>
533 <string>/Library/Application Support/com.dcpomatic/dcpomatic2_disk_writer</string>
535 <key>EnvironmentVariables</key>
537 <key>DYLD_LIBRARY_PATH</key>
538 <string><![CDATA[/Library/Application Support/com.dcpomatic]]></string>
546 <key>StandardOutPath</key>
547 <string>/var/log/dcpomatic_disk_writer_out.log</string>
548 <key>StandardErrorPath</key>
549 <string>/var/log/dcpomatic_disk_writer_err.log</string>
554 # Get the binaries together in $pkgbin then move them to the
555 # place with spaces in the filename to avoid some of the pain of escaping
558 copy $ROOT src/dcpomatic/build/src/tools/dcpomatic2_disk_writer "$pkgbin"
561 rl=("$pkgbin/dcpomatic2_disk_writer" "$pkgbin/"*.dylib)
562 relink_absolute "/Library/Application Support/com.dcpomatic" "${rl[@]}"
564 mkdir $pkgbase/scripts
565 cat > $pkgbase/scripts/postinstall <<EOF
567 /bin/launchctl unload "/Library/LaunchDaemons/com.dcpomatic.disk.writer.plist"
568 /bin/launchctl load "/Library/LaunchDaemons/com.dcpomatic.disk.writer.plist"
571 chmod gou+x $pkgbase/scripts/postinstall
573 find "$pkgbin" -iname "*.dylib" -print0 | while IFS= read -r -d '' f; do
576 sign "$pkgbin/dcpomatic2_disk_writer"
578 mkdir -p "$pkgroot/Library/Application Support/com.dcpomatic"
579 mv $pkgbin/* "$pkgroot/Library/Application Support/com.dcpomatic/"
580 pkgbuild --root $pkgroot --identifier com.dcpomatic.disk.writer --scripts $pkgbase/scripts "DCP-o-matic Disk Writer.pkg"
582 make_dmg "$appdir" "DCP-o-matic Disk Writer.pkg" "DCP-o-matic Disk Writer" com.dcpomatic.disk