mk from AT&T

Andrew Hume andrew at alice.UUCP
Wed Mar 1 14:37:50 AEST 1989


In article <518 at ksr.UUCP>, benson at ksr.UUCP (Benson Margulies) writes:
> It seems impossible to set up a regular expression metarule
> in mk that will permit dependencies of the form:
> 
> 
> foo.o : ../x/foo.c
> 
> The regular expression (not to mention the % rules) insist that the
> source pathname be built entirely out of literals and pieces of the
> target. There is no provision for the source containing things that
> the target lacks.
> 
> One could try to write:
> 
> '\(.*\)\.o' :R: '.*\1.c'
> 
> but that won't work, since the source is not regexp matched, it
> is only regexp expanded from the target. This is a fairly common
> thing to want to do. In nmake, the .SOURCE targets often obviate it
> by allowing searching for sources.
> 
> Does anyone know a trick that I don't? Is there some theory 
> at work here?
> -- 
> Benson I. Margulies                         Kendall Square Research Corp.
> harvard!ksr!benson			    benson at ksr.com


	This is a very incisive question that points out one of
mk's awkwardnesses. But as we shall see, mk isn't the only one.

	The theory (such as it is) is that glob expansion is
done on reading the mkfile and as the metarules have not had their
% or \\1 expanded, it would be pointless to do glob expansion
on them as well as being ambiguous (does the * mean a glob *
or a reg exp *).

	As Benson points out, the real difficulty is that information
can only decrease going from target to dependents. It is constructive to
understand what is going on here. The canonical example is the mkfile
for libc. For simplicity, assume that libc.a is made from pow.o
(made from math/pow.c) and abs.o (made from gen/abs.c). The question
is how to construct a mkfile with the minimal amount of information?

	I am not really too proud of the solution i use for our libc
but it does work and is succint:

OBJ=libc.a(abs.o) libc.a(pow.o)

libc.a:Q:	$OBJ
	names=`membername $newprereq`
	ar rv libc.a $names && rm $names
	ranlib libc.a

pow.o:	math/pow.c
abs.o:	gen/abs.c

$L(%.o):N:	%.o
%.o:
	cc -O -c $prereq
	ld -o $nproc.o -x -r $target && mv $nproc.o $target

Apart from the normal mucking around to do the library correctly
this is quite short. you have to say the element names once
and you have to say where the source is. (at least,
that is my taste so as to avoid problems with multiple
answers to pow.o: */pow.c.) The slime in this mkfile is the rule
for %.o; the prerequisites come from the xx.o: yy/xx.c in
a somewhat sleazy indirect manner.

	How do other makes handle this problem?
nmake does it by the equivalent of viewpathing with all the glories
and problems of that technique; the main problem being that you
have to have a database to get the right answer as the filesystem
doesn't hold enough information to deal with the case of generating
a foo.o from a foo.c; removing that foo.c and uncovering an older
foo.c. According to the dates, foo.o is okay but it ain't the foo.o
i married.

gnumake does it by a curious rule that makes little sense on its own
but is really useful here; when you say %.o: %.c, the % on the right
is not the same as the % on the left, it is actually basename(%). or
at least, it is sometimes.

	in summary, i am not proud of how mk does it but i think it does
it honestly. if viewpathing is your game, use nmake. gnumake can support
it by special purpose hack but at the cost of ruining the meaning of %
(for example, if gnumake ever does transitive closure, what value of
% is used?). if you have cycles to burn, you might try cake. it has
rather a different slant on things and evaluates predicates etc before
deciding to use rules so you should be able to do something clever.



More information about the Comp.unix.questions mailing list