<?xml version='1.0'?>
<?xml-stylesheet type="text/xml" media="screen" href="params.xsl"?>
<!-- vim: set ai tw=80 ts=3 sw=3 et: -->
<!DOCTYPE slides PUBLIC "-//Norman Walsh//DTD Slides Full XML V3.3.0//EN"
       "http://docbook.sourceforge.net/release/slides/3.3.0/schema/dtd/slides.dtd" [

<!ENTITY malcolm-email "<email>malcolm@commsecure.com.au</email>">
<!ENTITY am "<application>automake</application>">
<!ENTITY ac "<application>autoconf</application>">
<!ENTITY ah "<application>autoheader</application>">
]>

<slides>
   <slidesinfo>
      <title>Autoconf, automake and friends</title>
      <titleabbrev>LCA tutorial</titleabbrev>
      <author>
         <firstname>Malcolm</firstname><surname>Tredinnick</surname>
         <affiliation><address>&malcolm-email;</address></affiliation>
      </author>
      <pubdate>Wednesday 22 January 2003</pubdate>
<!--
      <copyright>
         <year>2003</year>
         <holder>Malcolm Tredinnick</holder>
      </copyright>
-->
   </slidesinfo>

   <foil id="introduction">
      <title>Introduction</title>

      <para>The information I would like to convey...</para>
      <itemizedlist>
         <listitem>
            <para>Where &ac; and &am; fit into the build process and the roles
            they fill.</para>
         </listitem>
         <listitem>
            <para>Why they are necessary.</para>
         </listitem>
         <listitem>
            <para>Brief introduction to each tool.</para>
         </listitem>
         <listitem>
            <para>The more difficult bits.</para>
         </listitem>
      </itemizedlist>

   </foil>

   <foilgroup id="intro-tools">
      <title>A Brief Introduction To The Tools</title>

      <para>Wherein we consider why there are so many tools involved here and
      what roles they fulfill.</para>

      <itemizedlist>
         <listitem><para>&am;</para></listitem>
         <listitem><para>&ac;</para></listitem>
         <listitem><para>autoheader</para></listitem>
         <listitem><para>aclocal</para></listitem>
         <listitem><para>make</para></listitem>
      </itemizedlist>

      <foil id="standard-build">
         <title>The Standard Build Procedure</title>

         <para>Standard source code build, after unpacking the tarball, will
         typically proceed as </para>
