...making Linux just a little more fun!

Building the GNOME Desktop from Source

By Oscar Laycock

First, I must say that the GNOME documentation "strongly recommends" against building from source files. If you do, it suggests using the GARNOME scripted system. Even GARNOME it says, is only for the "brave and patient".

I started building programs from source as I wanted to upgrade a very old distribution and did not have enough disk space to install a Fedora or Ubuntu. The memory on my old PC is probably a bit low too, at 128 Meg Also, it is fun to run the latest versions, be on the leading edge, and get ahead of the major distributions. You could not run Windows Vista (tm) on my old PC!

I took the files from the latest GNOME release I could find, being version 2.25. This was probably a mistake. I later found out that odd numbered minor releases like 25 are development releases and may be unstable. The stable 2.26 series should have come out in March. In fact, when I built the file manager "Nautilus", I could not find a dependency, "libunique", so I went back to version 2.24. The GNOME sources are at http://ftp.gnome.org/pub/gnome.

I used the Beyond Linux from Scratch (BLFS) guide to know where to find packages and in what order to build them. You can find it at http://www.linuxfromscratch.org (LFS). Unfortunately the BLFS guide uses versions from the summer of 2007, GNOME version 2.18. Also, I installed the libraries and programs in the default location /usr/local, but looking back it would have been better to have put them in their own directory and give a --prefix option to "configure", as the BLFS project recommends.

It took me about a month to build a basic GNOME desktop in my spare time. Disappointingly, you don't see anything until the last piece, "gnome-session", is in place.

When I ran my first applications like the image-viewer "eye-of-gnome", some appeared on the desktop and then core-dumped. The core file said the last function called was in GTK, in the libgtk-x11 library. I had had to upgrade my GTK when building gnome-panel. I had chosen the latest version 2.15.2. This is probably a development releases too. When I switched back to my year-old GTK, everything was fine. I finally settled for the stable version recommended by GARNOME. It took me a few days to sort this out!

There is a free book on programming GNOME, "GTK+ / Gnome Application Development" by Havoc Pennington available at http://developer.gnome.org/doc/GGAD. This is somewhat old.

Overall, I like GNOME because it is truly free and lighter than KDE.

GNOME versus KDE

Last year (2008), I built the 4.0 release of KDE from the source files. GNOME is made up of around sixty packages, KDE about twenty. Qt (the user interface framework) and KDE are much larger than GNOME. The compressed source of Qt is about three times the size of the equivalent GTK+, GLib, Cairo and Pango put together. But, of course, KDE includes the web browser Konqueror. GNOME needs the Gecko layout engine from Mozilla.org that you see in Firefox.

Qt and KDE's C++ code is slower to compile than GNOME's C, at least on my old laptop - a Pentium III with only 128 Meg RAM! KDE uses CMake rather than "configure" to generate the makefiles. It took a while to learn how to use CMake, but its files are much clearer.

The BLFS instructions only covered KDE 3.5, so I had to adjust things for KDE 4.0. In GNOME, if you wanted to find out where to find some unusual packages, you could look at the makefiles of the GARNOME project. Its website is at http://projects.gnome.org/garnome. GARNOME automatically fetches and builds a given GNOME release.

For KDE, I had to change a little code when building the "strigi" library. (It searches through files for the semantic desktop). To be exact, I had to add definitions for "__ctype_b" and "wstring". For GNOME, it was easier. I mostly had to go off and find required libraries that were not in the BLFS notes.

KDE has trouble starting up on my laptop, although it is all right on my PC. There is a lot of swapping in and out and thrashing with my low memory. In fact, both computers have 128 Megabytes. The laptop even has a faster processor. It has a Pentium III processor whereas than the PC has a Pentium II. The disks even seem about the same speed in simple tests. It is a puzzle. Anyway, KDE takes over ten minutes to start on my laptop! GNOME takes one minute. (KDE takes just over a minute on my PC.)

Browsers

