-->
Previous | Table of Contents | Next |
It is possible to trick make into doing (or not doing) recompiles. An example of a situation in which you may not want make to recompile is when you have copied files from another directory. This operation updates the modification times of the files, though they may not need to be recompiled. You can use the touch utility or make with the -t option to update the modification times of all target files defined in the makefile.
Tip:
Do you want to test your makefile? Use make with the -n option. It will echo the commands to you without actually executing them. Any coding errors written into the file generate proper error messages from the parser, but you wont have to wait for a compiler to complete its task.
make lets you define macros within your makefile which are expanded by make before the program executes the commands found in your makefile. Macros have the following format:
macro identifier = text
The text portion can be the name of a file, a directory, a program to execute, or just about anything. Text can also be a list of files or a literal text string enclosed by double quotes. The following is an example of macros that you might use in your someonehappy makefile:
LIBFILES=/usr/happy/lib/likeatree.a objects = main.o dothis.o CC = /usr/bin/cc 1version=This is one version of someonehappy OPTIONS =
As a matter of convention, macros are usually in uppercase, but they can be typed in lowercase as in the previous example. Notice that the OPTIONS macro defined in the list has no text after the equal sign. This means that you have assigned the OPTIONS macro to a null string. Whenever this macro is found in a command list, make generates the command as if there were no OPTIONS macro at all. By the same token, if you try to refer to an undefined macro, make will ignore it during command generation.
Macros can also include other macros, as in the following example:
BOOK_DIR = /users/book/ >MY_CHAPTERS = ${BOOK_DIR}/pete/book
Macros must be defined before they are used on a dependency line, although they can refer to each other in any order.
make has internal macros that it recognizes for commonly used commands. The C compiler is defined by the CC macro, and the flags that the C compiler uses are stored in the CFLAGS macro.
Macros are referred to in the makefile by enclosing the macro name in curly brackets and preceding the first bracket with a $. If you use macros in the first someonehappy makefile, it might look like this:
# Time to exercise some macros CC = /usr/bin/cc AS = /usr/bin/as OBJS = main.o dothis.o itquick.o YN = yes.h no.h # We could do the following if this part of the path might be used åelsewhere LIB_DIR = /usr/happy/lib LIB_FILES = ${LIB_DIR}/likeatree.a someonehappy: ${OBJS} ${LIB_FILES} ${CC} -o someonehappy ${OBJS} ${LIB_FILES} main.o: main.c cc -c main.c dothis.o: dothis.c cc -c dothis.c itquick.o: itquick.s ${AS} -o itquick.o itquick.s fresh: rm *.o maybe.h: ${YN} cp yes.h no.h /users/sue/
make also recognizes shell variables as macros if they are set in the same shell in which make is invoked. For example, if a C shell variable named BACKUP is defined by
$ setenv BACKUP /usr/happy/backup
you can use it as a macro in your makefile. The macro definition
OTHER_BACKUP = ${BACKUP}/last_week
is expanded by make to be
/usr/happy/backup/last_week
You can reduce the size of your makefile even further. For starters, you dont have to specify the executables for the C and assembler compilers because these are known to make. You can also use two other internal macros, referred to by the symbols $@ and $?. The $@ macro always denotes the current target; the $? macro refers to all the dependents that are newer than the current target. Both of these macros can only be used within command lines. Thus, the makefile command
someonehappy: ${OBJS} ${LIB_FILES} ${CC} -o $@ ${OBJS} ${LIB_FILES}
generates
/usr/bin/cc -o someonehappy main.o dothis.o itquick.o/usr/happy/lib/ ålikeatree.a
when using the following:
$ make someonehappy
The $? macro is a little trickier to use but quite powerful. Use it to copy the yes.h and no.h header files to Sues home directory whenever they are updated. The makefile command
maybe.h: ${YN} cp $? /users/sue/
evaluates to
cp no.h /users/sue/
if only the no.h header file has been modified. It also evaluates to
cp yes.h no.h /users/sue/
if both header files have been updated since the last make of someonehappy.
So, with a little imagination, you can make use of some well-placed macros to shrink your makefile further and arrive at the following:
# Papas got a brand new makefile OBJS = main.o dothis.o itquick.o YN = yes.h no.h LIB_DIR = /usr/happy/lib LIB_FILES = ${LIB_DIR}/likeatree.a someonehappy: ${OBJS} ${LIB_FILES} ${CC} -o $@ ${OBJS} ${LIB_FILES} main.o: main.c cc -c $? dothis.o: dothis.c cc -c $? itquick.o: itquick.s ${AS} -o $@ $? fresh: rm *.o maybe.h: ${YN} cp $? /users/sue/
Previous | Table of Contents | Next |