buildsystem : IndexToc

TEKlib / Build system documentation

By Timm S. Müller - Copyright © 2005 TEK neoscientists. All rights reserved.

TEKlib's build system is based on abstract makefiles (with the default name tmkmakefile) and a commandline tool to generate platform/compiler-specific makefiles, tmkmf. The principle is fully generic, and in its current configuration it supports a wide variety of compilers, platforms and build configurations. This document gives a rough overview. As it is not meant to be a comprehensive reference manual, one should stick to the examples of which there are plenty in TEKlib's source tree.

buildsystem : 1. Build targetsToc

Build targets according to TEKlib's standard terminology are:
Other targets are:
Regardless of the project structure, all makefiles allow traversal with all kinds of targets, even if no targets of a certain kind are actually present in a given hierarchy. The all target will traverse a hierarchy with the targets libs, modules, tools, in that order.
See also: Destinations

buildsystem : 2. Main tree and side projectsToc

The setup of an environment for software development is usually partitioned into at least two top-level directories, namely TEKlib's own source tree and any number of side projects, each comprising any number of subprojects.
Side projects normally reference TEKlib's source tree using relative paths, which makes the installation of TEKlib an optional step and may help to ease its deployment.
Example:
+- projects           targets defined on this level
    |
    +- teklib                   meta
    |	+- boot                 libs
    |	+- apps                 meta
    |	|   +- tmkmf            tools
    |	+ mods                  meta
    |	    +- exec             modules and tools
    |	    +- hal              modules
    |
    +- 3dengine                 meta
        +- engine               modules and tools
        +- tools                meta
            +- guihelper        libs
            +- viewer           tools
            +- objconv          tools
Notes:

buildsystem : 3. Build contextsToc

A context describes the configuration of a build and is a string consisting of path-like components.
Examples:
win32_vcpp_release_pentium3
amiga_sasc_debug     |
linux_gcc    |       +-- subflavour
  |    |     |
  |    |     +---------- flavour
  |    |
  |    +---------------- compiler
  |
  +--------------------- platform
Build contexts are usually threefold; the most significant part is the platform, followed by the compiler and a flavour. However, that doesn't mean that all components must be specified for a context to be descriptive; a setting with reasonable defaults will be assumed if the flavour (or a more specific component) is omitted.

buildsystem : 4. Build Directory StructureToc

There must be a subdirectory named build on each directory level that is subject to build traversal; the tmkmakefile to describe this node is expected in this directory. Here is an example of a project directory in more detail:
+- demos
    +- build
    |   +- tmkmakefile
    +- kinematic
    |   +- build
    |   |   +- tmkmakefile
    |   +- kinematic.c
    +- rotzoom
        +- build
        |   +- tmkmakefile
        +- rotzoom.c
The commandline tool tmkmf will generate platform-specific makefiles in the same directory as the originating tmkmakefile; For instance, after the application of the contexts fbsd_gcc_debug and win32_vcpp the directory structure would look like this:
+- demos
    +- build
    |   +- tmkmakefile
    |   +- tmk_fbsd_gcc_debug          <- added by tmkmf
    |   +- tmk_win32_vcpp              <- added by tmkmf
    +- kinematic
    |   +- build
    |   |   +- tmkmakefile
    |   |   +- tmk_fbsd_gcc_debug      <- added by tmkmf
    |   |   +- tmk_win32_vcpp          <- added by tmkmf
    |   +- kinematic.c
    +- rotzoom
        +- build
        |   +- tmkmakefile
        |   +- tmk_fbsd_gcc_debug      <- added by tmkmf
        |   +- tmk_win32_vcpp          <- added by tmkmf
        +- rotzoom.c

buildsystem : 5. Using tmkmfToc

