How to check a library into Gnome CVS

Recent Changes

11 Nov 1998: Some changes to CVS practice. The standard autogen.sh script now passes the --add-missing option, so the files that are added are not kept in the CVS repository. You'll want to update your .cvsignore file for sure, and also autogen.sh if you're not using macros. Thanks also to Joel Becker for changes to autogen.sh to make it more AIX-friendly.

30 Sep 1998: Added a little bit about gnome-libs.

9 Sep 1998: Added a blurb from miguel about macro-based autogen.sh scripts.

Please also see Importing a New Project by Tom Tromey for tips on importing into Gnome CVS.

Checking a library into Gnome CVS properly can be quite intimidating. It requires mastery (or at least competence) with a number of complex interacting software tools, and many of which are relatively new and not well documented. In particular, detailed knowledge of CVS, autoconf, automake, and libtool are needed. It also helps to be handy with RCS (which is the basis for CVS), make (which is the basis for the autoconfiguration stuff), and m4 (which is the language the autoconfiguration tools are written in).

Nonetheless, when checked in properly, these tools are immensely helpful in maintaining a portable code base in such a way that it can easily be developed by the Gnome community.

This document attempts to help navigate that maze, highlighting the traps that are so easy to fall into. It assumes a basic familiarity with Gnome CVS, and is not a replacement for the reference manuals for each piece of software.

Overview

The goal of checking in a library is to end up with a set of autoconfiguration scripts and a CVS configuration that "just works". In particular, running the "./autogen.sh" script should generate the needed Makefiles and other files for development without error, running "make distcheck" should generate a usable distribution, and within that distribution, "./confgure" followed by "make" should build the library. Similarly, "make install" should install the library in the right places.

The main files you need to add are:

You'll also want to maintain ChangeLog, NEWS, and README files.

Here's a broad outline of the way the configuration tools work, in the standard sequence aclocal; autoheader; automake; autoconf; configure; make.

Your .cvsignore file

The purpose of the .cvsignore file is to identify to CVS all files automatically generated by the configuration scripts, so that they won't be stored in the repository (it would be wrong, as well as inefficient, to store platform dependent files in the platform-independent repository). CVS is configured by default to ignore object and backup files, but it doesn't know about heavily autoconfigured packages.

Your .cvsignore should start with these entries:

*.lo
*.la
.deps
.libs
INSTALL
Makefile
Makefile.in
aclocal.m4
confdefs.h
config.cache
config.guess
config.h
config.h.in
config.log
config.status
config.sub
configure
install-sh
libtool
ltconfig
ltmain.sh
missing
mkinstalldirs
stamp-h
stamp-h.in

In addition, it should list all executables, such as test programs for the library.

Your configure.in file

We'll walk through a skeletal configure.in file here. These files can become quite large and complex - for example, as of September 1998, the Gimp's configure.in was over 600 lines. Please refer to the autoconf documentation for more details.

AC_INIT(libfoo.h)
Here, libfoo.h should be replaced with a header file included in your library. This just initializes autoconf.

AM_CONFIG_HEADER(config.h)
This configures autoheader to generate a config.h file.

AM_INIT_AUTOMAKE(libfoo,0.0.0)
This tells automake the name of your package and the version number. Please conform to standard Gnu version numbers. The triple is called "major", "minor", and "micro". Bump the major version every time there is an interface-altering rework of the library. The minor version should alternate between even (for stable releases) and odd (for development releases). Finally, bump the micro version every time you do a release of the software.

AC_PROG_CC
AC_PROG_CPP
AM_PROG_LIBTOOL

These set up the standard tools of a C compiler and libtool. The CPP line sets up the C preprocessor, which is needed for some library tests.

AM_MAINTAINER_MODE
This enables a maintainer mode (which is only actually turned on if --enable-maintainer-mode is passed as an argument to ./configure). I'm not sure exactly what good this does, but some people seem to like it, so it should probably be standard in packages checked into Gnome CVS.

Here in configure.in is where tests for libraries and architecture dependent features would go. Writing these tests is beyond the scope of this document. To learn more, refer to the autoconf documentation, or see configure.in files from some existing Gnome packages.

AC_OUTPUT(Makefile)
This causes the autoconfiguration scripts to generate a Makefile.

Incidentally, comments in configure.in begin with 'dnl '. Don't ask me why.

Your Makefile.am file

Again, we'll walk through a simple example.

noinst_PROGRAMS = testfoo
This lists programs that will get built but not installed. For a library, this generally covers some test programs.

