Saturday, August 15, 2015

Yet Another Make File Tutorial - V

The past four tutorials, III, and III, and IV have created a good make file for a sub-directory of sources and kept the build directories clean and neat, as well as configure make to run a bit faster.

[Again the source for these tutorials is found here.]

Note: These make files are NOT POSIX compliant.

These next tutorial(s) will build a production quality set of make files that handle libraries, unit tests, and the production program. There will be more discussion about compilers, linkers, unit tests, libraries as well as make files. Using make files also solves the requirement of having one button builds for build tools such a Jenkins. These next tutorials will set up a framework for production and unit test programs.

Unit tests are the sanity checkers for programmers. They make you feel good because they prove that you haven't messed up with your last set of changes. But building unit tests and that program you want to ship for $$s with the same code takes some planning.

A unit test program has a main(). Your program has a main(). You can't have two main() functions in the same program.

Solution: A library or libraries for your code that isn't main(). Each library gets a directory. Each unit test gets a directory, and the production program gets a directory. Thus three directories, lib, unitest, and target.

Each directory will need a make file. A master make file is required to 'run' each of the other make files.

This tutorial will introduce new make syntax and features.

Our first make file is not a make file that compiles code. It calls other make files. Some of the more experienced readers will see we are starting down the path to make file recursion, where make calls make.

There is an article detailing this topic here. The argument is to create a single make file instead of series of recursively called make files.

Let's start.

The new directory Make16 is where we start.

# makefile16

LIB := lib
UNITEST := unitest
TARGET := target

.PHONY: all clean

all: build_unitest build_target

clean:
$(MAKE) -C $(TARGET) -f makefile16target clean
$(MAKE) -C $(UNITEST) -f makefile16unitest clean
$(MAKE) -C $(LIB) -f makefile16lib clean

build_target: build_lib 
$(MAKE) -C $(TARGET) -f makefile16target

build_unitest: build_lib
$(MAKE) -C $(UNITEST) -f makefile16unitest

build_lib:
$(MAKE) -C $(LIB) -f makefile16lib    

[Links for more details here.]

The -C switch changes the working directory to the next argument. When using -C the option -w is automatically turned on. The -w option outputs Entering <directory> and Leaving <directory>. This helps with debugging.

The $(MAKE) variable is a special variable of the Gnu Make. As has been said before, this tutorial is NOT writing POSIX make files.

The make files for lib, unitest, and target are below. These are just shells. The make files have no source code. make still outputs its messages. There are no errors and the framework is shown correct.

# Makefile16lib

# Build the library

.PHONY: all clean

all: alibrary

clean:


alibrary:

================

# makefile16unitest

.PHONY: all clean

all: unitest

clean:

unitest:

===============

# makefile16target

# Build the target program

.PHONY: all clean

all: aprogram

clean:

aprogram:


To run enter

make -f makefile16

or

make -f makefile16 clean


If you don't want all of the Entering and Leaving messages, add the -s switch.

make -s -f makefile16

No output appears.

Next blog we'll add more details about the library. VI.


No comments:

Post a Comment