The Qt executables shouldn't need any wrappers. Just copy them over
[metze/wireshark/wip.git] / packaging / macosx / osx-app.sh
1 #!/bin/bash
2 #
3 # $Id$
4 #
5 # USAGE
6 # osx-app [-s] [-l /path/to/libraries] -bp /path/to/wireshark/bin -p /path/to/Info.plist
7 #
8 # This script attempts to build an Wireshark.app package for OS X, resolving
9 # dynamic libraries, etc.
10 # It strips the executable and libraries if '-s' is given.
11 # It adds python modules if the '-py option' is given
12 # The Info.plist file can be found in the base wireshark directory once
13 # configure has been run.
14 #
15 # AUTHORS
16 #                Kees Cook <kees@outflux.net>
17 #                Michael Wybrow <mjwybrow@users.sourceforge.net>
18 #                Jean-Olivier Irisson <jo.irisson@gmail.com>
19 #
20 # Copyright (C) 2005 Kees Cook
21 # Copyright (C) 2005-2007 Michael Wybrow
22 # Copyright (C) 2007 Jean-Olivier Irisson
23 #
24 # Released under GNU GPL, read the file 'COPYING' for more information
25 #
26 # Thanks to GNUnet's "build_app" script for help with library dep resolution.
27 #               https://gnunet.org/svn/GNUnet/contrib/OSX/build_app
28 #
29 # NB:
30 # This originally came from Inkscape; Inkscape's configure script has an
31 # "--enable-osxapp", which causes some of Inkscape's installation data
32 # files to have OS X-ish paths under Contents/Resources of the package
33 # or under /Library/Application Support.  We don't have such an option;
34 # we just put them in "bin", "etc", "lib", and "share" directories
35 # under Contents/Resources, rather than in the "bin", "etc", "lib",
36 # and "share" directories under the installation directory.
37 #
38
39 # Defaults
40 strip=false
41 binary_path="/tmp/inst/bin"
42 plist="./Info.plist"
43 util_dir="./Utilities"
44 cli_dir="$util_dir/Command Line"
45 chmodbpf_dir="$util_dir/ChmodBPF"
46
47 # "qt" or "gtk"
48 ui_toolkit="gtk"
49 # Name of the Wireshark executable
50 wireshark_bin_name="wireshark"
51
52 binary_list="
53         capinfos
54         dftest
55         dumpcap
56         editcap
57         mergecap
58         randpkt
59         rawshark
60         text2pcap
61         tshark
62 "
63
64 # Location for libraries (macosx-setup.sh defaults to whatever the
65 # various support libraries use as their standard installation location,
66 # which is /usr/local)
67 if [ -z $LIBPREFIX ]; then
68         LIBPREFIX="/usr/local"
69 fi
70
71
72 # Help message
73 #----------------------------------------------------------
74 help()
75 {
76 echo -e "
77 Create an app bundle for OS X
78
79 USAGE
80         $0 [-s] [-l /path/to/libraries] [-qt] -bp /path/to/wireshark/binaries -p /path/to/Info.plist
81
82 OPTIONS
83         -h,--help
84                 display this help message
85         -s
86                 strip the libraries and executables from debugging symbols
87         -l,--libraries
88                 specify the path to the libraries Wireshark depends on
89                 (typically /sw or /opt/local).  By default it is
90                 /usr/local.
91         -bp,--binary-path
92                 specify the path to the Wireshark binaries. By default it
93                 is /tmp/inst/bin.
94         -p,--plist
95                 specify the path to Info.plist. Info.plist can be found
96                 in the base directory of the source code once configure
97                 has been run.
98         -sdkroot
99                 specify the root of the SDK to use
100         -qt,--qt-flavor
101                 use the Qt flavor
102
103 EXAMPLE
104         $0 -s -l /opt/local -bp ../../Build/bin -p Info.plist -sdkroot /Developer/SDKs/MacOSX10.5.sdk
105 "
106 }
107
108
109 # Parse command line arguments
110 #----------------------------------------------------------
111 while [ "$1" != "" ]
112 do
113         case $1 in
114                 -s)
115                         strip=true ;;
116                 -l|--libraries)
117                         LIBPREFIX="$2"
118                         shift 1 ;;
119                 -bp|--binary-path)
120                         binary_path="$2"
121                         shift 1 ;;
122                 -p|--plist)
123                         plist="$2"
124                         shift 1 ;;
125                 -qt|--qt-flavor)
126                         ui_toolkit="qt"
127                         wireshark_bin_name="wireshark-qt"
128                         ;;
129                 -h|--help)
130                         help
131                         exit 0 ;;
132                 -sdkroot)
133                         sdkroot="$2"
134                         shift 1 ;;
135                 *)
136                         echo "Invalid command line option: $1"
137                         exit 2 ;;
138         esac
139         shift 1
140 done
141
142 echo -e "\nCREATE WIRESHARK APP BUNDLE\n"
143
144 # Safety tests
145 if [ ! -e "$LIBPREFIX" ]; then
146         echo "Cannot find the directory containing the libraries: $LIBPREFIX" >&2
147         exit 1
148 fi
149
150 for binary in $wireshark_bin_name $binary_list ; do
151         if [ ! -x "$binary_path/$binary" ]; then
152                 echo "Couldn't find $binary (or it's not executable)" >&2
153                 exit 1
154         fi
155 done
156
157 if [ ! -f "$plist" ]; then
158         echo "Need plist file" >&2
159         exit 1
160 fi
161
162
163 # Handle some version specific details.
164 VERSION=`/usr/bin/sw_vers | grep ProductVersion | cut -f2 -d'.'`
165 if [ "$VERSION" -ge "4" ]; then
166         # We're on Tiger (10.4) or later.
167         # XCode behaves a little differently in Tiger and later.
168         XCODEFLAGS="-configuration Deployment"
169         SCRIPTEXECDIR="ScriptExec/build/Deployment/ScriptExec.app/Contents/MacOS"
170         EXTRALIBS=""
171 else
172         # Panther (10.3) or earlier.
173         XCODEFLAGS="-buildstyle Deployment"
174         SCRIPTEXECDIR="ScriptExec/build/ScriptExec.app/Contents/MacOS"
175         EXTRALIBS=""
176 fi
177
178 # Set the SDK root, if an SDK was specified.
179 # (-sdk is only supported by the xcodebuild in the version of the
180 # developer tools that came with Snow Leopard and later versions)
181 if [ ! -z "$sdkroot" ]
182 then
183         XCODEFLAGS="$XCODEFLAGS SDKROOT=$sdkroot"
184 fi
185
186 # Package always has the same name. Version information is stored in
187 # the Info.plist file which is filled in by the configure script.
188 package="Wireshark.app"
189
190 # Remove a previously existing package if necessary
191 if [ -d $package ]; then
192         echo "Removing previous Wireshark.app"
193         rm -Rf $package
194 fi
195
196 # Remove a previously existing utility directory if necessary
197 if [ -d "$util_dir" ]; then
198         echo "Removing $util_dir directory"
199         rm -Rf "$util_dir"
200 fi
201
202 # Set the 'macosx' directory, usually the current directory.
203 resdir=`pwd`
204
205
206 # Prepare Package
207 #----------------------------------------------------------
208 pkgexec="$package/Contents/MacOS"
209 pkgres="$package/Contents/Resources"
210 pkgbin="$pkgexec"
211 # Should pkglib be Contents/Frameworks instead?
212 #pkglib="$pkgres/lib"
213 pkglib="$package/Contents/Frameworks"
214 pkgqtplugin="$package/Contents/PlugIns"
215 pkgplugin="$pkglib/wireshark/plugins"
216 pkgpython="$pkglib/wireshark/python"
217
218 mkdir -p "$pkgexec"
219 mkdir -p "$pkgbin"
220 mkdir -p "$pkgqtplugin"
221 mkdir -p "$pkgplugin"
222 mkdir -p "$pkgpython"
223
224 mkdir -p "$cli_dir"
225
226 if [ "$ui_toolkit" = "qt" ] ; then
227         cp "$binary_path/$wireshark_bin_name" "$pkgexec/Wireshark"
228 else
229 # Build and add the launcher
230 #----------------------------------------------------------
231         (
232                 # Build fails if CC happens to be set (to anything other than CompileC)
233                 unset CC
234
235                 cd "$resdir/ScriptExec"
236                 echo -e "Building launcher...\n"
237                 xcodebuild $XCODEFLAGS clean build
238         )
239         cp "$resdir/$SCRIPTEXECDIR/ScriptExec" "$pkgexec/Wireshark"
240
241 fi
242
243 # Copy all files into the bundle
244 #----------------------------------------------------------
245 echo -e "\nFilling app bundle and utility directory...\n"
246
247 # Wireshark executables
248 if [ "$ui_toolkit" = "gtk" ] ; then
249         cp -v utility-launcher "$cli_dir/$binary"
250         for binary in $binary_list ; do
251                 # Copy the binary to its destination
252                 dest_path="$pkgbin/$binary-bin"
253                 cp -v "$binary_path/$binary" "$dest_path"
254                 # TODO Add a "$verbose" variable and command line switch, which sets wether these commands are verbose or not
255
256                 ln -sv ./wireshark "$pkgbin/$binary"
257                 ln -sv ./wireshark "$cli_dir/$binary"
258         done
259 elif [ "$ui_toolkit" = "qt" ] ; then
260         for binary in $binary_list ; do
261                 # Copy the binary to its destination
262                 cp -v "$binary_path/$binary" "$pkgexec"
263         done
264 fi
265
266 # ChmodBPF
267 mkdir -p "$chmodbpf_dir"
268 cp -v ChmodBPF/* "$chmodbpf_dir"
269 chmod -R g-w "$chmodbpf_dir"
270
271 # The rest of the Wireshark installation (we handled bin above)
272 rsync -av \
273         --exclude bin/ \
274         --exclude lib/ \
275         "$binary_path/.."/* "$pkgres"
276
277 rsync -av $binary_path/../lib/*.dylib "$pkglib/"
278
279 # Remove the version number from the plugin path
280 find "$binary_path/../lib/wireshark/plugins" -type f \
281         -exec cp -fv "{}" "$pkgplugin/" \;
282
283 # Remove the version number from the python path
284 find "$binary_path/../lib/wireshark/python" -type f \
285         -exec cp -fv "{}" "$pkgpython/" \;
286
287 cp "$plist" "$package/Contents/Info.plist"
288
289 # Icons and the rest of the script framework
290 res_list="
291         Wireshark.icns
292         Wiresharkdoc.icns
293         bin
294         openDoc
295 "
296
297 if [ "$ui_toolkit" = "gtk" ] ; then
298         res_list="
299                 $res_list
300                 etc
301                 script
302                 MenuBar.nib
303                 ProgressWindow.nib
304                 themes
305         "
306 fi
307
308 for rl_entry in $res_list ; do
309         rsync -av "$resdir"/Resources/$rl_entry "$package"/Contents/Resources/
310 done
311
312 # PkgInfo must match bundle type and creator code from Info.plist
313 echo "APPLWshk" > $package/Contents/PkgInfo
314
315 if [ "$ui_toolkit" = "gtk" ] ; then
316
317         # Pull in extra requirements for Pango and GTK
318         pkgetc="$package/Contents/Resources/etc"
319         mkdir -p $pkgetc/pango
320         cp $LIBPREFIX/etc/pango/pangox.aliases $pkgetc/pango/
321         # Need to adjust path and quote in case of spaces in path.
322         sed -e "s,$LIBPREFIX,\"\${CWD},g" -e 's,\.so ,.so" ,g' $LIBPREFIX/etc/pango/pango.modules > $pkgetc/pango/pango.modules
323         cat > $pkgetc/pango/pangorc <<END_PANGO
324 [Pango]
325 ModuleFiles=\${HOME}/.wireshark-etc/pango.modules
326 [PangoX]
327 AliasFiles=\${HOME}/.wireshark-etc/pangox.aliases
328 END_PANGO
329
330         # We use a modified fonts.conf file so only need the dtd
331         mkdir -p $pkgetc/fonts
332         cp $LIBPREFIX/etc/fonts/fonts.dtd $pkgetc/fonts/
333         cp -r $LIBPREFIX/etc/fonts/conf.avail $pkgetc/fonts/
334         cp -r $LIBPREFIX/etc/fonts/conf.d $pkgetc/fonts/
335
336         mkdir -p $pkgetc/gtk-2.0
337         #
338         # In newer versions of GTK+, the gdk-pixbuf library was split off from
339         # GTK+, and the gdk-pixbuf.loaders file moved, so we check for its
340         # existence here.
341         #
342         # The file is ultimately copied to the user's home directory, with
343         # the pathnames adjusted to refer to the installed package, so we
344         # always put it in the same location in the installed package,
345         # regardless of where it lives in the machine on which it's built.
346         #
347         if [ -e $LIBPREFIX/etc/gtk-2.0/gdk-pixbuf.loaders ]
348         then
349                 sed -e "s,$LIBPREFIX,\${CWD},g" $LIBPREFIX/etc/gtk-2.0/gdk-pixbuf.loaders > $pkgetc/gtk-2.0/gdk-pixbuf.loaders
350         fi
351         sed -e "s,$LIBPREFIX,\${CWD},g" $LIBPREFIX/etc/gtk-2.0/gtk.immodules > $pkgetc/gtk-2.0/gtk.immodules
352
353         pango_version=`pkg-config --variable=pango_module_version pango`
354         mkdir -p $pkglib/pango/$pango_version/modules
355         cp $LIBPREFIX/lib/pango/$pango_version/modules/*.so $pkglib/pango/$pango_version/modules/
356
357         gtk_version=`pkg-config --variable=gtk_binary_version gtk+-2.0`
358         mkdir -p $pkglib/gtk-2.0/$gtk_version/{engines,immodules,loaders}
359         cp -r $LIBPREFIX/lib/gtk-2.0/$gtk_version/* $pkglib/gtk-2.0/$gtk_version/
360
361         gdk_pixbuf_version=`pkg-config --variable=gdk_pixbuf_binary_version gdk-pixbuf-2.0`
362         if [ ! -z $gdk_pixbuf_version ]; then
363                 mkdir -p $pkglib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders
364                 #
365                 # As per the above, check whether we have a loaders.cache file
366                 # in $LIBPREFIX/lib/gdk-pixbuf-2.0/$gdk_pixbuf_version, as
367                 # that's where the output of gdk-pixbuf-query-loaders gets
368                 # put if gdk-pixbuf and GTK+ are separated.
369                 #
370                 # The file is ultimately copied to the user's home directory,
371                 # with the pathnames adjusted to refer to the installed package,
372                 # so we always put it in the same location in the installed
373                 # package, regardless of where it lives in the machine on which
374                 # it's built.
375                 #
376                 if [ -e $LIBPREFIX/lib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders.cache ]
377                 then
378                         sed -e "s,$LIBPREFIX,\${CWD},g" $LIBPREFIX/lib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders.cache > $pkgetc/gtk-2.0/gdk-pixbuf.loaders
379                 fi
380                 cp -r $LIBPREFIX/lib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders/* $pkglib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders
381         fi
382 fi # GTK+ / Qt
383
384 # Find out libs we need from Fink, MacPorts, or from a custom install
385 # (i.e. $LIBPREFIX), then loop until no changes.
386 a=1
387 nfiles=0
388 endl=true
389 lib_dep_search_list="
390         $pkglib/*
391         $pkgbin/*-bin
392         "
393 if [ "$ui_toolkit" = "gtk" ] ; then
394         lib_dep_search_list="
395                 $lib_dep_search_list
396                 $pkglib/gtk-2.0/$gtk_version/loaders/*
397                 $pkglib/gtk-2.0/$gtk_version/immodules/*
398                 $pkglib/gtk-2.0/$gtk_version/engines/*.so
399                 $pkglib/pango/$pango_version/modules/*
400                 $pkglib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders/*
401                 "
402 elif [ "$ui_toolkit" = "qt" ] ; then
403         lib_dep_search_list="
404                 $pkgexec/Wireshark
405                 $lib_dep_search_list
406                 "
407 fi
408
409 while $endl; do
410         echo -e "Looking for dependencies. Round" $a
411         libs="`otool -L $lib_dep_search_list 2>/dev/null | fgrep compatibility | cut -d\( -f1 | grep $LIBPREFIX | sort | uniq`"
412         cp -vn $libs "$pkglib"
413         let "a+=1"
414         nnfiles=`ls "$pkglib" | wc -l`
415         if [ $nnfiles = $nfiles ]; then
416                 endl=false
417         else
418                 nfiles=$nnfiles
419         fi
420 done
421
422 # Add extra libraries of necessary
423 for libfile in $EXTRALIBS
424 do
425         cp -f $libfile "$pkglib"
426 done
427 chmod 755 "$pkglib"/*.dylib
428
429 # Strip libraries and executables if requested
430 #----------------------------------------------------------
431 if [ "$strip" = "true" ]; then
432         echo -e "\nStripping debugging symbols...\n"
433         strip -x "$pkglib"/*.dylib
434         strip -ur "$binpath"
435 fi
436
437 # NOTE: we must rpathify *all* files, *including* plugins for GTK+ etc.,
438 #       to keep GTK+ from crashing at startup.
439 #
440 rpathify_file () {
441         # Fix a given executable, library, or plugin to be relocatable
442         if [ ! -d "$1" ]; then
443                 #
444                 # OK, what type of file is this?
445                 #
446                 filetype=`otool -hv "$1" | sed -n '4p' | awk '{print $5}'`
447                 case "$filetype" in
448
449                 EXECUTE|DYLIB|BUNDLE)
450                         #
451                         # Executable, library, or plugin.  (Plugins
452                         # can be either DYLIB or BUNDLE; shared
453                         # libraries are DYLIB.)
454                         #
455                         # For DYLIB and BUNDLE, fix the shared
456                         # library identification.
457                         #
458                         if [[ "$filetype" = "DYLIB" || "$filetype" = "BUNDLE" ]]; then
459                                 echo "Changing shared library identification of $1"
460                                 base=`echo $1 | awk -F/ '{print $NF}'`
461                                 #
462                                 # The library will end up in a directory in
463                                 # the rpath; this is what we should change its
464                                 # ID to.
465                                 #
466                                 to=@rpath/$base
467                                 /usr/bin/install_name_tool -id $to $1
468                         fi
469
470                         #
471                         # Get the list of dynamic libraries on which this
472                         # file depends, and select only the libraries that
473                         # are in $LIBPREFIX, as those are the only ones
474                         # that we'll be shipping in the app bundle; the
475                         # other libraries are system-supplied or supplied
476                         # as part of X11, will be expected to be on the
477                         # system on which the bundle will be installed,
478                         # and should be referred to by their full pathnames.
479                         #
480                         libs="`otool -L $1 | egrep "$LIBPREFIX.* \(compatibility" | cut -d\( -f1`"
481                         for lib in $libs; do
482                                 #
483                                 # Get the file name of the library.
484                                 #
485                                 base=`echo $lib | awk -F/ '{print $NF}'`
486                                 #
487                                 # The library will end up in a directory in
488                                 # the rpath; this is what we should change its
489                                 # file name to.
490                                 #
491                                 to=@rpath/$base
492                                 #
493                                 # Change the reference to that library.
494                                 #
495                                 echo "Changing reference to $lib to $to in $1"
496                                 /usr/bin/install_name_tool -change $lib $to $1
497                         done
498                         ;;
499                 esac
500         fi
501 }
502
503 rpathify_dir () {
504         #
505         # Make sure we *have* that directory
506         #
507         if [ -d "$1" ]; then
508                 (cd "$1"
509                 #
510                 # Make sure we *have* files to fix
511                 #
512                 files=`ls $2 2>/dev/null`
513                 if [ ! -z "$files" ]; then
514                         for file in $files; do
515                                 rpathify_file "$file" "`pwd`"
516                         done
517                 fi
518                 )
519         fi
520 }
521
522 rpathify_files () {
523         #
524         # Fix package deps
525         #
526         rpathify_dir "$pkglib" "*.dylib"
527         if [ "$ui_toolkit" = "gtk" ] ; then
528                 rpathify_dir "$pkglib/gtk-2.0/$gtk_version/loaders" "*.so"
529                 rpathify_dir "$pkglib/gtk-2.0/$gtk_version/engines" "*.so"
530                 rpathify_dir "$pkglib/gtk-2.0/$gtk_version/immodules" "*.so"
531                 rpathify_dir "$pkglib/gtk-2.0/$gtk_version/printbackends" "*.so"
532                 rpathify_dir "$pkglib/gnome-vfs-2.0/modules" "*.so"
533                 rpathify_dir "$pkglib/gdk-pixbuf-2.0/$gtk_version/loaders" "*.so"
534                 rpathify_dir "$pkglib/pango/$pango_version/modules" "*.so"
535         fi
536         rpathify_dir "$pkgbin" "*"
537 }
538
539 PATHLENGTH=`echo $LIBPREFIX | wc -c`
540 if [ "$PATHLENGTH" -ge "6" ]; then
541         # If the LIBPREFIX path is long enough to allow 
542         # path rewriting, then do this.
543         # 6 is the length of @rpath, which replaces LIBPREFIX.
544         rpathify_files
545 else
546         echo "Could not rewrite dylib paths for bundled libraries.  This requires" >&2
547         echo "the support libraries to be installed in a PREFIX of at least 6 characters in length." >&2
548         echo "" >&2
549         echo "The package will still work if the following line is uncommented in" >&2
550         echo "Wireshark.app/Contents/Resources/bin/{various scripts}:" >&2
551         echo '        export DYLD_LIBRARY_PATH="$TOP/lib"' >&2
552         exit 1
553
554 fi
555
556 if [ "$ui_toolkit" = "qt" ] ; then
557         macdeployqt "$package" -verbose=2
558 fi
559
560 exit 0