help-make
[Top][All Lists]
Advanced

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

RE: how to: write a rule which expands the contents of an arbitrary text


From: Kaz Kylheku (gmake)
Subject: RE: how to: write a rule which expands the contents of an arbitrary text file?
Date: Fri, 14 May 2021 13:58:24 -0700
User-agent: Roundcube Webmail/0.9.2

On 2021-05-14 11:46, Cook, Malcolm wrote:
So I hit <send> too soon...

I would to be able to expand Gnu make variables and macros appearing in a text file using values of .VARIABLES in the current execution environment.

This in effect is using Gnu make as a kind of [Template
processor](https://en.wikipedia.org/wiki/Template_processor).

I find that this rule only copies the contents without expansion/interpolation

%.expanded: %
        $(file >$@,$(file < $<))

However the following seems to do exactly what I desire:

define \n :=


endef

%.expanded: %
$(file >$@,$(eval define .x:=${\n}$(file < $<)${\n}endef ${\n})${.x})

The problem with this approach is that, though it expands "correctly",
it builds the target during the first phase of reading the makefile
(c.f. [How make Reads a
Makefile](https://www.gnu.org/software/make/manual/make.html#Reading-Makefiles))
 and thus standard dependency processing is precluded, which is decidedly 
unfavorable.


My question is whether this is the best/fastest way to do what I desire.

My question is changed and is now how to accomplish this in the second phase.

Probably, just have a special target in the Makefile:

  prepro:
       ... magic here ...

such that "make prepro IN=infile OUT=outfile" somehow acts as that
preprocessor, such that simply reading that Makefile which contains
that rule has no effect.

Then just recurse out of the regular build job into this rule:

  $(MAKE) prepro IN=$< OUT=$@

Incidentally, many years ago I used, in a custom embedded distro that I rolled
from scratch, these GNU Make rules for preprocessing files:

%: %.ct
    cpp -P $(shell env | sed -e "s/.*/-D_ENV_'&'/") $< > $@

%: %.st
( export __FILE__=$< ; echo "cat <<!" ; cat $< ; echo "!" ) | bash > $@

%: %.mt
    rm -f $@.err
m4 -D__FILE__=$< $(shell env | sed -e "s/\([^=]*\)=\(.*\)/-D'_ENV_\\1=\\2'/"
    if [ -s $@.err ] ; then cat $@.err ; exit 1 ; fi
    rm -f $@.err

The idea we have three kinds of files requiring preprocessing .ct, .st and .mt files. .ct files use the C preprocessor; .st are "shell templates" which use
shell here-doc syntax, and .mt files use M4.

All three are handled by converting the environment into their respective
variable definitions.

In the case of cpp and m4, the variables are prefixed with _ENV_, so they
don't clash with built-in stuff. In the case of Shell and m4, we add a
__FILE__ variable, which is similar to the C preprocessor one.

For example, in the "shell template" syntax you can perform expansions like:

   $(for x in 1 2 3; do echo "foo-$x"; done)






reply via email to

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