bug-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Recursive $(call)


From: Philip Guenther
Subject: Re: Recursive $(call)
Date: Mon, 25 Feb 2002 21:14:48 -0800

"Paul D. Smith" <address@hidden> writes:
>%% Philip Guenther <address@hidden> writes:
>
>  pg> It would greatly increase the expressiveness of GNU make's macro
>  pg> expansion if it was possible to define recursive macro functions.
>  pg> For example, here's a function that performs calculates the
>  pg> transitive closure of a set of dependencies:
>
>  pg> # If $(firstword) is car, this is cdr:
>  pg> rest = $(wordlist 1,$(words ${1}),${1})
>
>  pg> tclose = $(if ${1},$(firstword ${1}) \
>  pg>             $(call tclose,$(sort ${DEP_$(firstword ${1})} \
>  pg>                             $(call rest,${1}))))
>
>Heh.  I see your point, but I have to say that your example proves
>exactly the amount of danger involved with allowing this: your
>definition of "rest" has a bug which causes this series to loop
>infinitely! :)

Oops...


>  pg> Unfortunately, the restriction on recursive macros not referencing
>  pg> themselves includes references via $(call).  I would argue that
>  pg> GNU make should not try to protect someone from themself if the
>  pg> write a recursive $(call).  Yes, you can trivially write infinite
>  pg> loops if it's allowed, but the increase in expressiveness is
>  pg> substantial.
>
>OK, I buy this argument.  As a test I removed the restriction on
>recursive variable definitions and (with the above fix) your example
>did work as you intended.  Neat.
>
>However, I think the restriction is valid for normal variable
>expansions, and most if not all builtin functions.  Are there any other
>builtins you think would benefit from loosening this restriction?

The only other one which could legitimately benefit would be $(foreach),
as it's the only other builtin which can change the value of a variable
during expansion.  That is, just as self-reference in $(call) can be
done safely by conditioning the recursion on the values of the argument
variables, self-reference in $(foreach) can be done safely by
conditioning it on the value of the iteration variable.

In fact, I _think_ the following pair of assignments would again
implement transitive closure:

tclose_ = ${dep} $(foreach dep,${DEP_${dep}},${tclose_})
tclose = $(sort $(foreach dep,${1},${tclose_}))

...but I think that's harder to read than the $(call) version.  From the
programming language perspective, $(call) is to be prefered as the
variable 'reassignment' is part of the recursion machinery, instead of
being done in the "parent's" $(foreach).


Philip Guenther



reply via email to

[Prev in Thread] Current Thread [Next in Thread]