Topic : Writing Makefiles
Author : LUPG
Page : << Previous 2  
Go to page :

For Everyone - Using "File Type" Rules
So, the next phase would be to eliminate the redundant rules, and try to use one rule for all source files. After all, they are all compiled in the same way. Here is a modified makefile:

# we'll skip all the variable definitions, just take them from the previous
# makefile
# linking rule remains the same as before.
$(PROG): $(OBJS)
        $(LD) $(LDFLAGS) $(OBJS) -o $(PROG)

# now comes a meta-rule for compiling any "C" source file.
%.o: %.c
        $(CC) $(CFLAGS) -c $<

We should explain two things about our meta-rule:

The "%" character is a wildcard, that matches any part of a file's name. If we mention "%" several times in a rule, they all must match the same value, for a given rule invocation. Thus, our rule here means "A file with a '.o' suffix is dependent on a file with the same name, but a '.c' suffix".
The "$<" string refers to the dependency list that was matched by the rule (in our case - the full name of the source file). There are other similar strings, such as "$@" which refers to the full target name, or "$*", that refers the part that was matched by the "%" character.

Automatic Creation Of Dependencies
One problem with the usage of implicit rules, is that we lost the full list of dependencies, that are unique to each file. This can be overcome by using extra rules for each file, that only contain dependencies, but no commands. This can be added manually, or be automated in one of various ways. Here is one example, using the "makedepend" Unix program.

# define the list of source files.
SRCS = main.c file1.c file2.c
# most of the makefile remains as it was before.
# at the bottom, we add these lines:

# rule for building dependency lists, and writing them to a file
# named ".depend".
        $(RM) .depend
        makedepend -f- -- $(CFLAGS) -- $(SRCS) > .depend

# now add a line to include the dependency list.
include .depend

Now, if we run "make depend", the "makedepend" program will scan the given source files, create a dependency list for each of them, and write appropriate rules to the file ".depend". Since this file is then included by the makefile, when we'll compile the program itself, these dependencies will be checked during program compilation.

There are many other ways to generate dependency lists. It is advised that programmers interested in this issue read about the compiler's "-M" flag, and read the manual page of "makedepend" carefully. Also note that gnu make's info pages suggest a different way of making dependency lists created automatically when compiling a program. The advantage is that the dependency list never gets out of date. The disadvantage is that many times it is being run for no reason, thus slowing down the compilation phase. Only experimenting will show you exactly when to use each approach.

Page : << Previous 2