Chapter 3
Building applications and libraries

 3.1 The top-level Makefile
 3.2 Bootstrapping and building the entire tree
 3.3 Building a single component
 3.4 Building monoliths
 3.5 Bootstrapping without building: configuring starconf and the autotools

This section applies only to building code which has been checked out of the CVS repository. It does not apply to building a distribution tarball: that process is nothing more than the usual:

  % ./configure
  % make
  % make install

with the usual options for the ./configure script, of which the most important is –prefix to control the installation location of the code. The default location is typically /star, though a particular distribution might have a different value (see ./configure –help for more details).

Recall that the make install, above, installs a manifest listing the files actually installed, in the directory /star/manifests (depending on the value of –prefix, which defaults to the value shown by ./starconf.status –show STARCONF_DEFAULT_PREFIX).

Most users of this document will likely be concerned only with the details of building a particular component, and thus concerned primarily with Sec. 3.3.

Only rather few users are concerned with building the entire tree, for example for the nightly build: this is dealt with in Sec. 3.2.

Note: In all cases, you should not have the INSTALL environment variable defined. In old-style Starlink makefiles this indicated the install location; in the new-style build system, this location is indicated by the ‘prefix’ described above abd elsewhere, and the generated Makefiles take the INSTALL variable to be the name of a program to use to perform the actual installation.

3.1 The top-level Makefile

The important targets in the top-level makefile are:

make world
This target builds the whole tree, in an order which respects the dependencies between components. It builds all the targets listed in the variable ALL_TARGETS within the top-level Makefile.in. Those targets are install manifests, in the default manifest directory (/local/star/manifests in the example below), so that make world both builds and installs the entire software set.

The bootstrap that this is part of is described in more detail in the next section.

make <manifest-file>
As an alternative to make world, you may specify a single manifest file. This builds and installs the corresponding component, and all of its dependencies. Note that this does nothing if the given manifest file is up-to-date with respect to its dependencies on other manifest files. If you have just updated a component, then you can rebuild and reinstall it by deleting the component’s manifest file and remaking it.
make or make all
This recurses into each of the directories listed in AC_CONFIG_SUBDIRS within the top-level configure.ac, and invokes make all there. This target brings the tree up-to-date after a CVS update, but it does so without respecting the dependencies between components. This target is present for the sake of consistency, and as a convenience for bringing the local tree up-to-date after a CVS update, and you should not use it as a shorthand or alternative for make world above.
make clean
The targets clean, distclean and maintainer-clean simply recurse into the children and invoke the corresponding target there.
make install
This targets does nothing, and is also present largely for the sake of consistency. Depending on the context, you should use make world or, if you have just updated and rebuild a particular component, then either delete and remake its manifest file (as mentioned above), or go to the component’s directory and use make install.

Note that the building above presumes that all the required code is checked out of the repository – it does not handle the checkouts for you, and if you do not have a required component checked out, it will simply fail.

3.2 Bootstrapping and building the entire tree

If you wish to build the entire tree after a fresh checkout, you do so at the top level, using the ./bootstrap script and Makefile.in located there. Neither of these is a ‘standard’ one, as installed by starconf or Starlink automake.

These instructions are echoed in the file README in the top-level directory.

The complete procedure for a full build is as shown below, for an installation into the notional directory /local/star; explanations follow.

  1% cvs -d :ext:username@cvs.starlink.ac.uk:/cvs checkout .
  2% unset STARLINK INSTALL
  3% export STARCONF_DEFAULT_STARLINK=/local/star
  4% export STARCONF_DEFAULT_PREFIX=/local/star
  5% rm -Rf /local/star
  6% PATH=/local/star/bin:/local/star/buildsupport/bin:...??? # see note
  7% ./bootstrap
  ... a few harmless warnings, and miscellaneous other chatter
  ... takes quite a while
  8% make configure-deps
  ... builds some programs needed before configure
  9% ./configure -C
  ... mucho blah-blah-blah
  10% make world
  ... etc
  11% ls /local/star/manifests
  adam      automake  ems     hlp      messgen  par       sae   star2html  task
  ams       chr       fio     lex      messys   parsecon  sla   starconf
  atimer    cnf       hds     libtool  misc     pcs       sock  string
  autoconf  dtask     hdspar  mers     msp      psx       sst   subpar

Line 1: check out the entire collection from the repository. See Sec. 2.7.2 for hints on how to be more discriminating, which may be desirable, since not everything in the repository is controlled by this bootstrapping build, most notably the contents of the java directory.

Lines 2-4: unset the STARLINK and INSTALL variables, and set the two starconf variables as shown. For a whole-tree build, these two should have the same value, to ensure that the build uses only tools and libraries which have been built at an earlier point in the build. For fuller details of these variables, and more information about controlling the bootstrapping process, see Sec. 3.5. This example shows sh-style commands for manipulating the environment; you will of course use the csh-style setenv and unsetenv if you’re using that shell.

