MSWSP: parse_CColumnGroupArray() etc.
[wireshark-wip.git] / packaging / macosx / osx-app.sh
blob4356d848b56bfac9e1b2958b1622cee54713d873
1 #!/bin/bash
3 # $Id$
5 # USAGE
6 # osx-app [-s] [-l /path/to/libraries] -bp /path/to/wireshark/bin -p /path/to/Info.plist
8 # This script attempts to build an Wireshark.app bundle 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.
15 # AUTHORS
16 # Kees Cook <kees@outflux.net>
17 # Michael Wybrow <mjwybrow@users.sourceforge.net>
18 # Jean-Olivier Irisson <jo.irisson@gmail.com>
20 # Copyright (C) 2005 Kees Cook
21 # Copyright (C) 2005-2007 Michael Wybrow
22 # Copyright (C) 2007 Jean-Olivier Irisson
24 # Released under GNU GPL, read the file 'COPYING' for more information
26 # Thanks to GNUnet's "build_app" script for help with library dep resolution.
27 # https://gnunet.org/svn/GNUnet/contrib/OSX/build_app
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 bundle
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.
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 exclude_prefixes="/System/|/Library/|/usr/lib/|/usr/X11/|/opt/X11/|@rpath|@executable_path"
49 # "qt" or "gtk"
50 ui_toolkit="gtk"
51 # Name of the Wireshark executable
52 wireshark_bin_name="wireshark"
54 binary_list="
55 capinfos
56 dftest
57 dumpcap
58 editcap
59 mergecap
60 randpkt
61 rawshark
62 text2pcap
63 tshark
65 cs_binary_list=
67 # Location for libraries (macosx-setup.sh defaults to whatever the
68 # various support libraries use as their standard installation location,
69 # which is /usr/local)
70 if [ -z $LIBPREFIX ]; then
71 LIBPREFIX="/usr/local"
75 # Help message
76 #----------------------------------------------------------
77 help()
79 echo -e "
80 Create an app bundle for OS X
82 USAGE
83 $0 [-s] [-l /path/to/libraries] [-qt] -bp /path/to/wireshark/binaries -p /path/to/Info.plist
85 OPTIONS
86 -h,--help
87 display this help message
89 strip the libraries and executables from debugging symbols
90 -l,--libraries
91 specify the path to the libraries Wireshark depends on
92 (typically /sw or /opt/local). By default it is
93 /usr/local.
94 -bp,--binary-path
95 specify the path to the Wireshark binaries. By default it
96 is /tmp/inst/bin.
97 -p,--plist
98 specify the path to Info.plist. Info.plist can be found
99 in the base directory of the source code once configure
100 has been run.
101 -sdkroot
102 specify the root of the SDK to use
103 -qt,--qt-flavor
104 use the Qt flavor
106 EXAMPLE
107 $0 -s -l /opt/local -bp ../../Build/bin -p Info.plist -sdkroot /Developer/SDKs/MacOSX10.5.sdk
112 # Parse command line arguments
113 #----------------------------------------------------------
114 while [ "$1" != "" ]
116 case $1 in
118 strip=true ;;
119 -l|--libraries)
120 LIBPREFIX="$2"
121 shift 1 ;;
122 -bp|--binary-path)
123 binary_path="$2"
124 shift 1 ;;
125 -p|--plist)
126 plist="$2"
127 shift 1 ;;
128 -qt|--qt-flavor)
129 ui_toolkit="qt"
130 wireshark_bin_name="wireshark-qt"
132 -h|--help)
133 help
134 exit 0 ;;
135 -sdkroot)
136 sdkroot="$2"
137 shift 1 ;;
139 echo "Invalid command line option: $1"
140 exit 2 ;;
141 esac
142 shift 1
143 done
145 echo -e "\nCREATE WIRESHARK APP BUNDLE\n"
147 # Safety tests
148 if [ ! -e "$LIBPREFIX" ]; then
149 echo "Cannot find the directory containing the libraries: $LIBPREFIX" >&2
150 exit 1
153 for binary in $wireshark_bin_name $binary_list ; do
154 if [ ! -x "$binary_path/$binary" ]; then
155 echo "Couldn't find $binary (or it's not executable)" >&2
156 exit 1
158 done
160 if [ ! -f "$plist" ]; then
161 echo "Need plist file" >&2
162 exit 1
166 # Handle some version specific details.
167 VERSION=`/usr/bin/sw_vers | grep ProductVersion | cut -f2 -d'.'`
168 if [ "$VERSION" -ge "4" ]; then
169 # We're on Tiger (10.4) or later.
170 # XCode behaves a little differently in Tiger and later.
171 XCODEFLAGS="-configuration Deployment"
172 SCRIPTEXECDIR="ScriptExec/build/Deployment/ScriptExec.app/Contents/MacOS"
173 EXTRALIBS=""
174 else
175 # Panther (10.3) or earlier.
176 XCODEFLAGS="-buildstyle Deployment"
177 SCRIPTEXECDIR="ScriptExec/build/ScriptExec.app/Contents/MacOS"
178 EXTRALIBS=""
181 # Set the SDK root, if an SDK was specified.
182 # (-sdk is only supported by the xcodebuild in the version of the
183 # developer tools that came with Snow Leopard and later versions)
184 if [ ! -z "$sdkroot" ]
185 then
186 XCODEFLAGS="$XCODEFLAGS SDKROOT=$sdkroot"
189 # Bundle always has the same name. Version information is stored in
190 # the Info.plist file which is filled in by the configure script.
191 bundle="Wireshark.app"
193 # Remove a previously existing bundle if necessary
194 if [ -d $bundle ]; then
195 echo "Removing previous $bundle"
196 rm -Rf $bundle
199 # Remove a previously existing utility directory if necessary
200 if [ -d "$util_dir" ]; then
201 echo "Removing $util_dir directory"
202 rm -Rf "$util_dir"
205 # Set the 'macosx' directory, usually the current directory.
206 resdir=`pwd`
209 # Prepare Package
210 #----------------------------------------------------------
211 pkgexec="$bundle/Contents/MacOS"
212 pkgres="$bundle/Contents/Resources"
213 pkgbin="$pkgexec"
214 if [ "$ui_toolkit" = "gtk" ] ; then
215 pkgbin="$pkgres/bin"
217 # Should pkglib be Contents/Frameworks instead?
218 #pkglib="$pkgres/lib"
219 pkglib="$bundle/Contents/Frameworks"
220 pkgqtplugin="$bundle/Contents/PlugIns"
221 pkgplugin="$pkglib/wireshark/plugins"
222 pkgpython="$pkglib/wireshark/python"
224 mkdir -p "$pkgexec"
225 mkdir -p "$pkgbin"
226 mkdir -p "$pkgqtplugin"
227 mkdir -p "$pkgplugin"
228 mkdir -p "$pkgpython"
230 mkdir -p "$cli_dir"
232 if [ "$ui_toolkit" = "qt" ] ; then
233 cp "$binary_path/$wireshark_bin_name" "$pkgexec/Wireshark"
234 else
235 # Build and add the launcher
236 #----------------------------------------------------------
238 # Build fails if CC happens to be set (to anything other than CompileC)
239 unset CC
241 cd "$resdir/ScriptExec"
242 echo -e "Building launcher...\n"
243 xcodebuild $XCODEFLAGS clean build
245 cp "$resdir/$SCRIPTEXECDIR/ScriptExec" "$pkgexec/Wireshark"
249 # Copy all files into the bundle
250 #----------------------------------------------------------
251 echo -e "\nFilling app bundle and utility directory...\n"
253 # CLI wrapper
254 cp -v utility-launcher "$cli_dir/wireshark"
256 # Wireshark executables
257 if [ "$ui_toolkit" = "gtk" ] ; then
258 for binary in $binary_list wireshark ; do
259 # Copy the binary to its destination
260 dest_path="$pkgbin/$binary-bin"
261 cs_binary_list="$cs_binary_list $dest_path"
262 cp -v "$binary_path/$binary" "$dest_path"
263 # TODO Add a "$verbose" variable and command line switch, which sets wether these commands are verbose or not
265 if [ "$binary" != "wireshark" ] ; then
266 ln -sv ./wireshark "$pkgbin/$binary"
267 ln -sv ./wireshark "$cli_dir/$binary"
269 done
270 elif [ "$ui_toolkit" = "qt" ] ; then
271 for binary in $binary_list ; do
272 # Copy the binary to its destination
273 cp -v "$binary_path/$binary" "$pkgexec"
274 cs_binary_list="$cs_binary_list $pkgexec/$binary"
275 done
278 # ChmodBPF
279 mkdir -p "$chmodbpf_dir"
280 cp -v ChmodBPF/* "$chmodbpf_dir"
281 chmod -R g-w "$chmodbpf_dir"
283 # The rest of the Wireshark installation (we handled bin above)
284 rsync -av \
285 --exclude bin/ \
286 --exclude lib/ \
287 "$binary_path/.."/* "$pkgres"
289 rsync -av $binary_path/../lib/*.dylib "$pkglib/"
291 # Remove the version number from the plugin path
292 find "$binary_path/../lib/wireshark/plugins" -type f \
293 -exec cp -fv "{}" "$pkgplugin/" \;
295 # Remove the version number from the python path
296 find "$binary_path/../lib/wireshark/python" -type f \
297 -exec cp -fv "{}" "$pkgpython/" \;
299 cp "$plist" "$bundle/Contents/Info.plist"
301 # Icons and the rest of the script framework
302 res_list="
303 Wireshark.icns
304 Wiresharkdoc.icns
307 if [ "$ui_toolkit" = "gtk" ] ; then
308 res_list="
309 $res_list
312 openDoc
313 script
314 MenuBar.nib
315 ProgressWindow.nib
316 themes
320 for rl_entry in $res_list ; do
321 rsync -av "$resdir"/Resources/$rl_entry "$bundle"/Contents/Resources/
322 done
324 # PkgInfo must match bundle type and creator code from Info.plist
325 echo "APPLWshk" > $bundle/Contents/PkgInfo
327 if [ "$ui_toolkit" = "gtk" ] ; then
329 # Pull in extra requirements for Pango and GTK
330 pkgetc="$bundle/Contents/Resources/etc"
331 mkdir -p $pkgetc/pango
332 cp $LIBPREFIX/etc/pango/pangox.aliases $pkgetc/pango/
333 # Need to adjust path and quote in case of spaces in path.
334 sed -e "s,$LIBPREFIX,\"\${CWD},g" -e 's,\.so ,.so" ,g' $LIBPREFIX/etc/pango/pango.modules > $pkgetc/pango/pango.modules
335 cat > $pkgetc/pango/pangorc <<END_PANGO
336 [Pango]
337 ModuleFiles=\${HOME}/.wireshark-etc/pango.modules
338 [PangoX]
339 AliasFiles=\${HOME}/.wireshark-etc/pangox.aliases
340 END_PANGO
342 # We use a modified fonts.conf file so only need the dtd
343 mkdir -p $pkgetc/fonts
344 cp $LIBPREFIX/etc/fonts/fonts.dtd $pkgetc/fonts/
345 cp -r $LIBPREFIX/etc/fonts/conf.avail $pkgetc/fonts/
346 cp -r $LIBPREFIX/etc/fonts/conf.d $pkgetc/fonts/
348 mkdir -p $pkgetc/gtk-2.0
350 # In newer versions of GTK+, the gdk-pixbuf library was split off from
351 # GTK+, and the gdk-pixbuf.loaders file moved, so we check for its
352 # existence here.
354 # The file is ultimately copied to the user's home directory, with
355 # the pathnames adjusted to refer to the installed bundle, so we
356 # always put it in the same location in the installed bundle,
357 # regardless of where it lives in the machine on which it's built.
359 if [ -e $LIBPREFIX/etc/gtk-2.0/gdk-pixbuf.loaders ]
360 then
361 sed -e "s,$LIBPREFIX,\${CWD},g" $LIBPREFIX/etc/gtk-2.0/gdk-pixbuf.loaders > $pkgetc/gtk-2.0/gdk-pixbuf.loaders
363 sed -e "s,$LIBPREFIX,\${CWD},g" $LIBPREFIX/etc/gtk-2.0/gtk.immodules > $pkgetc/gtk-2.0/gtk.immodules
365 pango_version=`pkg-config --variable=pango_module_version pango`
366 mkdir -p $pkglib/pango/$pango_version/modules
367 cp $LIBPREFIX/lib/pango/$pango_version/modules/*.so $pkglib/pango/$pango_version/modules/
369 gtk_version=`pkg-config --variable=gtk_binary_version gtk+-2.0`
370 mkdir -p $pkglib/gtk-2.0/$gtk_version/{engines,immodules,loaders}
371 cp -r $LIBPREFIX/lib/gtk-2.0/$gtk_version/* $pkglib/gtk-2.0/$gtk_version/
373 gdk_pixbuf_version=`pkg-config --variable=gdk_pixbuf_binary_version gdk-pixbuf-2.0`
374 if [ ! -z $gdk_pixbuf_version ]; then
375 mkdir -p $pkglib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders
377 # As per the above, check whether we have a loaders.cache file
378 # in $LIBPREFIX/lib/gdk-pixbuf-2.0/$gdk_pixbuf_version, as
379 # that's where the output of gdk-pixbuf-query-loaders gets
380 # put if gdk-pixbuf and GTK+ are separated.
382 # The file is ultimately copied to the user's home directory,
383 # with the pathnames adjusted to refer to the installed bundle,
384 # so we always put it in the same location in the installed
385 # bundle, regardless of where it lives in the machine on which
386 # it's built.
388 if [ -e $LIBPREFIX/lib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders.cache ]
389 then
390 sed -e "s,$LIBPREFIX,\${CWD},g" $LIBPREFIX/lib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders.cache > $pkgetc/gtk-2.0/gdk-pixbuf.loaders
392 cp -r $LIBPREFIX/lib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders/* $pkglib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders
394 fi # GTK+ / Qt
396 # Find out libs we need from Fink, MacPorts, or from a custom install
397 # (i.e. $LIBPREFIX), then loop until no changes.
399 nfiles=0
400 endl=true
401 lib_dep_search_list="
402 $pkglib/*
403 $pkgbin/*-bin
405 if [ "$ui_toolkit" = "gtk" ] ; then
406 lib_dep_search_list="
407 $lib_dep_search_list
408 $pkglib/gtk-2.0/$gtk_version/loaders/*
409 $pkglib/gtk-2.0/$gtk_version/immodules/*
410 $pkglib/gtk-2.0/$gtk_version/engines/*.so
411 $pkglib/pango/$pango_version/modules/*
412 $pkglib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders/*
414 elif [ "$ui_toolkit" = "qt" ] ; then
415 lib_dep_search_list="
416 $pkgexec/Wireshark
417 $lib_dep_search_list
421 while $endl; do
422 echo -e "Looking for dependencies. Round" $a
423 libs="`\
424 otool -L $lib_dep_search_list 2>/dev/null \
425 | fgrep compatibility \
426 | cut -d\( -f1 \
427 | egrep -v "$exclude_prefixes" \
428 | sort \
429 | uniq \
431 cp -vn $libs "$pkglib"
432 let "a+=1"
433 nnfiles=`ls "$pkglib" | wc -l`
434 if [ $nnfiles = $nfiles ]; then
435 endl=false
436 else
437 nfiles=$nnfiles
439 done
441 # Add extra libraries of necessary
442 for libfile in $EXTRALIBS
444 cp -f $libfile "$pkglib"
445 done
446 chmod 755 "$pkglib"/*.dylib
448 # Strip libraries and executables if requested
449 #----------------------------------------------------------
450 if [ "$strip" = "true" ]; then
451 echo -e "\nStripping debugging symbols...\n"
452 strip -x "$pkglib"/*.dylib
453 strip -ur "$binpath"
456 # NOTE: we must rpathify *all* files, *including* plugins for GTK+ etc.,
457 # to keep GTK+ from crashing at startup.
459 rpathify_file () {
460 # Fix a given executable, library, or plugin to be relocatable
461 if [ ! -d "$1" ]; then
463 # OK, what type of file is this?
465 filetype=`otool -hv "$1" | sed -n '4p' | awk '{print $5}'`
466 case "$filetype" in
468 EXECUTE|DYLIB|BUNDLE)
470 # Executable, library, or plugin. (Plugins
471 # can be either DYLIB or BUNDLE; shared
472 # libraries are DYLIB.)
474 # For DYLIB and BUNDLE, fix the shared
475 # library identification.
477 if [[ "$filetype" = "DYLIB" || "$filetype" = "BUNDLE" ]]; then
478 echo "Changing shared library identification of $1"
479 base=`echo $1 | awk -F/ '{print $NF}'`
481 # The library will end up in a directory in
482 # the rpath; this is what we should change its
483 # ID to.
485 to=@rpath/$base
486 /usr/bin/install_name_tool -id $to $1
490 # Show the minimum supported version of Mac OS X
491 # for each executable or library
493 if [[ "$filetype" = "EXECUTE" || "$filetype" = "DYLIB" ]] && [[ "$VERSION" -ge "7" ]] ; then
494 echo "Minimum Mac OS X version for $1:"
495 otool -l $1 | grep -A3 LC_VERSION_MIN_MACOSX
499 # Get the list of dynamic libraries on which this
500 # file depends, and select only the libraries that
501 # are in $LIBPREFIX, as those are the only ones
502 # that we'll be shipping in the app bundle; the
503 # other libraries are system-supplied or supplied
504 # as part of X11, will be expected to be on the
505 # system on which the bundle will be installed,
506 # and should be referred to by their full pathnames.
508 libs="`\
509 otool -L $1 \
510 | fgrep compatibility \
511 | cut -d\( -f1 \
512 | egrep -v "$exclude_prefixes" \
513 | sort \
514 | uniq \
517 for lib in $libs; do
519 # Get the file name of the library.
521 base=`echo $lib | awk -F/ '{print $NF}'`
523 # The library will end up in a directory in
524 # the rpath; this is what we should change its
525 # file name to.
527 to=@rpath/$base
529 # Change the reference to that library.
531 echo "Changing reference to $lib to $to in $1"
532 /usr/bin/install_name_tool -change $lib $to $1
533 done
535 esac
539 rpathify_dir () {
541 # Make sure we *have* that directory
543 if [ -d "$1" ]; then
544 (cd "$1"
546 # Make sure we *have* files to fix
548 files=`ls $2 2>/dev/null`
549 if [ ! -z "$files" ]; then
550 for file in $files; do
551 rpathify_file "$file" "`pwd`"
552 done
558 rpathify_files () {
560 # Fix bundle deps
562 rpathify_dir "$pkglib" "*.dylib"
563 if [ "$ui_toolkit" = "gtk" ] ; then
564 rpathify_dir "$pkglib/gtk-2.0/$gtk_version/loaders" "*.so"
565 rpathify_dir "$pkglib/gtk-2.0/$gtk_version/engines" "*.so"
566 rpathify_dir "$pkglib/gtk-2.0/$gtk_version/immodules" "*.so"
567 rpathify_dir "$pkglib/gtk-2.0/$gtk_version/printbackends" "*.so"
568 rpathify_dir "$pkglib/gnome-vfs-2.0/modules" "*.so"
569 rpathify_dir "$pkglib/gdk-pixbuf-2.0/$gtk_version/loaders" "*.so"
570 rpathify_dir "$pkglib/pango/$pango_version/modules" "*.so"
572 rpathify_dir "$pkgbin" "*"
575 if [ "$ui_toolkit" = "qt" ] ; then
576 macdeployqt "$bundle" -verbose=2 || exit 1
579 PATHLENGTH=`echo $LIBPREFIX | wc -c`
580 if [ "$PATHLENGTH" -ge "6" ]; then
581 # If the LIBPREFIX path is long enough to allow
582 # path rewriting, then do this.
583 # 6 is the length of @rpath, which replaces LIBPREFIX.
584 rpathify_files
585 else
586 echo "Could not rewrite dylib paths for bundled libraries. This requires" >&2
587 echo "the support libraries to be installed in a PREFIX of at least 6 characters in length." >&2
588 echo "" >&2
589 echo "The bundle will still work if the following line is uncommented in" >&2
590 echo "Wireshark.app/Contents/Resources/bin/{various scripts}:" >&2
591 echo ' export DYLD_LIBRARY_PATH="$TOP/lib"' >&2
592 exit 1
596 codesign_file () {
597 codesign --sign "Developer ID Application: $CODE_SIGN_IDENTITY" --verbose "$1"
598 codesign --verify --verbose "$1" || exit 1
599 spctl --assess --type execute "$1" || exit 1
602 if [ -n "$CODE_SIGN_IDENTITY" ] ; then
603 security find-identity -v -s "$CODE_SIGN_IDENTITY" -p codesigning
605 echo "Signing executables"
606 for binary in $cs_binary_list ; do
607 codesign_file "$binary"
608 done
609 echo "Signing frameworks"
610 for framework in $pkglib/*.framework/Versions/*/* ; do
611 codesign_file "$framework"
612 done
613 echo "Signing libraries"
614 for library in $pkglib/*.dylib ; do
615 codesign_file "$library"
616 done
617 echo "Signing plugins"
618 for plugin in $pkgplugin/*.so ; do
619 codesign_file "$plugin"
620 done
621 echo "Signing $bundle"
622 codesign_file "$bundle"
623 else
624 echo "Code signing not performed (no identity)"
627 exit 0