Code

- Fix bug #390024: "raster image extensions fail on osx: missing ImageMagick
[inkscape.git] / packaging / macosx / osx-app.sh
1 #!/bin/bash
2 #
3 # USAGE
4 # osx-app [-s] [-l /path/to/libraries] -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
9 # If the '-s' option is given, then the libraries and executable are stripped.
10
11 # The Info.plist file can be found in the base inkscape directory once
12 # configure has been run.
13 #
14 # AUTHORS
15 #                Kees Cook <kees@outflux.net>
16 #                Michael Wybrow <mjwybrow@users.sourceforge.net>
17 #                Jean-Olivier Irisson <jo.irisson@gmail.com>
18
19 # Copyright (C) 2005 Kees Cook
20 # Copyright (C) 2005-2009 Michael Wybrow
21 # Copyright (C) 2007-2009 Jean-Olivier Irisson
22 #
23 # Released under GNU GPL, read the file 'COPYING' for more information
24 #
25 # Thanks to GNUnet's "build_app" script for help with library dep resolution.
26 #               https://gnunet.org/svn/GNUnet/contrib/OSX/build_app
27
28 # NB:
29 # When packaging Inkscape for OS X, configure should be run with the 
30 # "--enable-osxapp" option which sets the correct paths for support
31 # files inside the app bundle.
32
34 # Defaults
35 strip=false
36 add_python=false
37 python_dir=""
39 # 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)
40 if [ -z $LIBPREFIX ]; then
41         LIBPREFIX=""
42 fi
45 # Help message
46 #----------------------------------------------------------
47 help()
48 {
49 echo -e "
50 Create an app bundle for OS X
52 \033[1mUSAGE\033[0m
53         $0 [-s] [-l /path/to/libraries] -py /path/to/python/modules -b /path/to/bin/inkscape -p /path/to/Info.plist
55 \033[1mOPTIONS\033[0m
56         \033[1m-h,--help\033[0m 
57                 display this help message
58         \033[1m-s\033[0m
59                 strip the libraries and executables from debugging symbols
60         \033[1m-py,--with-python\033[0m
61                 add python modules (numpy, lxml) from given directory
62                 inside the app bundle
63         \033[1m-l,--libraries\033[0m
64                 specify the path to the librairies Inkscape depends on
65                 (typically /sw or /opt/local)
66         \033[1m-b--binary\033[0m
67                 specify the path to Inkscape's binary. By default it is in
68                 Build/bin/ at the base of the source code directory
69         \033[1m-p,--plist\033[0m
70                 specify the path to Info.plist. Info.plist can be found
71                 in the base directory of the source code once configure
72                 has been run
74 \033[1mEXAMPLE\033[0m
75         $0 -s -py ~/python-modules -l /opt/local -b ../../Build/bin/inkscape -p ../../Info.plist
76 "
77 }
80 # Parse command line arguments
81 #----------------------------------------------------------
82 while [ "$1" != "" ]
83 do
84         case $1 in
85                 -py|--with-python)
86                         add_python=true
87                         python_dir="$2"
88                         shift 1 ;;
89                 -s)
90                         strip=true ;;
91                 -l|--libraries)
92                         LIBPREFIX="$2"
93                         shift 1 ;;
94                 -b|--binary)
95                         binary="$2"
96                         shift 1 ;;
97                 -p|--plist)
98                         plist="$2"
99                         shift 1 ;;
100                 -h|--help)
101                         help
102                         exit 0 ;;
103                 *)
104                         echo "Invalid command line option: $1" 
105                         exit 2 ;;
106         esac
107         shift 1
108 done
110 echo -e "\n\033[1mCREATE INKSCAPE APP BUNDLE\033[0m\n"
112 # Safety tests
114 if [ "x$binary" == "x" ]; then
115         echo "Inkscape binary path not specified." >&2
116         exit 1
117 fi
119 if [ ! -x "$binary" ]; then
120         echo "Inkscape executable not not found at $binary." >&2
121         exit 1
122 fi
124 if [ "x$plist" == "x" ]; then
125         echo "Info.plist file not specified." >&2
126         exit 1
127 fi
129 if [ ! -f "$plist" ]; then
130         echo "Info.plist file not found at $plist." >&2
131         exit 1
132 fi
134 PYTHONPACKURL="http://inkscape.modevia.com/macosx-snap/Python-packages.dmg"
136 if [ "x$python_dir" == "x" ]; then
137         echo "Python modules directory not specified." >&2
138         echo "Python modules can be downloaded from:" >&2
139         echo "    $PYTHONPACKURL" >&2
140         exit 1
141 fi
143 if [ ! -e "$python_dir/i386" -o ! -e "$python_dir/ppc" ]; then
144         echo "Directory does not appear to contain the i386 and ppc python modules:" >&2
145         echo "    $python_dir" >&2
146         echo "Python modules can be downloaded from:" >&2
147         echo "    $PYTHONPACKURL" >&2
148         exit 1
149 fi
151 if [ ! -e "$LIBPREFIX" ]; then
152         echo "Cannot find the directory containing the libraires: $LIBPREFIX" >&2
153         exit 1
154 fi
156 if [ ! -e "$LIBPREFIX/share/themes/Clearlooks-Quicksilver" ]; then
157         echo "Missing Clearlooks -- please install gtk2-clearlooks and try again." >&2
158         exit 1
159 fi
161 if [ ! -e "$LIBPREFIX/lib/gnome-vfs-2.0" ]; then
162         echo "Missing gnome-vfs -- please install gnome-vfs and try again." >&2
163         exit 1
164 fi
166 if ! pkg-config --modversion ImageMagick >/dev/null 2>&1; then
167         echo "Missing ImageMagick -- please install ImageMagick and try again." >&2
168         exit 1
169 fi
171 if [ ! -e "$LIBPREFIX/lib/aspell-0.60/en.dat" ]; then
172         echo "Missing aspell en dictionary -- please install at least 'aspell-dict-en', but" >&2
173         echo "preferably all dictionaries ('aspell-dict-*') and try again." >&2
174         exit 1
175 fi
178 # Handle some version specific details.
179 VERSION=`/usr/bin/sw_vers | grep ProductVersion | cut -f2 -d'.'`
180 if [ "$VERSION" -ge "4" ]; then
181         # We're on Tiger (10.4) or later.
182         # XCode behaves a little differently in Tiger and later.
183         XCODEFLAGS="-configuration Deployment"
184         SCRIPTEXECDIR="ScriptExec/build/Deployment/ScriptExec.app/Contents/MacOS"
185         EXTRALIBS=""
186 else
187         # Panther (10.3) or earlier.
188         XCODEFLAGS="-buildstyle Deployment"
189         SCRIPTEXECDIR="ScriptExec/build/ScriptExec.app/Contents/MacOS"
190         EXTRALIBS=""
191 fi
194 # Package always has the same name. Version information is stored in
195 # the Info.plist file which is filled in by the configure script.
196 package="Inkscape.app"
198 # Remove a previously existing package if necessary
199 if [ -d $package ]; then
200         echo "Removing previous Inkscape.app"
201         rm -Rf $package
202 fi
205 # Set the 'macosx' directory, usually the current directory.
206 resdir=`pwd`
209 # Prepare Package
210 #----------------------------------------------------------
211 pkgexec="$package/Contents/MacOS"
212 pkgbin="$package/Contents/Resources/bin"
213 pkglib="$package/Contents/Resources/lib"
214 pkglocale="$package/Contents/Resources/locale"
215 pkgpython="$package/Contents/Resources/python/site-packages/"
216 pkgresources="$package/Contents/Resources"
218 mkdir -p "$pkgexec"
219 mkdir -p "$pkgbin"
220 mkdir -p "$pkglib"
221 mkdir -p "$pkglocale"
222 mkdir -p "$pkgpython"
224 mkdir -p "$pkgresources/Dutch.lprj"
225 mkdir -p "$pkgresources/English.lprj"
226 mkdir -p "$pkgresources/French.lprj"
227 mkdir -p "$pkgresources/German.lprj"
228 mkdir -p "$pkgresources/Italian.lprj"
229 mkdir -p "$pkgresources/Spanish.lprj"
230 mkdir -p "$pkgresources/fi.lprj"
231 mkdir -p "$pkgresources/no.lprj"
232 mkdir -p "$pkgresources/sv.lprj"
234 # Build and add the launcher
235 #----------------------------------------------------------
237         # Build fails if CC happens to be set (to anything other than CompileC)
238         unset CC
239         
240         cd "$resdir/ScriptExec"
241         echo -e "\033[1mBuilding launcher...\033[0m\n"
242         xcodebuild $XCODEFLAGS clean build
244 cp "$resdir/$SCRIPTEXECDIR/ScriptExec" "$pkgexec/Inkscape"
247 # Copy all files into the bundle
248 #----------------------------------------------------------
249 echo -e "\n\033[1mFilling app bundle...\033[0m\n"
251 binary_name=`basename "$binary"`
252 binary_dir=`dirname "$binary"`
254 # Inkscape's binary
255 binpath="$pkgbin/inkscape-bin"
256 cp -v "$binary" "$binpath"
257 # TODO Add a "$verbose" variable and command line switch, which sets wether these commands are verbose or not
259 # Share files
260 rsync -av "$binary_dir/../share/$binary_name"/* "$pkgresources/"
261 cp "$plist" "$package/Contents/Info.plist"
262 rsync -av "$binary_dir/../share/locale"/* "$pkgresources/locale"
264 # Copy GTK shared mime information
265 mkdir -p "$pkgresources/share"
266 cp -rp "$LIBPREFIX/share/mime" "$pkgresources/share/"
268 # Icons and the rest of the script framework
269 rsync -av --exclude ".svn" "$resdir"/Resources/* "$pkgresources/"
271 # Add python modules if requested
272 if [ ${add_python} = "true" ]; then
273         # 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
274         cp -rvf "$python_dir"/* "$pkgpython"
275 fi
277 # PkgInfo must match bundle type and creator code from Info.plist
278 echo "APPLInks" > $package/Contents/PkgInfo
280 # Pull in extra requirements for Pango and GTK
281 pkgetc="$package/Contents/Resources/etc"
282 mkdir -p $pkgetc/pango
283 cp $LIBPREFIX/etc/pango/pangox.aliases $pkgetc/pango/
284 # Need to adjust path and quote in case of spaces in path.
285 sed -e "s,$LIBPREFIX,\"\${CWD},g" -e 's,\.so ,.so" ,g' $LIBPREFIX/etc/pango/pango.modules > $pkgetc/pango/pango.modules
286 cat > $pkgetc/pango/pangorc <<END_PANGO
287 [Pango]
288 ModuleFiles=\${HOME}/.inkscape-etc/pango.modules
289 [PangoX]
290 AliasFiles=\${HOME}/.inkscape-etc/pangox.aliases
291 END_PANGO
293 # We use a modified fonts.conf file so only need the dtd
294 mkdir -p $pkgetc/fonts
295 cp $LIBPREFIX/etc/fonts/fonts.dtd $pkgetc/fonts/
296 cp -r $LIBPREFIX/etc/fonts/conf.avail $pkgetc/fonts/
297 cp -r $LIBPREFIX/etc/fonts/conf.d $pkgetc/fonts/
299 mkdir -p $pkgetc/gtk-2.0
300 sed -e "s,$LIBPREFIX,\${CWD},g" $LIBPREFIX/etc/gtk-2.0/gdk-pixbuf.loaders > $pkgetc/gtk-2.0/gdk-pixbuf.loaders
301 sed -e "s,$LIBPREFIX,\${CWD},g" $LIBPREFIX/etc/gtk-2.0/gtk.immodules > $pkgetc/gtk-2.0/gtk.immodules
303 for item in gnome-vfs-mime-magic gnome-vfs-2.0
304 do
305         cp -r $LIBPREFIX/etc/$item $pkgetc/
306 done
308 pango_version=`pkg-config --variable=pango_module_version pango`
309 mkdir -p $pkglib/pango/$pango_version/modules
310 cp $LIBPREFIX/lib/pango/$pango_version/modules/*.so $pkglib/pango/$pango_version/modules/
312 gtk_version=`pkg-config --variable=gtk_binary_version gtk+-2.0`
313 mkdir -p $pkglib/gtk-2.0/$gtk_version/{engines,immodules,loaders,printbackends}
314 cp -r $LIBPREFIX/lib/gtk-2.0/$gtk_version/* $pkglib/gtk-2.0/$gtk_version/
316 mkdir -p $pkglib/gnome-vfs-2.0/modules
317 cp $LIBPREFIX/lib/gnome-vfs-2.0/modules/*.so $pkglib/gnome-vfs-2.0/modules/
319 imagemagick_version=`pkg-config --modversion ImageMagick`
320 cp -r "$LIBPREFIX/lib/ImageMagick-$imagemagick_version" "$pkglib/"
321 cp -r "$LIBPREFIX/share/ImageMagick-$imagemagick_version" "$pkgresources/share/"
323 # Copy aspell dictionary files:
324 cp -r "$LIBPREFIX/lib/aspell-0.60" "$pkglib/"
325 cp -r "$LIBPREFIX/share/aspell" "$pkgresources/share/"
327 # Find out libs we need from fink, darwinports, or from a custom install
328 # (i.e. $LIBPREFIX), then loop until no changes.
329 a=1
330 nfiles=0
331 endl=true
332 while $endl; do
333         echo -e "\033[1mLooking for dependencies.\033[0m Round" $a
334         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/* $pkglib/ImageMagick/modules-Q16/{filters,coders}/*.so $binary 2>/dev/null | fgrep compatibility | cut -d\( -f1 | grep $LIBPREFIX | sort | uniq`"
335         cp -f $libs $package/Contents/Resources/lib
336         let "a+=1"      
337         nnfiles=`ls $package/Contents/Resources/lib | wc -l`
338         if [ $nnfiles = $nfiles ]; then
339                 endl=false
340         else
341                 nfiles=$nnfiles
342         fi
343 done
345 # Add extra libraries of necessary
346 for libfile in $EXTRALIBS
347 do
348         cp -f $libfile $package/Contents/Resources/lib
349 done
352 # Strip libraries and executables if requested
353 #----------------------------------------------------------
354 if [ "$strip" = "true" ]; then
355         echo -e "\n\033[1mStripping debugging symbols...\033[0m\n"
356         chmod +w "$pkglib"/*.dylib
357         strip -x "$pkglib"/*.dylib
358         strip -ur "$binpath"
359 fi
361 # NOTE: This works for all the dylibs but causes GTK to crash at startup.
362 #                               Instead we leave them with their original install_names and set
363 #                               DYLD_LIBRARY_PATH within the app bundle before running Inkscape.
365 fixlib () {
366         libPath="`echo $2 | sed 's/.*Resources//'`"
367         pkgPath="`echo $2 | sed 's/Resources\/.*/Resources/'`"
368         # Fix a given executable or library to be relocatable
369         if [ ! -d "$1" ]; then
370                 libs="`otool -L $1 | fgrep compatibility | cut -d\( -f1`"
371                 for lib in $libs; do
372                         echo "  $lib"
373                         base=`echo $lib | awk -F/ '{print $NF}'`
374                         first=`echo $lib | cut -d/ -f1-3`
375                         relative=`echo $lib | cut -d/ -f4-`
376                         to=@executable_path/../$relative
377                         if [ $first != /usr/lib -a $first != /usr/X11 -a $first != /System/Library ]; then
378                                 /usr/bin/install_name_tool -change $lib $to $1
379                                 if [ "`echo $lib | fgrep libcrypto`" = "" ]; then
380                                         /usr/bin/install_name_tool -id $to $1
381                                         for ll in $libs; do
382                                                 base=`echo $ll | awk -F/ '{print $NF}'`
383                                                 first=`echo $ll | cut -d/ -f1-3`
384                                                 relative=`echo $ll | cut -d/ -f4-`
385                                                 to=@executable_path/../$relative
386                                                 if [ $first != /usr/lib -a $first != /usr/X11 -a $first != /System/Library -a "`echo $ll | fgrep libcrypto`" = "" ]; then
387                                                         /usr/bin/install_name_tool -change $ll $to $pkgPath/$relative
388                                                 fi
389                                         done
390                                 fi
391                         fi
392                 done
393         fi
396 rewritelibpaths () {
397         # 
398         # Fix package deps
399         (cd "$package/Contents/Resources/lib/gtk-2.0/2.10.0/loaders"
400         for file in *.so; do
401                 echo "Rewriting dylib paths for $file..."
402                 fixlib "$file" "`pwd`"
403         done
404         )
405         (cd "$package/Contents/Resources/lib/gtk-2.0/2.10.0/engines"
406         for file in *.so; do
407                 echo "Rewriting dylib paths for $file..."
408                 fixlib "$file" "`pwd`"
409         done
410         )
411         (cd "$package/Contents/Resources/lib/gtk-2.0/2.10.0/immodules"
412         for file in *.so; do
413                 echo "Rewriting dylib paths for $file..."
414                 fixlib "$file" "`pwd`"
415         done
416         )
417         (cd "$package/Contents/Resources/lib/gtk-2.0/2.10.0/printbackends"
418         for file in *.so; do
419                 echo "Rewriting dylib paths for $file..."
420                 fixlib "$file" "`pwd`"
421         done
422         )
423         (cd "$package/Contents/Resources/lib/gnome-vfs-2.0/modules"
424         for file in *.so; do
425                 echo "Rewriting dylib paths for $file..."
426                 fixlib "$file" "`pwd`"
427         done
428         )
429         (cd "$package/Contents/Resources/lib/pango/1.6.0/modules"
430         for file in *.so; do
431                 echo "Rewriting dylib paths for $file..."
432                 fixlib "$file" "`pwd`"
433         done
434         )
435         (cd "$package/Contents/Resources/lib/ImageMagick/modules-Q16/filters"
436         for file in *.so; do
437                 echo "Rewriting dylib paths for $file..."
438                 fixlib "$file" "`pwd`"
439         done
440         )
441         (cd "$package/Contents/Resources/lib/ImageMagick/modules-Q16/coders"
442         for file in *.so; do
443                 echo "Rewriting dylib paths for $file..."
444                 fixlib "$file" "`pwd`"
445         done
446         )
447         (cd "$package/Contents/Resources/bin"
448         for file in *; do
449                 echo "Rewriting dylib paths for $file..."
450                 fixlib "$file" "`pwd`"
451         done
452         cd ../lib
453         for file in *.dylib; do
454                 echo "Rewriting dylib paths for $file..."
455                 fixlib "$file" "`pwd`"
456         done
457         )
460 PATHLENGTH=`echo $LIBPREFIX | wc -c`
461 if [ "$PATHLENGTH" -ge "50" ]; then
462         # If the LIBPREFIX path is long enough to allow 
463         # path rewriting, then do this.
464         rewritelibpaths
465 else
466         echo "Could not rewrite dylb paths for bundled libraries.  This requires" >&2
467         echo "Macports to be installed in a PREFIX of at least 50 characters in length." >&2
468         echo "" >&2
469         echo "The package will still work if the following line is uncommented in" >&2
470         echo "Inkscape.app/Contents/Resources/bin/inkscape:" >&2
471         echo '        export DYLD_LIBRARY_PATH="$TOP/lib"' >&2
472         exit 1
474 fi
476 exit 0