Ron Heiby (The Moderator) <unix-request@cbosgd.UUCP> (03/26/85)
Unix Technical Digest Tue, 26 Mar 85 Volume 1 : Issue 33 Today's Topics: Administrivia make depend Multi-step implicit rules for make(1) What's wrong w/this makefile? (.SUFFIXES:) What's wrong with this picture (makefile bug?) (2 msgs) ---------------------------------------------------------------------- Date: Tue, 26 Mar 85 19:48:58 GMT From: Ron Heiby (The Moderator) <unix-request@cbosgd.UUCP> Subject: Administrivia The last four articles in this digest are in response to a question on "make" that was included in Volume 1, Issue 26 of the mod.unix digests. I have received several notes indicating strong interest/confusion regarding "make", so have included all four in their entirety, although some of the material is duplicated. Each contains valuable information on how "make" works and should be used. The first article is from another conversational thread, but looked interesting. The only commonly available documentation on "make" that I have found to be of any use is in the "Unix System V - Release 2.0 Support Tools Guide" from AT&T, April 1984, 307-108, Issue 2. I don't know what it costs. Many other tools are described in there, as well. Ron. ------------------------------ Date: 24 Mar 85 21:49:19 GMT From: throopw@rtp47.UUCP (Wayne Throop) Subject: make depend > > ... > > People don't keep their dependency lists up to date, things > > ... > > Guy Harris > > I agree entirely with Guy concerning the importance of automated > dependeny generators. > ... > The solution is to use ONLY source files as a basis for > dependency generation. > ... > Kim Walden Kim's solution seems quite good given the way make works. If you are willing to change make's model of the world, another solution becomes available. In particular, if a make-like tool allowed dependencies to be specified dynamically, the problem of intermediate files being needed before make is invoked (to allow dependencies to be discovered) becomes a non-problem. There are many ways for make to be modified to allow for dynamic inputs, but suppose a syntax something like foo.o: foo.c (foo.c; find_includes foo.c) cc -c foo.c foo.c: foo.x make_c_from_x foo.x The parenthesized text specifies a list of inputs to the "command" at the end of the list. The output of the command will be a list of include files, and the effect is as though that list of files had been supplied instead of the parenthesized text. What make would do for this makefile fragment would be to invoke make_c_from_x, then invoke find_includes (discovering any include file dependencies of foo.c), and then cc foo.c, producing foo.o. This is essentially an "incremental make-file generator". It has problems, such as what to do about include files that include other files, and so on, but these problems can be overcome. Note also that make would then need a database of already-run dynamic input lists, for efficency (otherwise it would need to re-run find_includes every time make runs, not just when foo.c changes). ------------------------------ Date: 20 Mar 85 23:48:50 GMT From: hoey@nrl-aic.ARPA (Dan Hoey) Subject: Multi-step implicit rules for make(1) In <177@osiris.UUCP> eric@osiris.UUCP (Eric Bergan) has a problem with make's use of implicit rules. An example of the problem can be seen with a makefile like .SUFFIXES: .D .C .B .A CONVERT_A_TO_B=cp CONVERT_B_TO_C=cp CONVERT_C_TO_D=cp .A.B: $(CONVERT_A_TO_B) $< $@ .B.C: $(CONVERT_B_TO_C) $< $@ .C.D: $(CONVERT_C_TO_D) $< $@ all: foo.D Executed in a directory with only makefile and foo.A, this make will complain that it doesn't know how to make foo.D. As both howard@cyb-eng.UUCP (Howard Johnson) and greg@ncr-tp.UUCP (Greg Noel) have pointed out, the problem is that for an implicit make rule ".A.B" to be invoked foo.A must either exist or be mentioned as a target or dependent in some rule. Thus the problem can be circumvented by the addition of the dependency foo.D: foo.B foo.C or even foo.C: foo.B in the makefile. One problem with adding lines like this is that they must be added for bar.D, baz.D, ad infinitum. Another problem is that the methods fool make's error handling. If we instead add the line foo.D: foo.B make will create only foo.B, with no complaints. The problem is that it treats "foo.D" as a target like "all" in this case, not as a file that must be created. We now turn to methods for getting make to use implicit rules to create foo.D. Both Howard and Greg propose adding a rule like .A.D: $(CONVERT_A_TO_B) $< $*.B $(CONVERT_B_TO_C) $*.B $*.C $(CONVERT_C_TO_D) $*.C $@ (their solutions are identical except for Greg's cleanup line rm -f $*.B $*.C ) to the makefile. In this case, with four suffixes involved, we might want to also add rules for .A.C: and .B.D:. I find these methods unsatisfactory because of the proliferation of the information about the commands used for converting one object into another. For instance, if the procedure for $(CONVERT_B_TO_C) took the arguments in the opposite order, we would have to change the information in two or three rules. I would suggest that the rules to be added should tell make to use the previously defined implicit rules, for example .A.D .B.D: @make $(MFLAGS) $*.C $@ rm -f $*.C .A.C: @make $(MFLAGS) $*.B $@ rm -f $*.B There are a few things to watch out for here. For one thing, the inclusion of $(MFLAGS) does not pass all of make's invocation to the subsidiary make. If you expect to invoke this script as, for instance ``make CONVERT_B_TO_C=mv'', you must set up the recursive invocations to say ``@make CONVERT_B_TO_C=$(CONVERT_B_TO_C) $(MFLAGS) ...''. It is clear this could get out of hand. And if you like to try things out with ``make -f fakefile'' you had better forget this approach entirely. Another thing to watch out for is the ordering of ".SUFFIXES:". The dependents of .SUFFIXES must be in reverse temporal order for this to work. Since lines like ".SUFFIXES: .A" append to the list of suffixes, this is sufficient if you want to add preprocessors to your source files. If you want to add postprocessors to targets already known to make, be sure to start with a ``.SUFFIXES:'' line with no dependents. It would of course be nicer if we could get make to know how to recursively apply its own implicit rules as it does for explicit rules, but I suppose there are problems with that. Dan Hoey Navy Center for Applied Research in Artificial Intelligence ------------------------------ Date: 14 Mar 85 21:58:57 GMT From: howard@cyb-eng.UUCP (Howard Johnson) Subject: What's wrong w/this makefile? (.SUFFIXES:) The problem with Mr. Bergan's makefile stems from the evaluation of the .SUFFIXES dependencies. His goal was to have a preprocessor perform some transformation on his source code and produce C code (presumably "cat" is for illustration). The solution: .SUFFIXES: .qc mtest: mtest.o $(CC) -o $@ mtest.o .qc.o: cat $< > $*.c $(CC) $(CFLAGS) -c $*.c .qc.c: # optional rule so "make mtest.c" works cat $< > $*.c The problem with Mr. Bergan's first example is discussed below: > .SUFFIXES: .qc > > .qc.c: > cat $< >mtest.c > > mtest: mtest.o > cc -o mtest mtest.o First, "make mtest" is invoked. Unless a .SUFFIXES: dependency with nothing after the colon is given (to clear default dependencies), the .qc suffix is appended to a default list producing something like: .SUFFIXES: .o .c .e .r .f .y .yr .ye .l .s .qc "mtest" depends on "mtest.o". Since there are no explicit dependencies for mtest.o, the .SUFFIXES list is scanned. Note that the first suffix which has an implicit dependency for .o is .c. Several other implicit dependency rules are found, but none of them have the inferred prerequisites either. (This includes the .qc prerequisite, since there is no .qc.o rule.) Hence, *make* gives up, complaining that (most likely) the prerequisite mtest.c file is missing. Mr. Bergan's quick fix (including the explicit "mtest.o: mtest.c" dependency) works because it forces make to match the .SUFFIX dependencies for a .qc.c rule. After wading through a few 10-page makefiles, one soon has motivation to learn about details such as this. -- Howard Johnson Cyb Systems, Austin, TX cyb-eng!howard@ut-sally.ARPA or ..!{gatech,harvard,ihnp4,nbires,seismo,ucb-vax}!ut-sally!cyb-eng!howard ------------------------------ Date: 15 Mar 85 17:07:00 GMT From: gdsd1@homxb.UUCP (M.LAI) Subject: What's wrong with this picture (makefile bug?) Try: .SUFFIXES: .qc .qc: cat $< > $(?:.qc=.c) $(CC) $(CFLAGS) -o $@ $(?:.qc=.c) @rm $(?:.qc=.c) and you won't need to specify any dependencies. Just: $ make mtest cat mtest.qc > mtest.c cc -O -o mtest mtest.c Neal Nuckolls ..!houxa!homxb!gdsd1 ------------------------------ Date: 19 Mar 85 05:49:47 GMT From: greg@ncr-tp.UUCP (Greg Noel) Subject: What's wrong with this picture (makefile bug?) In article <177@osiris.UUCP> eric@osiris.UUCP (Eric Bergan) writes: >......................................... Has anyone gotten user defined >suffixes to work correctly? Er, I don't know how to break this to you, but make is working exactly as advertised; it is your makefile that is not correct. The thing you need to understand is that make will take no leaps of faith in finding the files it needs -- in other words, it won't chain rules together. In particular, the fragment: > mtest: mtest.o > cc -o mtest mtest.o says that mtest depends upon mtest.o -- a reasonable thing. Since mtest.o does not exist, make now tries to find a way to make it. It does this by searching for a rule of the form ".XXX.o" for which mtest.XXX \already/ \exists/. It can't find it, hence it says "don't know how to make mtest.o". > However if I do "make mtest.c" and then "make mtest" it works fine. Yep -- it knows how to convert mtest.qc into mtest.c using the rule you have given and it knows how to convert mtest.c into mtest.o using the built-in rule, but it won't chain the rules. If you think about it, this is a reasonable restriction: suppose you have the rules .y.c, .y.s, .c.o, and .s.o and you want to convert xx.y into xx.o -- there are two possible paths (.y => .c => .o and .y => .s => .o) and it couldn't chose between them. > If I change the makefile to: > > [ same as before ] > > mtest.o: mtest.c > >and the only file is "mtest.qc", and I do a "make mtest", it works fine. Again true -- this time you have given make an explicit dependancy so that make knows that it must create mtest.c, so it searchs to find a rule .XXX.c for which a file mtest.XXX already exists; it finds the rule .qc.c and the file mtest.qc. It then applies the rule, making mtest.c, and then tries to make mtest.o again. Since you didn't give any specific actions for making mtest.o, it applies the search rules again, looking for a rule .XXX.o and a file mtest.XXX; this time it finds .c.o and mtest.c. (Just because you said you needed it doesn't mean that make will use it -- if you had a mtest.s in the directory (and the .SUFFIXES were in a slightly different order), this makefile would make mtest.c as you told it, but then it would make mtest.o by assembling mtest.s. It can be confusing at times......) To cause make to combine the rules in the way you want, you must explicitly tell it how. I.e., you must have a rule that goes from your special suffix all the way to the desired object: .SUFFIXES: .qc .qc.o: cat $< >$*.c $(CC) $(CFLAGS) -c $*.c rm -f $*.c Hope this helps. -- -- Greg Noel, NCR Torrey Pines Greg@ncr-tp.UUCP or Greg@nosc.ARPA ------------------------------ End of Unix Technical Digest ****************************** -- Ronald W. Heiby / ihnp4!{wnuxa!heiby|wnuxb!netnews} AT&T Information Systems, Inc. Lisle, IL (CU-D21)