Argument template:
-f=FROM source filename [default tmkmakefile]
-c=CONTEXT/K build context [default linux_gcc]
-r=RECURSE/S recurse from current directory
-b=BUILDDIR/K path to the BUILD: directory [default PROGDIR://build]
-q=QUIET/S silent execution
-h=HELP/S get help
If the RECURSE option is given then FROM specifies the filename to look up in a recursive directory scan, starting at the current directory. Without the RECURSE option, FROM specifies the path and filename of a distinct tmkmakefile.
Example processing a hierarchy starting at the current directory:
> build\bin\tmkmf_win32 context win32_vcpp recurse
Example processing a single tmkmakefile:
> build/bin/tmkmf_morphos mods/hal/build/tmkmakefile -c morphos_gcc
(See also a description of TEKlib's commandline templates.)

buildsystem : 6. The tmkmakefile formatToc

Tmkmakefiles use a notation similar to XML, with the biggest difference being that tags are enclosed in square brackets. Another point is that tmkmakefiles do make a difference regarding individual lines, whereas linebreaks do not normally play a role in the structure of XML.
First we have a look at a tmkmakefile sitting on a meta node named demos in a side project, defining two subprojects named kinematic and rotzoom, according to the following directory structure:
+- projects
    |
    +- teklib
    |   +- build                <- assigned to BUILD:
    |       +- config.tmk       <- included by tmkmakefile
    |       +- builds.tmk       <- included by tmkmakefile
    |
    +- demos                    <- the node being described
        +- build
        |   +- tmkmakefile      <- makefile describing this node
        |   +- tmk_linux_gcc    <- a makefile generated by tmkmf
        +- kinematic
        +- rotzoom
The tmkmakefile in detail:
[include name="BUILD:config.tmk"/]
[!----------------------------------------]
[body name="metatargets"]
    [embed body="meta"] kinematic [/embed]
    [embed body="meta"] rotzoom [/embed]
[/body]
[!----------------------------------------]
[include name="BUILD:builds.tmk"/]
[render to="tmk_"] makefile_meta [/render]
The notation BUILD: addresses a path (using a logical assign) that is determined from the location of the tmkmf executable. This path can be overridden with the BUILDDIR option of tmkmf. Two files are included from the TEKlib tree:
When the tmkmakefile is interpreted, the [render] tag will finally produce one or more context-specific makefile Destinations, named after the current context added to a filename prefix, tmk_.
See also: TEKlib's path naming conventions

buildsystem : 7. Makefile destinationsToc

Makefile destinations are, according to the build targets and the possible combinations thereof,
See also: Targets

buildsystem : makefile_metaToc

The makefile_meta destination will produce a makefile for descending into one or more subdirectories.
Use the body section metatargets to enclose the meta build:
[body name="metatargets"]
    [embed body="meta"]
    	[!-- name of subdirectories; one directory per line --]
    [/embed]
[/body]

buildsystem : makefile_libsToc

The makefile_libs destination will produce a makefile for building one or more link libraries on a given directory level.
The body section named teklib specifies the path to the TEKlib source tree. Use $(PARENT) to step one directory up, e.g.
[body name="teklib"]
    TEKLIB = $(PARENT)$(PARENT)teklib/
[/body]
Use the body section libtargets to enclose the libs build:
[body name="libtargets"]
    [embed body="libs"]
    	[!-- libs: name of libraries to be built; one per line --]
    [/embed]
    [embed body="liblink"]
        [!-- a library link; first line: libname,
        second line: list of objects --]
    [/embed]
    [embed body="libdep"]
        [!-- a library dependency: first line: objectname,
        second line: source,
        third line: list of dependencies --]
    [/embed]
[/body]
See also: a complete Example, Destinations

buildsystem : makefile_modulesToc

The makefile_modules destination will produce a makefile for building one or more modules on a given directory level.
The body section named teklib specifies the path to the TEKlib source tree. Use $(PARENT) to step one directory up, e.g.
[body name="teklib"]
    TEKLIB = $(PARENT)$(PARENT)teklib/
[/body]
Use the body section modtargets to enclose the modules build:
[body name="modtargets"]
    [embed body="mods"]
    	[!-- mods: name of modules to be built; one per line --]
    [/embed]
    [embed body="modlink"]
        [!-- a module link; first line: module name,
        second line: list of objects --]
    [/embed]
    [embed body="moddep"]
        [!-- a module dependency; first line: objectname,
        second line: source,
        third line: list of dependencies --]
    [/embed]
[/body]
See also: a complete Example, Destinations

buildsystem : makefile_toolsToc

The makefile_tools destination will produce a makefile for building one or more executables (applications, tests...) on a given directory level.
The body section named teklib is used to specify the paths to the TEKlib source tree and to a directory for putting the executables. Use $(PARENT) to step one directory up and $(PLATFORM) to address the name of the platform of a given context, e.g.
[body name="teklib"]
    TEKLIB = $(PARENT)$(PARENT)teklib/
    BINDIR = $(TEKLIB)bin/$(PLATFORM)
[/body]
Use the body section tooltargets to enclose the tools build:
[body name="tooltargets"]
    [embed body="tools"]
    	[!-- tools: name of tools to be built; one per line --]
    [/embed]
    [embed body="toollink"]
        [!-- a tool link; first line: tool name,
        second line: list of objects --]
    [/embed]
    [embed body="tooldep"]
        [!-- a tool dependency; first line: objectname,
        second line: source,
        third line: list of dependencies --]
    [/embed]
[/body]
See also: a complete Example, Destinations

buildsystem : makefile_modules_and_toolsToc

This build combines the body sections from the makefile_modules and makefile_tools builds; use the body section teklib to specify the paths to the TEKlib source tree and to a directory for putting the executables (as seen in makefile_tools).
See also: a complete Example, Destinations

buildsystem : makefile_libs_and_toolsToc

This build combines the body sections from the makefile_libs and makefile_tools builds; use the body section teklib to specify the paths to the TEKlib source tree and to a directory for putting the executables (as seen in makefile_tools).
See also: a complete Example, Destinations

buildsystem : A complete tmkmakefile exampleToc

An example (taken from teklib/mods/util/build) is given below:
[include name="BUILD:config.tmk"/]
[!---------------------------------------------------------------]
[body name="teklib"]
    TEKLIB = $(PARENT)$(PARENT)
    BINDIR = $(TEKLIB)bin/$(PLATFORM)
[/body]
[body name="modtargets"]
    [embed body="mods"] util [/embed]
    [embed body="modlink"]
        util
        $(LIBDIR)/util_mod.o \
            $(LIBDIR)/util_args.o \
            $(LIBDIR)/util_string.o \
            $(LIBDIR)/util_searchsort.o
    [/embed]
    [embed body="moddep"] $(LIBDIR)/util_mod.o
                          util_mod.c            [/embed]
    [embed body="moddep"] $(LIBDIR)/util_args.o
                          util_args.c           [/embed]
    [embed body="moddep"] $(LIBDIR)/util_string.o
                          util_string.c         [/embed]
    [embed body="moddep"] $(LIBDIR)/util_searchsort.o
                          util_searchsort.c     [/embed]
[/body]
[body name="tooltargets"]
    [embed body="tools"] modscan
                         sorttest               [/embed]
    [embed body="tooldep"] $(LIBDIR)/modscan.o
                           tests/modscan.c      [/embed]
    [embed body="tooldep"] $(LIBDIR)/sorttest.o
                           tests/sorttest.c     [/embed]
    [embed body="toollink"] modscan
                            $(LIBDIR)/modscan.o [/embed]
    [embed body="toollink"] sorttest
                            $(LIBDIR)/sorttest.o [/embed]
[/body]
[!---------------------------------------------------------------]
[include name="BUILD:builds.tmk"/]
[render to="tmk_"] makefile_modules_and_tools [/render]


buildsystem : 8. Conditional buildsToc

TEKlib's build system allows conditional builds with the directives [switch] and [if], which act on the current context for case differentiation. Despite their simplicity, they allow for a good deal of flexibility. Example:
[if config="linux"]
    [!-- considered if context is linux... --]
[/if]

[switch]
    [case config="win32_vcpp"]
        [!-- considered if context is win32_vcpp... --]
    [/case]
[/switch]
If the config attribute is fully contained at the beginning of the current context then the dependent block will be entered.
The matching part of the context is removed from the current context string, and the dependent block will be entered with the remaining subcontext. This allows for cascading differentiations, for instance
[if config="linux_gcc"]
    [switch]
        [case config="_release"]
            OPT = -O2 -finline-functions -fomit-frame-pointer
        [/case]
        [case config="_debug"]
            OPT = -O1
            DEBUG = -DTDEBUG=5 -g
        [/case]
        [default]
            OPT = -O2
            DEBUG = -DTDEBUG=10 -g
        [/default]
    [/switch]
[/if]
If you don't want to enter a block with the matching part of the context being removed then use the [case_no_descend] tag instead of [case]. This can be useful in meta builds, for example:
[switch]
    [case_no_descend config="ps2"]
        [!-- this block will be entered with the
        unmodified context. --]
        [embed body="meta"] ps2 [/embed]
    [/case_no_descend]
[/switch]
As a last note on cases, there is currently no such statement like [ifnot]. Use a [switch] and the [default] statement instead, like this:
[switch]
    [case config="amiga"][/case]
    [case config="morphos"][/case]
    [case config="darwin"][/case]
    [default]
        [!-- the "if not" case goes here --]
    [/default]
[/switch]

buildsystem : 9. Adapting the build system to your needsToc

On a final note, the build system is no way hardwired or limited to the definitions outlined in this document; these resulted from the specific requirements of the TEKlib project and are part of its configuration.
Edit the configuration files (starting at build/config.tmk and build/builds.tmk) to adapt the build system according to your needs; more platforms, compilers, contexts and destinations can be added.

buildsystem : Table of contents


Generated Sat Oct 8 16:06:19 2005 from buildsystem.doc