make on older systems (RHEL3)

Tommy Reynolds Tommy.Reynolds at MegaCoder.com
Fri Nov 18 04:45:21 UTC 2005


Uttered Patrick Barnes <nman64 at n-man.com>, spake thus:

> I've made some revisions to docs-common/Makefile.common in an attempt to
> resolve build failures on RHEL3.  I'd like this to undergo more testing
> (particularly on older systems) before committing it.  In particular, I
> would like Tommy to take a quick look at this to make sure it doesn't
> break anything.  It is a syntax change that, to the best of my
> knowledge, shouldn't change behavior, but I'm not overly experienced
> with Makefiles.
> 
> The altered file is attached.

Sorry, but it's not even close ;-(

Let me explain what's going on in a bit of detail, so everybody will
be on the same page.  Someday I'll fold it into the docs... (yeah,
right)

The magic is all driven from a ${LANGUAGES} macro that holds a simple
list of all the languages we must support in the make(1) setup.

Here is the target and some rules for one language:

$(DOCBASE)-en/index.html:: ${DOCBASE}-en.xml ${EXTRAXMLFILES-en}
	LANG=en.UTF-8 ${XMLTO} html -x $(XSLHTML) -o $(DOCBASE)-en \
		$(DOCBASE)-en.xml
	mkdir -p $(DOCBASE)-en/stylesheet-images/
	cp ${FDPDIR}/docs-common/stylesheet-images/*.png \
		$(DOCBASE)-en/stylesheet-images
	cp ${FDPDIR}/docs-common/css/fedora.css $(DOCBASE)-en/
	[ ! -d figs ] || (						\
		mkdir -p ${DOCBASE}-en/figs;				\
		find figs -type f -iname '*.*' -print		|	\
		egrep -vi '*.eps'				|	\
		egrep '(.*-$(1)..*)|([^-]*[.][^-]*)'		|	\
		while read x; do cp -f $$$${x} ${DOCBASE}-$(1)/figs; done \
	) && exit 0

Now, here is another target and its rules for a translation:

$(DOCBASE)-it/index.html:: ${DOCBASE}-it.xml ${EXTRAXMLFILES-it}
	LANG=en.UTF-8 ${XMLTO} html -x $(XSLHTML) -o $(DOCBASE)-it \
		$(DOCBASE)-it.xml
	mkdir -p $(DOCBASE)-it/stylesheet-images/
	cp ${FDPDIR}/docs-common/stylesheet-images/*.png \
		$(DOCBASE)-it/stylesheet-images
	cp ${FDPDIR}/docs-common/css/fedora.css $(DOCBASE)-it/
	[ ! -d figs ] || (						\
		mkdir -p ${DOCBASE}-it/figs;				\
		find figs -type f -iname '*.*' -print		|	\
		egrep -vi '*.eps'				|	\
		egrep '(.*-$(1)..*)|([^-]*[.][^-]*)'		|	\
		while read x; do cp -f $$$${x} ${DOCBASE}-$(1)/figs; done \
	) && exit 0

So, using traditional make(1) constructs, we would have an "unrolled
loop" that looks like this:

${DOCBASE-en/index.html:: ${DOCBASE}-en.xml ${EXTRAXMLFILES-en}
	LANG=en.UTF-8 ${XMLTO} html -x $(XSLHTML) -o $(DOCBASE)-it \
		$(DOCBASE)-it.xml
	...
${DOCBASE-de/index.html:: ${DOCBASE}-de.xml ${EXTRAXMLFILES-de}
	LANG=en.UTF-8 ${XMLTO} html -x $(XSLHTML) -o $(DOCBASE)-it \
		$(DOCBASE)-it.xml
	...
${DOCBASE-it/index.html:: ${DOCBASE}-it.xml ${EXTRAXMLFILES-it}
	LANG=en.UTF-8 ${XMLTO} html -x $(XSLHTML) -o $(DOCBASE)-it \
		$(DOCBASE)-it.xml
	...

See the emerging pattern?  GNU make(1) implements a "template", which
is a bit like a CPP macro preprocessor for the Makefile:

define	HTML_template
${DOCBASE}-$(1)/index.html:: ${DOCBASE}-$(1).xml $$(XMLEXTRAFILES-$(1))
	LANG=$(1).UTF-8 ${XMLTO} html -x $(XSLHTML) -o $(DOCBASE)-$(1) $(DOCBASE)-$(1).xml
	mkdir -p $(DOCBASE)-$(1)/stylesheet-images/
	cp ${FDPDIR}/docs-common/stylesheet-images/*.png $(DOCBASE)-$(1)/stylesheet-images
	cp ${FDPDIR}/docs-common/css/fedora.css $$(DOCBASE)-$(1)/
	[ ! -d figs ] || (						\
		mkdir -p ${DOCBASE}-$(1)/figs;				\
		find figs -type f -iname '*.*' -print		|	\
		egrep -vi '*.eps'				|	\
		egrep '(.*-$(1)..*)|([^-]*[.][^-]*)'		|	\
		while read x; do cp -f $$$${x} ${DOCBASE}-$(1)/figs; done \
	) && exit 0
endef

Here, the "HTML_template" will take one parameter, the locale code
that marks the language of interest.  We get these from the
${LANGUAGES} macro, so we somehow need to obtain a Makefile line
like:

html:: ${DOCBASE}-en/index.html ${DOCBASE}-de/index.html ... \
	${DOCBASE}-it/index.html

without needing to do any editing when a new language gets added.

One way to do this would have been to use various patsubst verbs for
an in-line expansion, something like:

html:: ${LANGUAGES:^%=${DOCBASE}-%:%$=%/index.html}

(OK, that's not a valid line, but it gets the point across.  The real
code was even uglier.)  Assume "LANGUAGES=en de it"; the construct you used:

html:: ${DOCBASE}-${LANGUAGES}/index.html

expands to

html:: example_tutorial-en de it/index.html

which is not what we want.

Meanwhile, back at the patsubst example: well and good, as far as it
goes.  Unfortunately, this works only for in-line expansion and is
useless to "unroll the loop" to generate all the code and rules we
need for every language we need to support.  When the Makefile.common
does:

$(foreach LANG,${LANGUAGES},$(eval $(call HTML_template,${LANG})))

it is exactly the same as having cut & pasted the lines within the
template body while replacing each instance of "$(1)" with one
language locale from the ${LANGUAGES} list.

You can watch all this happen by going into the "release-notes"
document and typing this:

$ make -n -p | less

In particular, look for the stanzas introduced by lines with
"LANG=<foo>.UTF-8".  All of these were generated as the template was
expanded in the $(foreach ...) lines.

Maybe this technique was just too cute to be maintainable.  I don't
know when template support was introduced, but it's in FC4 and later.

If this is a real problem, we have other technologies such as shell
scripts, awk scripts, perl scripts, m4 macros, and on.

HTH
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/fedora-docs-list/attachments/20051117/8a5566c0/attachment.sig>


More information about the fedora-docs-list mailing list