<programlisting>
./configure --prefix=/foo/bar/
make
make check
su -
make install
</programlisting>

   <para>For the maintainer, the first step is the most interesting and
   fiddly.  After that, it is easy. </para>

      </foil>

      <foil id="maintainer-pov">
         <title>The Maintainer's Point Of View</title>

         <para>Two areas that can be managed by tools:</para>

	      <itemizedlist>
            <listitem>
               <para>Configuration details that are specific to the particular
               build. </para>
            </listitem>

            <listitem>
               <para>Generating the repetitive and routine portions of
               Makefiles. </para>
            </listitem>
         </itemizedlist>

      </foil>

      <foil id="build-specific-details">
         <title>Configuration Details Specific to a Particular Build</title>

         <itemizedlist>
            <listitem>
               <para>Feature selection</para>
            </listitem>
            <listitem>
               <para>Library and other support file locations</para>
            </listitem>
            <listitem>
               <para>Machine-specific features </para>
               <itemizedlist>
                  <listitem><para>compiler flags, </para></listitem>
                  <listitem><para>function names, </para></listitem>
                  <listitem><para>...</para></listitem>
               </itemizedlist>
            </listitem>
            <listitem>
               <para>Install locations</para>
            </listitem>
         </itemizedlist>

         <para>All of this detection and flag parsing is done by &ac;. </para>

      </foil>

      <foil id="determining-build-details">
         <title>Determining the Build Details</title>

         <para>A few different sources of tests and command-line parsing code
         exist. </para>

         <itemizedlist>
            <listitem>
               <para>Many common tests are packaged with &ac;. </para>
            </listitem>
            <listitem>
               <para>Some tests become common enough that they are distributed
               in third-party macro libraries (<filename>*.m4</filename>
               files). </para>
            </listitem>
            <listitem>
               <para>Once-off tests can be coded directly into the
               <filename>configure.in</filename> file. </para>
            </listitem>
         </itemizedlist>

         <para>Collecting together the macros that come &ac; and third-party
         packages is done by <application>aclocal</application>. </para>

      </foil>

      <foil id="recording-build-details">
         <title>Recording the Build Details</title>

         <itemizedlist>
            <listitem>
               <para>Some details can be recorded in a header file for
               inclusion throughout the package (typically,
               <filename>config.h</filename>). This is handled by a combination
               of &ah; and &ac;. </para>
            </listitem>
            <listitem>
               <para>Some information becomes flags to the compiler, linker and
               other processors: include file paths, some definitions that
               cannot go into <filename>config.h</filename>. This is handled by
               &ac; and &am;. </para>
            </listitem>
         </itemizedlist>

      </foil>

      <foil id="what-to-build">
         <title>Knowing What To Build</title>

         <itemizedlist>
            <listitem>
               <para>What files need to be built? </para>
            </listitem>
            <listitem>
               <para>What does each file depend upon to be built? </para>
            </listitem>
            <listitem>
               <para>What are the &quot;types&quot; of these files? This
               affects installation procedures. </para>
            </listitem>
            <listitem>
               <para>Are there any tests that can be run? </para>
            </listitem>
         </itemizedlist>

         <para>Determining which files to build, how to install and test them
         and what their dependencies are is the domain of &am;. </para>

         <para>At this point in the process, the build is ready to proceed on
         this particular machine. It is now just a trivial matter of running
         <application>make</application> and so forth (this was the
         &quot;uninteresting&quot; portion mentioned earlier, so it is not
         covered here). </para>

      </foil>

      <foil id="putting-it-all-together">
         <title>Putting All The Pieces Together</title>

         <para>Combining all of the steps from the previous slides results in a
         file that is often called <filename>autogen.sh</filename>. </para>

         <para>This file just runs the various autotools programs in an
         appropriate order. To wit, it is essentially </para>

<programlisting>
#!/bin/sh

aclocal
autoheader
automake --add-missing
autoconf
</programlisting>

         <para>In practice, this file usually includes checks for the correct
         versions of programs. It may also run things like
         <filename>autopoint</filename> (from the
         <application>gettext</application> package) and other preliminary
         scripts. </para>

         <para>The above fragment is the essence of the procedure, though, and
         is the portion we are concerned about in this tutorial. </para>

      </foil>

      <foil id="extra-diagram">
         <title>Pictorial View Of The Process</title>

         <para>(This slide was not in the original tutorial. Instead the
         diagram was drawn up on the whiteboard at the request of some of the
         participants. I have included it here for completeness and because it
         adds another explanation of the last few slides.) </para>

         <mediaobject>
            <imageobject>
               <imagedata fileref="file-path.png" format="PNG"/>
            </imageobject>
         </mediaobject>

      </foil>

   </foilgroup>

   <foilgroup id="developer-vs-distributor">
      <title>Developing versus Distributing</title>

      <para>The previous group of slides describe the situation as the package
      developer sees it. The minimal number of necessary source files are
      somewhat magically transformed into a complete package. </para>

      <para>Recall the earlier sequence: </para>

