.\"
.\" aegis - project change supervisor
.\" Copyright (C) 1997, 2001, 2002, 2006-2008, 2010, 2012 Peter Miller
.\"
.\" This program is free software; you can redistribute it and/or modify
.\" it under the terms of the GNU General Public License as published by
.\" the Free Software Foundation; either version 3 of the License, or
.\" (at your option) any later version.
.\"
.\" This program is distributed in the hope that it will be useful,
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
.\" General Public License for more details.
.\"
.\" You should have received a copy of the GNU General Public License
.\" along with this program. If not, see .
.\"
.nh 1 "The Big Picture"
This section brings together all of the preceding discussion, and
presents the example project with its separate modules, but with a
whole\[hy]project \f(CWMakefile\fP. The directory structure is changed
little from the recursive case, except that the deeper \f(CWMakefiles\fP
are replaced by module specific include files:
.so lib/en/auug97/07.figure1.so
.LP
The \f(CWMakefile\fP looks like this:
.TS H
center,box;
lw(2.5i)f(CW).
.TH
MODULES := ant bee
.sp 0.2
# look for include files in
# each of the modules
CFLAGS += $(patsubst %,\-I%,\e
$(MODULES))
.sp 0.2
# extra libraries if required
LIBS :=
.sp 0.2
# each module will add to this
SRC :=
.sp 0.2
# include the description for
# each module
include $(patsubst %,\e
%/module.mk,$(MODULES))
.sp 0.2
# determine the object files
OBJ := \e
$(patsubst %.c,%.o, \e
$(filter %.c,$(SRC))) \e
$(patsubst %.y,%.o, \e
$(filter %.y,$(SRC)))
.sp 0.2
# link the program
prog: $(OBJ)
$(CC) \-o $@ $(OBJ) $(LIBS)
.sp 0.2
# include the C include
# dependencies
include $(OBJ:.o=.d)
.sp 0.2
# calculate C include
# dependencies
%.d: %.c
depend.sh `dirname $*.c` \e
$(CFLAGS) $*.c > $@
.TE
This looks absurdly large, but it has all of the common elements in the
one place, so that each of the modules' \fImake\fP includes may be small.
.LP
The \f(CWant/module.mk\fP file looks like:
.TS
center,box;
lw(2.5i)f(CW).
SRC += ant/main.c
.TE
The \f(CWbee/module.mk\fP file looks like:
.TS
center,box;
lw(2.5i)f(CW).
SRC += bee/parse.y
LIBS += \-ly
.sp 0.2
%.c %.h: %.y
$(YACC) \-d $*.y
mv y.tab.c $*.c
mv y.tab.h $*.h
.TE
.LP
Notice that the built\[hy]in rules are used for the C files,
but we need special yacc processing to get the generated \f(CW.h\fP file.
.LP
The savings in this example look irrelevant, because the top\[hy]level
\f[CW]Makefile\fP is so large. But consider if there were 100 modules,
each with only a few non\[hy]comment lines, and those specifically relevant
to the module. The savings soon add up to a total size often \fIless
than\fP the recursive case, without loss of modularity.
.LP
The equivalent DAG of the \f(CWMakefile\fP after all of the includes
looks like this:
.so lib/en/auug97/07.figure2.so
.LP
The vertexes and edges for the include file dependency files are also
present as these are important for \fImake\fP to function correctly.
.nh 2 "Side Effects"
There are a couple of desirable side\[hy]effects of using a single Makefile.
.LP
\(bu
The GNU Make \f[CW]\-j\fP option, for parallel builds, works even better
than before. It can find even more unrelated things to do at once,
and no longer has some subtle problems.
.\" My thanks to Marcus Harnisch for this
.\" insight into parallel build problems.
.LP
\(bu
The general make \f[CW]\-k\fP option, to continue as far as possible even
in the face of errors, works even better than before. It can find even
more things to continue with.
.\" vim: set ts=8 sw=4 et :