4 # osx-app [-s] [-l /path/to/libraries] -bp /path/to/wireshark/bin -p /path/to/Info.plist
6 # This script attempts to build an Wireshark.app bundle for OS X, resolving
7 # dynamic libraries, etc.
8 # It strips the executable and libraries if '-s' is given.
9 # The Info.plist file can be found in the base wireshark directory once
10 # configure has been run.
13 # Kees Cook <kees@outflux.net>
14 # Michael Wybrow <mjwybrow@users.sourceforge.net>
15 # Jean-Olivier Irisson <jo.irisson@gmail.com>
17 # Copyright (C) 2005 Kees Cook
18 # Copyright (C) 2005-2007 Michael Wybrow
19 # Copyright (C) 2007 Jean-Olivier Irisson
21 # Released under GNU GPL, read the file 'COPYING' for more information
23 # Thanks to GNUnet's "build_app" script for help with library dep resolution.
24 # https://gnunet.org/svn/GNUnet/contrib/OSX/build_app
27 # This originally came from Inkscape; Inkscape's configure script has an
28 # "--enable-osxapp", which causes some of Inkscape's installation data
29 # files to have OS X-ish paths under Contents/Resources of the bundle
30 # or under /Library/Application Support. We don't have such an option;
31 # we just put them in "bin", "etc", "lib", and "share" directories
32 # under Contents/Resources, rather than in the "bin", "etc", "lib",
33 # and "share" directories under the installation directory.
38 binary_path="/tmp/inst/bin"
40 exclude_prefixes="/System/|/Library/|/usr/lib/|/usr/X11/|/opt/X11/|@rpath|@executable_path"
43 # Bundle always has the same name. Version information is stored in
44 # the Info.plist file which is filled in by the configure script.
45 bundle="Wireshark.app"
49 # Name of the Wireshark executable
50 wireshark_bin_name="wireshark"
66 # Location for libraries (macosx-setup.sh defaults to whatever the
67 # various support libraries use as their standard installation location,
68 # which is /usr/local)
69 if [ -z $LIBPREFIX ]; then
70 LIBPREFIX="/usr/local"
75 #----------------------------------------------------------
79 Create an app bundle for OS X
82 $0 [-s] [-l /path/to/libraries] [-qt] -bp /path/to/wireshark/binaries -p /path/to/Info.plist
86 Display this help message.
88 Strip the libraries and executables from debugging symbols.
90 Specify the path to the libraries Wireshark depends on
91 (typically /sw or /opt/local). By default it is
94 Create the application bundle (Wireshark.app). This flag
95 should be supplied when building using Autotools. It
96 should not be specified when building using CMake.
98 Specify the path to the Wireshark binaries. By default it
101 Specify the path to Info.plist. Info.plist can be found
102 in the base directory of the source code once configure
105 Specify the root of the SDK to use.
107 Use the Qt flavor. This is the default.
112 $0 -s -l /opt/local -bp ../../Build/bin -p Info.plist -sdkroot /Developer/SDKs/MacOSX10.5.sdk
117 # Parse command line arguments
118 #----------------------------------------------------------
137 wireshark_bin_name="wireshark"
141 wireshark_bin_name="wireshark-gtk"
150 echo "Invalid command line option: $1"
157 if [ ! -e "$LIBPREFIX" ]; then
158 echo "Cannot find the directory containing the libraries: $LIBPREFIX" >&2
162 if [ "$create_bundle" = "true" ]; then
163 echo -e "\nCREATE WIRESHARK APP BUNDLE\n"
165 for binary in $wireshark_bin_name $binary_list ; do
166 binary=$( basename $binary )
167 if [ ! -x "$binary_path/$binary" ]; then
168 echo "Couldn't find $binary (or it's not executable)" >&2
173 if [ ! -f "$plist" ]; then
174 echo "Need plist file" >&2
177 elif [ ! -d "$bundle" ] ; then
178 echo "$bundle not found" >&2
182 if [ "$ui_toolkit" = "qt" ] ; then
185 qt_frameworks_dir=`pkg-config --libs Qt${i}Core | sed -e 's/-F//' -e 's/ -framework.*//'`
186 if [ ! -z "$qt_frameworks_dir" ] ; then
191 if [ -z "$qt_frameworks_dir" ] ; then
192 echo "Can't find the Qt frameworks directory" >&2
197 # Leave the Qt frameworks out of the special processing.
199 exclude_prefixes="$exclude_prefixes|$qt_frameworks_dir"
203 pkgexec="$bundle/Contents/MacOS"
204 pkgres="$bundle/Contents/Resources"
206 pkglib="$bundle/Contents/Frameworks"
207 pkgplugin="$bundle/Contents/PlugIns/wireshark"
209 # Set the 'macosx' directory, usually the current directory.
212 # Create the application bundle.
213 # This is only used by Autotools. This can be removed if we start using
216 # Handle some version specific details.
217 VERSION=`/usr/bin/sw_vers | grep ProductVersion | cut -f2 -d'.'`
218 if [ "$VERSION" -ge "4" ]; then
219 # We're on Tiger (10.4) or later.
220 # XCode behaves a little differently in Tiger and later.
221 XCODEFLAGS="-configuration Deployment"
222 SCRIPTEXECDIR="ScriptExec/build/Deployment/ScriptExec.app/Contents/MacOS"
225 # Panther (10.3) or earlier.
226 XCODEFLAGS="-buildstyle Deployment"
227 SCRIPTEXECDIR="ScriptExec/build/ScriptExec.app/Contents/MacOS"
231 # Set the SDK root, if an SDK was specified.
232 # (-sdk is only supported by the xcodebuild in the version of the
233 # developer tools that came with Snow Leopard and later versions)
234 if [ ! -z "$sdkroot" ]
236 XCODEFLAGS="$XCODEFLAGS SDKROOT=$sdkroot"
239 # Remove a previously existing bundle if necessary
240 if [ -d $bundle ]; then
241 echo "Removing previous $bundle"
245 # Remove a previously existing utility directory if necessary
246 if [ -d "$util_dir" ]; then
247 echo "Removing $util_dir directory"
252 #----------------------------------------------------------
255 # For Qt, the Wireshark binary is the main binary of the app bundle.
256 # For GTK+, the Wireshark binary is wireshark-bin in
257 # Contents/Resources/bin, so some of the above setting have to change.
259 if [ "$ui_toolkit" = "gtk" ] ; then
265 mkdir -p "$pkgexec/extcap"
267 mkdir -p "$pkgplugin"
269 if [ "$ui_toolkit" = "qt" ] ; then
270 cp -v "$binary_path/$wireshark_bin_name" "$pkgexec/Wireshark"
272 # Build and add the launcher
273 #----------------------------------------------------------
275 # Build fails if CC happens to be set (to anything other than CompileC)
278 cd "$resdir/ScriptExec"
279 echo -e "Building launcher...\n"
280 xcodebuild $XCODEFLAGS clean build
282 cp "$resdir/$SCRIPTEXECDIR/ScriptExec" "$pkgexec/Wireshark"
286 # Copy all files into the bundle
287 #----------------------------------------------------------
288 echo -e "\nFilling app bundle and utility directory...\n"
290 # Wireshark executables
291 if [ "$ui_toolkit" = "gtk" ] ; then
292 for binary in $binary_list wireshark ; do
293 # Copy the binary to its destination
294 dest_path="$pkgbin/$binary-bin"
295 cs_binary_list="$cs_binary_list $dest_path"
296 cp -v "$binary_path/$binary" "$dest_path"
297 # TODO Add a "$verbose" variable and command line switch, which sets wether these commands are verbose or not
299 if [ "$binary" != "wireshark" ] ; then
300 ln -sv ./wireshark "$pkgbin/$binary"
303 elif [ "$ui_toolkit" = "qt" ] ; then
304 for binary in $binary_list ; do
306 if [ "$( dirname $binary )" == "extcap" ] ; then
307 binary=$( basename $binary )
308 bin_dest="$pkgexec/$( dirname $binary )"
311 # Copy the binary to its destination
312 cp -v "$binary_path/$binary" "$bin_dest"
313 cs_binary_list="$cs_binary_list $bin_dest/$binary"
317 # The rest of the Wireshark installation (we handled bin above)
321 "$binary_path/.."/* "$pkgres"
323 rsync -av $binary_path/../lib/*.dylib "$pkglib/"
325 # Copy the plugins from the "make install" location for them
326 # to the plugin directory, removing the version number
327 find "$binary_path/../lib/wireshark/plugins" \
329 \( -name "*.so" -o -name "*.dylib" \) \
330 -exec cp -fv "{}" "$pkgplugin/" \;
332 cp "$plist" "$bundle/Contents/Info.plist"
334 # Icons and the rest of the script framework
340 if [ "$ui_toolkit" = "gtk" ] ; then
353 for rl_entry in $res_list ; do
354 rsync -av "$resdir"/Resources/$rl_entry "$bundle"/Contents/Resources/
357 # PkgInfo must match bundle type and creator code from Info.plist
358 echo "APPLWshk" > $bundle/Contents/PkgInfo
360 if [ "$ui_toolkit" = "gtk" ] ; then
361 echo -e "\nPulling in GTK+ libraries and resources...\n"
363 # Pull in extra requirements for Pango and GTK
364 pkgetc="$bundle/Contents/Resources/etc"
365 mkdir -p $pkgetc/pango
366 cp $LIBPREFIX/etc/pango/pangox.aliases $pkgetc/pango/
367 # Need to adjust path and quote in case of spaces in path.
368 sed -e "s,$LIBPREFIX,\"\${CWD},g" -e 's,\.so ,.so" ,g' $LIBPREFIX/etc/pango/pango.modules > $pkgetc/pango/pango.modules
369 cat > $pkgetc/pango/pangorc <<END_PANGO
371 ModuleFiles=\${HOME}/.wireshark-etc/pango.modules
373 AliasFiles=\${HOME}/.wireshark-etc/pangox.aliases
376 # We use a modified fonts.conf file so only need the dtd
377 mkdir -p $pkgetc/fonts
378 cp $LIBPREFIX/etc/fonts/fonts.dtd $pkgetc/fonts/
379 cp -r $LIBPREFIX/etc/fonts/conf.avail $pkgetc/fonts/
380 cp -r $LIBPREFIX/etc/fonts/conf.d $pkgetc/fonts/
382 mkdir -p $pkgetc/gtk-2.0
384 # In newer versions of GTK+, the gdk-pixbuf library was split off from
385 # GTK+, and the gdk-pixbuf.loaders file moved, so we check for its
388 # The file is ultimately copied to the user's home directory, with
389 # the pathnames adjusted to refer to the installed bundle, so we
390 # always put it in the same location in the installed bundle,
391 # regardless of where it lives in the machine on which it's built.
393 if [ -e $LIBPREFIX/etc/gtk-2.0/gdk-pixbuf.loaders ]
395 sed -e "s,$LIBPREFIX,\${CWD},g" $LIBPREFIX/etc/gtk-2.0/gdk-pixbuf.loaders > $pkgetc/gtk-2.0/gdk-pixbuf.loaders
397 sed -e "s,$LIBPREFIX,\${CWD},g" $LIBPREFIX/etc/gtk-2.0/gtk.immodules > $pkgetc/gtk-2.0/gtk.immodules
399 pango_version=`pkg-config --variable=pango_module_version pango`
400 mkdir -p $pkglib/pango/$pango_version/modules
401 cp $LIBPREFIX/lib/pango/$pango_version/modules/*.so $pkglib/pango/$pango_version/modules/
403 gtk_version=`pkg-config --variable=gtk_binary_version gtk+-2.0`
404 mkdir -p $pkglib/gtk-2.0/$gtk_version/{engines,immodules,loaders}
405 cp -r $LIBPREFIX/lib/gtk-2.0/$gtk_version/* $pkglib/gtk-2.0/$gtk_version/
407 gdk_pixbuf_version=`pkg-config --variable=gdk_pixbuf_binary_version gdk-pixbuf-2.0`
408 if [ ! -z $gdk_pixbuf_version ]; then
409 mkdir -p $pkglib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders
411 # As per the above, check whether we have a loaders.cache file
412 # in $LIBPREFIX/lib/gdk-pixbuf-2.0/$gdk_pixbuf_version, as
413 # that's where the output of gdk-pixbuf-query-loaders gets
414 # put if gdk-pixbuf and GTK+ are separated.
416 # The file is ultimately copied to the user's home directory,
417 # with the pathnames adjusted to refer to the installed bundle,
418 # so we always put it in the same location in the installed
419 # bundle, regardless of where it lives in the machine on which
422 if [ -e $LIBPREFIX/lib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders.cache ]
424 sed -e "s,$LIBPREFIX,\${CWD},g" $LIBPREFIX/lib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders.cache > $pkgetc/gtk-2.0/gdk-pixbuf.loaders
426 cp -r $LIBPREFIX/lib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders/* $pkglib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders
431 if [ "$create_bundle" = "true" ]; then
435 if [ -z "$cs_binary_list" ]; then
437 for binary in Wireshark $binary_list ; do
438 cs_binary_list="$cs_binary_list $pkgexec/$binary"
443 echo -e "\nFixing up $bundle...\n"
445 # Find out libs we need from Fink, MacPorts, or from a custom install
446 # (i.e. $LIBPREFIX), then loop until no changes.
450 lib_dep_search_list="
454 if [ "$ui_toolkit" = "gtk" ] ; then
455 lib_dep_search_list="
457 $pkglib/gtk-2.0/$gtk_version/loaders/*
458 $pkglib/gtk-2.0/$gtk_version/immodules/*
459 $pkglib/gtk-2.0/$gtk_version/engines/*.so
460 $pkglib/pango/$pango_version/modules/*
461 $pkglib/gdk-pixbuf-2.0/$gdk_pixbuf_version/loaders/*
463 elif [ "$ui_toolkit" = "qt" ] ; then
464 lib_dep_search_list="
471 echo -e "Looking for dependencies. Round" $a
473 otool -L $lib_dep_search_list 2>/dev/null \
474 | fgrep compatibility \
476 | egrep -v "$exclude_prefixes" \
480 cp -vn $libs "$pkglib"
482 nnfiles=`ls "$pkglib" | wc -l`
483 if [ $nnfiles = $nfiles ]; then
490 # Add extra libraries of necessary
491 for libfile in $EXTRALIBS
493 cp -v -f $libfile "$pkglib"
495 chmod 755 "$pkglib"/*.dylib
497 # Strip libraries and executables if requested
498 #----------------------------------------------------------
499 if [ "$strip" = "true" ]; then
500 echo -e "\nStripping debugging symbols...\n"
501 strip -x "$pkglib"/*.dylib
505 if [ "$ui_toolkit" = "qt" ] ; then
507 # This may not work on Qt 5.5.0 or 5.5.1:
508 # https://bugreports.qt.io/browse/QTBUG-47868
510 macdeployqt "$bundle" -verbose=2 || exit 1
513 # The build process added to the Wireshark binary an rpath entry
514 # pointing to the directory containing the Qt frameworks; remove
515 # that entry from the Wireshark binary in the package.
517 /usr/bin/install_name_tool -delete_rpath "$qt_frameworks_dir" $pkgbin/Wireshark
520 # NOTE: we must rpathify *all* files, *including* plugins for GTK+ etc.,
521 # to keep GTK+ from crashing at startup.
524 # Fix a given executable, library, or plugin to be relocatable
525 if [ ! -f "$1" ]; then
530 # OK, what type of file is this?
532 filetype=$( otool -hv "$1" | sed -n '4p' | awk '{print $5}' ; exit ${PIPESTATUS[0]} )
533 if [ $? -ne 0 ] ; then
534 echo "Unable to rpathify $1 in $( pwd ): file type failed."
540 EXECUTE|DYLIB|BUNDLE)
542 # Executable, library, or plugin. (Plugins
543 # can be either DYLIB or BUNDLE; shared
544 # libraries are DYLIB.)
546 # For DYLIB and BUNDLE, fix the shared
547 # library identification.
549 if [[ "$filetype" = "DYLIB" || "$filetype" = "BUNDLE" ]]; then
550 echo "Changing shared library identification of $1"
551 base=`echo $1 | awk -F/ '{print $NF}'`
553 # The library will end up in a directory in
554 # the rpath; this is what we should change its
558 /usr/bin/install_name_tool -id $to $1
561 # If we're a library and we depend on something in
562 # @executable_path/../Frameworks, replace that with
565 otool -L $1 | grep @executable_path/../Frameworks | awk '{print $1}' | \
566 while read dep_lib ; do
567 base=`echo $dep_lib | awk -F/ '{print $NF}'`
569 echo "Changing reference to $dep_lib to $to in $1"
570 /usr/bin/install_name_tool -change $dep_lib $to $1
575 # Find our local rpaths and remove them.
577 otool -l $1 | grep -A2 LC_RPATH \
578 | awk '$1=="path" && $2 !~ /^@/ {print $2}' \
579 | egrep -v "$exclude_prefixes" | \
580 while read lc_rpath ; do
581 echo "Stripping LC_RPATH $lc_rpath from $1"
582 install_name_tool -delete_rpath $lc_rpath $1
586 # Add -Wl,-rpath,@executable_path/../Frameworks
587 # to the rpath, so it'll find the bundled
588 # frameworks and libraries if they're referred
589 # to by @rpath/, rather than having a wrapper
590 # script tweak DYLD_LIBRARY_PATH.
592 if [[ "$filetype" = "EXECUTE" ]]; then
593 if [ -d ../Frameworks ] ; then
594 framework_path=../Frameworks
595 elif [ -d ../../Frameworks ] ; then
596 framework_path=../../Frameworks
598 echo "Unable to find relative path to Frameworks for $1 from $( pwd )"
602 echo "Adding @executable_path/$framework_path to rpath of $1"
603 /usr/bin/install_name_tool -add_rpath @executable_path/$framework_path $1
607 # Show the minimum supported version of Mac OS X
608 # for each executable or library
610 if [[ "$filetype" = "EXECUTE" || "$filetype" = "DYLIB" ]] && [[ "$VERSION" -ge "7" ]] ; then
611 echo "Minimum Mac OS X version for $1:"
612 otool -l $1 | grep -A3 LC_VERSION_MIN_MACOSX
616 # Get the list of dynamic libraries on which this
617 # file depends, and select only the libraries that
618 # are in $LIBPREFIX, as those are the only ones
619 # that we'll be shipping in the app bundle; the
620 # other libraries are system-supplied or supplied
621 # as part of X11, will be expected to be on the
622 # system on which the bundle will be installed,
623 # and should be referred to by their full pathnames.
627 | fgrep compatibility \
629 | egrep -v "$exclude_prefixes" \
636 # Get the file name of the library.
638 base=`echo $lib | awk -F/ '{print $NF}'`
640 # The library will end up in a directory in
641 # the rpath; this is what we should change its
646 # Change the reference to that library.
648 echo "Changing reference to $lib to $to in $1"
649 /usr/bin/install_name_tool -change $lib $to $1
657 # Make sure we *have* that directory
662 # Make sure we *have* files to fix
664 files=`ls $2 2>/dev/null`
665 if [ ! -z "$files" ]; then
666 for file in $files; do
667 rpathify_file "$file" "`pwd`"
672 if [ $rf_ret -ne 0 ] ; then exit $rf_ret ; fi
680 rpathify_dir "$pkglib" "*.dylib"
681 rpathify_dir "$pkgbin" "*"
682 rpathify_dir "$pkgplugin" "*"
684 if [ "$ui_toolkit" = "qt" ] ; then
685 rpathify_dir "$pkgbin/extcap" "*"
688 if [ "$ui_toolkit" = "gtk" ] ; then
689 rpathify_dir "$pkglib/gtk-2.0/$gtk_version/loaders" "*.so"
690 rpathify_dir "$pkglib/gtk-2.0/$gtk_version/engines" "*.so"
691 rpathify_dir "$pkglib/gtk-2.0/$gtk_version/immodules" "*.so"
692 rpathify_dir "$pkglib/gtk-2.0/$gtk_version/printbackends" "*.so"
693 rpathify_dir "$pkglib/gnome-vfs-2.0/modules" "*.so"
694 rpathify_dir "$pkglib/gdk-pixbuf-2.0/$gtk_version/loaders" "*.so"
695 rpathify_dir "$pkglib/pango/$pango_version/modules" "*.so"
699 PATHLENGTH=`echo $LIBPREFIX | wc -c`
700 if [ "$PATHLENGTH" -ge "6" ]; then
701 # If the LIBPREFIX path is long enough to allow
702 # path rewriting, then do this.
703 # 6 is the length of @rpath, which replaces LIBPREFIX.
706 echo "Could not rewrite dylib paths for bundled libraries. This requires" >&2
707 echo "the support libraries to be installed in a PREFIX of at least 6 characters in length." >&2
709 echo "The bundle will still work if the following line is uncommented in" >&2
710 echo "Wireshark.app/Contents/Resources/bin/{various scripts}:" >&2
711 echo ' export DYLD_LIBRARY_PATH="$TOP/lib"' >&2
717 codesign --sign "Developer ID Application: $CODE_SIGN_IDENTITY" --verbose "$1"
718 codesign --verify --verbose "$1" || exit 1
719 spctl --assess --type execute "$1" || exit 1
722 if [ -n "$CODE_SIGN_IDENTITY" ] ; then
723 security find-identity -v -s "$CODE_SIGN_IDENTITY" -p codesigning
725 echo "Signing executables"
726 if [ -z "$cs_binary_list" ] ; then
727 echo "No executables specified for code signing."
730 for binary in $cs_binary_list ; do
731 codesign_file "$binary"
734 echo "Signing frameworks"
735 for framework in $pkglib/*.framework/Versions/*/* ; do
736 codesign_file "$framework"
739 echo "Signing libraries"
740 for library in $pkglib/*.dylib ; do
741 codesign_file "$library"
744 echo "Signing plugins"
745 for plugin in $pkgplugin/*.so ; do
746 codesign_file "$plugin"
749 echo "Signing $bundle"
750 codesign_file "$bundle"
752 echo "Code signing not performed (no identity)"