Code

- Fix bug #396322: "Spell checker crashes the OS X package"
[inkscape.git] / packaging / macosx / osx-app.sh
1 #!/bin/bash
2 #
3 # USAGE
4 # osx-app [-s] [-py /path/to/python/modules] [-l /path/to/libraries] -b /path/to/bin/inkscape -p /path/to/Info.plist
5 #
6 # This script attempts to build an Inkscape.app package for OS X, resolving
7 # dynamic libraries, etc.        
8 # It strips the executable and libraries if '-s' is given.
9 # It adds python modules if the '-py option' is given
10 # The Info.plist file can be found in the base inkscape directory once
11 # configure has been run.
12 #
13 # AUTHORS
14 #                Kees Cook <kees@outflux.net>
15 #                Michael Wybrow <mjwybrow@users.sourceforge.net>
16 #                Jean-Olivier Irisson <jo.irisson@gmail.com>
17
18 # Copyright (C) 2005 Kees Cook
19 # Copyright (C) 2005-2007 Michael Wybrow
20 # Copyright (C) 2007 Jean-Olivier Irisson
21 #
22 # Released under GNU GPL, read the file 'COPYING' for more information
23 #
24 # Thanks to GNUnet's "build_app" script for help with library dep resolution.
25 #               https://gnunet.org/svn/GNUnet/contrib/OSX/build_app
26
27 # NB:
28 # When packaging Inkscape for OS X, configure should be run with the 
29 # "--enable-osxapp" option which sets the correct paths for support
30 # files inside the app bundle.
31
33 # Defaults
34 strip=false
35 add_python=false
36 python_dir=""
38 # If LIBPREFIX is not already set (by osx-build.sh for example) set it to blank (one should use the command line argument to set it correctly)
39 if [ -z $LIBPREFIX ]; then
40         LIBPREFIX=""
41 fi
44 # Help message
45 #----------------------------------------------------------
46 help()
47 {
48 echo -e "
49 Create an app bundle for OS X
51 \033[1mUSAGE\033[0m
52         $0 [-s] [-py /path/to/python/modules] [-l /path/to/libraries] -b /path/to/bin/inkscape -p /path/to/Info.plist
54 \033[1mOPTIONS\033[0m
55         \033[1m-h,--help\033[0m 
56                 display this help message
57         \033[1m-s\033[0m
58                 strip the libraries and executables from debugging symbols
59         \033[1m-py,--with-python\033[0m
60                 add python modules (numpy, lxml) from given directory
61                 inside the app bundle
62         \033[1m-l,--libraries\033[0m
63                 specify the path to the librairies Inkscape depends on
64                 (typically /sw or /opt/local)
65         \033[1m-b--binary\033[0m
66                 specify the path to Inkscape's binary. By default it is in
67                 Build/bin/ at the base of the source code directory
68         \033[1m-p,--plist\033[0m
69                 specify the path to Info.plist. Info.plist can be found
70                 in the base directory of the source code once configure
71                 has been run
73 \033[1mEXAMPLE\033[0m
74         $0 -s -py ~/python-modules -l /opt/local -b ../../Build/bin/inkscape -p ../../Info.plist
75 "
76 }
79 # Parse command line arguments
80 #----------------------------------------------------------
81 while [ "$1" != "" ]
82 do
83         case $1 in
84                 -py|--with-python)
85                         add_python=true
86                         python_dir="$2"
87                         shift 1 ;;
88                 -s)
89                         strip=true ;;
90                 -l|--libraries)
91                         LIBPREFIX="$2"
92                         shift 1 ;;
93                 -b|--binary)
94                         binary="$2"
95                         shift 1 ;;
96                 -p|--plist)
97                         plist="$2"
98                         shift 1 ;;
99                 -h|--help)
100                         help
101                         exit 0 ;;
102                 *)
103                         echo "Invalid command line option: $1" 
104                         exit 2 ;;
105         esac
106         shift 1
107 done
109 echo -e "\n\033[1mCREATE INKSCAPE APP BUNDLE\033[0m\n"
111 # Safety tests
112 if [ ${add_python} = "true" ]; then
113         if [ ! -e "$python_dir" ]; then
114                 echo "Cannot find the directory containing python modules: $python_dir" >&2
115                 exit 1
116         fi
117 fi
119 if [ ! -e "$LIBPREFIX" ]; then
120         echo "Cannot find the directory containing the libraires: $LIBPREFIX" >&2
121         exit 1
122 fi
124 if [ ! -e "$LIBPREFIX/share/themes/Clearlooks-Quicksilver" ]; then
125         echo "Missing Clearlooks -- please install gtk2-clearlooks and try again." >&2
126         exit 1
127 fi
129 if [ ! -e "$LIBPREFIX/lib/gnome-vfs-2.0" ]; then
130         echo "Missing gnome-vfs -- please install gnome-vfs and try again." >&2
131         exit 1
132 fi
134 if [ ! -e "$LIBPREFIX/lib/aspell-0.60/en.dat" ]; then
135         echo "Missing aspell en dictionary -- please install at least 'aspell-dict-en', but" >&2
136         echo "preferably all dictionaries ('aspell-dict-*') and try again." >&2
137         exit 1
138 fi
140 if [ ! -f "$binary" ]; then
141         echo "Need Inkscape binary" >&2
142         exit 1
143 fi
145 if [ ! -f "$plist" ]; then
146         echo "Need plist file" >&2
147         exit 1
148 fi
150 if [ ! -x "$binary" ]; then
151         echo "Not executable: $binary" >&2
152         exit 1
153 fi
156 # Handle some version specific details.
157 VERSION=`/usr/bin/sw_vers | grep ProductVersion | cut -f2 -d'.'`
158 if [ "$VERSION" -ge "4" ]; then
159         # We're on Tiger (10.4) or later.
160         # XCode behaves a little differently in Tiger and later.
161         XCODEFLAGS="-configuration Deployment"
162         SCRIPTEXECDIR="ScriptExec/build/Deployment/ScriptExec.app/Contents/MacOS"
163         EXTRALIBS=""
164 else
165         # Panther (10.3) or earlier.
166         XCODEFLAGS="-buildstyle Deployment"
167         SCRIPTEXECDIR="ScriptExec/build/ScriptExec.app/Contents/MacOS"
168         EXTRALIBS=""
169 fi
172 # Package always has the same name. Version information is stored in
173 # the Info.plist file which is filled in by the configure script.
174 package="Inkscape.app"
176 # Remove a previously existing package if necessary
177 if [ -d $package ]; then
178         echo "Removing previous Inkscape.app"
179         rm -Rf $package
180 fi
183 # Set the 'macosx' directory, usually the current directory.
184 resdir=`pwd`
187 # Prepare Package
188 #----------------------------------------------------------
189 pkgexec="$package/Contents/MacOS"
190 pkgbin="$package/Contents/Resources/bin"
191 pkglib="$package/Contents/Resources/lib"
192 pkglocale="$package/Contents/Resources/locale"
193 pkgpython="$package/Contents/Resources/python/site-packages/"
194 pkgresources="$package/Contents/Resources"
196 mkdir -p "$pkgexec"
197 mkdir -p "$pkgbin"
198 mkdir -p "$pkglib"
199 mkdir -p "$pkglocale"
200 mkdir -p "$pkgpython"
202 mkdir -p "$pkgresources/Dutch.lprj"
203 mkdir -p "$pkgresources/English.lprj"
204 mkdir -p "$pkgresources/French.lprj"
205 mkdir -p "$pkgresources/German.lprj"
206 mkdir -p "$pkgresources/Italian.lprj"
207 mkdir -p "$pkgresources/Spanish.lprj"
208 mkdir -p "$pkgresources/fi.lprj"
209 mkdir -p "$pkgresources/no.lprj"
210 mkdir -p "$pkgresources/sv.lprj"
212 # Build and add the launcher
213 #----------------------------------------------------------
215         # Build fails if CC happens to be set (to anything other than CompileC)
216         unset CC
217         
218         cd "$resdir/ScriptExec"
219         echo -e "\033[1mBuilding launcher...\033[0m\n"
220         xcodebuild $XCODEFLAGS clean build
222 cp "$resdir/$SCRIPTEXECDIR/ScriptExec" "$pkgexec/Inkscape"
225 # Copy all files into the bundle
226 #----------------------------------------------------------
227 echo -e "\n\033[1mFilling app bundle...\033[0m\n"
229 binary_name=`basename "$binary"`
230 binary_dir=`dirname "$binary"`
232 # Inkscape's binary
233 binpath="$pkgbin/inkscape-bin"
234 cp -v "$binary" "$binpath"
235 # TODO Add a "$verbose" variable and command line switch, which sets wether these commands are verbose or not
237 # Share files
238 rsync -av "$binary_dir/../share/$binary_name"/* "$pkgresources/"
239 cp "$plist" "$package/Contents/Info.plist"
240 rsync -av "$binary_dir/../share/locale"/* "$pkgresources/locale"
242 # Copy GTK shared mime information
243 mkdir -p "$pkgresources/share"
244 cp -rp "$LIBPREFIX/share/mime" "$pkgresources/share/"
246 # Icons and the rest of the script framework
247 rsync -av --exclude ".svn" "$resdir"/Resources/* "$pkgresources/"
249 # Add python modules if requested
250 if [ ${add_python} = "true" ]; then
251         # copy python site-packages. They need to be organized in a hierarchical set of directories, by architecture and python major+minor version, e.g. i386/2.3/ for Ptyhon 2.3 on Intel; ppc/2.4/ for Python 2.4 on PPC
252         cp -rvf "$python_dir"/* "$pkgpython"
253 fi
255 # PkgInfo must match bundle type and creator code from Info.plist
256 echo "APPLInks" > $package/Contents/PkgInfo
258 # Pull in extra requirements for Pango and GTK
259 pkgetc="$package/Contents/Resources/etc"
260 mkdir -p $pkgetc/pango
261 cp $LIBPREFIX/etc/pango/pangox.aliases $pkgetc/pango/
262 # Need to adjust path and quote in case of spaces in path.
263 sed -e "s,$LIBPREFIX,\"\${CWD},g" -e 's,\.so ,.so" ,g' $LIBPREFIX/etc/pango/pango.modules > $pkgetc/pango/pango.modules
264 cat > $pkgetc/pango/pangorc <<END_PANGO
265 [Pango]
266 ModuleFiles=\${HOME}/.inkscape-etc/pango.modules
267 [PangoX]
268 AliasFiles=\${HOME}/.inkscape-etc/pangox.aliases
269 END_PANGO
271 # We use a modified fonts.conf file so only need the dtd
272 mkdir -p $pkgetc/fonts
273 cp $LIBPREFIX/etc/fonts/fonts.dtd $pkgetc/fonts/
274 cp -r $LIBPREFIX/etc/fonts/conf.avail $pkgetc/fonts/
275 cp -r $LIBPREFIX/etc/fonts/conf.d $pkgetc/fonts/
277 mkdir -p $pkgetc/gtk-2.0
278 sed -e "s,$LIBPREFIX,\${CWD},g" $LIBPREFIX/etc/gtk-2.0/gdk-pixbuf.loaders > $pkgetc/gtk-2.0/gdk-pixbuf.loaders
279 sed -e "s,$LIBPREFIX,\${CWD},g" $LIBPREFIX/etc/gtk-2.0/gtk.immodules > $pkgetc/gtk-2.0/gtk.immodules
281 for item in gnome-vfs-mime-magic gnome-vfs-2.0
282 do
283         cp -r $LIBPREFIX/etc/$item $pkgetc/
284 done
286 pango_version=`pkg-config --variable=pango_module_version pango`
287 mkdir -p $pkglib/pango/$pango_version/modules
288 cp $LIBPREFIX/lib/pango/$pango_version/modules/*.so $pkglib/pango/$pango_version/modules/
290 gtk_version=`pkg-config --variable=gtk_binary_version gtk+-2.0`
291 mkdir -p $pkglib/gtk-2.0/$gtk_version/{engines,immodules,loaders,printbackends}
292 cp -r $LIBPREFIX/lib/gtk-2.0/$gtk_version/* $pkglib/gtk-2.0/$gtk_version/
294 mkdir -p $pkglib/gnome-vfs-2.0/modules
295 cp $LIBPREFIX/lib/gnome-vfs-2.0/modules/*.so $pkglib/gnome-vfs-2.0/modules/
297 # Copy aspell dictionary files:
298 cp -r "$LIBPREFIX/lib/aspell-0.60" "$pkglib/"
299 cp -r "$LIBPREFIX/share/aspell" "$pkgresources/share/"
301 # Find out libs we need from fink, darwinports, or from a custom install
302 # (i.e. $LIBPREFIX), then loop until no changes.
303 a=1
304 nfiles=0
305 endl=true
306 while $endl; do
307         echo -e "\033[1mLooking for dependencies.\033[0m Round" $a
308         libs="`otool -L $pkglib/gtk-2.0/$gtk_version/{engines,immodules,loaders,printbackends}/*.{dylib,so} $pkglib/pango/$pango_version/modules/* $pkglib/gnome-vfs-2.0/modules/* $package/Contents/Resources/lib/* $binary 2>/dev/null | fgrep compatibility | cut -d\( -f1 | grep $LIBPREFIX | sort | uniq`"
309         cp -f $libs $package/Contents/Resources/lib
310         let "a+=1"      
311         nnfiles=`ls $package/Contents/Resources/lib | wc -l`
312         if [ $nnfiles = $nfiles ]; then
313                 endl=false
314         else
315                 nfiles=$nnfiles
316         fi
317 done
319 # Add extra libraries of necessary
320 for libfile in $EXTRALIBS
321 do
322         cp -f $libfile $package/Contents/Resources/lib
323 done
326 # Strip libraries and executables if requested
327 #----------------------------------------------------------
328 if [ "$strip" = "true" ]; then
329         echo -e "\n\033[1mStripping debugging symbols...\033[0m\n"
330         chmod +w "$pkglib"/*.dylib
331         strip -x "$pkglib"/*.dylib
332         strip -ur "$binpath"
333 fi
335 # NOTE: This works for all the dylibs but causes GTK to crash at startup.
336 #                               Instead we leave them with their original install_names and set
337 #                               DYLD_LIBRARY_PATH within the app bundle before running Inkscape.
339 fixlib () {
340         libPath="`echo $2 | sed 's/.*Resources//'`"
341         pkgPath="`echo $2 | sed 's/Resources\/.*/Resources/'`"
342         # Fix a given executable or library to be relocatable
343         if [ ! -d "$1" ]; then
344                 libs="`otool -L $1 | fgrep compatibility | cut -d\( -f1`"
345                 for lib in $libs; do
346                         echo "  $lib"
347                         base=`echo $lib | awk -F/ '{print $NF}'`
348                         first=`echo $lib | cut -d/ -f1-3`
349                         relative=`echo $lib | cut -d/ -f4-`
350                         to=@executable_path/../$relative
351                         if [ $first != /usr/lib -a $first != /usr/X11 -a $first != /System/Library ]; then
352                                 /usr/bin/install_name_tool -change $lib $to $1
353                                 if [ "`echo $lib | fgrep libcrypto`" = "" ]; then
354                                         /usr/bin/install_name_tool -id $to $1
355                                         for ll in $libs; do
356                                                 base=`echo $ll | awk -F/ '{print $NF}'`
357                                                 first=`echo $ll | cut -d/ -f1-3`
358                                                 relative=`echo $ll | cut -d/ -f4-`
359                                                 to=@executable_path/../$relative
360                                                 if [ $first != /usr/lib -a $first != /usr/X11 -a $first != /System/Library -a "`echo $ll | fgrep libcrypto`" = "" ]; then
361                                                         /usr/bin/install_name_tool -change $ll $to $pkgPath/$relative
362                                                 fi
363                                         done
364                                 fi
365                         fi
366                 done
367         fi
369
370 # Fix package deps
371 # (cd "$package/Contents/Resources/lib/gtk-2.0/2.10.0/loaders"
372 # for file in *.so; do
373 #       echo "Rewriting dylib paths for $file..."
374 #       fixlib "$file" "`pwd`"
375 # done
376 # )
377 # (cd "$package/Contents/Resources/lib/gtk-2.0/2.10.0/engines"
378 # for file in *.so; do
379 #       echo "Rewriting dylib paths for $file..."
380 #       fixlib "$file" "`pwd`"
381 # done
382 # )
383 # (cd "$package/Contents/Resources/lib/gtk-2.0/2.10.0/immodules"
384 # for file in *.so; do
385 #       echo "Rewriting dylib paths for $file..."
386 #       fixlib "$file" "`pwd`"
387 # done
388 # )
389 # (cd "$package/Contents/Resources/lib/gtk-2.0/2.10.0/printbackends"
390 # for file in *.so; do
391 #       echo "Rewriting dylib paths for $file..."
392 #       fixlib "$file" "`pwd`"
393 # done
394 # )
395 # (cd "$package/Contents/Resources/bin"
396 # for file in *; do
397 #       echo "Rewriting dylib paths for $file..."
398 #       fixlib "$file" "`pwd`"
399 # done
400 # cd ../lib
401 # for file in *.dylib; do
402 #       echo "Rewriting dylib paths for $file..."
403 #       fixlib "$file" "`pwd`"
404 # done
405 # )
407 exit 0