Also at this point you should review any other environment variables that might affect the build. For example, the variables F77, FC and CC will force the build system to use the specified compilers. In particular, the default IRAF installation sets the F77 variable to be a script which works happily in most cases, but which will not work with libtool, and will cause the build to fail with opaque error messages about being ‘unable to infer tagged configuration’. Unless you do wish to force certain compilers to be used, it is probably better to unset these variables before building the software. Try ./configure –help for a list of ‘some influential environment variables’, and Sec. 2.1.5 for more discussion of this issue.

Line 5: the directory where the components are to be installed can be empty, and need not exist at the start. It doesn’t matter if this is not empty in fact, since most of the installation tree is not examined by the build. The only exception is /local/star/manifests, since the files in this directory control what is actually built – see the notes for line 9.

Line 6: put /local/star/bin and /local/star/buildsupport/bin in the path. Make sure that there are no Starlink binary directories elsewhere in the path: running which messgen (for example) at this point should find nothing.

Line 7: run the ./bootstrap script. This configures, builds and installs the ‘buildsupport’ tools – the autotools plus the starconf application – then recursively runs the bootstrap code in a selection of the directories beneath this one. The directories the bootstrap recurses into, in this directory and its children, are those listed in a AC_CONFIG_SUBDIRS macro in configure.ac. After this, you should be able to do

  % which autoconf
  /local/star/buildsupport/bin/autoconf
  % autoconf --version
  autoconf (GNU Autoconf) 2.59
  ...
  %

to verify that the correct tools have indeed been installed in the correct place.

Line 8: configure the entire tree (the -C option indicates that configure should cache its results, speeding up the process). This configures this directory and recurses into the children named in AC_CONFIG_SUBDIRS in this configure.ac and those below it.

If you will need to give ./configure some help to find include files and libraries, you might try setting the CFLAGS or LDFLAGS variables in the environment, in the manner described in Sec. 2.1.5. Note, however, that this is not a recommended practice.

Line 9: build the entire tree, using the make world target described in Sec. 3.1. The make builds all the components in an order which ensures that each component is build after the components it depends on, as declared in STAR_DECLARE_DEPENDENCIES invocations in those components’ configure.ac files. The set of dependencies can be examined (if you’re interested) in the file componentset.xml, which is built up from the various directories’ component.xml files, as reprocessed into Makefile.dependencies .

Note that the dependencies are expressed as dependencies of components’ manifest files on each other, and the top-level makefile is written so that each component is built with the pair of commands make; make install, which builds the component then installs both it and its manifest. Thus, if you need to ask for a particular component, foo, to be built, you can do so from the top-level directory with make /local/star/manifests/foo.

Line 10: after the make, a manifest is installed for each of the built components.

3.3 Building a single component

In Sec. 3.2 we saw how you would bootstrap and build the entire tree, building each component’s dependencies before building the component itself.

If, on the other hand, you wish to build only one component, because you wish to install the latest and greatest version of some application, or because you want to work on the CVS version, then you can do that without, in principle, building the entire code collection.

The component directories are organised so that you can build a component from a CVS checkout by moving to the component’s directory and giving the sequence of commands:

  % ./bootstrap
  % ./configure
  % make
  % make install

Before you can do this, however, you will have to do a little preparation, and there are two cases.

One of the functions of the ./bootstrap script is to regenerate the ./configure script if necessary, since it is not checked in to the repository. This requires that the Starlink-specific autotools are in your path, and so you must first install these ‘buildsupport’ tools if they are not installed already. Instructions for that are below

There are two cases next. The first is where you currently have a built and installed Starlink system which you either built yourself earlier, or which you installed from a Starlink distribution (note: a Starlink CD distribution dating before 2005 doesn’t count here – though the applications and libraries are essentially the same, the distribution and building arrangements changed radically). The second case is where you are only interested in one component, but are starting from scratch, without a pre-existing distribution (of course, once you successfully complete the second case, you are in the situation where the first case applies).

Case 1 – pre-built Starlink system: This is the easy one. You need check out only the component of interest (see Sec. 2.7.2 for notes on that).

At this point you can run ./bootstrap as above, and have these locations baked in to the configuration as the defaults.

Alternatively, you can control these two locations at configure time, after you have run ./bootstrap. You control the installation location with the –prefix option and the location of the Starlink tree either with the STARLINK environment variable or, better, with the –with-starlink option. Although the use of the STARLINK variable is supported, it involves less (easily forgettable) defaulting if you use the –with-starlink option instead. See Sec. 2.1.5 for details. Having said this, setting the STARCONF_DEFAULT... variables is probably preferable, since you don’t then have to remember to supply the options if you run ./configure again.

