.\" .\" aegis - project change supervisor .\" Copyright (C) 1994, 1995, 1996, 1998 Peter Miller; .\" All rights reserved. .\" .\" 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 2 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, write to the Free Software .\" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. .\" .\" MANIFEST: User Guide, The Dependency Maintenance Tool, Using Make .\" .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 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 create_symlinks_before_build field of the project .I config 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 is in each change's development directory. .nh 3 "Invoking Make" .LP The .I build_command field of the project .I config 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 .I config file: .E( link_integration_directory = true; .E) .LP The files must be removed first, otherwise the baseline would cease to be self-consistent. .LP Another field to be set in this file is .E( create_symlinks_before_build = true; .E) which tells aegis to maintain symbolic links between the development directory and the baseline. This also requires that rules remove their targets before constructing them, to ensure that rules do not attempt to write their results onto the read-only versions in the baseline. .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 aegis -l pf -terse -p \e $(project) -c $(change)) change_files := \e $(shell aegis -l cf -terse -p \e $(project) -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 (because the integrator will not have write permission on the integration directory). .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 .I config 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 VAPTH+" In theory, using GNU Make 3.76 or later (or a suitable patched earlier version) is similar to using Cook. The project .I config 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.