help-make
[Top][All Lists]
Advanced

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

Re: eval awesomeness and thanks to Paul (Was: multiple wildcards in a st


From: Noel Yap
Subject: Re: eval awesomeness and thanks to Paul (Was: multiple wildcards in a static pattern rule)
Date: Thu, 30 Oct 2003 16:11:19 -0500

Yeah, one of my favorite things I've done with eval is:

# sets __FILE__ macro to file to be included, then includes the file.
# allows included file to know where it is in relation to includer.
# caching of included makefile is allowed if $(2).contents is defined as the 
contents of the makefile.
# $(1) is the include method, either "include" or "-include"
# $(2) is the file to be included
# $(3) is the includer
define _include-makefile
  __FILE__ := $(2)

  ifndef $(2).contents
    $(2): | $(dir $(2)).

    $(1) $(2)
  else
    $$(eval $$($(2).contents))
  endif

  __FILE__ := $(3)
endef

# include makefile passing in its name as __FILE__
# $(1) is the file to be included
include-makefile = $(foreach m,$(1),$(eval $(call 
_include-makefile,include,$(m),$(__FILE__))))

which does two things:
  1. The macro __FILE__ is defined for the included makefile which:
    1. allows the included makefile to know where it is in relation to the 
includer thereby allowing for relocatable makefiles
    2. allows for macro definitions that are "local" to the included makefile 
by using macro names like $(__FILE__).sources.
  2. The $(2).contents allows for the makefile contents to be cached decreasing 
the number of file opens/closes occurring.  For example, I've created the 
following rule for makefiles that are meant to be published for inclusion by 
other makefiles:

.SUFFIXES: .mk
$(build.DIR)/common/%.mk: $(src.DIR)/%.mk
        @( \
                echo 'define $$(__FILE__).contents'; \
                echo "$@: $< | $(@D)/."; \
                echo; \
                echo clean: FILES += $@; \
                echo; \
                cat $<; \
                echo endef; \
                echo; \
                echo '$$(__FILE__).contents := $$(value 
$$(__FILE__).contents)'; \
                echo; \
                echo '$$(eval $$($$(__FILE__).contents))'; \
        ) >$@

Anyway, enough bragging.  When I'm all done with the framework I'm working on, 
I'm planning on writing a paper entitled "Recursive Make Considered Harmful, 
Part II: Advanced Non-Recursive Make", but this may still be months in the 
making.

I've been rambling, to summarize, $(eval) is one of the greatest things to come 
out of the GNU make project in years.  I personally thank Paul lots and lots.

Noel

Ram Bhamidipaty wrote:
> 
> Thanks! I just started to read the manual for 3.80 - $(eval) looks great. Once
> I can upgrade this will make a lot of things nicer.
> 
> Thanks for your input.
> -Ram
> 
> Noel Yap writes:
>  > Oops, sorry.  $(eval) is new in gmake-3.80.  I haven't checked the 
> distribution, but the last I heard, you might also have to install a patch to 
> get it to work correctly.
>  >
>  > If you can't upgrade to 3.80 (eval is such an awesome feature it's letting 
> me do stuff I'd wanted to do, but was unable, for years so I recommend the 
> upgrade), the only other thing I can think of is to autogenerate the 
> makefiles for these rules.  This is
>  > probably overkill in your case since:
>  >
>  >   - if you have only a few rules, you might as well write them out 
> yourself although I'd suggest two things:
>  >     - use an action macro rather than hardcoding the actions into the 
> rules; this reduces the redundancy
>  >     - define the action macros within a separate makefile; this allows the 
> action macros to be used outside of your rules
>  >   - if you have a lot of rules, the inclusion of all these makefiles may 
> slow down the build
>  >
>  > You can also take an in-between approach where you manually generate one 
> makefile, then paste the contents into your existing makefile.
>  >
>  > HTH,
>  > Noel
>  >
>  > Ram Bhamidipaty wrote:
>  > >
>  > > Noel Yap writes:
>  > >  > I'm not sure about your syntax.  I think you might mean:
>  > >  >
>  > >  > $(ROOT)etc/dir1/%: %
>  > >  >      cp $< $@
>  > >  >      chmod 644 $@
>  > >  >
>  > >  > and so on.
>  > >  >
>  > >  > Anyway the way I'd go about this would be:
>  > >  >
>  > >  >   $(foreach d,etc/dir1 etc/dir2 etc/dirN,$(eval $(ROOT)$(d)/%: % ; cp 
> $< $@ && chmod 644 $@))
>  > >  >
>  > >  > I haven't tested it, but it should at least be close to what I
>  > >  > think you want.
>  > >
>  > > Thank you - I'll give this a try - btw - what does $(eval ...) do? I 
> could
>  > > not find a reference for it in the manual for version 3.79 of gnu make.
>  > >
>  > > -Ram
>  >
>  > --
>  > NOTICE: If received in error, please destroy and notify sender.  Sender 
> does not waive confidentiality or privilege, and use is prohibited.

-- 
NOTICE: If received in error, please destroy and notify sender.  Sender does 
not waive confidentiality or privilege, and use is prohibited.




reply via email to

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