- Building GTK-OSX
Building the core libraries and preconfigured applications in GTK-OSX is pretty simple: Download the installation script, run a few commands in Terminal.app (or your favorite substitute), and watch.
Building other libraries or applications can be only a little harder. See Building Other Programs below.
Open Terminal.app or your favorite terminal app. Download gtk-osx-build-setup.sh to your home directory.
./gtk-osx-build-setup.sh jhbuild bootstrap jhbuild build meta-gtk-osx-bootstrap meta-gtk-osx-core
Substitute meta-gtk-osx-gtk3 for meta-gtk-osx-core if your project requires Gtk3 instead of Gtk2.
How It Works
GTK+ is a unix graphical framework originally designed to run on Unix systems with X-Windows... but it provides multiple backends including one for OS X's Quartz graphics engine, so it can be built to run on OS X without enabling the X11 subsystem.
But there is a lot to GTK+, including a lot of dependencies, that are included as part of most Linux distributions and either aren't included or aren't sufficiently up to date on OSX. End applications may have even more dependencies falling into one of those categories. GTK-OSX provides an easy way to download, build, and install all of those various dependencies.
GTK-OSX's installation script installs jhbuild along with some extra code, a configuration file, and a set of modulesets which have been tailored and tested for OSX.
You obvdiously need a compiler and an SDK. For simply building you need only the command-line tools for your MacOS version. On newer versions (>=10.8) simply running gtk-osx-build-install.sh should offer to install them for you if they're not already there. Failing that you can download them from Apple's developer site(you'll need to sign in with your Apple ID and accept some terms and conditions if you don't already have an Apple developer account). Aside from that if you're running and building for a recent version of OS X there are no special considerations. If you're building for an older version see Building on Older Versions of Mac OS X. It takes about 1 GB of disk space to compile GTK.
If you have MacPorts or Fink installed, you must remove all traces of them from your environment before you try to run jhbuild. The easiest way is to create a new user and run jhbuild while logged in as that user. Mixing Fink or MacPorts and GTK-OSX will fail.
Note that there are other ways to deal with Fink and MacPorts: You can write a shell script or a special .bashrc to add your Fink or MacPorts environments (removing those settings from your default profile/bashrc) and start a new shell to use Fink or MacPorts just as you do for jhbuild, or you can add python os.environ commands to your .jhbuildrc-custom which remove the Fink or MacPorts environment settings. What's important is that nothing from Fink or MacPorts is visible to programs running under jhbuild: Getting m4 files from the wrong aclocal will be immediately catastrophic (the build will break), but installing a python module to the wrong place could lose you an afternoon trying to figure out why your program doesn't work, and linking the wrong shared library might work on your computer (until the next time you run fink selfupdate -- there goes another afternoon figuring out what changed) but fail for other users when you distribute a bundled application.
Download gtk-osx-build-setup.sh to your home directory and run it:
$ sh gtk-osx-build-setup.sh
It will install jhbuild in ~/Source and create ~/.local/bin/jhbuild. It will also install ~/.jhbuildrc and ~/.jhbuildrc-custom and will copy the current gtk-osx modules into ~/Source/jhbuild/modulesets.
jhbuild is installed in ~/.local/bin. You must either add that to your path, alias jhbuild, or call jhbuild with that path, e.g.
$ ~/.local/bin/jhbuild shell
Note: jhbuild requires Python 2.5 to unpack tar files, but Tiger provides Python 2.3. We provide a Python 2.7 module, which you can build like so:
$ jhbuild build python
You will also need to make sure that the shell uses this version of Python to run jhbuild, for instance by defining an alias:
$ alias jhbuild="PATH=gtk-prefix/bin:$PATH jhbuild"
Obviously you should substitute the actual path of your gtk installation for gtk-prefix. If you add it to your .bashrc or .bash_profile you won't need to worry about it.
$ jhbuild bootstrap $ jhbuild build meta-gtk-osx-bootstrap meta-gtk-osx-core
And you have a reasonably complete GTK+ installation ready for you to build the application that interests you.
$ jhbuild build gimp
For example will build The GIMP and all of its dependencies. Two things of note: First, it's best to do a whole build in one go by putting all of the required modules and meta-modules in one command. That allows jhbuild to figure out the best order to build everything. Second, The GIMP is an example of an application module that has everything it needs defined as hard dependencies, but not all applications do.
You may want to set
build_policy = "updated-deps"
in your .jhbuildrc-custom to avoid rebuilding packages which haven't changed since the last build.
Read the jhbuild manual for details and many more options.
When you're working on your GTK+ application or any libraries, it's important to have the environment properly configured. jhbuild build does this when it's building things, of course, but if you're tweaking and building manually the easiest thing to do is start a jhbuild shell:
$ jhbuild shell
If you work from inside an IDE or programmer's editor, you'll need to configure its shell environment to match what jhbuild shell does.
When running jhbuild shell, note that it sets $PATH before running your .bashrc, so depending on how you set $PATH, you may want to
$ export PATH=$PREFIX/bin:$PATH
after starting the jhbuild shell and before you try to do anything. We don't recommend making this your ordinary $PATH because some of the programs installed in the gtk directory work differently from the ones which Apple provides, which could cause trouble elsewhere. ($PREFIX won't work right outside of the jhbuild shell anyway.)
Parts of Gtk-Osx
~/.jhbuildrc and ~/.jhbuildrc-custom
Jhbuild is written to load a user-generated file named ~/.jhbuildrc for setting the configuration variables documented in its configuration file page. Gtk-Osx uses that file to add MacOS-specific version detection and configuration code and provides for another file, ~/.jhbuildrc-custom, for user configuration. An example , jhbuildrc-gtk-osx-custom-example, will be installed by gtk-osx-build-setup.sh if none is found. jhbuildrc-gtk-osx-custom-example really is an example; users are expected to modify it to meet their needs. To that end it is heavily commented with additional information about the sorts of things one can do with it.
setup_sdk(sdk='native', target='native', architecture=[_default_arch]) The main configuration function in .jhbuildrc is setup_sdk(). .jhbuildrc-custom must call setup_sdk() to set up the build with the right compiler path and flags including the path to the Apple Software Development Kit (SDK) that contains all of the system headers and library stubs. setup_sdk() takes the three arguments noted above: SDK, which can be either 'native' or a MacOS version number (e.g. '10.10') tells setup_sdk() what SDK to build with (it will use xcode-select to find it); target, also either 'native' or a MacOS version number, sets the minimum version of MacOS on which the resulting code will run,\; and architecture, which takes an array with one or more of the following: _default_arch, i386, x86_64, ppc, and ppc64. _default_arch will build whatever is the default for the current running system. That will be x86_64 for 64-bit Intel Macs, i386 for 32-bit Intel Macs, and ppc for PowerPC Macs. If left to itself Gtk-Osx will build for the currently-running version of MacOS. If you want the result to run on earlier versions see #Building for Older Versions of MacOS. NOTE: Passing multiple arguments to architectures will cause the compiler to build universal binaries. That doesn't work well, so if you need to do this see the comments about setup_universal() in jhbuildrc-gtk-osx-custom-example.
GTK-OSX supplies 3 modulesets: modulesets-stable, modulesets, and modulesets-unstable. The default is modulesets-stable. You can switch to one of the others by putting the line
to your ~/.jhbuildrc-custom, substituting one of the modulesets listed above for MODULESETS.
Modulesets-stable pulls in mostly tar archives ("mostly" because there are a couple of modules for which tar archives aren't available). Modulesets pulls mostly from development version control repositories (git, subversion, or cvs, mostly git) with revision or tag attributes designating a stable release, with a few tarballs where version control access isn't available, the project is dormant (no updates in over a year), or there is no suitable tag, revision id, or stable branch to ensure a stable release. Modulesets-unstable pulls from the same repositories as modulesets, but has the revision and tag attributes removed so that you get the latest development work for almost all modules.
NB: Modulesets-unstable is really unstable. Any one of the modules can be broken by a developer checking in a change that causes the module to not compile. If it won't compile at all, it will in most cases be fixed within a few hours, but if it just won't compile on OSX, then it may take some work on your part to get it going again. We don't regard this as our problem, and won't provide support. Don't use modulesets-unstable unless you are comfortable with autotools, C programming, glib (and particularly GObject), Cocoa, and bugzilla! In general, if you want to work on a module under version control, the best plan is to use modulesets and override the branch on that specific module in ~/.jhbuildrc-custom: (Git; consult the jhbuild documentation for other repository types.)
branches["foo"]=[None, "master"]This may not work if the module specifies a tag instead of a branch.
Sometimes you may need to build a tree when you don't have network connectivity. For this to work, you'll obviously need to have all of the sources already downloaded. You also need a local set of modulesets; when you run gtk-osx-build-setup.sh, the stable modulesets are installed in ~/Source/jhbuild/modulesets alongside the modulesets that come with jhbuild. To use them, add a line
moduleset=os.path.join(os.environ["HOME"], "Source", "jhbuild", "modulesets", "gtk-osx.modules")
to your .jhbuildrc-custom. If you are using one of the other modulesets (i.e. modulesets or modulesets-unstable) you'll need to retrieve them from git.gnome.org (the easiest way is to clone the project) and adapt the line above to point to the right place.
If you're using tarball modules (and the bootstrap modules always are tarballs) and building multiple trees, you'll want to set a single directory for downloading:
tarballdir=os.path.join(os.environ["HOME"], "Source", "pkgs")
To prevent jhbuild from trying to get updates from source control repositories, you can pass --no-network on the command line or add
to .jhbuildrc-custom, but that will risk not updating when you are connected, so it's probably better to use the command line option.
Download now, build later
If you want to pull everything in in one go so you can build offline, here's how:
After running gtk-osx-setup.sh and setting up your .jhbuildrc-custom file, you can make jhbuild download the modulesets as follows:
jhbuild -m bootstrap update meta-bootstrap jhbuild update meta-gtk-osx-bootstrap jhbuild update meta-gtk-osx-core
If you want to target multiple architectures, set up your .jhbuildrc-custom for each architecture and then rerun the above commands, because different architectures call in different modules.
Once jhbuild has downloaded the modulesets, you can build them offline later like this:
jhbuild bootstrap --no-network jhbuild build meta-gtk-osx-bootstrap --no-network jhbuild build meta-gtk-osx-core --no-network
Building for Older Versions of Mac OS X
Gtk-OSX is maintained mostly for the current stable release of Mac OS X and Xcode, but it can be used to build applications which run on older systems as well.
If you're building with Xcode 7.0 (provided with MacOS X 10.10) or later and MacOSX10.10.sdk or later, just set the target argument of setup_sdk() to the earliest version you want to support. Note: Some features of Gtk and Glib will not be built if the minimum OS X version is too low. Which features are affected are not documented, you'll have to examine the code to find them. Be sure to set `architectures=['i386'] if you want to support 32-bit Intel Macs; 32-bit binaries run just fine on a 64-bit machine but 64-bit binaries won't run on a 32-bit machine.
If you're building with an older compiler or SDK you must in general use the SDK and its corresponding compiler for the earliest version of MacOS that you want to support. See OSX Version Notes.
- MacOSX 10.4 (Tiger) or later. It builds successfully on both PowerPC and Intel Macs.
- On an Intel Mac running 10.6 (Snow Leopard) or earlier, you can build for either a PowerPC or Intel target.
- On an Intel Mac running 10.7 (Lion), you can only build for an Intel target.
On a PowerPC Mac, you can build GTK only for a PowerPC target. Thanks to Rosetta, the resulting binaries will work on both PowerPC and Intel Macs, but only under 10.6 (Snow Leopard) and earlier.
In some cases, you can compile GTK itself on an Intel Mac, then copy the Intel libraries to a PowerPC Mac and build Intel binaries of the GTK application on the PowerPC Mac.
- Developer Tools (Xcode)
On 10.4 (Tiger), use Xcode 2.5, which you can download from Apple Developer Connection after signing up for a free Apple ID. Earlier versions of XCode might work, but there is no reason not to use version 2.5.
- On 10.5 (Leopard), you can either use Xcode 3.0 (which is included on the installation DVD, but must be installed separately after OSX is configured), or upgrade to Xcode 3.1.
10.6 (Snow Leopard) comes with XCode 3.2. Xcode 4 also runs on Snow Leopard, but it will only produce Intel object code. If you want to build for PowerPC targets, the most recent Xcode version you can use is 3.2.6. Note that the Xcode 4 series use the llvm-gcc compiler which has been found to create a rather insidious GLib bug, so we advise that you not use it.
- On 10.7 (Lion) and later use Xcode 5 or 6, which use the clang compiler even when you tell it to use gcc. This compiler seems to work well.
It is possible to install multiple versions of XCode on one Mac. Use <tt>xcodeselect</tt> to determine which one is "current" for the command-line tools.
- Subversion. Leopard and later includes it with XCode; jhbuild will build it for you on Tiger.
git. Included with Xcode 4 and later; if you're running an older version of OS X, you'll want to download a dmg. Note that this page offers OSX binaries only, and the most recent PPC build is from October 2009. PPC users who want more recent software should build their own. Sources are available at http://kernel.org/pub/software/scm/git, where you want a file named something like git-1.74.tar.bz2 . Jhbuild needs git to bootstrap itself, so it can't build it for you.
OpenSSL ≥ 0.9.8 and Curl built with it. SnowLeopard and earlier ship with 0.9.7, so if you're on one of those old platforms you'll need to upgrade both. Again, this must be done before starting to use jhbuild. Binaries are available for SnowLeopard; users of earlier systems will need to build from source. Fortunately both packages compile and install without any issues.
The first stable release of Gtk+-3 occurred in January 2011; Gtk+-2 is in maintenance mode, but because few major programs have migrated to Gtk+-3 yet, Gtk+-2 remains the default. If you're building a program that does use Gtk+-3, or you're working on migrating your project, you'll want to build a Gtk+-3 tree. Just substitute meta-gtk-osx-gtk3 for meta-gtk-osx-core in your list of modules. Python users can use meta-gtk-osx-python-gtk3, and C++ users meta-gtk-osx-gtkmm3.
Modulesets-unstable, which builds the latest code from git, allows you to have both Gtk+-2 and Gtk+-3 installed in the same tree. The more stable modulesets (modulesets-stable and modulesets build different versions of GLib and Pango because Gtk+-3.2.0 requires an unstable version of GLib (2.29.0), and we didn't want to propagate that back into the default build. If you want both Gtk+-2 and 3 in a stable build tree, build meta-gtk-osx-core first, then meta-gtk-osx-gtk3. That way GLib-2.29.0 will overwrite GLib-2.28.4 and everything should work out OK. We suggest that you not do that when building your project for binary distribution.
There is a nice migration guide at Gnome.org.
To get your project ready for 3.0, you might find it useful to set up configure to select which one is to be used for a particular build. You can copy the similar change from gtk-mac-integration into your own project.
Building Other Programs
The procedure for building other programs is the same as for included programs, once you have set up a moduleset. Before you dive in, though, look through (or grep) the gtk-osx modulesets in ~/Source/jhbuild/modulesets. If the program you need is already there, then you just have to tell jhbuild to build it: jhbuild build theprogram
If it's not there, the first step is to open ~/.jhbuildrc-custom and ~/mymodules.modules in your favorite editor. .jhbuildrc-custom needs only one line for now:
moduleset=os.environ['HOME'] + '/mymodules.modules'
mymodules.modules (which can be any name you like, but must use the "modules" extension) will start off like this:
<?xml version="1.0"?> <!DOCTYPE moduleset SYSTEM "moduleset.dtd"> <?xml-stylesheet type="text/xsl" href="moduleset.xsl"?> <moduleset> <include href="http://git.gnome.org/browse/gtk-osx/plain/modulesets-stable/gtk-osx.modules"/> </moduleset>
You'll insert any new modules and repositories after the <include/> element.
Before writing a module yourself, be sure to look through the modules in ~/Source/jhbuild/modulesets and see if there's one that you can copy into mymodules.modules. Be sure to copy the repository as well as the module.
Writing modules is beyond the scope of this page, but it's pretty easy to do. Read through jhbuild's documentation and look at the provided modulesets for examples. The hard work is in figuring out the dependencies.
Gtk+-2 python bindings are provided via a package called PyGtk. (Gtk+-3 python bindings -- and many others -- are provided by a new feature called "gobject introspection", which doesn't require a separate module but does require rewriting your application.) Getting it built is almost straightforward, but bundling python apps can be tricky. Visit the Python page for more information or to share tips.
A Note About Building Your Own Programs
It is common for people new to Unix programming to think that they can distribute their sources with just a Makefile (or even a bunch of Makefiles). This is unfortunately naive, because there are a number of different sorts of Unix and Unix-like operating systems, and the way that they provide services to programs varies greatly. This is true even among different versions of Linux.
To get around this problem, there have arisen a variety of different build systems which are able to explore the operating system hosting the build and make appropriate adjustments to the build files so that the program builds and runs correctly. The most commonly encountered is the GNU Autotools suite, which provides the familiar ./configure && make && sudo make install sequence. You'll find several choices supported by jhbuild in the documentation. Make sure that you use one for your program!
When you have GTK+ built as above, and once you have built your own application, investigate bundling your application for distribution.
There are dedicated mailing lists: Gtk-Users and Gtk-Devel. The former is for discussing usage and getting help, the latter for proposing changes to the build system. The maintainer announces important changes to the modulesets and customization files on these lists, so it is a good idea to subscribe to at least one of them. They are very low traffic.
Bugs should be reported to the gtk-mac-integration project in Gnome's Bugzilla.