On KDE, I could get the Konqueror browser running fairly easily. But I had to add about 250 Meg of swap space to get the WebKit library to link with the low memory on my PC. WebKit is the rendering engine. I like the way Konqueror uses many of the same libraries as other parts of KDE. It makes Konqueror a bit lighter when running inside of KDE. (I have put the commands I use to add swap at the end).

With Firefox 3, I had to turn the compiler optimization off with the "-O0" switch to avoid thrashing with the small memory on my old laptop. I also had to leave out a lot of the components in "libxul". Otherwise the link of libxul ends up just swapping in and out as well. (I understand XUL is the toolkit used to build the user interface of Mozilla). Firefox does not work without a real libxul though.

I thought I would try building GNOME's own browser - Epiphany. But I had trouble configuring it to use the Gecko rendering libraries in the Mozilla Firefox 3 browser I had just built. Epiphany offers a simpler interface than Firefox and concentrates just on web browsing, taking features like mail from other GNOME applications. Unfortunately Epiphany seems to expect "pkg-config" entries for Gecko, which Firefox 3 had not generated. (When you install a library, a file in /usr/lib/pkgconfig is created, listing the compiler flags (-L, -l and -I) needed by a program using the library.) I manually added in all the Firefox shared libraries I could find. But there seemed to be some core Firefox functions that Epiphany still could not access. However, Epiphany does really recommend Firefox 2. But Firefox 2 uses a lot of deprecated functions in my more modern version of Cairo. I got lost in all the errors.

Then I noticed that Epiphany's web page mentions an experimental version using WebKit as the browser engine. But the configuration seemed to have incomplete autoconf/automake files and use the Apple xcodebuild tool. It was too difficult for me. You can begin to see there is some skill required to build a complete distribution!

I later learnt from a GNOME blog that the Mozilla version of Epiphany is not actively developed any more, because about a year ago GNOME started to switch to WebKit. But the switch has not been completed. It was originally scheduled to be delivered with GNOME 2.26, but has been postponed to GNOME 2.28. I remembered that WebKit is a fork of KDE's KHTML browser engine used by Konqueror. It was made by Apple for their Safari browser, and more recently used by Google in its Chrome browser.

In the end, I built the Dillo browser. It used to use GTK and Glib. But it now uses the FLTK (Fast Light Tool Kit) - a C++ GUI toolkit. Of course, it does not support Javascript or Java.

Strangely enough, Konqueror runs quite well within GNOME! I think I will use it when developing complicated web pages which use Javascript and AJAX.

Problems compiling packages

Would you enjoy building programs from the source tarballs? I think you probably need some knowledge of C. Not too much, as I didn't know a lot about C++ when I built KDE. There always seem to be a few problem with compiling packages. Here are a few to give you an idea.

A simple problem occurred when I was building the "dbus-glib-bindings" package:

DBUS_TOP_BUILDDIR=.. dbus-send --system --print-reply=literal --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.Introspectable.Introspect > dbus-bus-introspect.xml.tmp && mv dbus-bus-introspect.xml.tmp dbus-bus-introspect.xml
Failed to open connection to system message bus: Failed to connect to socket /usr/local/var/run/dbus/system_bus_socket: Connection refused

I guessed it wanted the dbus system bus running. I remembered something from building D-Bus last year, had a look around, and ran "dbus-daemon --system".

A typical problem was with gnome-terminal. It included the "dbus-glib-bindings.h" header file which itself included the glib header "glib-2.0/glib/gtypes.h". But glib did not want its header file directly included and had put a "#error" statement in to give a warning. I solved this by crudely commenting out the #error.

The strangest problem I got was when running GStreamer's configure script:

    ./configure: line 32275: syntax error near unexpected token `('
    ./configure: line 32275: `  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do'

