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