<programlisting>
./configure --prefix=/foo/bar/
make
make check
su -
make install
</programlisting>

      <para>The <filename>configure</filename> script is the
      <emphasis>result</emphasis> of running &ac;, &am; and friends. </para>

      <foil id="distributed-files">
         <title>Distributed Files</title>

         <orderedlist>
            <listitem>
               <para>The developer will often have more tools at their disposal
               than the typical builder. </para>
            </listitem>
            <listitem>
               <para>Extra tools may be difficult to install or time-consuming
               to run. </para>
            </listitem>
            <listitem>
               <para>Some files change over time, but are not specific to the
               build environment. They can safely be generated at distribution
               time. </para>
            </listitem>
         </orderedlist>

         <para>Typically, some files are therefore generated by the developer
         and distributed with the package. Examples include </para>

         <variablelist>
            <varlistentry>
               <term>Documentation</term>
               <listitem>
                  <para>Documentation transformation tools can be difficult to
                  install correctly with many pre-requisites.  </para>
               </listitem>
            </varlistentry>
            <varlistentry>
               <term>Translation catalogs</term>
               <listitem>
                  <para>Support tools not available everywhere. Can be
                  time-consuming and the result is not machine specific. </para>
               </listitem>
            </varlistentry>
            <varlistentry>
               <term>Instruction files for building <filename>.deb</filename>
               or <filename>.rpm</filename> packages. </term>
               <listitem>
                  <para>These are changing files but remain fixed for each
                  <emphasis>official</emphasis> release.  </para>
               </listitem>
            </varlistentry>
         </variablelist>

      </foil>

      <foil id="build-or-distribute">
         <title>Distributing Built Files</title>

         <itemizedlist>
            <listitem>
               <para>One school of though: distributing built files is a waste
               of time, since the means exist to generate them on the target
               machine. </para>
            </listitem>
            <listitem>
               <para>The other side of the coin: All the arguments on the
               previous slide about being nice to the package builders. </para>
            </listitem>
            <listitem>
               <para>Common result: both source and built files are
               distributed.  Users can then regenerate things from source, but
               this is not required. </para>
            </listitem>
         </itemizedlist>

         <para>Note that this last point is not universally true. Some package
         maintainers will only distribute the built files and not their
         sources. In practice, this is probably the worst case, although it
         does make the distributed tarball slightly smaller. </para>

      </foil>

   </foilgroup>

   <foilgroup id="automake-details">
      <title>Automake</title>

      <para>Enough philosophy and general concepts! </para>

      <para>Onto the good stuff... </para>

      <para>We begin with &am; and work back to &ac;. </para>

      <foil id="sample-am-file">
         <title>A Sample Automake File (fragment)</title>

         <para>A real-life example, from the gtk-doc package. </para>

<programlisting>
bin_SCRIPTS = \
	gtkdoc-scanobj  \
	gtkdoc-scangobj \
...

gtkdocdatadir = $(datadir)/gtk-doc
gtkdocdata_DATA = \
	gtkdoc-common.pl	\
	gtk-doc.xsl		\
	devhelp.xsl		\
...

pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = gtk-doc.pc

EXTRA_DIST= \
	MAINTAINERS	\
	gtk-doc.pc.in	\
...

