- 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 python 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. If you want a python3 build you need to build it separately before the other modules, then link python to python3 and python-config to python3-config:
cd <prefix> ln -s python3 python ln -s python3-config python-config
There's another wrinkle: Python needs openssl to build its crypto and hashing modules. It doesn't seem to find the installed ones, so it depends on the openssl module that crashes jhbuild if left to its own devices because it doesn't like jhbuild's install to a scratch directory and then ccopy everything only if it all worked. Do the following to prevent the crash:
- Stop the openssl configure phase with control-C, then drop to a shell (4).
- Copy the configure command from the jhbuild output and paste it into the command prompt. Yes, openssl's Configure really is capitalized.
Run make && make install_sw. make install crashes, so don't do that.
Exit the shell and use 2 - ignore error and continue.... Stop and ignore the build and install phases too.
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.
Gtk-OSX requires MacOS X 10.8 or later and the command-line compile tools from Xcode 5 or later.
You obvdiously need a compiler and an SDK. For simply building you need only the command-line tools for your MacOS version.Simply running gtk-osx-build-setup.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 have HomeBrew, 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 HomeBrew, MacPorts, or Fink and GTK-OSX will fail.
Note that there are other ways to deal with these "Linux on your Mac" package systems: You can write a shell script or a special .bashrc to add a special environment (removing those settings from your default profile/bashrc) and start a new shell to use the software they've built just as you do for jhbuild, or you can add python os.environ commands to your .jhbuildrc-custom which remove the package system's environment settings. What's important is that nothing from the package system is visible to programs running under jhbuild: Getting m4 files from the wrong aclocal will be immediately catastrophic (the build will break), 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
$ alias jhbuild="PATH=gtk-prefix/bin:$PATH jhbuild"
$ jhbuild bootstrap $ jhbuild build python meta-gtk-osx-bootstrap meta-gtk-osx-core
See the notes under quickstart about using python3 instead of python and working around the openssl breakage. And you have a reasonably complete GTK+ installation ready for you to build the application that interests you. For example
$ jhbuild build gimp
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.
The Setup Function
setup_sdk(target='native', sdk=None, 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: target, also either 'native' or a MacOS version number, sets the minimum version of MacOS on which the resulting code will run; SDK used to set the SDK to use but modern Xcode versions have made that unnecessary so it's ignored;and architecture, which takes an array with one or both of i386 and x86_64. _default_arch will build whatever is the default for the current running system. 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. This may or may not work. All supported (see Older Versions) versions of MacOS X run only on 64-bit Intel so it nearly always makes the most sense to accept the default.
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 uses 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 Gitlab! 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.)
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 gitlab.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. The oldest supported version is the one that Apple considered current 5 years ago; at the time of this writing that is 10.8 Mountain Lion and Xcode 5. At the 5th anniversary of the release of 10.9 Mavericks 10.9 will become the oldest supported version, and so on.
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. This is known to work for versions as early as SnowLeopard, but some modules may not compile cleanly or work properly on that MacOS versions older than the supported one. Note that SnowLeopard is also the last version of MacOS to support 32-bit hardware, so if you're building for it you may want to set archiecture=['i386'].
The last commit of Gtk-OSX that supported building on systems older than MountainLion is tagged "LastLion". You can clone the Gtk-OSX repository and check out that tag to build with earlier SDKs; the modulesets in that commit are also known to work with MacOS X 10.5 and may have worked with MacOS X 10.4.
- 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:
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="https://gitlab.gnome.org/GNOME/gtk-osx/raw/master/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 in the issue tracker.