I tried narrowing it down by putting in some simple echo statements and then I changed some back ticks to the more modern "$()". But, I had the same problem with the GStreamer Plugins package. So I decided to upgrade my version of Bash, which was a year old. The LFS project suggests using the "malloc" (memory allocation) from the libc library rather than that bundled with Bash, so I also ran configure with the option "--without-bash-malloc". All this luckily fixed the problem.

Out of interest, I have added the commands I typed (over sixty times) to build the packages, at the end of this article.

GNOME libraries

I enjoy reading about the libraries as I build them. I also wanted to draw a diagram showing which packages needed to be built first.

The libraries are, in fact, described very well in the GNOME documentation at http://library.gnome.org/devel/platform-overview.

The libraries shown below are used in various combinations by the GNOME applications you see on the desktop.

My diagrams show the dependencies between packages. For example GTK requires Pango and Cairo. A package usually generates many libraries, so it is nice to think at the package level. I believe you can generate graphs of dependencies automatically from the GNOME build systems.

I have included some notes that I found in the README file or documentation that came with the packages.

I did not build most of the audio or video libraries, as I don't play music or watch videos on my laptop! It also keeps things simple.

Base libraries

       /|\                 /|\
        +-------------------+
        |       pygtk       |
        |      pycairo      |
        |     pygobject     |                        /|\            /| |\
        | (python bindings) |          +---- gail ----+  +-----------+ +------+
        +-------------------+          |    (GNOME    |  | dbus-glib | |libxml|
/|\                                    |accessibility)|  | bindings  | |      |
 +----------------------- gtk+ -----------------------+  +-----------+ +------+
 |     (GIMP Tool Kit - graphical user interfaces)    |  |   D-Bus   |
 |-- pango --+--------+                +---- atk -----+  | (message  |
 |(rendering)| libpng |      +---------+(accessibility|  |  passing  |
 | of text)  | libjpeg|      | libtiff |  interfaces) |  |  system)  |
 +----------------------- cairo ----------------------+  +-----------+
 |  (2D graphics library for multiple output devices) |
 +------------------+------------ pixman -------------+
                    |         (low level pixel        |
                    | manipulation, e.g. compositing) |
                    +----------------------------------
                                                     /|\
                              +-------- gvfs ---------+ 
                              |   (backends include   |
/|\                           | sftp, smb, http, dav) | 
 +----------------------- glib -----------------------+ 
 |(data structures, portability wrappers, event loop, |
 |threads, dynamic loading, algorithms, object system,|
 |GIO - the virtual file system replacing gnome-vfs)  |
 +----------------------------------------------------+   
 
Notes

The GIO library in GLib tries not to clone the POSIX API like the older gnome-vfs package, but instead provides higher-level, document-centric interfaces. The GVFS backends for GIO are run in separate processes, which minimizes dependencies and makes the system more robust. The GVFS package contains the GVFS daemon, which spawns further mount daemons for each individual connection.

The core Pango layout engine can be used with different font and drawing backends. GNOME uses FreeType, fontconfig, and Cairo. But on Microsoft Windows, Pango can use the native Uniscribe fonts and render with the Win32 API.

The Cairo documentation says it is "designed to produce consistent output on all output media while taking advantage of display hardware acceleration when available (for example, through the X Render Extension) ... The cairo API provides operations similar to the drawing operators of PostScript and PDF. Operations in cairo include stroking and filling cubic Bezier splines, transforming and compositing translucent images, and antialiased text rendering. All drawing operations can be transformed by any affine transformation (scale, rotation, shear, etc."

GTK+ was first developed as a widget set for the GIMP (GNU Image Manipulation Program). The FAQ mentions one of the original authors, Peter Mattis, saying "I originally wrote GTK which included the three libraries, libglib, libgdk and libgtk. It featured a flat widget hierarchy. That is, you couldn't derive a new widget from an existing one. And it contained a more standard callback mechanism instead of the signal mechanism now present in GTK+. The + was added to distinguish between the original version of GTK and the new version. You can think of it as being an enhancement to the original GTK that adds object oriented features." The GTK+ package contains GDK, the GTK+ Drawing Kit, an easy to use wrapper around the standard Xlib function calls for graphics and input devices. GDK provides the same API on MS Windows.

