Porting to Mac/gtk-mac-bundler

Jump to: navigation, search

← Porting to Mac

This page contains some notes on how gtk-mac-bundler (formerly called ige-mac-bundler) (and maybe other tools) do the job of making portable, self-contained GTK+ applications work on Mac. The notes were prepared during the course of porting ASCEND to Mac. Please feel free to set me straight on any wrong observations, missing information, etc.

The following observations come from bundling up GtkDemo using ige-mac-bundler.

GTK libraries

GTK libraries are copied into the Contents/Resources/lib directory in the application bundle. Their 'install names' are changed so that they look like:

$ otool -L libgtk-quartz-2.0.0.dylib 
	/Users/john/gtk/inst/lib/libgtk-quartz-2.0.0.dylib (compatibility version 1801.0.0, current version 1801.2.0)
	@executable_path/../Resources/lib/libgdk_pixbuf-2.0.0.dylib (compatibility version 1801.0.0, current version 1801.2.0)
	@executable_path/../Resources/lib/libgdk-quartz-2.0.0.dylib (compatibility version 1801.0.0, current version 1801.2.0)
	@executable_path/../Resources/lib/libpangocairo-1.0.0.dylib (compatibility version 2401.0.0, current version 2401.5.0)

For the GtkDemo app, the following libraries are copied:

$ ls
charset.alias			libfreetype.6.dylib		libgobject-2.0.0.dylib		libpangoft2-1.0.0.dylib
gtk-2.0				libgdk-quartz-2.0.0.dylib	libgtk-quartz-2.0.0.dylib	libpixman-1.0.dylib
libatk-1.0.0.dylib		libgdk_pixbuf-2.0.0.dylib	libintl.8.dylib			libpng12.0.dylib
libcairo.2.dylib		libgio-2.0.0.dylib		libjpeg.7.dylib			libtiff.3.dylib
libexpat.1.dylib		libglib-2.0.0.dylib		libpango-1.0.0.dylib
libfontconfig.1.dylib		libgmodule-2.0.0.dylib		libpangocairo-1.0.0.dylib

Pixbuf loaders

The environment variable GDK_PIXBUF_MODULE_FILE is used to specify the path to a file usually named gdk-pixbuf.loaders. This file contains a list of shared libraries that perform the task of loading various kinds of images into GTK+.

This gdk-pixbuf.loaders file can be automatically generated by the script ~/gtk/inst/bin/gdk-pixbuf-query-loaders.

This contents of gdk-pixbuf.loaders are automatically edited by ige-mac-bundler to replace the absolute file paths with paths like @executable_path/../Resources/lib/gtk-2.0/loaders/libpixbufloader-png.so, etc.

The pixbuf loaders are copied into the locally-consistent location Contents/Resources/lib/gtk-2.0/2.xx.xx/loaders, where xx.xx is the particular GTK+ version being used.

Icons and themes

Icons and themes are copied into Contents/Resources/share. I got the following files:

$ ls -R
icons	themes



Default	Emacs	Raleigh







Didn't see any sign of actual image or icon files anywhere... perhaps the default ones are embedded in the shared library somehow.

Pango configuration files

In Contents/Resources/etc/pango/pangorc the following text was found:

$ cat pangorc

The file pango.modules is present in the same directory, but is empty.

GTK configuration files

In Contents/Resources/etc/gtk-2.0/gtkrc the following text was found:

$ cat gtkrc
gtk-icon-theme-name = "Tango"
gtk-enable-mnemonics = 0

In same directory, there is another empty file called gtk.immodules.

Use of install_name_tool

In ige-mac-bundler, all DYLD paths have been set relative to the @executable_path. The executable is kept inside the bundle as Contents/MacOS/GtkDemo-bin. This means, for example, that @executable_path/../Resources/lib takes the loader to folder containing all the GTK shared libraries.

Note: for the case of PyGTK bundles, assuming Apple Python or MacPython are being used but not being included in the bundle, we can't pull this trick, because the @executable_path would then be outside the application bundle, and no help for locating GTK libraries. An alternative approach might be possible using @rpath set on the PyGTK shared libraries, and this needs to be tried out.

Environment variables

The file Contents/MacOS/GtkDemo is the entry-point for the application (as directed by Info.plist) and is a shell-script that sets various required environment variables so that GTK can find all its stuff:

NOTE: in the following, the "`pwd`/$0" causes problems if you invoke the ige-mac-bundler-bundled from the command line from any directory other than Contents/MacOS. I think that this is a bug.

name="`basename $0`"

tmp=`dirname "$tmp"`
tmp=`dirname "$tmp"`
bundle=`dirname "$tmp"`


export DYLD_LIBRARY_PATH="$bundle_lib"
export XDG_CONFIG_DIRS="$bundle_etc"/xdg
export XDG_DATA_DIRS="$bundle_data"

export GTK_DATA_PREFIX="$bundle_res"
export GTK_EXE_PREFIX="$bundle_res"
export GTK_PATH="$bundle_res"

export GTK2_RC_FILES="$bundle_etc/gtk-2.0/gtkrc"
export GTK_IM_MODULE_FILE="$bundle_etc/gtk-2.0/gtk.immodules"
export GDK_PIXBUF_MODULE_FILE="$bundle_etc/gtk-2.0/gdk-pixbuf.loaders"

export PANGO_RC_FILE="$bundle_etc/pango/pangorc"

After the above, there is some locale-related stuff (see launcher.sh for the details.

Next the script does something with charset alias (FIXME what's this doing?):

if test -f "$bundle_lib/charset.alias"; then
export CHARSETALIASDIR="$bundle_lib"


Next, a variable EXTRA_ARGS is initialised empty and an optional environment.sh is run, allowing command-line arguments to be appended to EXTRA_ARGS, or just to set additional application-specific or user-specific environment variables.

Then, the script throws out some Mac-related command-line parameters that are useless to GTK:

# Strip out the argument added by the OS.
if [ x`echo "x$1" | sed -e "s/^x-psn_.*//"` == x ]; then

shift 1

Finally, the script launches the executable.

$EXEC "$bundle_contents/MacOS/$name-bin" $* $EXTRA_ARGS