C + Make

Wayne Throop throopw at sheol.UUCP
Mon Sep 17 03:34:58 AEST 1990


>,>>> chris at mimsy.umd.edu (Chris Torek)
>> throopw at sheol.UUCP (Wayne Throop)

>>>I have two recommendations ... 1. Put the dependency-making in a
>>>separate program.
>>Much as I am aware of the dangers of disagreeing with somebody as
>>usually-correct as Chris, I disagree slightly here.  
> would you prefer `in separate programs'?

Ah.  The clarification shows me where I was misinterpreting.
I fully agree that different types of dependency should be packaged
apart, for the usual modularity and information-hiding reasons.

I misinterpreted Chris to mean that it *should* be packaged
separately from the construction step.  This and other comments in
the referenced posting show me that he is accepting this latter
separation (to which I was objecting) only as a matter of current
necessity.  (I've probably distorted what Chris means a little
here again, but I'm probably close enough this time... I hope.)

>> the construction engine must [.. should ..]
>> construct the dependency graph on the fly
> Indeed.  Unfortunately, this requires the construction engine (`make')
> to have access to the actual dependency information, which means either
> pushing all those rules from mkdep-* into `make' itself, or else an
> incestuous relationship between the compiler(s) and `make'.

Yes make must have a way of accessing dependency information other than
the static data it starts up with, but the two solutions mentioned
aren't (quite) exhaustive.  There is middle ground, in that make could
have an "incestuous" relationship with mkdep-like subprograms.

And note that it is no less "incestuous" or shocking that make should
delegate construction tasks than that it should delegate dependency
derivation tasks.  In fact, people often do that both now in the
two-step process Chris detailed in an earlier posting.  I think it
is a simple step up to have make invoke dependency rules as needed
rather than all at once and "up front".  It is this segregation that
leads to problems of deriving dependencies of intermediate files, or
files in archive or library systems, and so on and on.

Now, "ideally" the construction steps (eg: compilers) and make should
talk to each other about dependencies.  For example, a compiler shouln't
just open a .h file willy-nilly... it should make sure the file is
up-to-date by invoking make as a coprocess, then open it.  

( BTW, a way of tackling this is via virtual file systems.  Then, the
  "open" system call uttered by the compiler would invoke the make
  co-process "automagically", and existing compilers and tools could be
  cleanly integrated into a "smart" build system...  note that Sun's NSE
  is just a small bit removed from such a possibility (but they don't seem
  to pursue it, but on the other hand I'm not privy).  )

But the poor man's version of having the compiler co-operate with make
is to have the much more modest mkdep-like tools co-operate with make. 
This leads to mis-predictions as to which files the compiler will open,
but the predictions can be made very good, and are no worse than the
predictions such tools make today.  And while no worse, they have the
added advantage that they can be applied in a much more modular way.

> (Too, it has the drawback of requiring that there be room in every
> output file for the information needed by `make', or else that output
> files come in pairs: foo.o and .depend.foo.o, or some such.

Right.  On the other hand, the way "shape" uses to extend the filesystem
to produce an "attributed file system" isn't terribly unatractive.  Or,
another way of looking at it is that make shouldn't work directly with
the file system at all, but with an OODB some of the objects in which
have data stored in the file system.  This has the advantage of solving
the where-to-put-the-timestamp problems for make-able objects which have
no natural file system component, like "release-3.00" or "the .h files
for foo are ready" and other such non-file-y-but-make-able states of
affairs.  It also has the advantage that you can uniformly deal with
buildable entities that have other data, but store it in places other
than one file per object in the the file system, such as database
schemata, smalltalk classes, C declarations, and so on and on.  (As an
example application of this last, you could recompile only when the .h
you include changed something that you actually use.)

But to come down from the blue sky, a simple lookaside database
a-la shape or Atherton Backplane or whatever could do very much to
improve make's capabilities quickly and naturally, and then the more
blue-sky-ish notions could be brought to reality a bit at a time. 
( Sun NSE's make has one as well, but it is not really adequate or
  general purpose enough (IMHO, ie: dependency one compile out of sync). )

And as to integrating make and source code libraries, ideas like "boxes"
from the ptools (or was that ktools... anyway, from the Usenet meeting
on software management) would go (and have gone) a long way towards
making things smooth for the developer working as part of a group.

> In any case, it is important that a makefile---even one as minimal as a
> source list (`bill of materials', as it were) for a system like the one
> above---not be altered by the dependency-update step, because such a
> file *is* a source file, just as much as any C program.

Absolutely.  It is (I think strongly) bad practice to mix the notions
of source and object in a single entity (though sometimes one is "forced"
to do so, eg: patching object code during testing and analogous stuff...
but the point remains that this is something to avoid.)

( BTW, inserting dynamically interpreted code during a debugging session
       to work around bugs isn't what I'd call patching, and is entirely
       acceptable.  But I digress.  And there are dratted few debuggers
       that allow you to do it in full generality :-(     )
--
Wayne Throop <backbone>!mcnc!rti!sheol!throopw or sheol!throopw at rti.rti.org



More information about the Comp.lang.c mailing list