"The good news about computers is that they do what you tell them to do. The bad news is that they do what you tell them to do."
-- unsure; often attributed without source to information philosopher Ted Nelson
Every package should have a text file "INSTALL" in its top-level directory describing how to install the package.
Every package should also provide a Makefile in its top-level directory with at least the targets "all" to compile all programs and libraries, "install" to build and install all programs and other files needed for the package to operate, and "clean" to remove all temporary files (like .o's) from the package directory.
Every package that has C or C++ sources should provide a file config.h in its top-level directory defining PACKAGE and VERSION. For example:
#define PACKAGE "hello" #define VERSION "1.0.0"
The automake and autoconf tools described below do all this automatically.
The GNU tools automake and autoconf provide a powerful capability to enable a software package to be installed on virtually any Unix-like operating system. Some of their benefits:
The tools do not have to be installed on the user's system, only on the developer's system. (The developer's system also needs Perl, GNU make and GNU m4.)
They automatically determine the installing system's capabilities without requiring the user to know technical details of what the OS supports.
They provide a convenient, user-friendly method for setting installation options such as where to install programs and any compile-time configuration the package needs.
They are licensed such that a package can use them without any restrictions on how the package itself can be licensed.
This is much preferable to the practice of requiring the user to hand-edit a header file to define symbols appropriate to the local system, or using different Makefiles for different systems.
The process works like this:
The developer creates files "configure.in", "acconfig.h" and "stamp-h.in" in the package's top-level directory, and "Makefile.am" files in each directory that needs a Makefile.
The developer runs aclocal to generate an "aclocal.m4" file, autoconf to create a shell script "configure", autoheader to create a file "config.h.in", and automake to create "Makefile.in" files.
The user installing the package runs the configure script, which determines the local system capabilities, then generates appropriate Makefiles and a config.h header file which are used to build the package.
An initial "configure.in" should look something like this:
AC_INIT(src/main.c) AM_INIT_AUTOMAKE(hello, 0.1.0) AM_CONFIG_HEADER(config.h) AC_OUTPUT([ Makefile src/Makefile doc/Makefile ])
The file name in the first line (src/main.c) is the name of any file in the package. It is simply used to make sure configure is called from the right place. Edit the AM_INIT_AUTOMAKE line to specify your package name (or a filename-safe equivalent) and version number. The AC_OUTPUT section at the end will specify which files will be created by autoconf, and generally will be a Makefile in each subdirectory that needs one. Each of the files in AC_OUTPUT requires a ".in" template (typically created from Makefile.am files by automake).
See the autoconf and automake documentation for macros that can be defined between "AM_CONFIG_HEADER" and "AC_OUTPUT". There are macros to check for the existence, location and behavior of commonly used programs, libraries, header files, library functions, and more. The list of possible macros gives a good idea of what features vary from system to system. For example, "AC_PROG_CC" is needed if the package includes any C source code, and "AC_PROG_CXX" is needed for C++.
acconfig.h will contain a list of symbols that your source code might want to use. Initially, it can be empty, so create it with something like "touch acconfig.h".
stamp-h.in is just used as a timestamp, so it can be empty. Create it initially with something like "touch stamp-h.in".
The developer should create a Makefile.am file in each directory that requires a Makefile (generally, directories containing source code and/or files that need to be distributed with the package).
Every Makefile.am should begin with the comment:
## Process this file with automake to produce Makefile.in
Makefile.am files in directories containing subdirectories should have a "SUBDIRS" macro. For example, the top-level Makefile.am for hello might look something like this:
## Process this file with automake to produce Makefile.in SUBDIRS = doc libhello src
Makefile.am files in source code directories should additionally specify everything that needs to be installed, using the "bin_PROGRAMS" macro for most compiled programs and the "bin_SCRIPTS" macro for most interpreted scripts. Each program should specify its source code and header files with a "*_SOURCES" macro. For example, the hello package's src/Makefile.am might look like this:
## Process this file with automake to produce Makefile.in bin_PROGRAMS = hello hello_SOURCES = main.c sub.c hellomain.h hello_INCLUDES = -I../libhello
There are special macros for programs intended to be run by system administrators or by other programs, for shell scripts, for man pages, for data files, and a few other categories. Essentially, any file that will be included with the distribution must be specified in some macro. Read the automake documentation for details.
After you've defined a configure.in, and whenever it changes,
run aclocal to regenerate the "aclocal.m4" file and
run autoconf to regenerate the "configure" script.
After you've defined a acconfig.h, and whenever it changes, run
autoheader to regenerate the "config.h.in" file.
After you've defined Makefile.am files, and whenever they change,
run automake --foreign --add-missing from the top-level
directory to regenerate the
"Makefile.in" files in all subdirectories. The "--foreign" option
turns off certain GNU requirements, such as requiring an AUTHORS file.
The "--add-missing" option copies certain support files to your package.
Generally, this is not a problem, but check the files to see if their
licenses impose any restrictions on your package. For example, GPL'd
files like the script named "missing" require that your package also
be GPL'd; if you don't want that, you'll have to replace such files.
Finally, if any of the above changes, re-run the "configure" script to regenerate the config.h and Makefiles for the development system.
Once everything is set up, the generated Makefiles will automatically run the tools when needed, so you don't have to remember any of the above.
Sometimes, a package requires or can optionally use other software packages which are already installed. Autoconf provides an easy method for configuring this behavior when the package is installed.
From the installer's perspective, the installer gives "--with-XXX" or "--without-XXX" arguments to "configure." For example, if your package can optionally use the "foo" package, the installer might run:
./configure --with-foo
An optional argument can be given to "--with-XXX." "--with-foo" is equivalent to "--with-foo=yes" and "--without-foo" is equivalent to "--with-foo=no".
To use a "--with" option, the developer adds an AC_ARG_WITH macro to "configure.in". An example:
dnl Configure support for foo. AC_ARG_WITH(foo, [ --with-foo use foo for freeing ornery objects --without-foo do not use foo (default)], opt_foo=$withval, opt_foo=no ) if test $opt_foo = "yes"; then AC_DEFINE(WITH_FOO, 1, Configure support for foo) fi
The second AC_ARG_WITH argument (enclosed in brackets) is a help string to be printed by "./configure --help" (the columns should line up as above). "opt_foo=no" says the default value is "no". The AC_DEFINE will #define the preprocessor macro WITH_FOO in config.h. The package's source files can then wrap foo-specific code with "#ifdef WITH_FOO" and "#endif".
In many cases of this sort, the package will need to find both the header files and the libraries for the other package. To allow the installer to specify a nonstandard location for these, two additional "--with-XXX" options can be used, "--with-XXX-includes" and "--with-XXX-libs". The installer can then specify something like:
./configure --with-foo --with-foo-includes=/home/me/foo/include --with-foo-libs=/home/me/foo/lib
With the two additional options, configure.in might look like this:
AC_ARG_WITH(foo,
[ --with-foo use foo for freeing ornery objects
--without-foo do not use foo (default)],
opt_foo=$withval, opt_foo=no
)
AC_ARG_WITH(foo-includes,
[ --with-foo-includes=DIR where to find foo header files],
foo_includes="-I$withval",
foo_includes='-I${prefix}/include/'
)
AC_ARG_WITH(foo-libs,
[ --with-foo-libs=DIR where to find foo libraries],
foo_libs="-L$withval -lfoo",
foo_libs='-L${prefix}/lib/ -lfoo'
)
if test $opt_foo = "no"; then
foo_includes=''
foo_libs=''
else
AC_DEFINE(WITH_FOO, 1, Configure support for foo)
fi
AC_SUBST(foo_includes)
AC_SUBST(foo_libs)
This will set variables for use in all Makefile templates. For source files that need to use foo, edit the Makefile.am in that directory and add @foo_includes@ to the INCLUDES macro, and @foo_libs@ to the LIBS macro.
All files should be installed explicitly specifying their permissions. (Autoconf and automake will use reasonable permissions for most files.)