Sunday, October 7, 2007

Setting Environment Variables From Make Targets

In my current project I needed to pass some pass information to some of my automated unit test programs. I needed the path that the program is being executed from to be able to read test data. As I am using a unit test framework I didn't have access to the command line variables and didn't want to take the time to change the framework to support this. So I decided to define an environment variable with the path information for the program. The unit tests can be run in two different ways, which needed different mechanisms to define the environment variable. The makefiles are setup with rules to run a single set of tests (e.g. make check_config), or running all unit tests (e.g. make check).

To support running a single set of unit tests the make file defines two targets. One that exports the environment variable and one that executes the test. For example:

TST_CONFIG_MODULE := $(d)/test_config
check_config : export TST_DIR:= \
check_config : $(TST_CONFIG_MODULE)

Where the TST_CONFIG_MODULE defines the test program. The first check_config target exports an environment variable TST_DIR that is the directory component of, $(d), of TST_CONFIG_MODULE. The make file has to be structured this way as $(d) will not be valid by the time the target is evaluated.

For the second case the makefiles add test modules to the macro CHECK_MODULES and the check target just executes each element of this macro. As this is executed in a shell the target becomes:

check : $(CHECK_MODULES)
@for m in $(CHECK_MODULES) ; do \
export TST_DIR=`dirname $$m`; \

It is a bit of a kludge to use the dirname executable to get the directory path from the test program name. Doing this assumes that we have dirname installed and that it is on the path. Bash has a built in to do this, ${dirname file}, but there does not seem to be such a builtin in sh.

Setting a Macro to Wildcarded Files

I found a mistake in one of my macro definitions. The macro was to hold all of the public header files and was defined as:

HEADERS := $(d)/*.h

This only set HEADERS to src/include/*.h instead of setting it to the files. To get they desired result the macro was changed to:

HEADERS := $(wildcard $(d)/*.h)