The Documentation Build Process This chapter covers organization of the documentation build process and how &man.make.1; is used to control it. Rendering DocBook into Output Different types of output can be produced from a single DocBook source file. The type of output desired is set with the FORMATS variable. A list of known formats is stored in KNOWN_FORMATS: &prompt.user; cd ~/doc/en_US.ISO8859-1/books/handbook &prompt.user; make -V KNOWN_FORMATS Common Output Formats FORMATS Value File Type Description html HTML, one file A single book.html or article.html. html-split HTML, multiple files Multiple HTML files, one for each chapter or section, for use on a typical web site. pdf PDF Portable Document Format
The default output format can vary by document, but is usually html-split. Other formats are chosen by setting FORMATS to a specific value. Multiple output formats can be created at a single time by setting FORMATS to a list of formats. Build a Single HTML Output File &prompt.user; cd ~/doc/en_US.ISO8859-1/books/handbook &prompt.user; make FORMATS=html Build HTML-Split and <acronym>PDF</acronym> Output Files &prompt.user; cd ~/doc/en_US.ISO8859-1/books/handbook &prompt.user; make FORMATS="html-split pdf"
The &os; Documentation Build Toolset These are the tools used to build and install the FDP documentation. The primary build tool is &man.make.1;, specifically Berkeley Make. Package building is handled by &os;'s &man.pkg-create.8;. &man.gzip.1; is used to create compressed versions of the document. &man.bzip2.1; archives are also supported. &man.tar.1; is used for package building. &man.install.1; is used to install the documentation. Understanding <filename>Makefile</filename>s in the Documentation Tree There are three main types of Makefiles in the &os; Documentation Project tree. Subdirectory Makefiles simply pass commands to those directories below them. Documentation Makefiles describe the documents that are produced from this directory. Make includes are the glue that perform the document production, and are usually of the form doc.xxx.mk. Subdirectory <filename>Makefile</filename>s These Makefiles usually take the form of: SUBDIR =articles SUBDIR+=books COMPAT_SYMLINK = en DOC_PREFIX?= ${.CURDIR}/.. .include "${DOC_PREFIX}/share/mk/doc.project.mk" The first four non-empty lines define the &man.make.1; variables SUBDIR, COMPAT_SYMLINK, and DOC_PREFIX. The SUBDIR statement and COMPAT_SYMLINK statement show how to assign a value to a variable, overriding any previous value. The second SUBDIR statement shows how a value is appended to the current value of a variable. The SUBDIR variable is now articles books. The DOC_PREFIX assignment shows how a value is assigned to the variable, but only if it is not already defined. This is useful if DOC_PREFIX is not where this Makefile thinks it is - the user can override this and provide the correct value. What does it all mean? SUBDIR mentions which subdirectories below this one the build process should pass any work on to. COMPAT_SYMLINK is specific to compatibility symlinks (amazingly enough) for languages to their official encoding (doc/en would point to en_US.ISO-8859-1). DOC_PREFIX is the path to the root of the &os; Document Project tree. This is not always that easy to find, and is also easily overridden, to allow for flexibility. .CURDIR is a &man.make.1; builtin variable with the path to the current directory. The final line includes the &os; Documentation Project's project-wide &man.make.1; system file doc.project.mk which is the glue which converts these variables into build instructions. Documentation <filename>Makefile</filename>s These Makefiles set &man.make.1; variables that describe how to build the documentation contained in that directory. Here is an example: MAINTAINER=nik@FreeBSD.org DOC?= book FORMATS?= html-split html INSTALL_COMPRESSED?= gz INSTALL_ONLY_COMPRESSED?= # SGML content SRCS= book.xml DOC_PREFIX?= ${.CURDIR}/../../.. .include "$(DOC_PREFIX)/share/mk/docproj.docbook.mk" The MAINTAINER variable allows committers to claim ownership of a document in the &os; Documentation Project, and take responsibility for maintaining it. DOC is the name (sans the .xml extension) of the main document created by this directory. SRCS lists all the individual files that make up the document. This should also include important files in which a change should result in a rebuild. FORMATS indicates the default formats that should be built for this document. INSTALL_COMPRESSED is the default list of compression techniques that should be used in the document build. INSTALL_ONLY_COMPRESS, empty by default, should be non-empty if only compressed documents are desired in the build. The DOC_PREFIX and include statements should be familiar already. &os; Documentation Project <application>Make</application> Includes &man.make.1; includes are best explained by inspection of the code. Here are the system include files: doc.project.mk is the main project include file, which includes all the following include files, as necessary. doc.subdir.mk handles traversing of the document tree during the build and install processes. doc.install.mk provides variables that affect ownership and installation of documents. doc.docbook.mk is included if DOCFORMAT is docbook and DOC is set. <filename>doc.project.mk</filename> By inspection: DOCFORMAT?= docbook MAINTAINER?= doc@FreeBSD.org PREFIX?= /usr/local PRI_LANG?= en_US.ISO8859-1 .if defined(DOC) .if ${DOCFORMAT} == "docbook" .include "doc.docbook.mk" .endif .endif .include "doc.subdir.mk" .include "doc.install.mk" Variables DOCFORMAT and MAINTAINER are assigned default values, if these are not set by the document make file. PREFIX is the prefix under which the documentation building tools are installed. For normal package and port installation, this is /usr/local. PRI_LANG should be set to whatever language and encoding is natural amongst users these documents are being built for. US English is the default. PRI_LANG does not affect which documents can, or even will, be built. Its main use is creating links to commonly referenced documents into the &os; documentation install root. Conditionals The .if defined(DOC) line is an example of a &man.make.1; conditional which, like in other programs, defines behavior if some condition is true or if it is false. defined is a function which returns whether the variable given is defined or not. .if ${DOCFORMAT} == "docbook", next, tests whether the DOCFORMAT variable is "docbook", and in this case, includes doc.docbook.mk. The two .endifs close the two above conditionals, marking the end of their application. <filename>doc.subdir.mk</filename> This file is too long to explain in detail. These notes describe the most important features. Variables SUBDIR is a list of subdirectories that the build process should go further down into. ROOT_SYMLINKS is the name of directories that should be linked to the document install root from their actual locations, if the current language is the primary language (specified by PRI_LANG). COMPAT_SYMLINK is described in the Subdirectory Makefile section. Targets and Macros Dependencies are described by target: dependency1 dependency2 ... tuples, where to build target, the given dependencies must be built first. After that descriptive tuple, instructions on how to build the target may be given, if the conversion process between the target and its dependencies are not previously defined, or if this particular conversion is not the same as the default conversion method. A special dependency .USE defines the equivalent of a macro. _SUBDIRUSE: .USE .for entry in ${SUBDIR} @${ECHO} "===> ${DIRPRFX}${entry}" @(cd ${.CURDIR}/${entry} && \ ${MAKE} ${.TARGET:S/realpackage/package/:S/realinstall/install/} DIRPRFX=${DIRPRFX}${entry}/ ) .endfor In the above, _SUBDIRUSE is now a macro which will execute the given commands when it is listed as a dependency. What sets this macro apart from other targets? Basically, it is executed after the instructions given in the build procedure it is listed as a dependency to, and it does not adjust .TARGET, which is the variable which contains the name of the target currently being built. clean: _SUBDIRUSE rm -f ${CLEANFILES} In the above, clean will use the _SUBDIRUSE macro after it has executed the instruction rm -f ${CLEANFILES}. In effect, this causes clean to go further and further down the directory tree, deleting built files as it goes down, not on the way back up. Provided Targets install and package both go down the directory tree calling the real versions of themselves in the subdirectories (realinstall and realpackage respectively). clean removes files created by the build process (and goes down the directory tree too). cleandir does the same, and also removes the object directory, if any. More on Conditionals exists is another condition function which returns true if the given file exists. empty returns true if the given variable is empty. target returns true if the given target does not already exist. Looping Constructs in <command>make (.for)</command> .for provides a way to repeat a set of instructions for each space-separated element in a variable. It does this by assigning a variable to contain the current element in the list being examined. _SUBDIRUSE: .USE .for entry in ${SUBDIR} @${ECHO} "===> ${DIRPRFX}${entry}" @(cd ${.CURDIR}/${entry} && \ ${MAKE} ${.TARGET:S/realpackage/package/:S/realinstall/install/} DIRPRFX=${DIRPRFX}${entry}/ ) .endfor In the above, if SUBDIR is empty, no action is taken; if it has one or more elements, the instructions between .for and .endfor would repeat for every element, with entry being replaced with the value of the current element.