lib_LTLIBRARIES = libfoo.la
This tells libtool which libraries to install in the standard lib location (usually /usr/local/lib). Note that the .la extension represents libtool files that reference the actual libraries.

libfoo_la_SOURCES = \
foo.c \
foo_private.h

This lists the source files used to build the library, including any private headers (headers that get installed in the include directory are listed next). Make sure not to leave a backslash on the last line.

libfooincdir = $(includedir)/libfoo
libfooinc_HEADERS = \
libfoo.h

Here, you list all header files that will get installed. This setup creates a subdirectory for include files in this library, which is standard Gnome practice.

One minor problem here is that make uninstall doesn't delete the new directory, just leaves it empty.

EXTRA_DIST = foo-data-file
If your package has extra files that don't get compiled (including little extra READMEs, etc.), here is the place to put them.

DEPS = $(top_builddir)/libfoo.la
LDADDS = $(top_builddir)/libfoo.la

These are variable settings needed to build your test program with the library.

testfoo_SOURCES=testfoo.c
testfoo_LDFLAGS =
testfoo_DEPENDENCIES = $(DEPS)
testfoo_LDADD= $(LDADDS)

And these are the variables needed to actually build the test program. This is also where you might add extra libraries (for example, -lm).

tests: testfoo
Here, you list the test programs you want build by a "make tests". You can also add commands to actually run tests (assuming that this is appropriate for your library). The syntax here is basically standard Makefile.

It's a good idea to check your Makefile.am for correctness by running a "make distcheck". A very common mistake is to forget to list .h files in Makefile.am, and this step will catch that.

Your autogen.sh file

Here's the one I use:

#!/bin/sh
# Run this to generate all the initial makefiles, etc.
# This was lifted from the Gimp, and adapted slightly by
# Raph Levien .

DIE=0

PROJECT=LibFoo

(autoconf --version) < /dev/null > /dev/null 2>&1 || {
	echo
	echo "You must have autoconf installed to compile $PROJECT."
	echo "Download the appropriate package for your distribution,"
	echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
	DIE=1
}

# Do we really need libtool?
(libtool --version) < /dev/null > /dev/null 2>&1 || {
	echo
	echo "You must have libtool installed to compile $PROJECT."
	echo "Get ftp://ftp.gnu.org/pub/gnu/libtool-1.2.tar.gz"
	echo "(or a newer version if it is available)"
	DIE=1
}

(automake --version) < /dev/null > /dev/null 2>&1 || {
	echo
	echo "You must have automake installed to compile $PROJECT."
	echo "Get ftp://ftp.gnu.org/pub/gnu/automake-1.3.tar.gz"
	echo "(or a newer version if it is available)"
	DIE=1
}

if test "$DIE" -eq 1; then
	exit 1
fi

if test -z "$*"; then
	echo "I am going to run ./configure with no arguments - if you wish "
        echo "to pass any to it, please specify them on the $0 command line."
fi

case $CC in
*xlc | *xlc\ * | *lcc | *lcc\ *) am_opt=--include-deps;;
esac

for dir in .
do 
  echo processing $dir
  (cd $dir; \
  aclocalinclude="$ACLOCAL_FLAGS"; \
  aclocal $aclocalinclude; \
  autoheader; automake --add-missing --gnu $am_opt; autoconf)
done

./configure "$@"

echo 
echo "Now type 'make' to compile $PROJECT."

In general, you will need to customize the line that sets PROJECT, but otherwise it should be ok.

This autogen.sh is very similar to most of the ones in Gnome CVS, but differs in a couple of ways. First, I've moved autoheader from after autoconf to before automake. I believe this is more correct. Many existing packages get around the error message by including a config.h.in file in the repository. I do not believe this is correct.

Also, some packages (notably Gtk+) use a separate macros directory to store a standardized autogen.sh. This approach is reasonable, but seems to me a little excessive to avoid a one-line customization. It's your library, your call.

Make sure to chmod 755 autogen.sh.

Generally, you have to rerun ./autogen.sh every time you change the structure of the package, for example adding a new source file. It would be nice if the autoconfiguration tools were smart enough to automatically rerun themselves when needed, but they're not.

9 Sep 1998: Miguel de Icaza sent in this blurb, recommending the use of the macro-based autogen.sh as opposed to rolling your own.

GNOME shares a number of directories that are part of the gnome-support module: these are the internationalization routines, and the macros directory where various detection autoconf macros are found as well as the main autogen.sh body (the intl and the macros directories respectively)

