hua@cmu-cs-edu2.ARPA (Ernest Hua) (06/30/85)
___________________________________________________________________________ Got another question for y'all wizards out there ... Are there utilities (perhaps "make" improvements) that take into account source file dependencies that sit in several places (some possibly in libraries). I have several programs that depend upon quite a few object files and each of them reside in a separate directory that could be moved at any time. I tried placing the common subroutines in libraries, but I could not figure out how to detect a revised library and recompile all dependent programs. It comes down to this: If I revise a particular source file, how do I systematically find all programs dependent upon the corresponding object file without resorting to some sledgehammer manual hack of sorts? Some examples of "sledgehammer manual hacks": - A single cover-everything makefile. - Using "find" to search through all makefiles and to examine all "#includes". All solutions are GREATLY APPRECIATED! ___________________________________________________________________________ Live long and prosper. Keebler { hua@cmu-cs-gandalf }
itkin@luke.UUCP (Steven List) (07/04/85)
In article <209@cmu-cs-edu2.ARPA> hua@cmu-cs-edu2.ARPA (Ernest Hua) writes: >Are there utilities (perhaps "make" improvements) that take into account >source file dependencies that sit in several places (some possibly in >libraries). I'm posting a reply rather than mailing to Ernest for two reasons: I hope what I'm posting will be of interest and I'd like to hear a little discussion. The approach we've taken is to build a hierarchy of makefiles that are each specific to a directory and a level. Thus, to build a "system" composed of several programs, the directory structure might look like: root | --------------------------------------------------- | | | | | | | | bin include lib sh src1 src2 src3 src4 In each named directory, there is a makefile (with the possible exception of `bin'). In the root there is another makefile. Since the makefiles are all designed to work together, it is possible to cause all interrelated parts to be remade with a single command, invoking the smarts inherent in make. When you expand this upward into a larger tree, the whole system still hangs together, since you end up with a tree of executive makefiles at each node and individual makefiles at each leaf. What follows are two templates: our executive makefile template and our individual makefile template. The executive is used in any directory that is strictly the root of a subtree rather than containing sources. I would like to solicit comment on these, since we have found them quite useful, but they still do have problems. Also note in the individual makefile template the use of the `depend:' target - it invokes the `mdep' program I recently posted through mod.sources. The print target also uses one of my recently posted programs, `cpg'. Substitute your own program here. -------------------------------executive template------------------------- ###################################################################### # # Executive Makefile for SuperSubsystem/Subsystem/Function _______________ # ###################################################################### MFLAGS = # # Tape device for making tapes # TAPE = /dev/nrmt0 # ###################################################################### # # list of directories under this executive # DIRS = \ XX_ # # all documentation for this product # PDOC = doc/XX_xmit.mem # # all executables that are part of this product # PBINS = \ bin/XX_ # # all shell scripts that are part of this product # PSH = \ sh/XX_conf.sh # # compile and load the entire product # ###################################################################### exe: dirs @for i in $(DIRS);\ do \ echo "\n\tprocessing $$i - `date`\n"; \ cd $$i;\ $(MAKE) $(MFLAGS) $@; \ cd ..; \ done # # ensure that all necessary directories exist before starting # the builds # dirs: @if [ -z "$(DIRS)" ]; \ then \ echo "\n\tNo Directories in this executive\n";\ exit 99;\ fi @for i in $(DIRS) bin lib include sh ;\ do \ if [ ! -d $$i ];\ then \ mkdir $$i;\ echo "\tmaking directory $$i";\ fi; \ touch 0101010101 $$i/ignore ;\ done # # make the transmittal tape for Development to give to CM # create the list of checksums at the same time # tape: @echo "\n\tFirst, the checksums" @sum $(PBINS) $(PMSGS) $(PSH) > sumdev @echo "\tNow put the checksums and executive files on tape" @tar cvbf 20 $(TAPE) sumdev makefile $(PDOC) @for i in $(DIRS); \ do \ echo "\n\tprocessing $$i - `date`\n"; \ cd $$i; \ $(MAKE) $(MFLAGS) $@ TAPE=$(TAPE) TD=$$i; \ cd ..; \ done @echo "\nDONE MAKING XMITAL TAPE\n" # # make the archive tape for CM to store # tapear: @tar cbvf 20 $(TAPE) $(PBINS) $(PSH) $(PFORMS) $(PMSGS) @tar cvbf 20 $(TAPE) sumcm makefile $(PDOC) @for i in $(DIRS); \ do \ echo "\n\tprocessing $$i - `date`\n"; \ cd $$i; \ $(MAKE) $(MFLAGS) tape TAPE=$(TAPE) TD=$$i; \ cd ..; \ done @echo "\nDONE MAKING ARCHIVE TAPE\n" # # make the install tape for CM to give to Product Support # tapeins: @tar cbvf 20 $(TAPE) $(PBINS) $(PSH) $(PFORMS) $(PMSGS) sumcm @echo "\nDONE MAKING INSTALL TAPE\n" # # for CM: generate and verify checksums of components # sumcheck: @sum $(PBINS) $(PMSGS) $(PSH) > sumcm @if diff sumcm sumdev > sums.diff;\ then \ echo "sums differ\n" ; \ else \ echo "sums match\n"; \ fi @if [ -n "$(PFORMS)" ] ; then sum $(PFORMS) >> sumcm; fi # # for CM if sums don't match: generate checksums of all subsys parts # This creates a file called sumlog in each subdirectory # sumlist: @for i in $(DIRS); \ do \ echo "\n\tprocessing $$i - `date`\n"; \ cd $$i; \ $(MAKE) $(MFLAGS) $@; \ cd ..; \ done # ###################################################################### .PRECIOUS: $(DIRS) # # the default target is good for things like "depend" # .DEFAULT: @echo "Start $@ at `date`" for i in $(DIRS);\ do\ echo "-------------------------------" echo "\tProcessing $$i" echo "-------------------------------" cd $$i; $(MAKE) $(MFLAGS) $(MTARG) TD=$$i $@; cd ..;\ done @echo "End $@ at `date`" force: --------------------------------individual makefile----------------------- ###################################################################### # # Makefile for Subsystem/Function XX # ###################################################################### # # DBASE is defined in the environment to be the `development' base # in which useful stuff is rooted. It could be `/usr' or any other # directory # ###################################################################### # # In this makefile, there are two possibilities: # # 1) An archive is built and the executable loaded from the # archive # This uses the LIB, LOBJ macros # 2) An executable is loaded from individual object modules # The LIB and LOBJ macros are unused # ###################################################################### BIDIR = $(DBASE)/include BLDIR = $(DBASE)/lib BUDIR = /usr/include GIDIR = ../include GLDIR = ../lib GSDIR = ../sh GADIR = ../bin SUMLOG = sumlog TMPDIR = ar.tmp TAPE = /dev/nrmt0 TD = . BLOG = TFLOG = CC = cc $(BLOG) $(TFLOG) $(IFLAGS) IFLAGS = -I$(GIDIR)\ -I$(BIDIR) MAKEFILE = $(TD)/Makefile # .PRECIOUS: $(LIB) ######################### Executable File(s) ######################### EXE = XX_ ######################### Object File(s) ############################# OBJ = XX_.o ######################### Archive Name ############################### LIB = libXX_.a ######################### Objects to Load ############################ LDOBJ = \ $(OBJ) \ $(LIB) \ $(GLDIR)/libYY_.a ########################## Shell Scripts ############################# SH = $(TD)/XX_adb.sh ########################## Source Files ############################## CSRC = \ $(TD)/XX_.c \ $(TD)/XX_arpt.c ########################## Library (archive) Objects ################# LOBJ = \ $(LIB)(XX_arpt.o) ########################## Local Include Files ####################### LINC = \ $(TD)/XX_glob.h \ $(TD)/XX_hdr.h ########################## External Load Dependencies ################ XDEP = \ $(BLDIR)/libXY.a\ $(GLDIR)/libYZ.a ########################## Default/First Target ###################### exe: $(EXE) ###################################################################### $(EXE): $$@.o exedeps $(XDEP) $(CC) $@.o $(LDOBJ) -o $@ ########################## Executable Dependencies ################### exedeps: misc $(OBJ) $(LIB) ########################## Build the Archive, if necessary ########### $(LIB):: $(LOBJ) mkdir $(TMPDIR) cd $(TMPDIR); ar x ../$(LIB); ar cq $(LIB) `lorder *.o |tsort` mv $(TMPDIR)/$(LIB) $(LIB) -rm -rf $(TMPDIR) ###################################################################### misc: $(SH) @if [ -n "$(SH)" ]; then cp $(SH) $(GSDIR); fi ###################################################################### tape: cd ..; tar cbvf 20 $(TAPE) $(MAKEFILE) $(CSRC) \ $(LINC) $(SH) ###################################################################### sumlist: if [ -n "$(OBJ)" ]; \ then \ sum $(OBJ) > $(SUMLOG);\ else \ > $(SUMLOG); \ fi if [ -n "$(LIB)" ]; then\ ar tv $(LIB) >> $(SUMLOG);\ mkdir $(TMPDIR);cd $(TMPDIR);\ ar x ../$(LIB); sum *.o >> ../$(SUMLOG);\ -rm -rf $(TMPDIR);\ fi ###################################################################### ignore:: @touch 0101010101 $@ depend: echo '/^## DO NOT/+1,$$d\nw' | ed - $(MAKEFILE) mdep $(IFLAGS) $(CSRC) | \ sed -e 's-$(BIDIR)-$$(BIDIR)-' \ -e 's-\.\./include-$$(GIDIR)-' \ -e 's-\./--' \ >> $(MAKEFILE) print: cd .. ; cpg -t4 $(MAKEFILE) $(CSRC) $(LINC) $(MSGSRC) $(SH) | lpr include /usr/include/rules.h # Benetics rules ###################################################################### ## DO NOT REMOVE THIS LINE - DEPENDENCIES WILL FOLLOW ###################################################################### -- *** * Steven List @ Benetics Corporation, Mt. View, CA * Just part of the stock at "Uncle Bene's Farm" * {cdp,greipa,idi,oliveb,sun,tolerant}!bene!luke!steven ***