make-alpha
[Top][All Lists]
Advanced

[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



reply via email to

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