# Copyright (C) 2007-2009 Internet Systems Consortium, Inc. ("ISC")
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# $Id$
# Generic GNUmakefile for use with xml2rfc.
# Default targets
all:: text
# Where to find citations, etcetera.
#
# We use XML_LIBRARY for the search path for compatability with xml2rfc.
# Since we expand all file inclusions before xml2rfc ever sees them,
# this isn't really necessary, we could use, eg, RFC2629TOOLS_PATH.
#
# Since xmllint and xsltproc can take URLs as pathname components
# (using space rather than colon as a separator), what I'd really
# -like- to do here is allow that, but all the fun GNU make vpath
# stuff would break, with good reason, so for now we're stuck with
# local files.
#
# It would not be hard, however, to write a script that did all the
# XSLT preprocessing using URLs pointing to, eg, a Subversion
# repository, it just wouldn't work like a Makefile.
ifndef RFC2629TOOLS_BASE
RFC2629TOOLS_BASE := ${HOME}/rfc2629tools
endif
ifndef XML_LIBRARY
XML_LIBRARY := ${RFC2629TOOLS_BASE}
XML_LIBRARY += ${RFC2629TOOLS_BASE}/xml
XML_LIBRARY += ${RFC2629TOOLS_BASE}/xml/rfc
XML_LIBRARY += ${RFC2629TOOLS_BASE}/xml/draft
XML_LIBRARY += ${RFC2629TOOLS_BASE}/xml/rfc2629xslt
endif
__EMPTY :=
__SPACE := ${__EMPTY} ${__EMPTY}
__PATH = $(subst ${__SPACE},:,$(strip $(1)))
export XML_LIBRARY := $(call __PATH, . ${XML_LIBRARY})
vpath %.xml ${XML_LIBRARY}
vpath %.xsl ${XML_LIBRARY}
vpath %.xslt ${XML_LIBRARY}
XSLTPROC := xsltproc --path ${XML_LIBRARY}
XMLLINT := xmllint --path ${XML_LIBRARY}
# Whether to keep xml:base attributes from XInclude processing.
ifndef KEEP_XINCLUDE_ATTRIBUTES
KEEP_XINCLUDE_ATTRIBUTES = 1
endif
# Rules to expand file inclusions for every XML file in this directory
# with a docName attribute. We support both xml2rfc
# and XInclude inclusion.
#
# NB: we freeze the XML as docName.xml, so the source file can't have
# that name. Since the docName attribute includes the draft version
# number, which you probably don't want in the name of the source file
# anyway, this is unlikely to be a serious restriction, except perhaps
# for the RFC Editor (and the RFC Editor knows where to find me...).
define RULES
ifneq ($(1),$(2).xml)
TARGETS += $(2)
SOURCES += $(1)
$(2).xml : $(1) $(3) ; ${XSLTPROC} --xinclude --param keep_xinclude_attributes ${KEEP_XINCLUDE_ATTRIBUTES} -o $(2).xml expand-rfc2629-pi-rfc-include.xsl $(1)
else
SKIPPED += $(1)
endif
endef
# Generate the above rules for every XML file with a docName attribute.
GENERATE = $(if $(2),$(eval $(call RULES,$(1),$(firstword $(2)),$(sort $(filter-out $(firstword $(2)),$(2))))))
EXTRACT = $(shell 2>/dev/null ${XSLTPROC} --novalid GNUmakefile-helper.xsl $(1))
$(foreach F,$(wildcard *.xml),$(call GENERATE,${F},$(strip $(call EXTRACT,${F}))))
# Locate the DTD if we can
DTD := $(wildcard ${RFC2629TOOLS_BASE}/xml/rfc2629xslt/rfc2629.dtd)
ifeq (${DTD},)
DTD :=
else
DTD := --dtd=${DTD}
endif
# Rules to run xml2rfc on the frozen XML
%.txt : %.xml
xml2rfc ${DTD} $< $@
%.html : %.xml
xml2html ${DTD} $< $@
%.nr : %.xml
xml2nroff ${DTD} $< $@
# Force cleanup after xml2rfc errors
.DELETE_ON_ERROR:
# 2-up Postscript, for proofreading
PS_UNDERLAY := -uDRAFT
%.ps : %.txt
a2ps -2 ${PS_UNDERLAY} -o $@ $<
# Targets
TEXT := $(addsuffix .txt, ${TARGETS})
NROFF := $(addsuffix .nr, ${TARGETS})
HTML := $(addsuffix .html, ${TARGETS})
PS := $(addsuffix .ps, ${TARGETS})
XML := $(addsuffix .xml, ${TARGETS})
text: ${TEXT}
nroff: ${NROFF}
html: ${HTML}
ps: ${PS}
xml: ${XML}
clean::
rm -f ${TEXT} ${NROFF} ${HTML} ${PS} ${XML}
ifeq (,${TARGETS})
OOPS := $(filter-out $(addsuffix .xml,${TARGETS}),${SKIPPED})
all::
ifneq (,${OOPS})
@echo 'Skipped files: ${OOPS}'
@echo ''
endif
@echo "I couldn't find anything to build. Either I had trouble parsing your files,"
@echo 'or you forgot the docName attribute on the element (oops).'
@echo 'Running "make lint" to check for parse errors.'
@echo ''
all:: lint
endif
# Julian's reference checker
define CHECK_REFERENCES
check-references::
@echo Checking references in $(1) ; \
${XSLTPROC} --novalid --xinclude expand-rfc2629-pi-rfc-include.xsl $(1) 2>/dev/null | \
${XSLTPROC} --novalid check-references.xslt -
endef
$(foreach S,${SOURCES},$(eval $(call CHECK_REFERENCES,${S})))
# Julian's dependency plotter
define GEN_REFERENCE_GRAPH
gen-reference-graph::
@echo Checking references in $(1) ; \
${XSLTPROC} --novalid --xinclude expand-rfc2629-pi-rfc-include.xsl $(1) 2>/dev/null | \
${XSLTPROC} --novalid gen-reference-graph.xslt - | \
dot -Tps2 | ps2pdf - $(basename $(1)).reference-graph.pdf
endef
$(foreach S,${SOURCES},$(eval $(call GEN_REFERENCE_GRAPH,${S})))
# Lint checker
lint:
${XMLLINT} --noout *.xml
# Lint references
lint-references:
find $(subst :, ,${XML_LIBRARY}) -type f -name 'reference.*.xml' | \
xargs ${XMLLINT} --noout
# Validation against the RFC2629 DTD. Mostly works, but quirky.
#
# This doesn't work at all with because xmllint
# doesn't understand that. We could run xmllint on the expanded XML,
# but then the error messages would refer to the expanded XML rather
# than the original source, which would be annoying.
#
# Validation does mostly work with XInclude, but it spits out a lot of
# "No declaration for attribute base of element" errors when used with
# XInclude, due to a bad interaction between XInclude and the DTD.
# See:
#
# http://lists.oasis-open.org/archives/docbook/200211/msg00040.html
# http://sources.redhat.com/ml/docbook-apps/2003-q4/msg00072.html
#
# The fix is to add xml:base as an allowed attribute for any element
# that could usefully contain an XInclude (ie, all of them). Adding
# the xmlns:xi attribute to the DTD as well would make it possible to
# for validation to work with the xi namespace defined in the
# element; as it is, one has to define it in each XInclude element to
# avoid validation errors.
validate:
${XMLLINT} --noout --dtdvalid rfc2629.dtd --xinclude ${SOURCES}
relaxng:
${XMLLINT} --noout --relaxng rfc2629.rng --xinclude ${SOURCES}
# rfcdiff against immediately previous version of a draft. This looks in
# both the current directory and ${DRAFTDIR}, if the latter is defined.
diff::
define DIFF
ifeq ($(findstring -00,$1),)
_F0 := $(shell echo $1 | awk 'BEGIN {FS = OFS = "-"} {$$NF = sprintf("%02d", -1 + $$NF); print}').txt
ifdef DRAFTDIR
_F1 := $$(firstword $$(wildcard $${DRAFTDIR}/$${_F0} $${_F0}))
else
_F1 := $${_F0}
endif
_F2 := $1.txt
_F3 := $(shell echo $1 | awk 'BEGIN {FS = "-"} {printf "%s-from-%02d.diff.html\n", $$0, -1 + $$NF}')
ifneq ($${_F1},)
HTML += $${_F3}
diff:: $${_F3}
$${_F3} : $${_F1} $${_F2}
rfcdiff --stdout $${_F1} $${_F2} >$${_F3}.tmp
mv $${_F3}.tmp $${_F3}
endif
endif
endef
$(foreach T,${TARGETS},$(eval $(call DIFF,${T})))
all:: diff