spice up OSX DMG
[ardour.git] / tools / osx_packaging / osx_build
1 #!/bin/bash
2
3 # script for pulling together a MacOSX app bundle.
4
5 GTKSTACK_ROOT=$HOME/gtk/inst
6 ARDOURSTACK_ROOT=$HOME/a3/inst
7 BUILD_ROOT=../../build
8
9 SAE=
10 MIXBUS=
11 WITH_LADSPA=1
12 STRIP=1
13 PRINT_SYSDEPS=
14 WITH_NLS=
15
16 while [ $# -gt 0 ] ; do
17     echo "arg = $1"
18     case $1 in
19
20         #
21         # top level build targets
22         #
23
24         --sae) WITH_NLS= ; 
25                SAE=1 ; 
26                WITH_LADSPA=1; 
27                STRIP= ; 
28                PRODUCT_PKG_DIR=ArdourSAE ; 
29                APPNAME=Ardour ;
30                shift ;;
31         --mixbus) MIXBUS=1; 
32                   WITH_NLS=1 ; 
33                   SAE= ; 
34                   WITH_LADSPA=; 
35                   STRIP= ; 
36                   PRODUCT_PKG_DIR=MixBus;
37                   APPNAME=Mixbus ;
38                   shift ;;
39         --public) WITH_NLS= ; 
40                   SAE= ; 
41                   WITH_LADSPA=1; 
42                   STRIP= ; 
43                   PRODUCT_PKG_DIR=Ardour;
44                   APPNAME=Ardour ;
45                   shift ;;
46         --allinone) SAE= ; 
47                     WITH_NLS= ; 
48                     WITH_LADSPA=1; 
49                     STRIP= ; 
50                     PRODUCT_PKG_DIR=Ardour ;
51                     shift ;;
52         --test) SAE= ; WITH_LADSPA=; STRIP= ; shift ;;
53
54         #
55         # specific build flags
56         #
57
58         --noladspa) WITH_LADSPA= ; shift ;;
59         --nostrip) STRIP= ; shift ;;
60         --sysdeps) PRINT_SYSDEPS=1; shift ;;
61         --nls) WITH_NLS=1 ; shift ;;
62     esac
63 done
64
65 #release_version=`grep -m 1 '^VERSION' ../../wscript | cut -d' ' -f 3 | sed "s/'//g"`
66 release_version=3.0
67 svn_version=`grep -m 1 'svn_revision =' ../../libs/ardour/svn_revision.cc | cut -d' ' -f 8 | sed 's/[^0-9]//g'`
68 echo "Version is $release_version / $svn_version"
69 info_string="$release_version/$svn_version built on `hostname` by `whoami` on `date`"
70 echo "Info string is $info_string"
71
72 # setup directory structure
73
74 APPDIR=${APPNAME}.app
75 APPROOT=$APPDIR/Contents
76 Frameworks=$APPROOT/lib
77 Resources=$APPROOT/Resources
78 #
79 # Since this is OS X, don't try to distinguish between etc and shared
80 # (machine dependent and independent data) - just put everything
81 # into Resources.
82
83 Shared=$Resources
84 Etc=$Resources
85 Locale=$Resources/locale
86 #
87 # Bundled Plugins live in a top level folder
88
89 Plugins=$APPROOT/Plugins
90 Surfaces=$Frameworks/surfaces
91 Panners=$Frameworks/panners
92 MidiMaps=$Shared/midi_maps
93 ExportFormats=$Shared/export
94 Templates=$Shared/templates
95 PatchFiles=$Shared/patchfiles
96 MackieControl=$Shared/mcp
97
98 if [ x$PRINT_SYSDEPS != x ] ; then
99 #
100 # print system dependencies
101 #
102
103     for file in $APPROOT/MacOS/* $Frameworks/* $Frameworks/modules/* $Plugins/*.so ; do 
104         if ! file $file | grep -qs Mach-O ; then
105             continue
106         fi
107         otool -L $file | awk '{print $1}' | egrep -v "(^@executable_path|^Ardour[0-9][.0-9]*.app)" 
108     done | sort | uniq
109     exit 0
110 fi
111
112 echo "Removing old $APPDIR tree ..."
113
114 rm -rf $APPDIR
115
116 echo "Building new app directory structure ..."
117
118 # only bother to make the longest paths
119
120 mkdir -p $APPROOT/MacOS
121 mkdir -p $APPROOT/Resources
122 mkdir -p $Plugins
123 mkdir -p $Surfaces
124 mkdir -p $Panners
125 mkdir -p $MidiMaps
126 mkdir -p $ExportFormats
127 mkdir -p $Templates
128 mkdir -p $Frameworks/modules
129 mkdir -p $Shared/templates
130 mkdir -p $Etc
131 mkdir -p $MackieControl
132
133 # maybe set variables
134 env=""
135 if test x$SAE != x ; then
136     appname="Ardour3/SAE"
137     env="$env<key>ARDOUR_SAE</key><string>true</string>"
138     #
139     # current default for SAE version is German keyboard layout without a keypad
140     #
141     env="$env<key>ARDOUR_KEYBOARD_LAYOUT</key><string>de-nokeypad</string>"
142     env="$env<key>ARDOUR_UI_CONF</key><string>ardour3_ui_sae.conf</string>"
143     env="$env<key>ARDOUR3_UI_RC</key><string>ardour3_ui_dark_sae.rc</string>"
144 elif test x$MIXBUS != x ; then
145     appname="Ardour3/Mixbus"
146     env="$env<key>ARDOUR_MIXBUS</key><string>true</string>"
147     #
148     # current default for MIXBUS version is US keyboard layout without a keypad
149     #
150     env="$env<key>ARDOUR_KEYBOARD_LAYOUT</key><string>us-nokeypad</string>"
151     env="$env<key>ARDOUR_UI_CONF</key><string>ardour3_ui.conf</string>"
152     env="$env<key>ARDOUR3_UI_RC</key><string>ardour3_ui_dark.rc</string>"
153 else
154     appname="Ardour3"
155 fi
156
157 #
158 # if we're not going to bundle JACK, make sure we can find
159 # jack in the places where it might be
160 #
161
162 env="$env<key>PATH</key><string>/usr/local/bin:/opt/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>"
163 env="$env<key>DYLIB_FALLBACK_LIBRARY_PATH</key><string>/usr/local/lib:/opt/lib</string>"
164
165 env="<key>LSEnvironment</key><dict>$env<key>ARDOUR_BUNDLED</key><string>true</string></dict>"
166
167 # edit plist
168 sed -e "s?@ENV@?$env?g" \
169     -e "s?@VERSION@?$release_version/$svn_version?g" \
170     -e "s?@INFOSTRING@?$info_string?g" < Info.plist.in > Info.plist
171 # and plist strings
172 sed -e "s?@APPNAME@?$appname?" \
173     -e "s?@ENV@?$env?g" \
174     -e "s?@VERSION@?$release_version/$svn_version?g" \
175     -e "s?@INFOSTRING@?$info_string?g" < InfoPlist.strings.in > Resources/InfoPlist.strings || exit 1
176
177 # copy static files
178
179 cp Info.plist $APPROOT
180 cp -R Resources $APPROOT
181
182 #
183 # if we build a bundle without jack, then
184 # make the Ardour3 executable a helper
185 # script that checks to see if JACK is
186 # installed.
187 #
188
189 cp startup_script $APPROOT/MacOS/Ardour3
190 chmod 775 $APPROOT/MacOS/Ardour3
191 MAIN_EXECUTABLE=Ardour3.bin
192
193 echo "Copying ardour executable ...."
194 cp $BUILD_ROOT/gtk2_ardour/ardour-$release_version $APPROOT/MacOS/$MAIN_EXECUTABLE
195 if test x$SAE != x ; then
196     # cp $BUILD_ROOT/gtk2_ardour/evtest $APPROOT/MacOS/gtkevents
197     cp  Ardour3-SAE.icns $Resources/appIcon.icns
198 elif test x$MIXBUS != x ; then
199     cp  Mixbus.icns $Resources/appIcon.icns
200 else
201     cp  Ardour3.icns $Resources/appIcon.icns
202 fi
203 cp  typeArdour.icns $Resources/
204 if test x$STRIP != x ; then
205     strip $APPROOT/MacOS/Ardour3
206 fi
207
208 # copy locale files
209 if test x$WITH_NLS != x ; then
210     echo "NLS support ..."
211     echo "I hope you remembered to run scons msgupdate!"
212     LINGUAS=
213     for file in $BUILD_ROOT/gtk2_ardour/*.mo 
214     do
215         lang=`basename $file | sed 's/\.mo//'`
216         mkdir -p $Locale/$lang/LC_MESSAGES
217         cp $file $Locale/$lang/LC_MESSAGES/gtk2_ardour.mo
218         LINGUAS="$LINGUAS $lang"
219     done
220     for file in $BUILD_ROOT/libs/ardour/*.mo 
221     do
222         lang=`basename $file | sed 's/\.mo//'`
223         mkdir -p $Locale/$lang/LC_MESSAGES
224         cp $file $Locale/$lang/LC_MESSAGES/libardour.mo
225     done
226     for l in $LINGUAS
227     do
228       if [ -d $GTKSTACK_ROOT/share/locale/$l ] ; then
229           echo "Copying GTK i18n files for $l..."
230           cp -r $GTKSTACK_ROOT/share/locale/$l $Locale
231       else
232           # try with just the language spec
233           just_lang=`echo $l | sed 's/_[A-Z][A-Z]$//'`
234           if [ -d $GTKSTACK_ROOT/share/locale/$just_lang ] ; then
235               echo "Copying GTK i18n files for $l..."
236               cp -r $GTKSTACK_ROOT/share/locale/$just_lang $Locale
237           fi
238       fi
239     done
240 else
241     echo "Skipping NLS support"
242 fi
243
244 #
245 # Copy stuff that may be dynamically loaded
246
247
248 cp -R $GTKSTACK_ROOT/etc/* $Etc
249 echo "Copying all Pango modules ..."
250 cp -R $GTKSTACK_ROOT/lib/pango/1.6.0/modules/*.so $Frameworks/modules
251 echo "Copying all GDK Pixbuf loaders ..."
252 cp -R $GTKSTACK_ROOT/lib/gdk-pixbuf-2.0/2.10.0/loaders/*.so $Frameworks/modules
253 # charset alias file
254 cp -R $GTKSTACK_ROOT/lib/charset.alias $Resources
255
256 # generate new Pango module file
257 cat > pangorc <<EOF 
258 [Pango]
259 ModulesPath=$GTKSTACK_ROOT/lib/pango/1.6.0/modules
260 EOF
261 env PANGO_RC_FILE=pangorc $GTKSTACK_ROOT/bin/pango-querymodules | sed "s?$GTKSTACK_ROOT/lib/pango/1.6.0/modules/?@executable_path/../lib/modules/?" > $Resources/pango.modules
262 rm pangorc
263
264 # generate a new GDK pixbufs loaders file
265 gdk-pixbuf-query-loaders | sed "s?$GTKSTACK_ROOT/lib/gdk-pixbuf-2.0/2.10.0/loaders/?@executable_path/../lib/modules/?" > $Resources/gdk-pixbuf.loaders
266
267 # We rely on clearlooks, so include a version from our own build tree
268 # this one is special - we will set GTK_PATH to $Libraries/clearlooks
269
270 echo "Copying clearlooks ..."
271 cp $BUILD_ROOT/libs/clearlooks-newer/libclearlooks.dylib $Frameworks
272 mkdir -p $Frameworks/clearlooks/engines
273 (cd $Frameworks/clearlooks/engines && ln -s ../../libclearlooks.dylib libclearlooks.dylib && ln -s ../../libclearlooks.dylib libclearlooks.so)
274
275 if test x$WITH_LADSPA != x ; then
276     if test x$SAE != x ; then
277         plugdir=sae_ladspa
278     elif test x$MIXBUS != x ; then
279         plugdir=mixbus_ladspa
280     else
281         plugdir=ladspa
282     fi
283     if [ -d $plugdir -a "x$(ls $plugdir)" != x ] ; then 
284         echo "Copying `ls $plugdir | wc -l` plugins ..."
285         cp -r $plugdir/* $Plugins
286     fi
287 fi
288
289 # Control Surface shared libraries
290 cp $BUILD_ROOT/libs/surfaces/*/libardour_*.dylib $Surfaces
291 cp $BUILD_ROOT/libs/surfaces/control_protocol/libardourcp*.dylib $Frameworks
292
293 # Panners
294 cp $BUILD_ROOT/libs/panners/*/lib*.dylib $Panners
295
296
297 # Export Formats/Presets
298 for f in $BUILD_ROOT/../export/*.preset $BUILD_ROOT/../export/*.format ; do 
299     cp "$f" $ExportFormats ; 
300 done
301
302 # Session and Route templates
303 for f in $BUILD_ROOT/../templates/* ; do 
304     if [ -d "$f" ] ; then
305         cp -r "$f" $Templates ; 
306     fi
307 done
308
309 # MidiMaps
310 # got to be careful with names here
311 for x in $BUILD_ROOT/../midi_maps/*.map ; do
312     cp "$x" $MidiMaps
313 done
314
315 # MIDNAM Patch Files
316 # got to be careful with names here
317 for x in $BUILD_ROOT/../patchfiles/*.midnam ; do
318     cp "$x" $PatchFiles
319 done
320
321 # MackieControl data
322 # got to be careful with names here
323 for x in $BUILD_ROOT/../mcp/*.device $BUILD_ROOT/../mcp/*.profile ; do
324     cp "$x" $MackieControl
325 done
326
327 # VAMP plugins that we use
328 cp $BUILD_ROOT/libs/vamp-plugins/libardourvampplugins.dylib $Frameworks
329
330 # Suil modules
331 cp $ARDOURSTACK_ROOT/lib/suil-0/lib* $Frameworks
332
333 while [ true ] ; do 
334     missing=false
335     for file in $APPROOT/MacOS/* $Frameworks/* $Frameworks/modules/* $Panners/*.dylib $Surfaces/*.dylib $Plugins/*.so ; do 
336         if ! file $file | grep -qs Mach-O ; then
337             continue
338         fi
339         deps=`otool -L $file | awk '{print $1}' | egrep "($GTKSTACK_ROOT|$ARDOURSTACK_ROOT|/opt/|/local/|libs/)" | grep -v 'libjack\.'`
340         # echo -n "."
341         for dep in $deps ; do
342             base=`basename $dep`
343             if ! test -f $Frameworks/$base; then
344                 if echo $dep | grep -sq '^libs' ; then
345                     cp $BUILD_ROOT/$dep $Frameworks
346                 else
347                     cp $dep $Frameworks
348                 fi
349                 missing=true
350             fi
351         done
352     done
353     if test x$missing = xfalse ; then
354         # everything has been found
355         break
356     fi
357 done
358 echo
359
360 echo "Copying other stuff to $APPDIR  ..."
361
362 #cp $BUILD_ROOT/gtk2_ardour/ergonomic-us.bindings  $Resources
363
364 cp $BUILD_ROOT/gtk2_ardour/mnemonic-us.bindings  $Resources
365 cp ../../gtk2_ardour/mixer.bindings $Resources
366 cp ../../gtk2_ardour/step_editing.bindings $Resources
367 cp $BUILD_ROOT/gtk2_ardour/ardour.menus $Resources
368
369 if test x$SAE != x ; then
370     cp $BUILD_ROOT/gtk2_ardour/SAE-de-keypad.bindings  $Resources
371     cp $BUILD_ROOT/gtk2_ardour/SAE-de-nokeypad.bindings  $Resources
372     cp $BUILD_ROOT/gtk2_ardour/SAE-us-keypad.bindings  $Resources
373     cp $BUILD_ROOT/gtk2_ardour/SAE-us-nokeypad.bindings  $Resources
374     cp $BUILD_ROOT/ardour_system_sae.rc $Resources/ardour_system.rc
375     echo cp $BUILD_ROOT/ardour_system_sae.rc $Resources/ardour_system.rc
376     cp $BUILD_ROOT/instant.xml.sae $Resources/instant.xml
377     echo cp $BUILD_ROOT/instant.xml.sae $Resources/instant.xml
378 else
379     cp ../../ardour_system.rc $Resources/ardour_system.rc
380     cp ../../instant.xml $Resources/instant.xml
381     echo cp ../../instant.xml $Resources/instant.xml
382 fi
383 cp ../../gtk2_ardour/ardour3_ui_default.conf $Resources
384 cp ../../gtk2_ardour/ardour3_ui_default.conf $Resources/ardour3_ui.conf
385 cp $BUILD_ROOT/gtk2_ardour/ardour3_ui_light.rc $Resources
386 cp $BUILD_ROOT/gtk2_ardour/ardour3_ui_dark.rc $Resources
387
388 cp -r ../../gtk2_ardour/icons $Resources
389 cp -r ../../gtk2_ardour/pixmaps $Resources
390
391 # shared stuff
392 cp -R ../../gtk2_ardour/splash.png $Shared
393
394 # go through and recursively remove any .svn dirs in the bundle
395 for svndir in `find $APPDIR -name .svn -type dir`; do
396     rm -rf $svndir
397 done
398
399 # now fix up the executables
400 echo "Fixing up executable dependency names ..."
401 executables=$MAIN_EXECUTABLE
402 if test x$SAE != x ; then
403     executables="$executables"
404 fi
405
406 for exe in $executables; do
407     EXE=$APPROOT/MacOS/$exe
408     changes=""
409     for lib in `otool -L $EXE | egrep "($GTKSTACK_ROOT|$ARDOURSTACK_ROOT|/opt/|/local/|libs/)" | awk '{print $1}' | grep -v 'libjack\.'` ; do
410       base=`basename $lib`
411       changes="$changes -change $lib @executable_path/../lib/$base"
412     done
413     if test "x$changes" != "x" ; then
414         install_name_tool $changes $EXE
415     fi
416 done
417
418 echo "Fixing up library names ..."
419 # now do the same for all the libraries we include
420 for libdir in $Frameworks $Frameworks/modules $Surfaces $Panners ; do
421
422     libbase=`basename $libdir`
423     
424     for dylib in $libdir/*.dylib $libdir/*.so ; do
425         
426        # skip symlinks
427         
428         if test -L $dylib ; then
429             continue
430         fi
431         
432         # change all the dependencies
433         
434         changes=""
435         for lib in `otool -L $dylib | egrep "($GTKSTACK_ROOT|$ARDOURSTACK_ROOT|/opt/|/local/|libs/)" | awk '{print $1}' | grep -v 'libjack\.'` ; do
436             base=`basename $lib`
437             if echo $lib | grep -s libbase; then
438                 changes="$changes -change $lib @executable_path/../$libbase/$base"
439             else
440                 changes="$changes -change $lib @executable_path/../lib/$base"
441             fi
442         done
443         
444         if test "x$changes" != x ; then
445             if  install_name_tool $changes $dylib ; then
446                 :
447             else
448                 exit 1
449             fi
450         fi
451         
452         # now the change what the library thinks its own name is
453         
454         base=`basename $dylib`
455         install_name_tool -id @executable_path/../$libbase/$base $dylib
456     done
457 done
458
459 #
460 # and now ... the DMG
461
462
463 rm -rf $PRODUCT_PKG_DIR
464 mkdir $PRODUCT_PKG_DIR
465
466 if [ x$SAE != x ] ; then
467         
468     # SAE packaging
469     
470     echo "Creating SAE packaging directory"
471     mv $APPDIR $PRODUCT_PKG_DIR/Ardour3-SAE.app
472     cp HowToInstallArdourSAE.pdf "$PRODUCT_PKG_DIR/How To Install Ardour SAE.pdf"
473     cp SAE-de-keypad.pdf "$PRODUCT_PKG_DIR/Ardour SAE Shortcuts (keypad).pdf"
474     cp SAE-de-nokeypad.pdf "$PRODUCT_PKG_DIR/Ardour SAE Shortcuts.pdf"
475     
476 elif [ x$MIXBUS != x ] ; then
477
478      # Mixbus packaging
479
480     echo "Creating Mixbus packaging directory"
481     mv $APPDIR $PRODUCT_PKG_DIR/
482     cp MixBus_Install_QuickStart.pdf "$PRODUCT_PKG_DIR/Mixbus Install & Quick Start Guide.pdf"
483
484 else 
485
486     echo "Creating $APPNAME packaging directory"
487     mv $APPDIR $PRODUCT_PKG_DIR/
488
489 fi
490
491 echo "Building DMG ..."
492
493 # UC_DMG=$APPNAME-${release_version}-${svn_version}-UC.dmg
494 # FINAL_DMG=$APPNAME-${release_version}-${svn_version}.dmg
495 UC_DMG=$APPNAME-${release_version}-${svn_version}.dmg
496 VOLNAME=$APPNAME-$release_version
497
498 # TODO use mktemp
499 MNTPATH=`mktemp -d -t ardourimg`
500 TMPDMG=`mktemp -t ardour`
501 ICNSTMP=`mktemp -t ardouricon`
502 DMGSIZE=$[ `du -sm "$PRODUCT_PKG_DIR" | cut -f 1` * 1049 / 1000 + 3 ]
503
504 rm -f $UC_DMG "$TMPDMG" "${TMPDMG}.dmg" "$ICNSTMP"
505 rm -rf "$MNTPATH"
506 mkdir -p "$MNTPATH"
507
508 TMPDMG="${TMPDMG}.dmg"
509
510 hdiutil create -megabytes $DMGSIZE "$TMPDMG"
511 DiskDevice=$(hdid -nomount "$TMPDMG" | grep Apple_HFS | cut -f 1 -d ' ')
512 newfs_hfs -v "${VOLNAME}" "${DiskDevice}"
513 mount -t hfs "${DiskDevice}" "${MNTPATH}"
514
515 cp -r ${PRODUCT_PKG_DIR}/${APPDIR} "${MNTPATH}" || exit
516 mkdir "${MNTPATH}/.background"
517 cp -vi dmgbg.png "${MNTPATH}/.background/dmgbg.png"
518
519 echo "setting DMG background ..."
520
521 echo '
522    tell application "Finder"
523      tell disk "'${VOLNAME}'"
524            open
525            set current view of container window to icon view
526            set toolbar visible of container window to false
527            set statusbar visible of container window to false
528            set the bounds of container window to {400, 200, 800, 440}
529            set theViewOptions to the icon view options of container window
530            set arrangement of theViewOptions to not arranged
531            set icon size of theViewOptions to 64
532            set background picture of theViewOptions to file ".background:dmgbg.png"
533            make new alias file at container window to POSIX file "/Applications" with properties {name:"Applications"}
534            set position of item "'${APPDIR}'" of container window to {90, 100}
535            set position of item "Applications" of container window to {310, 100}
536            close
537            open
538            update without registering applications
539            delay 5
540            eject
541      end tell
542    end tell
543 ' | osascript
544
545 chmod -Rf go-w "${MNTPATH}"
546 sync
547
548 echo "compressing Image ..."
549
550 # Umount the image
551 umount "${DiskDevice}"
552 hdiutil eject "${DiskDevice}"
553 # Create a read-only version, use zlib compression
554 hdiutil convert -format UDZO "${TMPDMG}" -imagekey zlib-level=9 -o "${UC_DMG}"
555 # Delete the temporary files
556 rm "$TMPDMG"
557 rmdir "$MNTPATH"
558
559 echo "setting file icon ..."
560
561 cp ${PRODUCT_PKG_DIR}/$Resources/appIcon.icns ${ICNSTMP}.icns
562 /usr/bin/sips -i ${ICNSTMP}.icns
563 /Developer/Tools/DeRez -only icns ${ICNSTMP}.icns > ${ICNSTMP}.rsrc
564 /Developer/Tools/Rez -append ${ICNSTMP}.rsrc -o "$UC_DMG"
565 /Developer/Tools/SetFile -a C "$UC_DMG"
566
567 rm ${ICNSTMP}.icns ${ICNSTMP}.rsrc
568
569 echo
570 echo "packaging suceeded."
571 ls -l "$UC_DMG"
572
573 echo "Done."
574 exit