Build system

This document describes the Aldor build process, i.e. the Makefiles and scripts used to build the supporting tools, the Aldor compiler, and its libraries.

First of all, it should be noted that in general, convention is chosen over flexibility. The directory structure requirements are rather strict, in order to impose a common pattern on all library authors. This pattern can then be used by scripts and automated tools to perform actions with little or no configuration.

Compiler

The Aldor compiler has a layered design (see compiler internals for more details). This layering is represented in the build process by putting the object files (.o) for each layer in a separate convenience library (.a/.lib file). In general, code from one layer should not use code from a layer above it, and not include headers from that layer. Currently, this is violated in several instances.

The compiler is written in C and uses a LALR(1) macro-grammar to generate its parser. The tool zacc in aldor/tools/unix expands macros in axl.z and produces axl_y.c by calling yacc on the expanded grammar.

Compiler messages databases are generated by aldor/tools/unix/msgcat, which produces comsgdb.c and comsgdb.h from comsgdb.msg.

Libraries

The structure of an Aldor library follows a pattern:

Other subdirectories can be added, but the build scripts expect at least the three above to exist. By convention, we recommend the following names for optional directories:

The following is a high level view of the library build. A more in-depth explanation of what the build scripts and helpers do will follow in another section.

Root: Makefile.am

The root Makefile.am should be mostly empty, and only dispatch into sub-directories. For most complete libraries with documentation, it will look similar to this:

SUBDIRS = doc include src test

Sources: src/Makefile.am

Each Aldor library consists of one or more sub-libraries that are built in dependency order. This order must be stated explicitly in the source src/Makefile.am for the library by listing them in the SUBDIRS variable.

SUBDIRS = part1 part2

Second in the Automake file should be the file name of the library being built. We call our demo library here libsample.a.

lib_LIBRARIES = libsample.a

After this, we list all the C sources, including those generated from Aldor code. Extra support code for the C side should also be listed in this variable. The variable name is the above library name with non-alphanumeric characters such as - and . replaced by underscores _.

libsample_a_SOURCES =   \
        part1/doma.c    \
        part1/domb.c    \
        part2/domc.c    \
        part2/domd.c    \
        #

Note that Automake does not accept trailing backslashes, so you may either end the list with a comment or omit the last backslash. The order of this list is irrelevant, as there are no dependencies between these files; they can be built in parallel.

Library name

Next, the library name must be repeated without the lib prefix and the .a suffix. This name must be equal to the current directory. I.e. if the file you are creating is lib/sample/Makefile.am, then libraryname must be sample. This name is used to build the Aldor side of the library, i.e. the .al file, in this case libsample.al.

libraryname = sample

Due to Automake limitations, it is not possible to use $(libraryname) in the definition of lib_LIBRARIES.

Often, the headers provided by and included in the library being built contain code that is conditionalised on whether they are used to build the library or they are being used to build code against a completed library. The reason for this is that the header will import the Aldor Library (.al file) automatically when you include it in client code, but while building the library, this file does not yet exist.

By default, the symbol defined by the build system that tells the header whether it is currently being built is named Build followed by the capitalised $(libraryname) and Lib, so that in our case, the symbol would be BuildSampleLib. If you want to override the name between Build and Lib, you must define Libraryname.

E.g.:

Libraryname = Demo

will define BuildDemoLib, and not BuildSampleLib while compiling Aldor code for this library.

Default Makefile

Most libraries will want to include the default Automake rule file that produces and installs the Aldor library. This file resides in the lib under the aldor build root.

include ../../buildlib.am

Usually, this will be the last line of your src/Makefile.am. Other rules and variables can follow it. The following variables are defined by buildlib.am, and thus additions to them must be done with +=.

Extra files

The library is automatically installed in the appropriate place for the Aldor compiler to be able to find it with #library. If you would like to install other files in the same directory,

Sub-libraries: src/*/Makefile.in

A sub-library Makefile is not an Automake file, but rather a simple Makefile preprocessed by config.status, generated by configure. It starts with a common boilerplate that is required since we're not using Automake here, but we want to be integrated with the Automake-based build.

(TODO: move this to an extra file in the same directory (perhaps prelude.mk.in), so it can be updated automatically)

@SET_MAKE@
VPATH = @srcdir@

# For AM_V_*
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@

builddir        := @builddir@
abs_builddir    := @abs_builddir@
top_builddir    := @top_builddir@
abs_top_builddir:= @abs_top_builddir@
srcdir          := @srcdir@
abs_srcdir      := @abs_srcdir@
top_srcdir      := @top_srcdir@
abs_top_srcdir  := @abs_top_srcdir@

The boilerplate is followed by a list of Aldor source files without the .as suffix.

library = doma domb

Lastly, the common build variables for the library are included. A relative path using explicit ../.. should not be used, as that would break vpath (out of tree) builds.

include $(top_srcdir)/lib/sample/src/common.mk
src/common.am

The purpose of this extraction is to minimise reduncancy by defining common variables only once. The only required variable in this file is libraryname, whose purpose was described in the earlier section "Library name".

libraryname     := sample

Commonly, libraries will want to define their Aldor optimisation and debug flags, more generally speaking its compiler flags.

AXLFLAGS        := -Q8 -Zdb

Finally, at the end of a library's common.mk, the main build machinery for Aldor sub-libraries is included.

include $(top_srcdir)/lib/buildlib.mk

This file is always included, unless you have very specific needs, which require you to completely define your own. We recommend against this, and rather file a feature request describing your special needs. Although our design is purposefully inflexible and based on convention, we do want to be able to build any kind of Aldor library.

src/*/Makefile.deps

Next to each Makefile.in in a sub-library's directory, a dependency file is required. We are unfortunately unable to correctly generate these from the sources, for now, since it requires us to preprocess the Aldor sources with the same flags used during the build.

For each source name dom listed in library above, there is an optional dom_deps, containing its dependencies within the sub-library. If the sub-library itself depends on another sub-library from the same combined library, these should be listed in library_deps.

(TODO: this is bad, it reserves the source name library.as)

The following fragment might be for part2 of our sample library, which depends on part1, and in which domd depends on domc. Note that although files in part2 may depend on files in part1, these dependencies are not listed explicitly, but rather the complete part1 is imported.

# Intra-sublib dependencies
domd_deps       := domc

# Sublib dependencies
library_deps    := part1

Testing

Libraries are tested using test programs whose return value signals the success or failure of a test. Each program with name $P is in its own subdirectory $P with an Aldor source file $P/$P.as and an output reference file $P/$P.ref. Each test directory also contains a .gitignore file of this format:

/$P
/$P.c
/$P-aldormain.c

Makefile.am contains a list of libraries required for the tests, a list of test directories, a list of tests known to fail, and an include directive for the common test code.

libraries = aldor sample

AXLTESTS =              \
        domatest1       \
        domatest2       \
        #

# Known to fail:
XFAIL_TESTS =           \
        domatest2       \
        #

# Common code
include ../../testprog.am

After the include, one may add other C sources required for the tests to run, as well as dependencies between tests, if one test uses the Aldor object of another.

domatest2_domatest2_SOURCES += domatest2/support.c

domatest2/domatest2.c: domatest1/domatest1.c