There is no need for your package to have a copy of those directories, you should include them virtually, this is very simple to do, just checkout the CVSROOT module from the CVS and add a line to the file CVSROOT/modules that looks like this:

mylibrary mylibrary ¯os &intl

Miguel.

Adding the required files

You can add most of the required files with an "automake -a". However, you'll still need to add NEWS, README, AUTHORS, and ChangeLog yourself. You can just touch these files, but it's probably better to say something meaningful.

I get a warning that "./ltconfig" is not found, but it seems to be safely ignorable - the file does get added later. In any case, running "automake -a" a second time makes it go away.

By default, "automake -a" installs the GPL in the file COPYING. Since this is a library, the LGPL is probably more appropriate. In fact,

From emacs, you can use "Ctrl-x 4 a" as a convenient shortcut to add a ChangeLog entry. The Gnome standard is "old-style" ChangeLog date stamps. You can customize this by "M-x customize", then following the links to Programming, Tools, Change Log, Add Log Time Format. Perversely, the emacs customize uses [Go to Group] to represent a hyperlink, while blue underlined text is merely for emphasis. You might also want to customize your mailing address, as emacs tends to default to your machine name.

Please be in the habit of maintaining a good ChangeLog. It's the primary form of communication to other developers what's happening in the codebase.

Gnome-config

You may be interested in making your library conform to the gnome-config guidelines. Basically, you need to create a fooConf.sh.in file that looks like this:

#
# Configuration file for using the gnome-foo library
#
FOO_LIBDIR="@FOO_LIBDIR@"
FOO_LIBS="@FOO_LIBS@"
FOO_INCLUDEDIR="@FOO_INCLUDEDIR@"

And you also need to add this to your Makefile.am:

## We create fooConf.sh here and not from configure because we want
## to get the paths expanded correctly.  Macros like srcdir are given
## the value NONE in configure if the user doesn't specify them (this
## is an autoconf feature, not a bug).

fooConf.sh: fooConf.sh.in Makefile
## Use sed and then mv to avoid problems if the user interrupts.
	sed -e 's?\@FOO_LIBDIR\@?$(FOO_LIBDIR)?g' \
	    -e 's?\@FOO_INCLUDEDIR\@?$(FOO_INCLUDEDIR)?g' \
	    -e 's?\@FOO_LIBS\@?$(FOO_LIBS)?g' \
	      < $(srcdir)/fooConf.sh.in > fooConf.tmp \
	  && mv fooConf.tmp fooConf.sh

Also make sure to add fooConf.sh to your .cvsignore, as it is an autogenerated file.

The result of all this is to install a fooConf.sh file in /usr/local/lib (assuming the prefix is /usr/local), which basically contains the locations of the library and include files, as well some info on dependencies on other libs.

The upshot is that gnome-config --libs foo will now print out the command line options needed to link with your lib. Similarly, --cflags will print the options needed to compile. Life will become much easier for potential users of your library.

Checking it all in

Ok, you've created your configure.in and Makefile.am files, and added all the other required files. Now it's time to check it in to CVS.

Start by making sure you have a good CVS setup. I use ~/cvs as my toplevel CVS directory.

Before checking in, try to make sure you have a good .cvsignore file together. In particular, if it's missing or bad, you're likely to check in the .deps subdirectory by mistake. This really messes things up, and seems to be hard to fix up (in the past, people with shell access on the CVS server have nuked the dir by hand).

Cd to the directory where your package lives (not under ~/cvs). Make sure the directory is clean of any extra files (such as a .tar.gz left over from a make distcheck). Set the environment variable CVSROOT to the contents of your ~/cvs/CVS/Root file. Run:

cvs import libfoo HEAD INITIAL

All further work on the package should be done from cvs. Go to your ~/cvs directory and do a "cvs -z3 co libfoo".

The cvs import command skips over symbolic links, which is a problem because a lot of the required files are installed by "automake -a" as symbolic links. So, from the checked out module directory, run:

automake -a
cvs add missing install-sh config.guess mkinstalldirs config.sub ltconfig ltmain.sh INSTALL

You should add COPYING too if you decided to stick with the GPL. Finally, you need to do a cvs commit before these files are accessible to others.

Test the commit by trying to check it out and compile it from another machine.

Last words

Many thanks to Manish Singh for patient help with CVS and autoconfiguration advice.

Are you still confused? The #gimp irc channel is a good place to ask for advice. However, if it's something this document should cover, let me know.

Happy Gnome development!

levien.com Gnome home