The example here shows the autoconfing of the adam library, chosen simply because it's relatively simple.
Make a directory to hold the package, and add it to the repository
% pwd <cvs-checkout>/libraries/pcs % mkdir adam % cvs add adam Directory /cvs/libraries/pcs/adam added to the repository % cd adam
Get the complete set of source files, and check them in to
the repository. This means unpacking all the files in
adam_source.tar
, which you can find in
/star/sources/pcs/adam
(as it happens).
In this case, the adam_source.tar
distribution
tarball is a suitable set of sources. This is not always
true, since some Starlink distributions -- especially some of
the larger libraries and applications -- do quite elaborate
processing of their sources in the process of creating this
`source' tarball; in these cases, you should attempt to obtain
a more fundamental set of sources from the package's developer
(if that is not you).
The ideal source for new code is a CVS or RCS repository. A CVS repository is easy to import -- you just tar it up and unpack it into the correct place within the Starlink repository. An RCS repository is barely harder, with the only difference being that you have to create the Starlink repository directory structure by hand, and copy the RCS files into place within it. The only gotcha with this route is that you must make sure that the permissions are correct on the resulting repository: you must make sure that everyone who should have any access to the repository can read and write each of the directories.
CVS repository access is controlled by groups (at least
when the repository is shared), and so each directory within
the repository must have a suitable group ownership, with
group-write permissions; each directory must also have the
setgid bit set, so that any directories created within it
inherit its gid. Make sure you check this as soon as you
put the repository in place, or else everyone will have
problems with the repository. Within the
Starlink repository in
particular, all participants are part of the
cvs
group. In short, you can set the correct
permissions on an imported directory foo
with
the commands
This sets the group-owner of each directory to be% find foo -type d | xargs chgrp cvs % find foo -type d | xargs chmod g+sw
cvs
, and sets the group-write and set-group-id
bits in the permissions mask (don't tinker with file
permissions, since these affect the permissions of the
checked out files). You need not worry about file or
directory ownership, since this always ends up being the
last person who committed a file. Note: The instructions
here are based on observation of CVS repositories; the
actual requirements don't seem to be formally documented
anywhere.Add all of the source files, including files like
the mk
script and the old makefile
,
which we are about to remove. Tag this initial import with a
tag <component>-initial-import
, so
that it is possible to recover this old-style distribution if
necessary. As mentioned above, it is not
always completely clear what constitutes the old-style source
set: so don't do this step mechanically, use your judgement,
and above all avoid losing information. Note also that some
of the infrastructure libraries were added before we settled
on this particular tagging practice, and so lack such an
initial tag.
In this present case, the adam_source.tar
file includes a Fortran include file containing error codes,
adam_err
; there are two problems with this.
Firstly, the filename should be uppercase: the file is
generally specified within the program in uppercase, and it
should appear thus on the filesystem. The traditional
makefile works around this by creating a link from
adam_err
to ADAM_ERR
, but this won't
work (and indeed will fail messily) on a case-insensitive
filesystem like HFS+, used on OS X.
The second problem is that this is a generated file, though
the source is not distributed, is probably misplaced, and in any
case the generation was probably done on a VAX a decade ago.
All is not lost, however. The functionality of the VAX
`message' utility is duplicated in the application
messgen, in a component of the same name, along with
an application cremsg which constructs a source file
from this message file. Thus it is neither
adam_err
nor ADAM_ERR
which we
should check in, but the source file adam_err.msg
which we reconstruct using cremsg. Thus with error
files, it is the (probably reconstructed) .msg
file which should be checked in to the repository, and
not the _err
, _err.h
or
fac_xxx_err
files which you may have found in
the old-style distribution.
The file adam_defns
is similar, but this is
genuinely a source file, so we need do nothing more elaborate
than rename it to ADAM_DEFNS
, then add it to the
repository and remove the original lowercased version. Many
packages have one or two xxx_par
files,
and these should be similarly renamed to XXX_PAR
.
% tar xf /star/sources/pcs/adam/adam_source.tar % chmod +x adam_link_adam % cremsg adam_err % cvs add *.f mk makefile adam_link_adam adam_defns.h adam_defns adam_err.msg ... cvs server: scheduling file `adam_err.msg' for addition cvs server: use 'cvs commit' to add these files permanently % cvs commit -m "Initial import" % cvs tag adam-initial-import % mv adam_defns ADAM_DEFNS % cvs remove adam_defns % cvs add ADAM_DEFNS % rm mk makefile % cvs remove mk makefile
Note that CVS preserves
access modes when it
stores files, so we should make sure that the script
adam_link_adam
is executable before
checking it in, and we need not bother to make it executable
as part of the build process. On the other hand, scripts
which are substituted by configure do need to be made
executable explicitly, which you do by a variant of the
AC_CONFIG_FILES
macro. The macro invocation
substitutesAC_CONFIG_FILES(foo, [chmod +x foo])
foo
from source file
foo.in
and then makes it executable. Note that
the sequence
would not work, since this is one of the cases where autoconf macros do not simply expand inline to shell code. For further discussion, see the section Performing Configuration Actions in the autoconf manual.AC_CONFIG_FILES(foo) chmod +x foo
Create files configure.ac
,
Makefile.am
and component.xml.in
by
copying the templates in the starconf buildsupport directory
(starconf --show buildsupportdata
); the fields in
the component.xml.in
file are discussed in Section 2.2.4. If you have an editor that can use it,
you might also want to create a link to the DTD used for the
component.xml
file, which is in the same
directory. Edit these files as appropriate, using information
in the original Starlink makefile for guidance (so it's
useful to keep a copy of the original makefile
handy,
rather than simply deleting it as illustrated above). Then
check the files in.
What edits should you make?
The adam Makefile.am
file looks as follows:
Four out of six of these variable declarations are variables meaningful to automake (see Section 2.1.2), and the other two are simply copied from the originalbin_SCRIPTS = adam_link_adam lib_LTLIBRARIES = libadam_adam.la libadam_adam_la_SOURCES = $(PUBLIC_INCLUDES) $(F_ROUTINES) include_HEADERS = $(PUBLIC_INCLUDES) PUBLIC_INCLUDES = ADAM_ERR ADAM_DEFNS adam_defns.h F_ROUTINES = \ adm_acknow.f adm_getreply.f adm_getreplyt.f adm_path.f \ adm_prcnam.f adm_receive.f adm_reply.f adm_send.f \ adm_sendonly.f adm_sendt.f adm_trigger.f
makefile
.The adam configure.ac
looks like this:
The first five lines are straightforward boilerplate (see Section 2.1.1). The next three find a Fortran compiler, declare that we want to use libtool to build our libraries, and finally that we wish the symbols in that library to be of the sort that the CNF package is able to handle (see Appendix A.15). The `FC' autoconf macros will search for a Fortran compiler by looking for a f95 compiler before looking for a f77 compiler; if you know or discover this is inappropriate, then you can constrain the Fortran dialect thatAC_INIT(adam, 3.0, ussc@star.rl.ac.uk) AC_PREREQ(2.50) AM_INIT_AUTOMAKE(1.8.2-starlink) AC_CONFIG_SRCDIR([ADAM_DEFNS]) STAR_DEFAULTS AC_PROG_FC AC_PROG_LIBTOOL STAR_CNF_COMPATIBLE_SYMBOLS STAR_DECLARE_DEPENDENCIES(build, [sae messys]) STAR_DECLARE_DEPENDENCIES(link, [chr psx ems messys]) dnl There is no .msg file in this directory. The ADAM_ERR file dnl contains only a single definition, of the parameter ADAM__OK. AC_CONFIG_FILES(Makefile component.xml) AC_OUTPUT
AC_PROG_FC
will look
for by giving a value for
its optional dialect argument. Macro
AC_PROG_FC
is not yet documented in the
autoconf manual, but see Appendix B.After that, we declare the dependencies. The dependencies
you work out by any and all means you can. For a library, the set
of `build' dependencies is determined by the set of
components which supply files which the code here includes.
Grepping for all the Fortran INCLUDE
statements
and all the C #include
directives is a good
start. For link dependencies, grepping for
CALL
lines is useful for Fortran, and grepping
for
will probably be handy. In fact, the script= *\([A-Za-z][A-Za-z]*__*[A-Za-z][A-Za-z]*\) *(.*
should give you the raw material for most of the dependencies you need. It doesn't really matter too much if you get this wrong -- you might cause something to be built slightly later than it might be in the top-level bootstrap, might cause some eventual user to have to download one package more than they have to, or might create a circular dependency and break the nightly build, in which case you'll find out soon enough.#! /bin/sh - sed -n \ -e 's/^ *\(INCLUDE\|include\) *'\(.*\)'.*/_ \2/p' \ -e 's/^ *\(CALL\|call\) *\([A-Za-z]*_[A-Za-z]*\).*/\2/p' \ -e 's/.*= *\([A-Za-z][A-Za-z]*__*[A-Za-z][A-Za-z]*\) *(.*/\1/p' \ ${1+"$@"} | \ sort | \ uniq
See Appendix A.16 for the description of the various types of dependencies you can specify here.
By the way, remember (because everyone forgets) that there
are no components err
and msg
:
all of the err_
and msg_
functions
are in the mers
component.
The next couple of lines tells you that we lied
outrageously, above, when we were talking about
.msg
files. Though the remarks there are true
enough in general, the ADAM_ERR
file is special,
and doesn't come from any .msg
file. This is
surprising enough that it's worth making a remark to this
effect in the configure.ac
file.
Finally, we list the files that should be configured. Essentially all starconf-style configure files should have at least these two files mentioned here.
Now run starconf. As described in Section 2.2, this adds some required files, and checks that the directory looks right. It will look something like this:
% starconf starconf-validate: the following files are required but do not exist: bootstrap starconf-validate: the following files should be checked in, but aren't Makefile.am configure.ac bootstrap component.xml.in component.xml Configuring with STARCONF_DEFAULT_STARLINK=/export3/sun Configuring with STARCONF_DEFAULT_PREFIX=/export3/sun Creating bootstrap
That complained that the file bootstrap wasn't present, and then went on to install one for you; it listed a number of files which should be checked in; and it added a bootstrap script. The starconf application actually does the checking by running the starconf-validate script, which you can run yourself independently if you wish.
Now you have a bootstrap file, so run it:
The bootstrap script always re-runs starconf if it can, so this reminds you that you still haven't checked those files in. It also runs autoreconf (Section 2.1.4) for you, installing the helper files that requires, and constructing% ./bootstrap starconf-validate: the following files should be checked in, but aren't Makefile.am configure.ac bootstrap component.xml.in component.xml Configuring with STARCONF_DEFAULT_STARLINK=/export3/sun Configuring with STARCONF_DEFAULT_PREFIX=/export3/sun File bootstrap already exists, not overwriting autoreconf --install --symlink configure.ac: installing `./install-sh' configure.ac: installing `./missing'
configure
from
configure.ac
and Makefile.in
from
configure.ac
and Makefile.am
.Now, finally, you can try ./configure
and
make
. That might just work.
Iterate until success.
When the code is working, you will might want to add it to the
set of components which are explicitly built. To do
this, add it to the ALL_TARGETS
variable in the
top-level Makefile.in
. Next, go to the parent
directory of the directory you have just added: the
configure.ac
file there will almost certainly
have a skeleton configure.ac
which includes a
AC_CONFIG_SUBDIRS
line, to which you should add
your newly working directory.