dist-hook:
	mkdir $(distdir)/doc
	cp -pr $(srcdir)/doc/* $(distdir)/doc
	rm -rf $(distdir)/doc/CVS
	mkdir $(distdir)/db2man
	cp -pr $(srcdir)/db2man/* $(distdir)/db2man
...
</programlisting>

      </foil>

      <foil id="file-types">
         <title>Types of Files</title>

         <para>Automake knows that different types of files should be treated
         differently. </para>

         <variablelist>
            <varlistentry>
               <term>Data files (<literal>foo_DATA</literal>)</term>
               <listitem>
                  <para>For the build infrastructure, these are the simplest
                  files. Just install them without change. </para>
               </listitem>
            </varlistentry>
            <varlistentry>
               <term>Header files (<literal>foo_HEADERS</literal>)</term>
               <listitem>
                  <para>Public header files. </para>
               </listitem>
            </varlistentry>
            <varlistentry>
               <term>Executable binaries (<literal>foo_PROGRAMS</literal>)
               </term>
               <listitem>
                  <para>Usually built from a number of sources. Can be
                  stripped. Should be installed as executables. </para>
               </listitem>
            </varlistentry>
            <varlistentry>
               <term>Scripts (<literal>foo_SCRIPTS</literal>)</term>
               <listitem>
                  <para>Installed as executables. Can have their name
                  transformed (the <literal>--program-transorm-name</literal>
                  flag to <filename>configure</filename>). Cannot be stripped
                  (so they are different from programs). </para>
               </listitem>
            </varlistentry>
            <varlistentry>
               <term>Manual pages (<literal>foo_MAN</literal>) and info
               pages (<literal>foo_TEXINFOS</literal>)</term>
               <listitem>
                  <para>Installed into the appropriate directories. For
                  example, &am; knows that <filename>bar.3n</filename> goes in
                  section 3 (despite the trailing <literal>n</literal>). For
                  info documents, it knows to run
                  <filename>install-info</filename> on the results to put them
                  into the directory, and so forth. </para>
               </listitem>
            </varlistentry>
            <varlistentry>
               <term>Libraries (<literal>foo_LIBRARIES</literal> and
               <literal>foo_LTLIBRARIES</literal>) </term>
               <listitem>
                  <para>Specifies that the files are static or shared
                  libraries, possibly created with
                  <application>libtool</application> (not covered in this
                  tutorial). </para>
               </listitem>
            </varlistentry>
         </variablelist>

      </foil>

      <foil id="building-binaries">
         <title>Building files from multiple sources</title>

         <para>One of the most common operations in a makefile is turning a
         number of source files into one target file (for example, a program
         binary). </para>

<programlisting>
bin_PROGRAMS = bug-buddy

bug_buddy_SOURCES = \
        $(bb_built_sources)     \
        bug-buddy.c             \
        bug-buddy.h             \
        md5-utils.c             \
        md5-utils.h             \
        bugzilla.c              \
        bugzilla.h              \
        cell-renderer-uri.c     \
        cell-renderer-uri.h     \
        config.c                \
        gdb-buddy.c             \
        libglade-buddy.h        \
        save-buddy.c            \
        save-buddy.h            \
        signal-buddy.c          \
        signal-buddy.h          \
        united-states-of-bug-buddy.c
</programlisting>

      <para>Aside from the <literal>$(bb_built_sources)</literal> variable,
      everything here should be clear. </para>
      
      <para>The <filename>bug-buddy</filename> file is a
      <emphasis>program</emphasis> and will be installed in the
      <replaceable>bindir</replaceable> location when <literal>make
      install</literal> is run. </para>

      </foil>

      <foil id="generating-sources">
         <title>Including Generated Files As Sources</title>

         <para>Continuing with the previous example, the
         <filename>Makefile.am</filename> file contains this fragment which
         defines the <literal>bb_built_sources</literal> variable mentioned
         earlier. </para>

<programlisting>
bb_built_sources = \
        bb-marshal.c    \
        bb-marshal.h

bb-marshal.h: $(srcdir)/bb-marshal.list
        ...

bb-marshal.c: $(srcdir)/bb-marshal.list
        ...
</programlisting>

      <para>The portions replaced with ellipses in the above fragment and
      unimportant to this discussion. </para>

      <para>The point here is that anything that &am; cannot interpret as a
      <emphasis>special</emphasis> instruction, it assumes is a normal Makefile
      code fragment and copies the literal text into the resulting Makefile.
      </para>

      <para>Note also the use of the special <literal>$(srcdir)</literal>
      variable, which refers to the current source directory. Remember that the
      build directory and the source directory may not necessarily be the same,
      so you cannot just use the &quot;current&quot; directory in these
      situations. </para>

      </foil>

      <foil id="other-automake-constructs">
         <title>Other Common Automake Constructs</title>

         <para>Rather than provide an exhaustive (and somewhat tedious)
         coverage of all the automake constructs that are possible, let&apos;s
         look instead at a few of the more common constructions found in
         <filename>Makefile.am</filename> files. </para>

         <para>The idea here is to make you comfortable reading through an &am;
         file and using those ideas to construct your own. </para>

      </foil>

      <foil id="top-level-makefile.am">
         <title>Subdirectories And Extra Files</title>

      <para>In a project organised with mostly administrative files in the
      top-level directory and source, documentation, graphics, etc files one
      level down in subdirectories, the top-level
      <filename>Makefile.am</filename> will often look like: </para>

<programlisting>
SUBDIRS = libsmil dtd po

EXTRA_DIST =			\
	libsmil.spec.in	\
	libsmil.spec		\
	intltool-extract.in	\
	intltool-merge.in	\
	intltool-update.in

snap:
   cp libsmil.spec libsmil.spec.orig; \
   sed -e "s/\(^Version: \)\(.*\)/\1\2.`date +'%Y%m%d'`.snap/" libsmil.spec \
     > libsmil.spec.tmp; \
   mv libsmil.spec.tmp libsmil.spec; \
   $(MAKE) dist distdir=$(PACKAGE)-$(VERSION).`date +"%Y%m%d"`.snap; \
   mv libsmil.spec.orig libsmil.spec
</programlisting>

      <para>Note that the top-level subdirectory is not listed in
      <literal>SUBDIRS</literal>, so it is built last. To force the top-level
      directory to be built at a specific time, just put <literal>.</literal>
      into the <literal>SUBDIRS</literal> list somewhere. </para>

      </foil>

      <foil id="hooks-and-working-with-autoconf">
         <title>Working With Autoconf and Local Targets</title>

<programlisting>
INCLUDES = $(LIBGLADE_CFLAGS)

# build documentation when doing a distcheck.
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc

if HAVE_PYTHON
bin_SCRIPTS = libglade-convert
endif

pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libglade-2.0.pc

...

XMLCATALOG = /etc/xml/catalog

xmldir = $(datadir)/xml/libglade
xml_DATA = glade-2.0.dtd

install-data-local:
        -xmlcatalog --noout --add "system" \
          "http://glade.gnome.org/glade-2.0.dtd" \
          $(xmldir)/glade-2.0.dtd $(XMLCATALOG)

uninstall-local:
        -xmlcatalog --noout --del $(xmldir)/glade-2.0.dtd $(XMLCATALOG)

#small hack to get distcheck to work
clean-local:
        rm -f intl/po2tbl.sed .memdump
</programlisting>

      </foil>

   </foilgroup>

   <foil id="break">
      <title>Time for a break!</title>

      <para>Still to come...</para>

      <itemizedlist>
         <listitem>
            <para>Autoconf</para>
         </listitem>
         <listitem>
            <para>Portability considerations</para>
         </listitem>
         <listitem>
            <para>Conditional building</para>
         </listitem>
      </itemizedlist>

   </foil>

   <foilgroup id="autoconf-details">
      <title>Autoconf</title>

      <para>As mentioned previously, autoconf does a lot of the build-specific
      testing and configuration. </para>

      <itemizedlist>
         <listitem>
            <para>Parsing configuration arguments. </para>
         </listitem>
         <listitem>
            <para>Testing for the existence of various files and functions.
            </para>
         </listitem>
         <listitem>
            <para>Creating <filename>Makefile.in</filename> files for later
            processing by the <filename>configure</filename> script. </para>
         </listitem>
         <listitem>
            <para>Creating the <filename>config.h</filename> file from
            autoheader's <filename>config.h.in</filename> template. </para>
         </listitem>
      </itemizedlist>

      <foil id="general-setup">
         <title>General Setup Of <filename>configure.in</filename></title>

         <para>A lot of the preliminary and final portions of a
         <filename>configure.in</filename> file are very similar. </para>

<programlisting>
AC_INIT(slice-n-dice 0.1)
AM_CONFIG_HEADER(config.h)
AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)

# Checks for programs.
AC_PROG_CC
AC_PROG_LIBTOOL
AC_PROG_INTLTOOL

# Checks for libraries.
...

# Checks for header files.
AC_HEADER_STDC

...

# Checks for library functions.
...

AC_OUTPUT(
sliceNdice.spec
Makefile
src/Makefile
po/Makefile.in
)
</programlisting>

      </foil>

      <foil id="checking-for-functions">
         <title>Checking For Functions and Files</title>

         <para>Not unusual to see tests of the form</para>

<programlisting>
AC_CHECK_FUNCS([clearenv setenv])
AC_CHECK_HEADERS(dlfcn.h)
AC_CHECK_FUNCS(bind_textdomain_codeset)
</programlisting>

         <para>These tests set the values of various constants in
         <filename>config.h</filename>: </para>

<programlisting>
/* Define to 1 if you have the `clearenv' function. */
#undef HAVE_CLEARENV