Case 2 – building from scratch: This isn’t actually much more complicated, but does take a little longer. You need to check out all of the components that your component depends on; since there is (currently) no automatic way to discover what this set of components is, in practice you might as well check out the whole repository. Since you don’t have a pre-built Starlink directory available, then you will have to build all or most of the tree, before the component you’re interested in can be built. In this case, follow the instructions in Sec. 3.2 – which include setting the STARCONF_DEFAULT_... variables to suitable values – but instead of finishing with make world in step 9, do make /mystar/manifests/cpt, where /mystar is the location you have chosen for the installation tree (as specified in STARCONF_DEFAULT_STARLINK), and cpt is the component you are interested in. This will build and install in turn each of your component’s dependencies, and then the component itself.

If you are doing this because you want the latest and greatest version of a particular component, then you are finished.

If you are doing this because you want to do development work on the component, then you might well want to keep the functioning version separate from your development version. In this case, you need to go through this procedure once with STARCONF_DEFAULT_STARLINK and ..._PREFIX having the same values, as above. Next, you change to the component’s directory, and either bootstrap your development component a second time, with STARCONF_DEFAULT_PREFIX set to a separate installation location (you are now in the situation where case 1 applies, above, and you can give the comments ./bootstrap; ./configure; make); or else re-run ./configure with its –prefix option set to point to that alternative location (the first mechanism simply sets the default for the second, and is probably preferable for the reasons mentioned above).

Note that part of the function of the ./configure script is to find the location of important files and freeze them in to the Makefile. Thus the STARLINK variable is ignored after configure-time, so that you cannot, in general, change the STARLINK variable or change your path, and have new binaries picked up.

3.4 Building monoliths

As illustrated in Sec. 2.1.2, you can build monoliths in an analogous way to the way you build programs, by declaring the monoliths as the value of the bin_MONOLITHS variable.

Along with the bin_MONOLITHS variable, a Makefile must also declare a set of tasks using the TASKS primary, and this set will be empty if the monolith is an ATASK. If a monolith foo has a set of tasks a and b, then this declaration will look like this:

  bin_MONOLITHS = foo
  foo_TASKS = a b

That is, the tasks are listed without any .ifl extension.

The foo_TASKS primary indicates to automake that there will be .ifl files in the local directory corresponding to each of the tasks in the monolith, that these .ifl files should be distributed, and that the appropriate extra links should be made, in the binary directory, when the monolith is installed. The tasks variable might also be used in the foo_SOURCES variable to declare the dependence of the monolith on the Fortran files corresponding to the tasks (it would be possible to automake to have inferred this last step, but it seems clearer overall to have this dependency at least made explicit). Automake permits the usual Makefile variable rewritings, so that if you have a Fortran file corresponding to each task, then this set is $(foo_TASKS:=.f)which might be useful.

The generated Makefile.in will install each of the task .ifc files, plus the monolith .ifc file. The monolith .ifl file is constructed by appending each of the task .ifl files, wrapped in begin monolith and end monolith, and this generated .ifl file should not be included in the repository or the distribution.

If you are building an ATASK, then the task is the same name as the program. Indicate this by omitting the ..._TASKS variable:

  bin_MONOLITHS = foo
  # no variable foo_TASKS, since foo is an ATASK

(the extra comment is useful to help document the slightly non-obvious construction here). In this case, the only .ifl file is that for the ATASK. The makefile makes sure that this .ifl file is distributed, so the file should either exist, or have a rule in the Makefile.am.

The MONOLITH primary allows the prefixes bin, check and noinst, rather like PROGRAMS.

In order to use the monolith support, you must request this by including the declaration STAR_MONOLITHS in the configure.ac file, most rationally near the AC_PROG_CC-style declarations.

3.5 Bootstrapping without building: configuring starconf and the autotools

If you intend to work only on a single component, then you can configure and build it as described in the previous section. As described there, the bootstrapping procedure requires that the ‘buildsupport’ tools – starconf plus Starlink-specific autotools – be installed and in your path.

You must install the autotools which are part of the CVS repository, since these have been extended and customised specially for the Starlink build tree (for the details of the differences, see Sec. B). The standard autotools will not work.

The way to do this is to make sure you have the required components checked out (see Sec. 2.7.2), then go to the top of the tree and give the command

  % ./bootstrap --buildsupport

This builds and installs the ‘buildsupport’ tools – namely the autotools plus starconf – but does not go on to bootstrap the rest of the tree. The functions of the variables STARCONF_DEFAULT_PREFIX and STARCONF_DEFAULT_STARLINK were described in Sec. 2.2: in order to configure starconf at this stage, you must define these two variables as environment variables before running the ./bootstrap script. This will cause the tools to be installed in the directory $STARCONF_DEFAULT_PREFIX/buildsupport/bin, and the configured starconf to configure components, when it is itself invoked, so that the default value of STARCONF_DEFAULT_PREFIX is the value given here, as described in the previous section.

You must use this method of configuring starconf and the three autotools – autoconf, automake and libtool.

After that, you should put the .../buildsupport/bin directory in your path, and start work.

See also Sec. 2.2.1 for how to make a version of the buildsupport tools which has a default installation prefix different from the buildsupport installation location.