The GAIL documentation says "GAIL provides an implementation of the ATK interfaces for GTK+ and GNOME libraries, allowing accessibility tools to interact with applications written using these libraries ... ATK provides the set of accessibility interfaces that are implemented by other toolkits and applications. Using the ATK interfaces, accessibility tools have full access to view and control running applications." GAIL stands for GNOME Accessibility Implementation Layer. It has just been moved into GTK.

D-BUS is a simple inter process communication (IPC) library based on messages. The documentation says "a core concept of the D-BUS implementation is that 'libdbus' is intended to be a low-level API, similar to Xlib. Most programmers are intended to use the bindings to GLib, Qt, Python, Mono, Java, or whatever. These bindings have varying levels of completeness."

PyGObject allows you to use GLib, GObject and GIO from Python programs.

Platform libraries

                                                      gnome-icon-theme
                                                            /|\
                                                      icon-naming-utils
                                               (xml to translate old icon names)
                  libgnomeui* 
    (a few extra gui widgets, many now in gtk)
                      /|\
                       +---------------------------+
                       |                           |
                  libbonoboui*                gnome-keyring
           (user interface controls     (password and secrets daemon 
            for component framework)     and library interface)
                      /|\                          |
                       |                        libtasn1
                       |               (Abstract Syntax Notation One)
                       |
                       +--------------------------------------+
                       |                                      |
                    libgnome*                          libgnomecanvas*
    (initialising applications, starting programs,    (structured graphics:
     accessing configuration parameters, activating  polygons, beziers, text
     files and URI's, displaying help)               pixbufs, etc. Rendered
                      /|\                             by Xlib or libart)
  +--------------------+----------+                           |
  |                               |                          /|\
  |  gnome-vfs monikers           |                           |
  |   /|\       /|\               |                           |
  |    |         +-------- gnome-vfs* (virtual file system)   +----------+
  |    |                 (consistent API for local and        |          |
  |    |               remote files, cameras, WebDAV, etc)    |          |
  |    |                         /|\                          |          |
  |    |             +------------+--------+               libglade    libart*
  |    |             |                     |            (dynamically   (fast 2d
  |    |          Gconf             gnome-mime-data      load glade    graphic
  |    |      (configuration           (classify         user        primitives)
 libbonobo*     database -            file contents)     interface 
 (component      daemon &                                description
 system, e.g.    library)                                files)
 multimedia         /|\
 in word processor)  | 
 /|\                 |
  +------------------+ 
  |
 ORBit2+ * (fast and light CORBA object broker)
   +--- libIDL (parses interface definitions for CORBA)     
    

Note: * indicates library is depreciated
Notes

Many of the libraries on the left hand side of the diagram are not used in newly written code and references to them have been removed in some old code. But the API's are still supported, at least for the current GNOME 2.x series. GNOME is moving to using D-Bus for communication between processes. GNOME Panel applets use Bonobo to communicate with the panel. GnomeVFS has been replaced by GIO, and the GVFS library which supplies the network and local protocols.

According to the documentation, " Libglade is an alternative to using Glade's code generation. Instead of generating code from the XML interface description, libglade loads and parses the description at runtime. It also provides functions that can be used to connect signal handlers to parts of the interface."

Libart is, in its own words, a "sophisticated, antialiased, alpha-compositing engine."

The "gnome-keyring" README says it can "manage several keyrings, each with its own master password, and there is also a session keyring which is never stored to disk, but forgotten when the session ends."

According to the Wikipedia, Abstract Syntax Notation One (ASN.1), is used "in telecoms and computer networking... [and] is a standard and flexible notation that describes data structures for representing, encoding, transmitting and decoding data".

You can read the reference documentation for libbonobo at http://library.gnome.org/devel/libbonobo/stable. Maybe it is worth a skim through to get an overview. There are similar API references for GConf, gnome-vfs, libgnome, libgnomecanvas, libbonoboui and libgnomeui.

Desktop libraries

gnome-themes   gnome-user-docs   gnome-backgrounds   gnome-terminal
     |          (user, admin                        (just the shell:   
    /|\            guides)                           menubar, prefs dialog)
     |               |                                     /|\
gtk-engines    gnome-doc-utils                              |  
 (themes)     (xslt for Docbook                            vte 
               and translations)                    (terminal emulator
                                                 widget implemented in GTK)

                                   gnome-session
                                         | 
                                   control-center
                                        /|\
 +----+----------------+-----------------+------------+------------+ 
 |    |                |                 |            |            |
 | gnome-applets  metacity  nautilus (file manager)   |        gstreamer
 |   (for panel)  (window         |      |       |    |         plugins 
 |    |     |     manager)       /|\  libexif librsvg |            |
 |   /|\ libgtop       |          |  (digital  (fast  |     +------+------+     
 |    |  (portable     zenity     |   cameras)  SVG)  |     |             | 
 |    | performance   (dialogs    |              |    |    gstreamer   liboil 
 |    |  statistics    in         |      +-------+   /|\  (sound &    (optimized
 |    |  library       scripts)   | libcroco  libgsf  |    video)    inner loops
/|\   |  and server)              | (CSS2     (structured                  using
 |    |                           | parser)    files) |                 assembly
 |    |                           |                   +--+-------+     MMX, SSE)
 |    |                           |                      |       |
 | gnome-panel        eel (nautilus widgets, extensions) |  libgnomekdb
 |    |     |           /|\                        |     |      /|\
 |    |     +-------+----+                      gnome-menus      |
 |    |             |                           (engine)    libxklavier
 | libwnck          |                                   (accessing & setting
 | (library for window management e.g. workspace          keyboard layouts)     
 |                  |       pagers and tasklists)               /|\
 +--------+---------+                                            | 
          |                                                   isocodes 
    gnome-desktop                                     (list of country, language
(functions for background, monitor, thumbnails,           and currency names)
 desktop items, and gnome-about. Icon files)
Notes

Remember the diagram shows the dependencies. For example, some of the features in the GNOME control panel are implemented in Metacity, such as changing the window border theme, or window navigation shortcuts.

Libgnome-desktop contains APIs that really belong in libgnome(ui) or GTK+ but are limited in their use. It provides support for desktop backgrounds, monitor configuration, thumbnails, and desktop items.

Libwnck is the Window Navigator Construction Kit. It uses the Extended Window Manager Hints specification (EWMH).

The documentation for "eel" says "The Eazel Extensions Library is a collection of widgets and extensions to many modules of the GNOME platform. These widgets and extensions were developed by hackers working on Nautilus."

The "gnome-menus" package contains an implementation of the draft "Desktop Menu Specification" from freedesktop.org.

The README for "libexif" says it "contains a library for parsing, editing, and saving EXIF data. Most digital cameras produce EXIF files, which are JPEG files with extra tags that contain information about the image ... It is intended to replace lots of redundant implementations in command-line utilities and programs with GUIs."

Librsvg is a high performance SVG rendering. It can draw a SVG to a Cairo surface or render SVGs into GDK pixbufs for easy use in GTK+ applications. Librsvg is not used by the very latest Nautilus code, but is part of other GNOME applications.

The README file for "libcroco" says it is a "standalone css2 parsing and manipulation library. The parser provides a low level event driven SAC (Simple Api for CSS) like api and a css object model like api. Libcroco provides a CSS2 selection engine and an experimental xml/css rendering engine."

The documentation for "libgsf" says the "GNOME Structured File Library (GSF) is an I/O abstraction for reading/writing compound files... GSF was written as part of the Gnumeric project. It started in 2002 as a replacement for libole2 which Gnumeric was using to handle the Microsoft Excel". It reads gzip, bz2, zip, XML and OASIS Open Document formats amongst others.

According to its home page, "Liboil"is a library of simple functions that are optimized for various CPUs. These functions are generally loops implementing simple algorithms, such as converting an array of N integers to floating-point numbers or multiplying and summing an array of N numbers ... The goal of this project is to consolidate some of the code used by various multimedia projects, and also make optimizations easier to use by a broader range of applications."

The "gnome-applets" package includes the libpanel-applet library which allows you to develop small applications which can be embedded in the panel.

On systems like BSD and Solaris, "libgtop" provides a setgid/setuid server for graphical tools. On Linux, libgtop has a library that gives performance information in a generic way to the differents tools that use it such as "gtop" and panel applets.

In the Nautilus architecture document it says "Nautilus is a general-purpose shell application for browsing arbitrary content. It is implemented as `nautilus', a container application which exercises overall control and provides chrome, and a number of nautilus view components. These view components may use the `libnautilus' library to ease implementation."

Gstreamer, of course, is a framework for streaming media. According to the documentation, " It's based on plug-ins that will provide the various codec and other functionality ... Is GStreamer a media player ? No, GStreamer is a development framework for creating applications like media players, video editors, streaming media broadcasters and so on. That said, very good media players can easily be built on top of GStreamer".

VTE can also be used to embed a console/terminal in games, editors, IDEs, etc. VTE supports Unicode and character set conversion, as well as emulating any terminal known to the system's terminfo database.

The author of Metacity says it is a "boring window manager for the adult in you. Many window managers are like Marshmallow Froot Loops; Metacity is like Cheerios ... includes only the window manager; does not try to be a desktop environment. The pager, configuration, etc. are all separate and modular." According to Wikipedia, GNOME used the Enlightenment window manager and then Sawfish before choosing Metacity. Apparently, it is aimed at new computer users that do not need the extreme configurability offered by its predecessors.

Build commands

First I look at the README file in the package directory. Then I check if the INSTALL file is anything but the standard one, using "head".

set -b     # so bash tells me when jobs finish

configure --help=short 2>&1 | less    # shows options specific to package

configure >myconf01.lst 2>&1 &        # usually installs into /usr/local -
                                      # unless you add a --prefix=/mydir option
# have a look at the log file, -
# especially the end

make >mymake01.lst 2>&1 &
# at the start, "tail -f" the log file -
# to make sure the compiler options are OK

make install >mymakeinst01.lst 2>&1 & # you may need to be root, of course.
# look at the log file to see where the binaries are put, what are the actual
# names of the libraries installed, and where to find the documentation

Commands to add swap

Adding swap lets you pretend you have more memory. I did not know how to do this when I started!

# run as root
dd if=/dev/zero of=swap1 bs=1024 count=100k   # 100 Meg
mkswap swap1
swapon swap1

Sometimes the program really is too big and the PC will just swap files in and out all the time. I can see the laptop is "thrashing" simply by the hard-disk light staying on! I also use the "vmstat 5" command. It reports every five seconds. The CPU will be waiting for IO to finish most of the time. The "cpu wa" column will be high, say 97%. The program will not have much time to run, with a low "user time" for my non-kernel code. The "cpu us" column might say 3%. You can see the amount of blocks read and written rising in the "IO bi bo" columns. (The first line produced by vmstat gives averages since the system booted.)

Good luck!


Talkback: Discuss this article with The Answer Gang


[BIO]

I live by the River Thames in the suburbs of London, England. I play with Linux in my spare time on a ten year old PC. I was a C and Oracle programmer when I was younger.


Copyright © 2009, Oscar Laycock. Released under the Open Publication License unless otherwise noted in the body of the article. Linux Gazette is not produced, sponsored, or endorsed by its prior host, SSC, Inc.

Published in Issue 164 of Linux Gazette, July 2009

Tux