/* Define to 1 if you have the `setenv' function. */
#undef HAVE_SETENV

/* Define to 1 if you have the &lt;dlfcn.h> header file. */
#undef HAVE_DLFCN_H

/* Define to 1 if you have the `bind_textdomain_codeset' function. */
#undef HAVE_BIND_TEXTDOMAIN_CODESET
</programlisting>

      </foil>

      <foil id="conditional-flags">
         <title>Conditional Compiler Flag Setting </title>

         <para>Sometimes we want to only set a particular set of compiler flags
         if a particular header file or library is present. </para>

<programlisting>
AM_CONDITIONAL(HAVE_CDDA, false)
AC_CHECK_HEADERS(cdda_interface.h cdda_paranoia.h, [
        CDDA_LIBS="-lcdda_paranoia -lcdda_interface"
        AM_CONDITIONAL(HAVE_CDDA, true)
        ])
</programlisting>

         <para>Another, more complicated example. </para>

<programlisting>
AC_CHECK_LIB(jpeg, jpeg_start_decompress,
  [AC_CHECK_HEADER(jpeglib.h,
    jpeg_ok=yes,
    jpeg_ok=no)],
  AC_MSG_WARN(*** (jpeg library not found) ***), -lm)

if test "$jpeg_ok" = yes; then
  JPEG='jpeg'; LIBJPEG='-ljpeg'
  AC_DEFINE(HAVE_LIBJPEG)
