Thursday, August 20, 2015

Yet Another Make Tutorial - VI

Last post we created a framework to build a library, a unit test program, and a production program. Let's make a few changes to introduce the building of a library.

[This is a continuation of posts  III, and III, IV, and V. Make files are found here.]

Building a library requires a different program than clang, clang++, gcc, or g++. The program is called ar, for archive.

The standard arguments are:

ar rvf <libraryname>.a <object files>

Note: gcc (clang) requires, when using the -l switch to build a program, that the library name starts with the three letters lib, and the three letters lib are not supplied with the -l switch. The .a extension is also assumed.

For example:

# Create libmylibrary.
ar rvf libmylibrary.a iseven.o isnumber.o

#Use libmylibrary.a with gcc
gcc -o aprogram -lmylibrary

The ar program will be used for our $(TARGET): $(OBJS_C) $(OBJS_CXX) command in our make file in the lib directory.

The $(TARGET): $(OBJS_C) $(OBJS_CXX) command in the target and unitest directories will have have -lmylibrary added.

In addition, gcc (or clang) needs to know the path to the library. That is supplied with the -L switch (uppercase L). -L../lib/target

Duplicating two hard coded library names is not good coding practice.

In addition, the dependency list has to have the library added.

$(TARGET): $(OBJS_C) $(OBJS_CXX) ../lib/target/libmylibrary.a

Now there are three hard coded locations for the library.

Let's solve this problem using make variables.

One variable can hold the -L path and one variable can hold the -l library name.

But we have a problem, if the variables are defined in the lib directory make file, the variables are not seen by the unitest and target make files as the lib make file is a child of the parent make file. Variables don't flow up from the child make files.

If we define parts of the -L variable and the -l variable in the parent, pass them as variables to the child make file. We only change to the parent make file is the name of the library.

# makefile17

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

.PHONY: all clean

all: build_unitest build_target

clean:
  $(MAKE) -C $(TARGET) -f makefile17target clean
  $(MAKE) -C $(UNITEST) -f makefile17unitest clean
  $(MAKE) -C $(LIB) -f makefile17lib clean

build_target: build_lib 
  $(MAKE) -C $(TARGET) -f makefile17target LIBRARY=$(MYLIBRARY) LIBDIR=$(LIB)

build_unitest: build_lib
  $(MAKE) -C $(UNITEST) -f makefile17unitest LIBRARY=$(MYLIBRARY) LIBDIR=$(LIB)

build_lib:
  $(MAKE) -C $(LIB) -f makefile17lib LIBRARY=$(MYLIBRARY)


We've added the variable MYLIBRARYWe have added arguments to the make commands.

The argument of the form

<name>=<string>

defines <name> as a variable with the contents of <string>. <name> is a variable that is then available when make is run.

For the build_lib target, makefile17lib will have LIBRARY defined as mylibrary.

We will have a convention in directory names. The directory under lib where libmylibrary.a will be built is target. Yes, it is hard coded. A variable could be created, LIB_DIR_TARGET, but target will be fine for this tutorial.

Below are the other Make16 make files updated to use the new arguments. [Not complete makexx17 files]


# Makefile17lib

# Build the library

LIB_NAME := lib$(LIBRARY).a
TARGET_DIR := target

.PHONY: all clean

all: $(TARGET_DIR)/$(LIB_NAME)

clean:

$(TARGET_DIR)/$(LIB_NAME) :
mkdir -p $(TARGET_DIR)
cd $(TARGET_DIR)
touch $(TARGET_DIR)/$(LIB_NAME)



# makefile17unitest

LIB_NAME := lib$(LIBRARY).a


.PHONY: all clean

all: unitest

clean:

unitest: ../$(LIBDIR)/target/$(LIB_NAME)
echo Build unitest



# makefile17target

# Build the target program

LIB_NAME := lib$(LIBRARY).a

.PHONY: all clean

all: aprogram

clean:

aprogram: ../$(LIBDIR)/target/$(LIB_NAME)
echo Build target


The make files still don't do much, but the framework is coming into shape. We parameterized the library name.

Next post is to add some code. Add the make file commands from makefile15 to build a library, a unit test, and a program.

Next blog  VII.

No comments:

Post a Comment