rfg@MCC.COM (Ron Guilmette) (03/24/89)
This is *not* really a bug report, although my #2 suggestion below *may* illustrate a "bug" in GNU Make. Some may argue however that the behavior I describe is not a "bug" but a "feature". So be it. I don't really care what you call it so long as there is a way around it. Right now, there does not seem to be. I have three suggestions (Ahem... well requests actually) for very minor enhancements to GNU Make. I would be very glad to get feedback from anyone and everyone on these. Suggestion #1: -------------- Occasionally, I have had to create Makefiles with rules like: file1: file2 -rm -f file1 ln file2 file1 All this does is to make a hard link of "file2" called "file1". The problem is that whenever make is deciding on the up-to- date'ness of a given target file, it decides that the target is up to date *only* if it is strictly *newer* than all of the files it depends on. In the case above, even after the link has been made once, file1 is still *not newer* than file2. thus, the file1 target will be "remade" each and every time the Makefile is executed. This is silly, redundant, and useless. Would it be possible to make a slight change in the criteria used to compute the up-to-date'ness of targets so that a target is considered (by make) to be up-to-date relative to any one of the files it depends on if *either* (a) is is strictly newer than the given file, *or* (b) it has the same inode number as the given file (i.e. if it is a link to the file). Suggestion #2: -------------- If GNU make 3.27 encounters a circular chain of dependencies, is stops right away. This seems like a reasonable response in most cases, but for some applications, it would be nice to just get a warning and somehow try to continue on as though the final dependency link in the circularity wasn't there. I believe that some other versions of make do something like this. This is absolutely necessary if you have a set of include files which *may* seem to be circularly dependent, but which have conditional compilation stuff in them so that they never are really circularly dependent. Consider the following example files: Makefile: --------------------------------------------------------------- one.h: another.h another.h: one.h --------------------------------------------------------------- one.h: --------------------------------------------------------------- #ifndef ONE #define ONE #include "another.h" ... #endif --------------------------------------------------------------- another.h: --------------------------------------------------------------- #ifndef ANOTHER #define ANOTHER #include "one.h" ... #endif --------------------------------------------------------------- The Makefile is correct in asserting that "one.h" depends on "another.h" and vise versa. The problem is that GNU Make will choke on the given Makefile and never do anything because it will refuse to overlook the apparent inconsistancy. Since other versions of make *do* manage to continue in the face of circularities like this, it would certainly seem to be more "standard" if GNU Make did likewise. But, issues of "standardization" aside, perhaps the best way to implement this would be as an optional feature invoked only via a (new) special option. This would prevent unwary users of botched Makefiles from getting any unwarranted effects from Makefiles with "bad" circularities in them, while allowing knowledgable wizards to get the effect(s) they need out of "tricky" Makefiles with intentional circularities. Suggestion #3: -------------- As time goes on, I see (and build) more and more "hierarchies" of include files. Unfortunately, it seems that I am forced to be excessively verbose in my Makefiles in order to fully express all of the dependencies which arise from such hierarchies. As an example, imagine three include files called first.h, second.h, and third.h, and two source files called source_1.c, and source_2.c Now suppose that second.h includes first.h. Also suppose that third.h includes second.h, and that (finally) source_1.c and source_2.c each independently include third.h. Thus, the inclusions are as follows: second.h includes first.h third.h includes second.h source_1.c includes third.h source_2.c includes third.h In a Makefile for these files I have to say: ------------------------------------------------------------------- .c.o: cc $(CFLAGS) -c $< source_1.o: source_1.c third.h second.h first.h source_2.o: source_2.c third.h second.h first.h ------------------------------------------------------------------- This is too verbose. What I would prefer to do would be to express only the "direct" dependencies in my Makefiles, and let "make" figure out what the "indirect" dependencies are. Specifically, for this example situation, I would like to be able to just write: ------------------------------------------------------------------- .c.o: cc $(CFLAGS) -c $< second.h: first.h third.h: second.h source_1.c: third.h source_2.c: third.h ------------------------------------------------------------------- Note here that only the "direct" dependencies are given. It would be possible to write Makefiles this way if only "make" could be instructed to "pass on" dependencies. In the example above, the general effect of "passing on" a dependency could be done easily by changing the defined semantics of "make" as follows: For each (implicit or explicit) dependency rule which has no "action" lines associated with it, if the target file of the rule exists, but has a last-modification time which makes it "older" that any one of the files on which it depends, determine the last-modification time of the "youngest" file on which the given target depends, and, as long as the target file doesn't get updated, "make" *acts* as though the given target file is the same "age" as the youngest file on which it depends. This simple change would allow Makefiles to be enormously simpler and easier to update in response to changes somewhere up in the include hierarchy. This semantic extension could be implemented via a new option. Note that this change would be similar to the -t (touch) option already supported by "make", except that it is more selective (i.e. only rules *without* associated actions are affected). Also, it could preserve the "actual" last-modification times for the intermediate include files, because these files would never actually be touched. Rather, "make" would simply pretend (to itself) that these files had been touched (when required by the above semantic rules).