else
 AC_MSG_WARN(*** JPEG loader will not be built ***)
fi
</programlisting>

      </foil>

      <foil id="config-args">
         <title>Argument Parsing</title>

         <para>By default, &ac; understands a large number of different
         arguments. </para>

         <para>Users can always set things such as </para>

         <itemizedlist>
            <listitem>
               <para>Install prefixes for each component (binaries, headers,
               ...). </para>
            </listitem>
            <listitem>
               <para>Program name transformations. </para>
            </listitem>
            <listitem>
               <para>Host and target platforms (for cross-compiling). </para>
            </listitem>
         </itemizedlist>

      </foil>

      <foil id="adding-args">
         <title>Custom Arguments</title>

         <para>It is also possible to add your own arguments... </para>

<programlisting>
AC_ARG_WITH(html-dir, [  --with-html-dir=PATH path to installed docs ])

if test "x$with_html_dir" = "x" ; then
  HTML_DIR='${datadir}/gtk-doc/html'
else
  HTML_DIR=$with_html_dir
fi
</programlisting>

         <para>... and to have features which can be enabled and disabled.
         </para>

<programlisting>
AC_ARG_ENABLE(gtk-doc, [  --enable-gtk-doc  
                         Use gtk-doc to build documentation [default=auto]],
   enable_gtk_doc="$enableval", enable_gtk_doc=auto)

if test x$enable_gtk_doc = xauto ; then
  if test x$GTKDOC = xtrue ; then
    enable_gtk_doc=yes
  else
    enable_gtk_doc=no
  fi
fi
</programlisting>

      </foil>

      <foil id="substituting-variables">
         <title>Variable Substitution</title>

         <para>Configuring all these variables in
         <filename>configure.in</filename> is one thing. But they have to
         passed to the <filename>Makefile</filename> ultimately. </para>

         <para>This is done using <literal>AC_SUBST</literal>. </para>

