Development environment of the SchemeStation project: makefiles and related

Development environment of the SchemeStation project: makefiles and related
SchemeStation documentation

1 Purpose

The purpose of this document is to provide information about the makefiles and other related files that build up the skeleton of the SCHEMESTATION development environment.

2 Overview

The SCHEMESTATION project source codes are stored in a CVS tree. From now on we represent the root of this tree with /.

This document describes the following files:

/src/Makedefs.in
This file is source for generating /src/Makedefs.
/src/Makedefs
This file is generated from /src/Makedefs.in by the script /src/configure or /src/config.status.
/src/Makedepends
This file defines a make rule and certain auxiliary things to enable automatic making of dependencies.
/src/Makefile
This is the top level Makefile of the source code.
/src/config.h.in
This file is source for generating /src/include/config.h.
/src/include/config.h
This file is source for generating from /src/config.h.in by /src/configure or /src/config.status.
/src/config.status
This file is generated by /src/configure when it is run. /src/config.status (re)creates the files created by /src/configure without doing the actual configuration scan again.
/src/configure.in
This file is source for generating /src/configure. It is used by autoconf(1).
/src/configure
This is a configuration script that is generated from /src/configure.in by running autoconf(1).
directory-specific makefiles
Every active subdirectory contains a makefile.

3 Details

3.1 Configuration

The system is configured using GNU Autoconf. The general workings of autoconf in the situation present in the SCHEMESTATION project are presented here. For more details refer to the autoconf documentation.

Autoconf(1) takes as its input a file normally named configure.in and creates a shell script named configure. The configure script, when invoked, analyzes the system where it is run to find out various system-specific parameters, including byte order, features of the C compiler, libraries present etc.

After doing its scan, configure creates files that depend on the results of this scan. In SCHEMESTATION project these files are /src/include/config.h and /src/Makedefs. The files are created by reading in the corresponding templates /src/config.h.in and /src/Makedefs.in and by replacing certain expressions by results of the configuration scan.

This process can be illustrated as follows.

configure.in
    |             config.h.in
[autoconf]        Makedefs.in
    |                  |
   configure .... [configure]
                       |
                   Makedefs
                   config.h

When making distribution, it is sufficient to distribute the configure script but not the configure.in source code. This implies that distributions can be succesfully built in environments where autoconf is not available.

Most makefiles in the SCHEMESTATION project should include Makedefs at the first lines. It is not allowed to hardcode absolute directory paths etc. to the makefiles.

3.2 Makefiles

Every makefile should include src/Makedefs at its first lines. Use relative pathname, i.e.

include ../../Makedefs

The following makefile variables are defined in Makedefs:

INCLUDEDIR
This is the directory where include files are stored; corresponding to the CVS repository path schemestation/src/include/.
LIBDIR
This is the directory where built libraries will be installed.
BINDIR
This is the directory where executables will be installed.
DOCDIR
This is the main directory where documents will be stored; corresponding to the CVS repository path schemestation/doc/.
CC
C compiler.
INSTALL
Install command (see man install(1)).
RANLIB
ranlib command, or : (do nothing) in systems where running ranlib is not necessary.
SCHEME
Scheme executable.
AR
ar command.
RM
rm command.
CFLAGS
Flags to pass to the C compiler. Includes -I${INCLUDEDIR}.
X_LINK
A collection of flags that are needed when linking programs using X. Put $(X_LINK) before you enter the X libraries you want to link against, i.e. $(CC) ... $(X_LINK) -lX11 ...
X_CFLAGS
A collection of flags that are needed when compiling programs using X.
SS_LINK
Put $(SS_LINK) before any libraries that are done during the SCHEMESTATION project and reside in $LIBDIR.

Moreover, the following targets are predefined:

relink
This traverses the source tree recursively from the cwd down and in every subdirectory remakes files mentioned in the makefile variables EXECUTABLES and EXECUTABLE. EXECUTABLES can contain multiple names but EXECUTABLE should contain only one. If EXECUTABLE is present then make installexec is issued after EXECUTABLE has been remade.
wormkill
rm -f *~
distclean
This traverses the source tree recursively from the cwd down and in every subdirectory issues make clean.
summary
This is part of the support for automatic testing. make summary does nothing if the makefile variable TESTREPORTS is not set or is empty. Otherwise first make tests is issued and then a summary of the test report files TESTREPORTS is outputted.
recsummary
This is as summary but (1) it traverses the source tree recursively down from the cwd, (2) it gathers all test reports from the subdirectories into one file ./tests-results and (3) draws the summary to ./tests-summary.

3.3 Makedepends

Makedepends includes two rules and some auxiliary code to make and use dependencies automatically. It assumes that your makefile defines a variable OBJECTS which should be a list of object files that will be compiled by the particular makefile. All the corresponding .c-files but nothing else are used to create a dependency file .depend, which is then included into the Makefile.

More specifically, if .depend does not exist and you include Makedepends in your Makefile, then whenever you run make .depend will be created and included in the make process at any point from that forward. Whenever you delete .depend it will be created again when you run make. You can also force remaking .depend my doing ``make dependencies''.

Makedepends also defines a variable DEPCLEAN which you should include in your makefile's actions for ``clean'', i.e. something like

clean :
	rm -rf ... my files ...
	$(DEPCLEAN)

3.4 Standard additions for executables and libraries

Standard makefiles for executables and libraries can be conveniently defined by including Makedefs, Makedepends and StandardExecutable or StandardLibrary depending on whether the makefile creates an executable or a library. For an executable you need to specify the following make variables before including:

CSOURCES
A list of c-files that must be compiled.
OBJECTS
A list of o-files that the executable consists of.
EXECUTABLE
The name of the executable.
MODNAME
An arbitrary name for the current module, displayed during make
LINKAGAINST
Compiler flags specifying the libraries you want to link your executable against.

StandardExecutable defines the following additional targets:

all
Builds the executable and installs it to the executables repository
installexec
Installs the executable
clean
Removes $(OBJECTS), $(EXECUTABLE), $(EXECUTABLES), core, *~ and $(GENERATED), depending just on what values you have assigned to these variables.

For a library you need to specify the following make variables before including: CSOURCES, OBJECTS, MODNAME as above; and LIBNAME in the place of EXECUTABLE.

The targets defined are as above, except "installib" in place of "installexec".

3.5 Tips for writing makefiles

This is how you could and should write your makefiles in the SCHEMESTATION project.

  1. include Makedefs first
  2. if you need to keep track of dependencies (you are writing a C module), include Makedepends next (Makedefs must be included first)
  3. use StandardExecutable or StandardLibrary if possible
  4. otherwise, provide at least the following rules: all and clean. ``all'' should build everything and install everything that is needed for making other subdirectories. For example, SCHEMESTATION libraries should be installed to LIBDIR.

    ``clean'' should leave the directory to the state where it was before any make took place. distclean should do that and also make distclean recursively to all subdirectories.

  5. define your subdirectories [if you are not in a leaf directory] using the variable SUBDIRS and then include $(RECSUBDIRS) in the actions for ``all'' or something like that; for example
    SUBDIRS = baz goz
    all :
    	foobar # done in this directory
    	$(RECSUBDIRS)
    

To make the things more concrete, have a look on the plethora of makefiles already existing in the project.

4 Answers to some questions

How do I integrate my tests into the Makefiles?

  1. Add a target 'tests' that runs whatever tests you want and writes the test reports into one or more files with names of your choice
  2. Enumerate all the report names in a make variable TESTREPORTS at the beginning of the makefile

And how do I run the tests?

Do "make tests" to just run them, "make summary" to make them and output summary information, and "make recsummary" to do tests in all subdirectories and finally get a summary of all the results in all the subdirectories, drawn together.

What's the difference between the variables EXECUTABLE and EXECUTABLES?

EXECUTABLES is used by "relink" only; all executables in EXECUTABLES are re-made. However, they are not installed automatically. Using the variable EXECUTABLE assumes that you are also including StandardExecutable; otherwise "relink" might not work. EXECUTABLE specifies the binary executable name for StandardExecutable; EXECUTABLES is in no relation to StandardExecutable.