halting problem :: Gnome Hello Perl

:: ~6 min read

Gnome Hello is a simple Perl application showing how to create a Gnome project using the Perl language, the Gtk/Gnome Perl bindings and some autotools-fu in order to build and maintain the project.

Gnome Hello Perl Download Gnome Hello Perl 0.5

1. Tree Initialization

First of all, create a directory using the name of your project (not mandatory, but useful):

$ mkdir my-project

Then, move inside it, and begin creating some sub-directories, in order to split up the files, and building a more reliable source tree:

$ cd my-project
$ mkdir docs icons lib tests

Directories Layout

 my-project  Root
  docs Documentation
  data Miscellaneous data
  icons Theme icons
  lib Base module directory
   Modules
  tests Miscellaneous tests

Explanation:

  • docs will contain the documentation of your project, both auto-generated and hand-written files (e.g. the manual or some description of a protocol used by your application);
  • data will contain the miscellaneous data used by your application, such as the GConf schemas, the .desktop entry for the menu launcher, the main program icon, the Glade interface definition files, etc.
  • icons will contain the stock icons, the window icons or just the pixmaps used by your applications; if you plan to ship icons of different sizes, you should consider the creation of two sub-directories inside the icons directory: large and small;
  • lib will contain the modules needed by your application. Since we want to create a self-contained application, these modules will not be made publicly available;
  • tests will contain the test units for your code (you should really use those).

Gnome Hello Perl

2. Auto-tools

Autotools are the product of the same people that brought you Emacs, so you should keep this in mind when you decide to use them. Perl developers usually use the ExtUtils::MakeMaker module in order to create a Perl-friendly build enviroment. Unfortunately, in order to create a build environment for a Gnome project using MakeMaker would result in a great deal of code replication from the autotools land (or the creation of a specific module doing the translation back and forth from autotools macros to Perl code) that all that would be gained by using a Perl-ish environment would soon be lost.

For this reason, we’ll be using the widely known configure-make-makeinstall triad - that is, we’ll use autoconf to generate a (hopefully) platform-independent build environment, and automake to create the relative makefiles for our project.

In order to understand the auto* tools, you’d better off reading the autotools tutorial; what follows next is based on the assumption that you read the tutorial, and understood it.

2.1. Autoconf

The autoconf tool is a program which takes in input a script, written using a language much like the shell scripting language (plus macros) and generates as output a complex shell script which usually takes care of setting up a build environment based on the host configuration. Basically, it’s what makes your program build on every machine other than the developer’s.

But how does the input script (saved as configure.ac) look like, for a GTK+Perl program?

It’s really like a normal configure.ac script, as built for a C-based project; it has the usual preamble:

dnl -*- Mode: autoconf -*-
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.53)

AC_INIT(gnome-hello-perl, 0.6, http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-perl)
AC_CONFIG_SRCDIR(gnome-hello-perl.in)
AM_INIT_AUTOMAKE(1.7)
AM_MAINTAINER_MODE

And the usual declaration of requirements:

dnl required packages version
m4_define(REQUIRED_GTK, 2.8.0)
m4_define(REQUIRED_GTK2PERL, 1.100)
m4_define(REQUIRED_GNOME2PERL, 1.020)
m4_define(REQUIRED_GNOME2VFSPERL, 1.020)
m4_define(REQUIRED_GNOME2GCONFPERL, 1.020)

Note: While you could just require every version you like of the GTK library, you should always require the latest stable version of the Perl bindings module.

Since we are building a Perl program, it makes sense to explicitely require the Perl interpreter to be found, and give the user a switch in order to specify a non-standard location (useful for non-Un*x platforms - yes, they do exist):

dnl check for perl binary
AC_PATH_PROG(PERL, perl, no)
AC_ARG_WITH(perl,   [  --with-perl=[perl]]          Perl binary path)
if test x"$PERL" = xno; then
    if ! x$with_perl; then
        AC_MSG_ERROR([No perl binary found])
    else
        PERL = $with_perl
    fi
fi

AC_SUBST(PERL)

The code above also gives us the ability to use the @PERL@ variable inside files to be parsed out by the configure script.

Next, we check that the user actually has the packages we require - also, he has the right versions installed onto his system; checking for a library using PkgConfig is practically painless, thanks to the macros provided system-wide:

dnl check for a specific C library version
PKG_CHECK_MODULES(GTK2, gtk+-2.0 >= REQUIRED_GTK)

On the other hand, checking for a Perl module using the autotools might be a little trickier; usually, it boils down to checking that the module is present inside the @INC array (the include paths) by simply loading that module; if it’s found, the Perl interpreter will exit successfully, otherwise it won’t. Unfortunately, we also require a minimum version; thus, we need a little script, checking the VERSION value against the required version:

dnl check for Perl modules
dnl gtk2-perl
AC_MSG_CHECKING(for Gtk2 >= REQUIRED_GTK2PERL)
prog="
exit 0 if Gtk2->VERSION >= REQUIRED_GTK2PERL;
exit 1;
"
if $PERL -MGtk2 -e $prog >&AC_FD_CC 2>&AC_FD_CC; then
    AC_MSG_RESULT(found)
else
    AC_MSG_RESULT(not found)
    AC_MSG_ERROR(required gtk2-perl version not found)
fi

… to be continued…

2.2. Automake
2.3. Autogen

Gnome Hello Perl

3. The application launcher

Since we are creating an application in an object-oriented fashion, with the entire application code inside a class, we also need a simple perl program that instantiates that class, and launch the Gtk main loop.

The launcher script will reside in the default binary directory, and will most ikely consists of a few lines, telling the Perl interpreter where to find the application modules (remember: we are creating a self-contained application, with its modules stored outside Perl’s @INC), the actual object instatiation, and the mainloop call.

Something along these lines will probably be enough for every project:

  #!@PERL@
  use warnings;
  use strict;

  use lib '@PKGLIBDIR@';
  use Project;

  my $app = Project::App->new;
  $app->show;

  Project->main;
  0;

Both the @PERL@ and @PKGLIBDIR@ placeholders will be substituted by the autotools with the corresponding values, that is the full path of the Perl interpreter and the package library directory, respectively.

Save the launcher script with the .in suffix, in order to remember that you must “filter” it in order to create a valid launcher.

Inside you Makefile.am file, you’ll need to add a specific section for the application launcher:

  bin_in_files = project-application.in
  bin_SCRIPTS = project-application

  project-application: $(bin_in_files)
          sed -e "s|\@PERL\@|@PERL@|"            \
                 -e "s|@PKGLIBDIR@|$(pkglibdir)|" \
          $< > $@ &&                                             \
          chmod a+x $@

This code will expand the placeholders, will mark it as executable, and will install the launcher script inside the binary directory.

4. Configuration

To Do…

5. Extra files

To Do…

Gnome Hello Perl click to enlarge

context-switch wordpress old-blog