<programlisting>
HTML_DIR=/tmp/html

AC_SUBST(HMTL_DIR)
</programlisting>

         <para>This fragment will replace all occurences of
         <literal>@HTML_DIR@</literal> in any <filename>Makefile.am</filename>
         with the value of the <literal>HTML_DIR</literal> variable that is
         computed in the configure script. </para>

         <note>
            <para>If a variable's contents are empty when it is substituted,
            the empty string will be used as the value. This can be used to
            effect conditional compilation, amongst other things. </para>
         </note>

      </foil>

      <foil id="subst-in-action">
         <title>An Example Of AC_SUBST In Practice</title>

         <para>To see what is really going on, we need to look at
         <filename>configure.in</filename> and <filename>Makefile.am</filename>
         in tandem. </para>

         <para>In <filename>configure.in</filename>...

<programlisting>
PKG_CHECK_MODULES(LIBGLADE, libxml-2.0 >= 2.4.10 
                            atk >= 1.0.0
                            gtk+-2.0 >= 2.0.0)
AC_SUBST(LIBGLADE_LIBS)
AC_SUBST(LIBGLADE_CFLAGS)
</programlisting>

         and in <filename>Makefile.am</filename>. </para>

<programlisting>
INCLUDES = @LIBGLADE_CFLAGS@
libglade_LDADD = @LIBGLADE_LIBS@
</programlisting>

         <para>Since &ac; defines Makefile variables for each substitution that
         it does, the last example could also be written as</para>

<programlisting>
INCLUDES = $(LIBGLADE_CFLAGS)
libglade_LDADD = $(LIBGLADE_LIBS)
</programlisting>

      </foil>

      <foil id="third-party">
         <title>Third Party Macros</title>

         <itemizedlist>
            <listitem>
               <para>In the last example, we used a macro called
               <literal>PKG_CHECK_MODULES</literal>. This is not packaged with
               autoconf by default. </para>
            </listitem>
            <listitem>
               <para>Instead, the <application>pkg-config</application>
               application provides this macro when it is installed and
               installs the macro in (typically)
               <filename>/usr/share/aclocal/</filename>. </para>
            </listitem>
            <listitem>
               <para>This directory is searched when
               <filename>aclocal</filename> is run as part of
               <filename>autogen.sh</filename> and all of the relevant macros
               that are need by <filename>configure.in</filename> are pulled
               into <filename>aclocal.m4</filename>. </para>
            </listitem>
         </itemizedlist>

      </foil>

      <foil id="example-macro">
         <title>An Example Macro</title>

         <para>Macros are not trivial to write, since they need to extract
         their information without interfering with the external system. They
         also need to account for many possibilities. </para>

<programlisting>
AC_DEFUN([JH_PYTHON_CHECK],
[AC_CACHE_VAL([jh_cv_path_python],
[if test "x$PYTHON" != x; then
  jh_cv_path_python="$PYTHON"
else
    dnl python code to check for required python
    jh_python_check='
    import sys, string
    if sys.version_info &lt; $1:
        sys.exit(1)
    $2
    sys.exit(0)'
    dnl
    
      for jh_python in python python2 python2.3 python2.2 python2.1 python2.0;
      do
        jh_save_IFS=$IFS; IFS=$PATH_SEPARATOR
        jh_dummy="$PATH"
        for jh_dir in $jh_dummy; do
    ...
        done
        test -n "$jh_cv_path_python" &amp;&amp; break
      done
fi
])
</programlisting>

      </foil>

   </foilgroup>

   <foil id="questions-n-comments">
      <title>Questions? Comments?</title>

      <para>Slides will be available online later this week. I will publish the
      location at <ulink url="http://www.advogato.org/person/malcolm/"/>, or
      just ask me on Thursday or Friday. </para>

   </foil>

</slides>
	
