Tommy Reynolds wrote:
Uttered Patrick Barnes <nman64(a)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
D'oh. I should have caught my error on that one.
I don't think it is high-priority right now, and I hope it doesn't
become such. Elliot was trying to use an RHEL3 system, but just used an
RHEL4 system when it didn't work.
--
Patrick "The N-Man" Barnes
nman64(a)n-man.com
www.n-man.com
--