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 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.
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
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.
41 binary_path="/tmp/inst/bin"
43 util_dir="./Utilities"
44 cli_dir="$util_dir/Command Line"
45 chmodbpf_dir="$util_dir/ChmodBPF"
50 # Name of the Wireshark executable
51 wireshark_bin_name="wireshark"
65 # Location for libraries (macosx-setup.sh defaults to whatever the
66 # various support libraries use as their standard installation location,
67 # which is /usr/local)
68 if [ -z $LIBPREFIX ]; then
69 LIBPREFIX="/usr/local"
74 #----------------------------------------------------------
78 Create an app bundle for OS X
81 $0 [-s] [-l /path/to/libraries] [-qt] -bp /path/to/wireshark/binaries -p /path/to/Info.plist
85 display this help message
87 strip the libraries and executables from debugging symbols
89 specify the path to the libraries Wireshark depends on
90 (typically /sw or /opt/local). By default it is
93 specify the path to the Wireshark binaries. By default it
96 specify the path to Info.plist. Info.plist can be found
97 in the base directory of the source code once configure
100 specify the root of the SDK to use
105 $0 -s -l /opt/local -bp ../../Build/bin -p Info.plist -sdkroot /Developer/SDKs/MacOSX10.5.sdk
110 # Parse command line arguments
111 #----------------------------------------------------------
128 wireshark_bin_name="wireshark-qt"
137 echo "Invalid command line option: $1"
143 echo -e "\nCREATE WIRESHARK APP BUNDLE\n"
146 if [ ! -e "$LIBPREFIX" ]; then
147 echo "Cannot find the directory containing the libraries: $LIBPREFIX" >&2
151 for binary in $wireshark_bin_name $binary_list ; do
152 if [ ! -x "$binary_path/$binary" ]; then
153 echo "Couldn't find $binary (or it's not executable)" >&2
158 if [ ! -f "$plist" ]; then
159 echo "Need plist file" >&2
164 # Handle some version specific details.
165 VERSION=`/usr/bin/sw_vers | grep ProductVersion | cut -f2 -d'.'`
166 if [ "$VERSION" -ge "4" ]; then
167 # We're on Tiger (10.4) or later.
168 # XCode behaves a little differently in Tiger and later.
169 XCODEFLAGS="-configuration Deployment"
170 SCRIPTEXECDIR="ScriptExec/build/Deployment/ScriptExec.app/Contents/MacOS"
173 # Panther (10.3) or earlier.
174 XCODEFLAGS="-buildstyle Deployment"
175 SCRIPTEXECDIR="ScriptExec/build/ScriptExec.app/Contents/MacOS"
179 # Set the SDK root, if an SDK was specified.
180 # (-sdk is only supported by the xcodebuild in the version of the
181 # developer tools that came with Snow Leopard and later versions)
182 if [ ! -z "$sdkroot" ]
184 XCODEFLAGS="$XCODEFLAGS SDKROOT=$sdkroot"
187 # Package always has the same name. Version information is stored in
188 # the Info.plist file which is filled in by the configure script.
189 package="Wireshark.app"
191 # Remove a previously existing package if necessary
192 if [ -d $package ]; then
193 echo "Removing previous Wireshark.app"
197 # Remove a previously existing utility directory if necessary
198 if [ -d "$util_dir" ]; then
199 echo "Removing $util_dir directory"
203 # Set the 'macosx' directory, usually the current directory.
208 #----------------------------------------------------------
209 pkgexec="$package/Contents/MacOS"
210 pkgres="$package/Contents/Resources"
212 # Should pkglib be Contents/Frameworks instead?
214 pkgplugin="$pkglib/wireshark/plugins"
215 pkgpython="$pkglib/wireshark/python"
219 mkdir -p "$pkgplugin"
220 mkdir -p "$pkgpython"
224 if [ "$ui_toolkit" = "qt" ] ; then
225 cp "$binary_path/$wireshark_bin_name" "$pkgexec/Wireshark"
227 # Build and add the launcher
228 #----------------------------------------------------------
230 # Build fails if CC happens to be set (to anything other than CompileC)
233 cd "$resdir/ScriptExec"
234 echo -e "Building launcher...\n"
235 xcodebuild $XCODEFLAGS clean build
237 cp "$resdir/$SCRIPTEXECDIR/ScriptExec" "$pkgexec/Wireshark"
241 # Copy all files into the bundle
242 #----------------------------------------------------------
243 echo -e "\nFilling app bundle and utility directory...\n"
245 # Wireshark executables
246 cp -v utility-launcher "$cli_dir/$binary"
247 for binary in $binary_list ; do
248 # Copy the binary to its destination
249 dest_path="$pkgbin/$binary-bin"
250 cp -v "$binary_path/$binary" "$dest_path"
251 # TODO Add a "$verbose" variable and command line switch, which sets wether these commands are verbose or not
253 ln -sv ./wireshark "$pkgbin/$binary"
254 ln -sv ./wireshark "$cli_dir/$binary"
258 mkdir -p "$chmodbpf_dir"
259 cp -v ChmodBPF/* "$chmodbpf_dir"
260 chmod -R g-w "$chmodbpf_dir"
262 # The rest of the Wireshark installation (we handled bin above)
265 --exclude lib/wireshark/plugins/ \
266 --exclude lib/wireshark/python/ \
267 "$binary_path/.."/* "$pkgres"
269 # Remove the version number from the plugin path
270 find "$binary_path/../lib/wireshark/plugins" -type f \
271 -exec cp -fv "{}" "$pkgplugin/" \;
273 # Remove the version number from the python path
274 find "$binary_path/../lib/wireshark/python" -type f \
275 -exec cp -fv "{}" "$pkgpython/" \;
277 cp "$plist" "$package/Contents/Info.plist"
279 # Icons and the rest of the script framework
287 if [ "$ui_toolkit" = "gtk" ] ; then
298 for rl_entry in $res_list ; do
299 rsync -av "$resdir"/Resources/$rl_entry "$package"/Contents/Resources/
302 # PkgInfo must match bundle type and creator code from Info.plist
303 echo "APPLWshk" > $package/Contents/PkgInfo
305 if [ "$ui_toolkit" = "gtk" ] ; then
307 # Pull in extra requirements for Pango and GTK
308 pkgetc="$package/Contents/Resources/etc"
309 mkdir -p $pkgetc/pango
310 cp $LIBPREFIX/etc/pango/pangox.aliases $pkgetc/pango/
311 # Need to adjust path and quote in case of spaces in path.
312 sed -e "s,$LIBPREFIX,\"\${CWD},g" -e 's,\.so ,.so" ,g' $LIBPREFIX/etc/pango/pango.modules > $pkgetc/pango/pango.modules
313 cat > $pkgetc/pango/pangorc <<END_PANGO
315 ModuleFiles=\${HOME}/.wireshark-etc/pango.modules
317 AliasFiles=\${HOME}/.wireshark-etc/pangox.aliases
320 # We use a modified fonts.conf file so only need the dtd
321 mkdir -p $pkgetc/fonts
322 cp $LIBPREFIX/etc/fonts/fonts.dtd $pkgetc/fonts/
323 cp -r $LIBPREFIX/etc/fonts/conf.avail $pkgetc/fonts/
324 cp -r $LIBPREFIX/etc/fonts/conf.d $pkgetc/fonts/
326 mkdir -p $pkgetc/gtk-2.0
328 # In newer versions of GTK+, the gdk-pixbuf library was split off from
329 # GTK+, and the gdk-pixbuf.loaders file moved, so we check for its
332 # The file is ultimately copied to the user's home directory, with
333 # the pathnames adjusted to refer to the installed package, so we
334 # always put it in the same location in the installed package,
335 # regardless of where it lives in the machine on which it's built.
337 if [ -e $LIBPREFIX/etc/gtk-2.0/gdk-pixbuf.loaders ]
339 sed -e "s,$LIBPREFIX,\${CWD},g" $LIBPREFIX/etc/gtk-2.0/gdk-pixbuf.loaders > $pkgetc/gtk-2.0/gdk-pixbuf.loaders
341 sed -e "s,$LIBPREFIX,\${CWD},g" $LIBPREFIX/etc/gtk-2.0/gtk.immodules > $pkgetc/gtk-2.0/gtk.immodules
343 pango_version=`pkg-config --variable=pango_module_version pango`
344 mkdir -p $pkglib/pango/$pango_version/modules
345 cp $LIBPREFIX/lib/pango/$pango_version/modules/*.so $pkglib/pango/$pango_version/modules/
347 gtk_version=`pkg-config --variable=gtk_binary_version gtk+-2.0`
348 mkdir -p $pkglib/gtk-2.0/$gtk_version/{engines,immodules,loaders}
349 cp -r $LIBPREFIX/lib/gtk-2.0/$gtk_version/* $pkglib/gtk-2.0/$gtk_version/
351 gdk_pixbuf_version=`pkg-config --variable=gdk_pixbuf_binary_version gdk-pixbuf-2.0`
352 if [ ! -z $gdk_pixbuf_version ]; then
353 mkdir -p $pkglib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders
355 # As per the above, check whether we have a loaders.cache file
356 # in $LIBPREFIX/lib/gdk-pixbuf-2.0/$gdk_pixbuf_version, as
357 # that's where the output of gdk-pixbuf-query-loaders gets
358 # put if gdk-pixbuf and GTK+ are separated.
360 # The file is ultimately copied to the user's home directory,
361 # with the pathnames adjusted to refer to the installed package,
362 # so we always put it in the same location in the installed
363 # package, regardless of where it lives in the machine on which
366 if [ -e $LIBPREFIX/lib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders.cache ]
368 sed -e "s,$LIBPREFIX,\${CWD},g" $LIBPREFIX/lib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders.cache > $pkgetc/gtk-2.0/gdk-pixbuf.loaders
370 cp -r $LIBPREFIX/lib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders/* $pkglib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders
372 elif [ "$ui_toolkit" = "qt" ] ; then
373 frameworks="`otool -L $pkgexec/Wireshark 2>/dev/null | grep 'Qt.*framework' | sed -e 's:.framework/.*:.framework:' | sort | uniq`"
374 for fwk in $frameworks ; do
376 --exclude "Headers/" \
377 --exclude "*_debug*" \
382 # Find out libs we need from Fink, MacPorts, or from a custom install
383 # (i.e. $LIBPREFIX), then loop until no changes.
387 lib_dep_search_list="
391 if [ "$ui_toolkit" = "gtk" ] ; then
392 lib_dep_search_list="
394 $pkglib/gtk-2.0/$gtk_version/loaders/*
395 $pkglib/gtk-2.0/$gtk_version/immodules/*
396 $pkglib/gtk-2.0/$gtk_version/engines/*.so
397 $pkglib/pango/$pango_version/modules/*
398 $pkglib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders/*
400 elif [ "$ui_toolkit" = "qt" ] ; then
401 lib_dep_search_list="
404 $pkglib/Qt*.framework/Versions/[0-9]*/Qt*
409 echo -e "Looking for dependencies. Round" $a
410 libs="`otool -L $lib_dep_search_list 2>/dev/null | fgrep compatibility | cut -d\( -f1 | grep $LIBPREFIX | sort | uniq`"
411 cp -vn $libs "$pkglib"
413 nnfiles=`ls "$pkglib" | wc -l`
414 if [ $nnfiles = $nfiles ]; then
421 # Add extra libraries of necessary
422 for libfile in $EXTRALIBS
424 cp -f $libfile "$pkglib"
426 chmod 755 "$pkglib"/*.dylib
428 # Strip libraries and executables if requested
429 #----------------------------------------------------------
430 if [ "$strip" = "true" ]; then
431 echo -e "\nStripping debugging symbols...\n"
432 strip -x "$pkglib"/*.dylib
436 # NOTE: we must rpathify *all* files, *including* plugins for GTK+ etc.,
437 # to keep GTK+ from crashing at startup.
440 # Fix a given executable, library, or plugin to be relocatable
441 if [ ! -d "$1" ]; then
443 # OK, what type of file is this?
445 filetype=`otool -hv "$1" | sed -n '4p' | awk '{print $5}'`
448 EXECUTE|DYLIB|BUNDLE)
450 # Executable, library, or plugin. (Plugins
451 # can be either DYLIB or BUNDLE; shared
452 # libraries are DYLIB.)
454 # For DYLIB and BUNDLE, fix the shared
455 # library identification.
457 if [[ "$filetype" = "DYLIB" || "$filetype" = "BUNDLE" ]]; then
458 echo "Changing shared library identification of $1"
459 base=`echo $1 | awk -F/ '{print $NF}'`
461 # The library will end up in a directory in
462 # the rpath; this is what we should change its
466 /usr/bin/install_name_tool -id $to $1
470 # Get the list of dynamic libraries on which this
471 # file depends, and select only the libraries that
472 # are in $LIBPREFIX, as those are the only ones
473 # that we'll be shipping in the app bundle; the
474 # other libraries are system-supplied or supplied
475 # as part of X11, will be expected to be on the
476 # system on which the bundle will be installed,
477 # and should be referred to by their full pathnames.
479 libs="`otool -L $1 | egrep "$LIBPREFIX.* \(compatibility" | cut -d\( -f1`"
482 # Get the file name of the library.
484 base=`echo $lib | awk -F/ '{print $NF}'`
486 # The library will end up in a directory in
487 # the rpath; this is what we should change its
492 # Change the reference to that library.
494 echo "Changing reference to $lib in $1"
495 /usr/bin/install_name_tool -change $lib $to $1
498 # Rewrite framework paths
500 if [ "$ui_toolkit" = "qt" ] ; then
501 frameworks="`otool -L $1 | egrep "Qt.*framework/.* \(compatibility" | cut -d\( -f1`"
502 for fwk in $frameworks ; do
504 # Get the file name of the framework.
506 base=`echo $fwk | awk 'BEGIN{FS="/";OFS="/"} {print $(NF-3), $(NF-2), $(NF-1), $NF}'`
508 # The library will end up in a directory in
509 # the rpath; this is what we should change its
514 # Change the reference to that library.
516 echo "Changing reference to $fwk in $1"
517 /usr/bin/install_name_tool -change $fwk $to $1
527 # Make sure we *have* that directory
532 # Make sure we *have* files to fix
534 files=`ls $2 2>/dev/null`
535 if [ ! -z "$files" ]; then
536 for file in $files; do
537 rpathify_file "$file" "`pwd`"
548 rpathify_dir "$pkglib" "*.dylib"
549 if [ "$ui_toolkit" = "gtk" ] ; then
550 rpathify_dir "$pkglib/gtk-2.0/$gtk_version/loaders" "*.so"
551 rpathify_dir "$pkglib/gtk-2.0/$gtk_version/engines" "*.so"
552 rpathify_dir "$pkglib/gtk-2.0/$gtk_version/immodules" "*.so"
553 rpathify_dir "$pkglib/gtk-2.0/$gtk_version/printbackends" "*.so"
554 rpathify_dir "$pkglib/gnome-vfs-2.0/modules" "*.so"
555 rpathify_dir "$pkglib/gdk-pixbuf-2.0/$gtk_version/loaders" "*.so"
556 rpathify_dir "$pkglib/pango/$pango_version/modules" "*.so"
558 rpathify_dir "$pkgbin" "*"
559 if [ "$ui_toolkit" = "qt" ] ; then
560 rpathify_dir "$pkgexec" "Wireshark"
561 for fwk_dir in $pkglib/Qt*.framework/Versions/[0-9]* ; do
562 rpathify_dir "$fwk_dir" "Qt*"
567 PATHLENGTH=`echo $LIBPREFIX | wc -c`
568 if [ "$PATHLENGTH" -ge "6" ]; then
569 # If the LIBPREFIX path is long enough to allow
570 # path rewriting, then do this.
571 # 6 is the length of @rpath, which replaces LIBPREFIX.
574 echo "Could not rewrite dylib paths for bundled libraries. This requires" >&2
575 echo "the support libraries to be installed in a PREFIX of at least 6 characters in length." >&2
577 echo "The package will still work if the following line is uncommented in" >&2
578 echo "Wireshark.app/Contents/Resources/bin/{various scripts}:" >&2
579 echo ' export DYLD_LIBRARY_PATH="$TOP/lib"' >&2