Build scripts based on Unix make

Short instructions

a) Linux/simulator

ln -s build-configurations/Platform-linux Platform
ln -s build-configurations/Options-linux-debug Options
make rebuild
make tags

b) 8051 using SDCC

ln -s build-configurations/Platform-8051 Platform
ln -s build-configurations/Options-8051-sim-debug Options
make rebuild
make tags

Detailed explanations

Build scripts in Linux uses the 'make' utility.

The files used by the build subsystem include:
  • mk/{platform}/Makefile at leaf directories.
  • root Makefile in stack/
  • Options-xxx-xxx-xxx files in stack/build_configurations. Xxx-xxx-xxx means some set of features, like Options-linux-debug.
  • Platform-xxx file in stack/build_configurations, xxx means host platform, like Platform-linux.
  • Makefile files in subdirs like tests/ tests/certification etc

Before compiling the build subsystem must be configured by creating symbolic links for Options-xxx-xxx-xxx and Platform-xxx into the stack directory as follows:

ln -s build-configurations/Platform-linux Platform
ln -s build-configurations/Options-linux-debug Options

The idea here is that leaf makefiles first set its place related to the sources root using assignment like BUILD_HOME=.., and then includes Options file using string include $(BUILD_HOME)/Options.

Now all definitions from Options file are available for the leaf makefiles and all that is needed is to define a list of targets. As a result, leaf makefiles are very simple, usually containing only files lists and frequently can be used in environments other than Linux/PC.

Here is an example of the leaf makefile:

BUILD_HOME=..
include $(BUILD_HOME)/Options

SRCS = secur_ccm.c apsme_secur.c zdo_secur.c nwk_secur.c aps_secur.c

all: $(SECUR_LIB) $(SECUR_LIB_ED)

$(SECUR_LIB) : $(OBJS)
        $(MAKE_LIB)

$(SECUR_LIB_ED) : $(OBJS_ED)
        $(MAKE_LIB)

In this example there is only one file list and one target list. Note that XXX_ED (SECUR_LIB_ED, OBJS_ED) are used for ZED build and will be described later.

Sometimes leaf makefiles must be different for different platforms: for example, some OS-specific files must be compiled for Linux/ARM and do not have to be compiled for Linux/PC. To resolve this issue every leaf directory does not include a Makefile, but instead has mk/{platform}/Makefile. When 'make rebuild' is issued from the root directory, the build script creates a link to the proper Makefile.

If mk/{platform} directory does not exist (meaning, no special logic is necessary for this platform), the build script links mk/unix/Makefile generic file.

stack/Options file contains all definitions including C compiler options, command line used to translate .c to .o, libraries list, command-line to link executable files from the dependencies list, etc.

When Options files are functionally similar (for example, for debug and release builds for Linux), one file is used as a base while another includes it and redefines a few variables.

Build scripts automatically create dependencies file – it is a global stack/deps file.

Another problem stack/dups file causes is a necessity to include it in the Options file.

Root Makefile can't include Options file because at the time of the first build the stack/depth file does not exist and the make utility will fail.

The solution is to use the Platform file, which is included by every file (directly by root Makefile and indirectly from others – via Options file). That file contains the definition of the PLATFORM variable, so the root Makefile can correctly set up links at the leaf directories.

Root Makefile does common actions, such as links setup or cleanup, and runs make on its subdirectories.

One more problem which Linux build system also resolves is the existence of two stack builds: full, for ZC/ZR, and limited, for ZED. Both builds are necessary at the same time for testing ZC – ZE work.

This is the reason why the two versions of libraries are compiled with different definitions. The root makefiles have simple declaration of which library needs to be used

Here is an example of leaf makefile for both ed and zc:

BUILD_HOME=../../..
include $(BUILD_HOME)/Options

SRCS1 = tp_pro_bv_27_gZC.c
OBJS1 = ${SRCS1:.c=.o}

SRCS2 = tp_pro_bv_27_DUTZED1.c
OBJS2 = ${SRCS2:.c=.ed.o}

SRCS3 = tp_pro_bv_27_DUTZED2.c
OBJS3 = ${SRCS3:.c=.ed.o}

$(BIN)tp_pro_bv_27_gZC$(EXE) : $(OBJS1)  $(LIBS)
        $(LINK_BINARY)

$(BIN)tp_pro_bv_27_DUTZED1$(EXE) : $(OBJS2)  $(LIBS_ED)
        $(LINK_BINARY_ED)

$(BIN)tp_pro_bv_27_DUTZED2$(EXE) : $(OBJS3)  $(LIBS_ED)
        $(LINK_BINARY_ED)

BINS = $(BIN)tp_pro_bv_27_gZC$(EXE) $(BIN)tp_pro_bv_27_DUTZED1$(EXE) $(BIN)tp_pro_bv_27_DUTZED2$(EXE)

all: $(BINS)

The function of Makefiles in intermediate, non-leaf folders, such as stack/tests/, is to call the make procedure for every directory listed in it.