-->
Previous Table of Contents Next


Forcing Recompiles

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 won’t have to wait for a compiler to complete its task.

Macros

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 don’t 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 Sue’s 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:


# Papa’s 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