[gnu.utils.bug] Enhancement ideas for make

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).