.\"
.\" aegis - project change supervisor
.\" Copyright (C) 1994-1996, 1998, 2002, 2004-2008 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
.\" .
.\"
.bp
.nh 2 "Using Make"
.LP
The
\fImake\fP(1)
program exists in many forms,
usually one is available with each
.UX
version.
The one used in the writing of this section is
.I "GNU Make 3.70" ,
available by anonymous FTP from your nearest GNU archive site.
GNU Make was chosen because it was the most powerful,
it is widely available (usually for little or no cost)
and discussion of the alternatives (SunOS make, BSD 4.3 make, etc),
would not be universally applicable.
"Plain vanilla" make
(with no transitive closure, no pattern rules, no functions)
is not sufficiently capable to satisfy the demands placed on it by Aegis.
.LP
With the introduction of the \fIdevelopment_\%directory_\%style\fP field of
the project configuration file, any project which is currently using
a "plain vanilla" make may continue to use it, and still manage the
project using Aegis.
.LP
As mentioned earlier in this chapter,
.I make
is not really sufficient,
because it lacks dynamic include dependencies.
However,
GNU Make
has a form of dynamic include dependencies,
and it has a few quirks, but mostly works well.
.LP
The other feature lacking in
.I make
is a search path.
While
GNU Make
has functionality called
.I VPATH ,
the implementation leaves something to be desired,
and can't be used for the search path functionality
required by Aegis.
Because of this,
the
.I development_\%directory_\%style.\%source_\%file_\%symlink
field of the project
configuration
file is set to
.I true
so that Aegis will arrange for the development
directory to be full of symbolic links,
making it appear that the entire project source
is in each change's development directory.
.nh 3 "Invoking Make"
.LP
The
.I build_command
field of the project
configuration
file is used to invoke the relevant build command.
In this case, it is set as follows
.E(
build_command =
"gmake -f ${s Makefile} project=$p \e
change=$c version=$v";
.E)
.LP
This command tells make
where to find the rules.
The \f(CW${s Makefile}\fR expands to a path into the baseline
during development
if the file is not in the change.
Look in
.I aesub (5)
for more information about command substitutions.
.LP
The rules which follow will all remove their targets before constructing
them, which qualifies them for the next entry in the
configuration
file:
.E(
link_integration_directory = true;
.E)
.LP
The files must be removed first, otherwise the baseline would be
corrupted by integration builds (or even by developer builds, if your
aren't using a separate user for the project owner).
.LP
\fBNote:\fP if you are migrating an existing project \fBdo not set this
field\fP; only set it \fIafter\fP you have changed \fIall\fP of the Make
rules. If in doubt, \fBdon't\fP set this field.
.LP
Another field to be set in this file is
.E(
development_directory_style =
{
source_file_symlink = true;
};
.E)
which tells Aegis to maintain symbolic links between the development
directory and the baseline for source files (but not derived files).
See \fIaepconf\fP(5) for more information.
.nh 3 "The Rule File"
.LP
The file containing the rules is called
.I Makefile
and is given to make on the command line.
.LP
The following items are preamble to the rest of the file;
they ask Aegis for the source files of the project and change
so that make can determine what needs to be compiled and linked.
.E(
project_files := \e
$(shell aelpf -p $(project) \e
-c $(change))
change_files := \e
$(shell aelcf -p $(project) \e
-c $(change))
source_files := \e
$(sort $(project_files) \e
$(change_files))
CC := gcc
CFLAGS := -O
.E)
.LP
This example parallels the one from chapter 3,
and thus has a single executable
to be linked from all the object files
.E(
object_files := \e
$(patsubst %.y,%.o,$(filter \e
%.y,$(source_files))) \e
$(patsubst %.l,%.o,$(filter \e
%.l,$(source_files))) \e
$(patsubst %.c,%.o,$(filter \e
%.c,$(source_files)))
.E)
.LP
Constructing the program is straightforward,
remembering to remove the target first.
.E(
example: $(object_files)
rm -f example
$(CC) -o example $(object_files) \e
-ly -ll
.E)
.LP
This rule says that to make the example program,
you need the object files determined earlier,
and them link them together.
Object files which were up to date in the baseline are used wherever possible,
but files which were out of date are constructed in the current directory
and those will be linked.
.nh 3 "The Rule for C"
.LP
Next we need to tell make how to manage C sources.
On the surface, this is a simple rule:
.E(
%.o: %.c
$(CC) $(CFLAGS) -c $*.c
.E)
This example matches the built-in rule for most \fImake\fPs.
But it forgets to remove the target before constructing it.
.E(
%.o: %.c
rm -f $*.o
$(CC) $(CFLAGS) -c $*.c
.E)
The target may not yet exist, hence the \fI-f\fP option.
.LP
Something missing from this rule is
finding the include file dependencies.
The GNU Make User Guide
describes a method for obtaining include file dependencies.
A set of dependency files are constructed,
one per \fI.c\fP file.
.E(
%.d: %.c
rm -f %.d
$(CC) $(CFLAGS) -MM $*.c \e
| sed 's/^\e(.*\e).o :/\e1.o \e1.d :/' \e
> $*.d
.E)
These dependency files are then included into the
.I Makefile
to inform GNU Make of the dependencies.
.E(
include $(patsubst \e
%.o,%.d,$(object_files))
.E)
GNU Make has the property of making sure all its include files are up-to-date.
If any are not, they are made,
and then GNU Make starts over,
and re-reads the Makefile and the include files from scratch,
before proceeding with the operation requested.
In this case, it means that our dependency construction rule will be applied
before any of the sources are constructed.
.LP
This method is occasionally quirky about absent include files
which you have yet to write,
or which are generated and don't yet exist,
but this is usually easily corrected,
though you do need to watch out for things which will stall an integration.
.LP
The \fI-MM\fP option to the $(CC) command
means that this rule requires the \fIgcc\fP program
in order to work correctly.
It may be possible to use
.I c_incl (1)
from cook, or
.I ccincl (1)
from cake to build the dependency lists
instead;
but they don't understand the conditional preprocessing as well as
.I gcc
does.
.LP
This method also suffers when heterogeneous development is performed.
If you include different files,
depending on the environment being compiled within,
the \fI.d\fP files may be incorrect,
and GNU Make has no way of knowing this.
.nh 4 "Include Directives"
.LP
Unlike
.I cook
described in an earlier section,
using GNU Make as described here
allows you to continue using the
.E(
#include "\fIfilename\fP"
.E)
form of the include directive.
This is because the development directory appears,
to the compiler,
to be a complete copy of the baseline.
.nh 3 "The Rule for Yacc"
.LP
Having explained the complexities of the rules in the above section about C,
the rule for yacc will be given without delay:
.E(
%.c %.h: %.y
rm -f $*.c $*.h y.tab.c y.tab.h
$(YACC) $(YFLAGS) -d $*.y
mv y.tab.c $*.c
mv y.tab.h $*.h
.E)
.LP
This rule could be jazzed up to cope with the listing file,
too,
if that was desired,
but this is sufficient to work with the example.
.LP
GNU Make's ability to cope with transitive closure will
pick up the generated \fI.c\fP file and construct the necessary \fI.o\fP file.
.LP
To prevent GNU Make throwing away the transitive files,
and thus slowing things down in some cases,
make them precious:
.E(
\&.PRECIOUS: \e
$(patsubst %.y,%.c,$(filter \e
%.y,$(source_files))) \e
$(patsubst %.y,%.h,$(filter \e
%.y,$(source_files)))
.E)
.nh 3 "The Rule for Lex"
.LP
The rule for lex is vary similar to the rule for yacc.
.E(
%.c: %.l
rm -f $*.c lex.yy.c
$(LEX) $(LFLAGS) $*.l
mv lex.yy.c $*.c
.E)
.LP
GNU Make's ability to cope with transitive closure will
pick up the generated \fI.c\fP file and construct the necessary \fI.o\fP file.
.LP
To prevent GNU Make throwing away the transitive files,
and thus slowing things down in some cases,
make them precious:
.E(
\&.PRECIOUS: \e
$(patsubst %.l,%.c,$(filter \e
%.l,$(source_files)))
.E)
.nh 3 "Rules for Documents"
.LP
You can format documents,
such as user guides and manual entries with Aegis and GNU Make,
and the rules are similar
to the ones above.
.E(
%.ps: %.ms
rm -f $*.ps
groff -p -t -ms $*.ms > $*.ps
.E)
.LP
This rule says to run the document through groff,
with the
.I pic (1)
and
.I tbl (1)
filters,
use the
.I ms (7)
macro package,
to produce PostScript output.
.LP
This omits include file dependencies.
If this is important to you,
the
.I c_incl
program from
.I cook
can be used to find them.
Filtering its output can then produce the necessary dependency files
to be included,
rather like the C rules, above.
.LP
Manual entries may be handled in a similar way
.E(
%.cat: %.man
rm $*.cat
groff -Tascii -s -t -man $*.man \e
> $*.cat
.E)
.nh 3 "Other Makes"
.LP
All of the above discussion assumes that GNU Make and GCC are used.
If you do not want to do this,
or may not do this because of internal company politics,
it is possible to perform all of the automated features manually.
.LP
This may, however, rapidly become spectacularly tedious.
For example: if a user needs to copy the
.I Makefile
into their change for any reason,
they will need to constantly use
.I aed (1)
to "catch up" with integrations into the baseline.
.LP
Reviewers are also affected:
they must check that each change to the
.I Makefile
accurately reflects the
object list and the dependencies of each source file.
.nh 3 "Templates"
.LP
The
.I lib/config.example/make
file in the Aegis distribution
contains all of the above commands,
so that you may readily insert them into your project
configuration
file.
.nh 3 "GNU Make VPATH Patch"
.LP
Version 3.76 and later of GNU Make include this patch, so you don't need
to read this section unless you have GNU Make 3.75 or earlier.
.LP
There is a patch available for GNU Make 3.75 and earlier which gives
it improved VPATH semantics. At the time it was not maintained by the
same person who maintained GNU Make. Since then, the maintaier changed,
and the patch has been incorporated.
.LP
The patch is the work of
Paul D. Smith
and may be fetched By Anonymous FTP from
.TS
l l.
Host: ftp.wellfleet.com
Dir: /netman/psmith/gmake
File: vpath+.README
File: vpath+.patch.\fIversion\fP
.TE
The version numbers track the GNU Make version numbers.
.LP
For a description of the VPATH problem, and how this patch addresses it,
see the README file referenced.
.nh 3 "GNU Make's VPATH+"
.LP
In theory, using GNU Make 3.76 or later (or a suitable patched earlier
version) is similar to using Cook.
The project
configuration
file now requires
.E(
link_integration_directory = false;
.E)
which is the default.
The
.I Makefile
now requires
.E(
VPATH . bl
.E)
Assuming that
.I bl
is a symbolic link to the baseline.
The \f(CW.d\fP files continue to be used.