[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
New feature for GNU make.
From: |
psmith |
Subject: |
New feature for GNU make. |
Date: |
Sat, 6 Jul 2002 21:05:00 -0400 |
OK, I'm just about ready to check in the newest feature for GNU make:
two new functions.
The first is $(eval ...).
This function takes a single argument, expands it, then evaluates the
results of the expansion as makefile syntax. That means the expansion
can define new variables, new rules, etc. etc. Combined with
define/endef, which lets you create variables with newlines in them,
this is extremely powerful.
I was originally going to try to have make "magically" evaluate expanded
variables, even multiline ones, implicitly as it came across them so you
wouldn't need to use a function to do it explicitly, but the implicit
version involved too much magic. Besides, with a function you can put
the evaluation anywhere in the makefile, including a script. Very weird
to think that you can define new variables and targets from within the
command script of an existing target... but you can! In fact you can
implement a simple version of include using $(eval ...):
$(eval $(shell cat somefile.mk))
(not that you'd ever do this, but...). The one problem with eval is
error messages: it always looks like the error occurs on the makefile
line with the eval statement, regardless of how many lines are contained
in the expanded script make is reading. This can make it pretty hard to
find a syntax error. I'm thinking about ways to help people find these
kinds of problems.
The second function is $(quote ...). It turns out that when you use
$(eval ...), everything gets evaluated _twice_: the first time when make
expands the argument to eval, then again when the result of the
expansion is would normally be expanded by the makefile parser.
This means you need to add one extra level of quoting to anything you
don't want expanded during the eval phase. For example, this won't do
what you want:
define EXPAND
FOO = $(BAR)
all: ; echo $@: FOO = $(FOO)
endef
$(eval $(EXPAND))
BAR = baz
What happens is that the eval expands the EXPAND variable and resolves
the (unescaped) variables right then, so you end up with:
FOO =
all: ; echo : FOO =
BAR = baz
which is not what you want (presumably). To get what you want, you have
to add another level of quoting, like this:
define EXPAND
FOO = $$(BAR)
all: ; echo $$@: FOO = $$(FOO)
endef
$(eval $(EXPAND))
BAR = baz
Now after expansion you get this:
FOO = $(BAR)
all: ; echo $@: FOO = $(BAR)
and when make parses it, it will work as you intended. This is
annoying, and it's especially hard if you have a value you sometimes
want to use outside eval and sometimes within it. Even worse, if you
already needed to quote something, say :
loop = for p in $(LIST); do echo $$p; done
Now to use this with $(eval ...) you'd have to double-quote it:
loop = for p in $$(LIST); do echo $$$$p; done
Ugh!
The $(quote ...) function solves this problem. It takes a variable name
(just the name, like $(origin ...), etc.) as an argument. The expansion
of the $(quote ...) function is the contents of that variable, without
_any_ expansion performed on it. Thus, you can say:
FOO = echo $PATH
all: ; @echo $(quote FOO)
and this would be identical to saying:
FOO := echo $$PATH
all: ; @echo $(FOO)
I'm sort of unsatisfied with the function name "quote", as I think it
might be too generic a term for the specific thing this function does,
but I can't come up with anything better. Let me know if you can.
Thanks all.
--
-------------------------------------------------------------------------------
Paul D. Smith <address@hidden> Find some GNU make tips at:
http://www.gnu.org http://www.paulandlesley.org/gmake/
"Please remain calm...I may be mad, but I am a professional." --Mad Scientist
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- New feature for GNU make.,
psmith <=