% \iffalse %% %% File l3build.dtx (C) Copyright 2014 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of the %% LaTeX Project Public License (LPPL), either version 1.3c of this %% license or (at your option) any later version. The latest version %% of this license is in the file %% %% http://www.latex-project.org/lppl.txt %% %% This file is part of the "l3build bundle" (The Work in LPPL) %% and all files in that bundle must be distributed together. %% %% The released version of this bundle is available from CTAN. %% %% ----------------------------------------------------------------------- %% %% The development version of the bundle can be found at %% %% http://www.latex-project.org/svnroot/experimental/trunk/ %% %% for those people who are interested. %% %%%%%%%%%%% %% NOTE: %% %%%%%%%%%%% %% %% Snapshots taken from the repository represent work in progress and may %% not work or may contain conflicting material! We therefore ask %% people _not_ to put them into distributions, archives, etc. without %% prior consultation with the LaTeX Project Team. %% %% ----------------------------------------------------------------------- %% % % %<*driver> \RequirePackage{expl3} \def\ExplFileName{l3build} \def\ExplFileDescription{L3 Regression test suite} \def\ExplFileDate{2014/09/15} \def\ExplFileVersion{5423} \documentclass[full]{l3doc} \renewcommand\partname{Part} \usepackage{multicol,needspace} \makeatletter \addtolength\columnsep{1em} \renewcommand\columnseprule{0.4pt} \def\@starttoc#1{% \begin{multicols}{2} \small \makeatletter \@input{\jobname.#1}% \expandafter\newwrite\csname tf@#1\endcsname \immediate\openout \csname tf@#1\endcsname \jobname.#1\relax \@nobreakfalse \end{multicols}} \makeatother \newenvironment{buildcmd}[1]{% \bigskip\par\noindent\hspace{-\parindent}% \fbox{\ttfamily \textcolor[gray]{0.5}{\$} texlua build.lua #1}% \nopagebreak\smallskip\nopagebreak\par\nopagebreak\noindent\ignorespaces } {} \makeatletter \newcommand\luavar[1]{\@ifundefined{lua_#1}{\ERROR}{\texttt{\@nameuse{lua_#1}}}} \newcommand\luavarset[3]{\@namedef{lua_#1}{#2}} \newcommand\luavarseparator{} \makeatother \def\allluavars{ \luavarset{module}{""}{The name of the module.} \luavarset{bundle}{""}{The name of the bundle in which the module belongs.} \luavarseparator \luavarset{modules}{\{~\}}{The list of all modules in a bundle (when not auto-detecting)} \luavarset{exclmodules}{\{~\}}{Directories to be excluded from automatic module detection} \luavarseparator \luavarset{maindir} {"."}{The top level directory for this module or bundle.} \luavarset{supportdir} {maindir .. "/support"} {Where copies of files to support check/doc compilation are stored.} \luavarset{testfiledir} {maindir .. "/testfiles"} {Where the tests are.} \luavarset{testsuppdir} {testfiledir .. "/support"} {Where support files for the tests are.} \luavarseparator \luavarset{localdir} {maindir .. "/build/local"} {Generated folder where support files are placed to allow \enquote{sandboxed} \TeX{} runs.} \luavarset{testdir} {maindir .. "/build/test"} {Generated folder where tests are run.} \luavarset{typesetdir} {maindir .. "/build/doc"} {Generated folder where typesetting is run.} \luavarset{unpackdir} {maindir .. "/build/unpack"} {Generated folder where unpacking occurs.} \luavarset{distribdir} {maindir .. "/build/distrib"}{Generated folder where the archive is created.} \luavarset{ctandir} {distribdir .. "/ctan"} {Generated folder where files are organised for CTAN.} \luavarset{tdsdir} {distribdir .. "/tds"} {Generated folder where files are organised for a TDS.} \luavarset{tdsroot} {"latex"}{Root directory of the TDS structure for the bundle/module to be installed into.} \luavarseparator \luavarset{binaryfiles} {\{"*.pdf", "*.zip"\}} {Files to be added in binary mode to zip files.} \luavarset{checkfiles} {\{~\}}{Extra files unpacked purely for tests} \luavarset{checksuppfiles} { }{Files needed for performing regression tests.} \luavarset{cmdchkfiles} {\{~\}}{Files need to perform command checking (\cls{l3doc}-based documentation only).} \luavarset{demofiles} {\{~\}}{Files which show how to use a module.} \luavarset{cleanfiles} {\{"*.pdf", "*.zip"\}}{Files to delete when cleaning.} \luavarset{excludefiles} {\{"*\string~"\}} {Files to ignore entirely (default for Emacs backup files).} \luavarset{installfiles} {\{"*.sty"\}} {Files to install to the \TeX{} tree and similar tasks.} \luavarset{sourcefiles} {\{"*.dtx", "*.ins"\}}{Files to copy for unpacking.} \luavarset{txtfiles} {\{"*.markdown"\}} {Files which should have the extension removed when sent to CTAN.} \luavarset{typesetfiles} {\{"*.dtx"\}} {Files to typeset for documentation.} \luavarset{typesetsuppfiles}{\{~\}} {Files needed to support typesetting when \enquote{sandboxed}.} \luavarset{unpackfiles} {\{"*.ins"\}} {Files to run to perform unpacking.} \luavarset{unpacksuppfiles} {\{~\}} {Files needed to support unpacking when \enquote{sandboxed}.} \luavarseparator \luavarset{lvtext} {".lvt"} {Extension of test files.} \luavarset{tlgext} {".tlg"} {Extension of test file output.} \luavarset{logext} {".log"} {Extension of checking output, before processing it into a \texttt{.tlg}.} \luavarseparator \luavarset{checkdeps} {\{~\}} {List of build unpack dependencies for checking.} \luavarset{typesetdeps} {\{~\}} {\dots for typesetting docs.} \luavarset{unpackdeps} {\{~\}} {\dots for unpacking.} \luavarseparator \luavarset{checkengines}{\{"pdftex", "xetex", "luatex"\}} {Engines to check with \texttt{check} by default.} \luavarset{stdengine} {"pdtex"} {Engine to generate \texttt{.tlg} file from.} \luavarset{checkformat} {"latex"} {Format to use for tests.} \luavarseparator \luavarset{typesetexe} {"pdflatex"} {Executable for compiling \texttt{doc(s)}.} \luavarset{unpackexe} {"tex"} {Executable for running \texttt{unpack}.} \luavarset{zipexe} {"zip"} {Executable for creating archive with \texttt{ctan}.} \luavarseparator \luavarset{checkopts} {"-interaction=batchmode"} {Options based to engine when running checks.} \luavarset{cmdchkopts} {"-interaction=batchmode"} {Options based to engine when running command checks.} \luavarset{typesetopts}{"-interaction=nonstopmode"}{Options based to engine when typesetting.} \luavarset{unpackopts} {""} {Options based to engine when unpacking.} \luavarset{zipopts} {"-v -r -X"} {Options based to zip program.} \luavarseparator \luavarset{checksearch} {true} {Look in \texttt{tds} dirs for checking?} \luavarset{typesetsearch}{true} {Look in \texttt{tds} dirs for typesetting docs?} \luavarset{unpacksearch} {true} {Look in \texttt{tds} dirs for unpacking?} \luavarseparator \luavarset{checkruns} {1} {How many times to run a check file before comparing the log.} \luavarset{packtdszip} {false} {Build a TDS-style zip file for CTAN?} \luavarset{scriptname} {"build.lua"} {Name of script used in dependencies.} \luavarset{typesetcmds} {""} {Instructions to be passed to \TeX{} when doing typesetting.} } \allluavars \newcommand\luavartypeset{% \begingroup \frenchspacing \renewcommand\luavarset[3]{ \texttt{##1} & \texttt{##2} & ##3 \\ } \renewcommand\luavarseparator{\midrule} \setlength\LTleft{-0.21\linewidth} \begin{longtable}{@{}% >{\small} p{0.18\linewidth} @{\hspace{0.03\linewidth}} >{\footnotesize\hangindent=1em} p{0.34\linewidth} @{\hspace{0.03\linewidth}} >{\small\raggedright\arraybackslash} p{0.63\linewidth} @{}} \toprule Variable & Default & Description \\ \midrule\endhead \allluavars \bottomrule \end{longtable} \endgroup } \newcommand\code{\texttt} \newcommand\var{\texttt} \usepackage[procnames]{listings} \lstset{ basicstyle=\ttfamily\small, numbers=left, numberstyle={\tiny\color[gray]{0.4}}, } \usepackage{shortvrb} \usepackage{enumitem} \usepackage{longtable} \MakeShortVerb\| \begin{document} \DocInput{\jobname.dtx} \end{document} % % \fi % % \title{^^A % The \pkg{l3build} package\\ Checking and building packages^^A % \thanks{This file describes v\ExplFileVersion, % last revised \ExplFileDate.}^^A % } % % \author{^^A % The \LaTeX3 Project\thanks % {^^A % E-mail: % \href{mailto:latex-team@latex-project.org} % {latex-team@latex-project.org}^^A % }^^A % } % % \date{Released \ExplFileDate} % % \maketitle % \tableofcontents % % \begin{documentation} % % \section{The \pkg{l3build} system} % % \subsection{Introduction} % % The \pkg{l3build} system is a Lua script for building \TeX{} packages, with particular emphasis on regression testing. % It is written in cross-platform Lua code, so can be used by any modern \TeX{} distribution with the |texlua| interpreter. % A package for building with \pkg{l3build} can be written in any \TeX\ dialect; its defaults are set up for \LaTeX\ packages written in the DocStrip style. (Caveat: minimal testing has yet been performed for non-\LaTeX{} packages.) % % Test files are written as standalone \TeX{} documents using the |regression-test.tex| setup file; documentation on writing these tests is discussed in Section~\ref{sec:writing-tests}. % % The |l3build.lua| script is not designed to be executed directly; each package will define its own |build.lua| script as a driver file which both sets variables (such as the name of the package) and then calls the main |l3build.lua| script internally. % % \pagebreak[2] % A standard package layout might look something like the following: % \begin{Verbatim}[fontsize=\small] % abc/ % abc.dtx % abc.ins % build.lua % README % support/ % testfiles/ % \end{Verbatim} % Most of this should look fairly self-explanatory. % The top level |support/| directory (optional) would contain any necessary files for compiling documentation, running regression tests, and so on. % % The \pkg{l3build} system is also capable of building and checking \emph{bundles} of packages. % To avoid confusion, we refer to either a standalone package or a package within a bundle as a \emph{module}. % % For example, within the \LaTeX3 project we have the \textsf{l3packages} bundle which contains the \textsf{xparse}, \textsf{xtemplate}, etc., modules. % These are all built and distributed as one bundle for installation, distribution \emph{via} CTAN and so forth. % % Each module in a bundle will have its own build script, and a bundle build script brings them all together. % A standard bundle layout would contain the following structure. % \begin{Verbatim} % mybundle/ % build.lua % support/ % yyy/ zoo/ % build.lua build.lua % README README % testfiles/ testfiles/ % yyy.dtx zoo.dtx % yyy.ins zoo.ins % \end{Verbatim} % All modules within a bundle must use the same build script name. % % The |testfiles/| folder is local to each module, and its layout consists of a series of regression tests with their outputs. % \begin{Verbatim} % testfiles/ % test1.lvt % test1.tlg % ... % support/ % my-test.cls % \end{Verbatim} % Again, the |support/| directory contains any files necessary to run some or all of these tests. % % When the build system runs, it creates a directory |build/| for various unpacking, compilation, and testing purposes. % For a module, this build folder can be in the main directory of the package itself, but for a bundle it should be common for the bundle itself and for all modules within that bundle. % A |build/| folder can be safety deleted; all material within is re-generated for each command of the \pkg{l3build} system. % % \subsection{Main build commands} % % In the working directory of a bundle or module, the following commands can be executed: % \begin{itemize}[noitemsep]\ttfamily % \item check % \item check \meta{name} [\meta{engine}] % \item cmdcheck % \item clean % \item doc % \item install % \item save \meta{name} [\meta{engine}] % \end{itemize} % These commands are described below. % % \begin{buildcmd}{check} % The |check| command runs the entire test suite. % This involves iterating through each \texttt{.lvt} file in the test directory (specified by the \var{testfiledir} variable), compiling each test in a \enquote{sandbox} (a directory specified by \var{testdir}), and comparing the output against each matching predefined \texttt{.tlg} file. % % If changes to the package or the typesetting environment have affected the results, the check for that file fails. % A |diff| of the expected to actual output should then be inspected to determine the cause of the error; it is located in the \var{testdir} directory (default \luavar{testdir}). % % The following files are moved into the \enquote{sandbox} for the |check| process: % \begin{itemize} % \item all \var{installfiles} after unpacking; % \item all \var{checkfiles} after unpacking; % \item any files in the directory \var{testsuppdir}; % \item any files that match \var{checksuppfiles} in the \var{supportdir}. % \end{itemize} % This range of possibilities allow sensible defaults but significant flexibility for defining your own test setups. % % Checking can be performed with any or all of the `engines' \texttt{pdftex}, \texttt{xetex}, and \texttt{luatex}. % By default, each test is executed with all three, being compared against the \texttt{.tlg} file produced from the \var{pdftex} engine (these defaults are controlled by the |checkengines| and |stdengine| variable respectively). % The format used for tests can be altered by setting \var{checkformat}: the default setting \texttt{latex} means that tests are run using \emph{e.g.}~\texttt{pdflatex}, whereas setting to \texttt{plain} will run tests using \emph{e.g.}~\texttt{pdftex}. % (Currently, this should be one of \texttt{latex} or \texttt{plain}.) % To perform the check, the engine typesets each test \var{checkruns} times. % More detail on this in the documentation on |save|. % Options passed to the binary are defined in the variable \var{checkopts}. % % By default, |texmf| trees are searched for input files when checking. This can be disabled by setting \var{checksearch} to |false|: isolation provides confidence that the tests cannot accidentally be running with incorrect files installed in the main distribution or |hometexmf|. % \end{buildcmd} % % % \begin{buildcmd}{check \meta{name} [\meta{engine}]} % Checks only the test \texttt{\meta{name}.lvt} with optionally specified \meta{engine} (one of |pdftex|, |xetex|, or |luatex|). % If an \meta{engine} is not specified, all three engines are checked (or those defined by the |checkengines| variable if changed from the default). % \end{buildcmd} % % \begin{buildcmd}{cmdcheck} % For \cls{l3doc}-based sources, allows checking that the commands defined in the code part (by \var{cmdchkfiles}) are documented in the description part. % This is performed by passing the |check| option to the \cls{l3doc} class, typesetting the file(s) to check with engine \var{stdengine} with options \var{cmdchkopts}, and checking the resultant |.cmds| file(s). % Dependencies are specified also with \var{checkdeps}. % \end{buildcmd} % % % \begin{buildcmd}{clean} % This command removes all temporary files used for package bundling and regression testing. % In the standard layout, these are all files within the directories defined by \var{localdir}, \var{testdir}, \var{typesetdir} and \var{unpackdir}, as well as all files defined in the \var{cleanfiles} variable in the same directory as the script. % The defaults are |.pdf| files from typesetting (|doc|) and |.zip| files from bundling (|ctan|). % \end{buildcmd} % % % \begin{buildcmd}{ctan} % Creates an archive of the package and its documentation, suitable for uploading to CTAN % The archive is compiled in \var{distribdir}, and if the results are successful the resultant |.zip| file is moved into the same directory as the build script. % If \var{packtdszip} is set true then the building process includes a |.tds.zip| file containing the `\TeX\ Directory Structure' layout of the package or bundle. % The archive therefore may contain two `views' of the package: % \begin{Verbatim} % abc.zip/ % abc/ % abc.dtx % abc.ins % abc.pdf % README % abc.tds.zip/ % doc/latex/abc/ % abc.pdf % README % source/latex/abc/ % abc.dtx % abc.ins % tex/latex/abc/ % abc.sty % \end{Verbatim} % The files copied into the archive are controlled by a number of variables. % The `root' of the TDS structure is defined by \var{tdsroot}, which is \luavar{tdsroot} by default. Plain users would redefine this to |"plain"| (or perhaps |"generic"|), for example. % The build process for a |.tds.zip| file currently assumes a `standard' % structure in which all extracted files should be places inside the |tex| % tree in a single directory, as shown above. % % \pagebreak[2] % The |doc| tree is constructed from: % \begin{itemize} % \item all files matched by \var{demofiles}, and % \item all files matched by \var{typesetfiles} with their extension replaced with |.pdf|, and % \item all files matched by \var{txtfiles}, but when copied their extension is entirely removed (e.g., |README.markdown| is copied as just |README|). % \end{itemize} % The |source| tree is constructed from all files matched by \var{typesetfiles} and \var{sourcefiles}. % The |tex| tree from all files matched by \var{installfiles}. % % Files that should always be excluded from the archive are matched against the \var{excludefiles} variable; by default this is \luavar{excludefiles}, which match Emacs' autosave files. % % Binary files should be specified with the \var{binaryfiles} variable (default \luavar{binaryfiles}); these are added to the zip archive without normalising line endings (text files are automatically converted to Unix-style line endings). % % To create the archive, by default the binary \var{zipexe} is used (\luavar{zipexe}) with options \var{zipopts} (|-v -r -X|). The intermediate build directories \var{ctandir} and \var{tdsdir} are used to construct the archive. % \end{buildcmd} % % % \begin{buildcmd}{doc} % Compiles all documentation files in the \var{typesetdir} directory. % If the compilation is successful the |.pdf| is moved back into the main directory. % % The documentation compilation is performed with the \var{typesetexe} binary (default \texttt{pdflatex}), with options \var{typesetopts}. % Additional \TeX{} material defined in \var{typesetcmds} is passed to the document (e.g., for writing |\\PassOptionsToClass{l3doc}{letterpaper}|, and so on---note that backslashes need to be escaped in Lua strings). % % Files that match |typesetsuppfiles| in the |support| directory (|supportdir|) are copied into the |build/local| directory (|localdir|) for the typesetting compilation process. % Additional dependencies listed in the \var{typesetdeps} variable (empty by default) will also be installed. % % If \var{typesetsearch} is \code{true} (default), standard \texttt{texmf} search trees are used in the typesetting compilation. If set to false, \emph{all} necessary files for compilation must be included in the |build/local| sandbox. % \end{buildcmd} % % % \begin{buildcmd}{install} % Copies all package files (defined by \var{installfiles}) into the user's home \texttt{texmf} tree in the form of the \TeX\ Directory Structure. % \end{buildcmd} % % % \begin{buildcmd}{save \meta{name} [\meta{engine}]} % This command runs through the same execution as |check| for a specific test \texttt{\meta{name}.lvt} with optional \texttt{\meta{engine}}. % If no \meta{engine} is specific, this command saves the output of the test to a |.tlg| file. % This file is then used in all subsequent checks against the \texttt{\meta{name}.lvt} test. % % If the \meta{engine} is specified (one of |pdftex|, |xetex|, or |luatex|), the saved output is stored in \texttt{\meta{name}.\meta{engine}.tlg}. This is necessary if running the test through a different engine produces a different output. % A normalisation process is performed when checking to avoid common differences such as register allocation; full details are listed in section~\ref{sec:norm}. % \end{buildcmd} % % % \begin{buildcmd}{unpack} % This is an internal target that is normally not needed on user level. % It unpacks all files into the directory defined by \var{unpackdir}. This occurs before other build commands such as |doc|, |check|, etc. % % The unpacking process is performed by executing the \var{unpackexe} (default \texttt{tex}) with options \var{unpackopts} on all files defined by the \var{unpackfiles} variable; by default, all files that match \luavar{unpackfiles}. % % If additional support files are required for the unpacking process, these can be enumerated in the \var{unpacksuppfiles} variable. % Dependencies for unpacking are defined with \var{unpackdeps}. % % By default this process allows files to be accessed in all standard |texmf| trees; this can be disabled by setting \var{unpacksearch} to |false|. % \end{buildcmd} % % \subsection{Example build scripts} % % An example of a standalone build script for a package that uses self-contained |.dtx| files is shown in Figure~\ref{fig:breqn}. % Here, the |module| only is defined, and since it doesn't use |.ins| files so the variable \var{unpackfiles} is redefined to run |tex| on the |.dtx| files instead to generate the necessary |.sty| files. % There are some PDFs in the repository that shouldn't be part of a CTAN submission, so they're explicitly excluded, and here unpacking is done `quietly' to minimise console output when building the package. % Finally, because this is a standalone package, we assume that \pkg{l3build} is installed in the main \TeX{} distribution and find the Lua script by searching for it. % % \begin{figure}[!b] % \begin{lstlisting}[frame=single,language={[5.2]Lua},gobble = 6] % #!/usr/bin/env texlua % % -- Build script for breqn % % module = "breqn" % % unpackfiles = {"*.dtx"} % excludefiles = {"*/breqn-abbr-test.pdf", % "*/eqbreaks.pdf"} % unpackopts = "-interaction=batchmode" % % kpse.set_program_name("kpsewhich") % dofile(kpse.lookup("l3build.lua")) % \end{lstlisting} % \caption{The build script for the \pkg{breqn} package.} % \label{fig:breqn} % \end{figure} % % An example of a bundle build script for \pkg{l3packages} is shown in Figure~\ref{fig:bundle}. % Note for \LaTeX3 we use a common file to set all build variables in one place, and the path to the |l3build.lua| script is hard-coded so we always use our own most recent version of the script. % An example of an accompanying module build script is shown in Figure~\ref{fig:module}. % % \begin{figure}[p] % \begin{lstlisting}[frame=single,language={[5.2]Lua},gobble = 6] % #!/usr/bin/env texlua % % -- Build script for LaTeX3 "l3packages" files % % -- Identify the bundle: there is no module as this is the "driver" % bundle = "l3packages" % % -- Location of main directory: use Unix-style path separators % maindir = ".." % % -- Load the common build code: this is the one place that a path % -- needs to be hard-coded % dofile (maindir .. "/l3build/l3build-config.lua") % dofile (maindir .. "/l3build/l3build.lua") % \end{lstlisting} % \caption{The build script for the \pkg{l3packages} bundle.} % \label{fig:bundle} % \end{figure} % % \begin{figure}[p] % \begin{lstlisting}[frame=single,language={[5.2]Lua},gobble = 6] % #!/usr/bin/env texlua % % -- Build script for LaTeX3 "xparse" files % % -- Identify the bundle and module: % bundle = "l3packages" % module = "xparse" % % -- Location of main directory: use Unix-style path separators % -- Should match that defined by the bundle. % maindir = "../.." % % -- Load the common build code: this is the one place that a path % -- needs to be hard-coded % dofile (maindir .. "/l3build/l3build-config.lua") % dofile (maindir .. "/l3build/l3build.lua") % \end{lstlisting} % \caption{The build script for the \pkg{xparse} module.} % \label{fig:module} % \end{figure} % % \begin{figure}[p] % \begin{lstlisting}[frame=single,gobble = 6] % @echo off % texlua build.lua %* % \end{lstlisting} % \caption{Windows batch file wrapper for running the build process.} % \label{fig:batch} % \end{figure} % % Under a Unix-like platform, you may wish to run `|chmod +x build.lua|' on these files, which allows a simpler command line use. Instead of writing\\ % \hspace*{2\parindent}|texlua build.lua check|\\ for example, you would simply write\\ % \hspace*{2\parindent}|./build.lua check|\\ % instead. (Or even omit the |./| depending on your path settings.) % Windows users can achieve a similar effect by creating a file |build.bat| as show in Figure~\ref{fig:batch}. % % \subsection{Variables} % % This section lists all variables defined in the |l3build.lua| script that are available for customisation. % % \luavartypeset % % \subsection{Dependencies} % % If you have multiple packages that are developed separately but still interact in some way, it's often desirable to integrate them when performing regression tests. % For \LaTeX3, for example, when we make changes to \pkg{l3kernel} it's important to check that the tests for \pkg{l3packages} still run correctly, so it's necessary to include the \pkg{l3kernel} files in the build process for \pkg{l3packages}. % % In other words, \pkg{l3packages} is \emph{dependent} on \pkg{l3kernel}, and this is specified in \pkg{l3build} by setting appropriately the variables \texttt{checkdeps}, \texttt{typesetdeps}, and \texttt{unpackdeps}. % The relevant parts of the \LaTeX3 repository is structured as the following. % \Needspace{3\baselineskip} % \begin{Verbatim} % l3/ % l3kernel/ % build.lua % expl3.dtx % expl3.ins % ... % testfiles/ % l3packages/ % build.lua % xparse/ % build.lua % testfiles/ % xparse.dtx % xparse.ins % support/ % \end{Verbatim} % For \LaTeX3 build files, |maindir| is defined as top level folder |l3|, so all support files are located here, and the build directories will be created there. % To set \pkg{l3kernel} as a dependency of \pkg{l3package}, within |l3packages/xparse/build.lua| the equivalent of the following is set: % \begin{Verbatim} % maindir = "../.." % checkdeps = {maindir .. "/l3kernel"} % \end{Verbatim} % This ensures that the \pkg{l3kernel} code is included in all processes involved in unpacking and checking and so on. % The name of the script file in the dependency is set with the |scriptname| variable; by default these are |"build.lua"|. % % % \subsection{Output normalisation} % \label{sec:norm} % % To allow test files to be used between different systems (\emph{e.g.}~when % multiple developers are involved in a project), the log files are normalised % before comparison during checking. This removes some system-dependent % data but also some variations due to different engines and bugs in some % versions of some engines. This normalisation consists of two parts: removing % (\enquote{ignoring}) some lines and modifying others to give consistent % test. Currently, the following types of line are ignored: % \begin{itemize} % \item Lines before the \cs{START}, after the \cs{END} and within % \cs{OMIT}/\cs{TIMO} blocks % \item Entirely blank lines, including those consisting only of spaces. % \item Lines containing file dates in the % \texttt{\meta{yyyy}/\meta{mm}/\meta{dd}} format. % \item Lines starting \cs{openin} or \cs{openout}. % \item \LuaTeX{}-specific lines in box output for the \cs{local\ldots} % concepts it introduces when these are set to their defaults. % \item \LuaTeX{}-specific lines in box output which record % \cs{discretionary}. % \end{itemize} % Modifications made in lines are: % \begin{itemize} % \item Removal of the name of the test file itself. % \item Removal spaces at the start of lines (deals with some issues % with \LuaTeX{} using a different amount of indentation to other engines). % \item Removal of |./| at start of file names. % \item Standardisation of the list of units known to \TeX{} (\pdfTeX{} % and \LuaTeX{} add a small number of additional units which are not % known to \XeTeX{}). % \item Standardisation of \verb*|\csname\endcsname | to |\csname\endcsname| % (the former is formally correct, but the latter was produced for many % years due to a \TeX{} bug). % \item Conversion of \texttt{on line \meta{number}} to \texttt{on line ...} % to allow flexibility in changes to test files. % \item Restriction of glue set in boxes to four decimal places (\LuaTeX{} % may vary in the last digit from the \pdfTeX{} values). % \item Removal of the Omega-like \texttt{direction TLT} added by % \LuaTeX{} to boxes running in the \enquote{normal} way. % \item Conversion of low chars ($1$ to $31$) to |^^| notation (\LuaTeX{} % does not do this). % \item Correction of a \LuaTeX{} error message typo (|I''m going to assume|). % \end{itemize} % % \section{Writing test files} % \label{sec:writing-tests} % % Test files are written in a \TeX{} dialect using the support file |regression-test.tex|, which should be |\input| at the very beginning of each test. % Additional customisations to this driver can be included in a local |regression-test.cfg| file, which will be loaded automatically if found. % % The macros loaded by |regression-test.tex| set up the test system and provide a number of commands to aid the production of a structured test suite. % The basis of the test suite is to output material into the |.log| file, from which a normalised test output (|.tlg|) file is produced by the build command |save|. % A number of commands are provided for this; they are all written in uppercase to help avoid possible conflicts with other package commands. % % \subsection{Metadata and structural commands} % % Any commands that write content to the |.log| file that should be ignored can be surrounded by |\OMIT| \dots\ |\TIMO|. % At the appropriate location in the document where the |.log| comparisons should start (say, after |\begin{document}|), the test suite must contain the |\START| macro. % The test should then include \cs{AUTHOR}\marg{authors details} in case a test file fails in the future and needs to be re-analysed. % % Some additional diagnostic information can then be included as metadata for the conditions of the test. % The desired format can be indicated with \cs{FORMAT}\marg{format name}, and any packages or classes loaded can be indicated with % % \noindent\hspace*{2\parindent} \cs{CLASS}\oarg{options}\marg{class name, version}\par % \noindent\hspace*{2\parindent} \cs{PACKAGE}\oarg{options}\marg{package name, version} % % \noindent These do not provide information that is useful for automated checking; after all, packages change their version numbers frequently. % Rather, including this information in a test indicates the conditions under which the test was definitely known to pass at a certain time in the past. % % The |\END| command signals the end of the test (but read on). % Some additional diagnostic information is printed at this time to debug if the test did not complete `properly' in terms of mismatched brace groups or \cs{if}\dots\cs{fi} groups. % % In a \LaTeX{} document, |\end{document}| will implicitly call |\END| at the very end of the compilation process. % If |\END| is used directly (replacing |\end{document}| in the test), the compilation will halt almost immediately, and various tasks that |\end{document}| usually performs will not occur (such as potentially writing to the various |.toc| files, and so on). This can be an advantage if there is additional material printed to the log file in this stage that you wish to ignore, but it is a disadvantage if the test relies on various auxiliary data for a subsequent typesetting run. % (See the \var{checkruns} variable for how these tests would be test up.) % % \subsection{Commands to help write tests} % % A simple command \cs{CHECKCOMMAND}\cs{\meta{macro}} is provided to check whether a particular \cs{\meta{macro}} is defined, undefined, or equivalent to \cs{relax}. % This is useful to flag either that internal macros are remaining local to their definitions, or that defined commands definitely are defined, or even as a reminder that commands you intend to define in a future package need to be tested once they appear. % % \cs{TYPE} is used to write material to the \texttt{.log} file, like \LaTeX's \cs{typeout}, but it allows `long' input. % The following commands are defined to use \cs{TYPE} to output strings to the \texttt{.log} file. % \begin{itemize} % \item % \cs{SEPARATOR} inserts a long line of \texttt{=} symbols to break up the log output. % \item % \cs{NEWLINE} inserts a linebreak into the log file. % \item % \cs{TRUE}, \cs{FALSE}, \cs{YES}, \cs{NO} output those strings to the log file. % \item % \cs{ERROR} is \emph{not} defined but is commonly used to indicate a code path that should never be reached. % \item % The \cs{TEST}\marg{title}\marg{contents} command surrounds its \meta{contents} with some \cs{SEPARATOR}s and a \meta{title}. % \item % \cs{TESTEXP} surrounds its contents with \cs{TYPE} and formatting to match \cs{TEST}; this can be used as a shorthand to test expandable commands. % \item % TODO: would a \cs{TESTFEXP} command (based on \cs{romannumeral} expansion) be useful as well? % \end{itemize} % An example of some of these commands is shown following. % \begin{Verbatim} % \TEST{bool_set,~lazy~evaluation} % { % \bool_set:Nn \l_tmpa_bool % { % \int_compare_p:nNn 1=1 % && \bool_if_p:n % { % \int_compare_p:nNn 2=3 || % \int_compare_p:nNn 4=4 || % \int_compare_p:nNn 1=\ERROR % is skipped % } % && \int_compare_p:nNn 2=2 % } % \bool_if:NTF \l_tmpa_bool \TRUE \FALSE % } % \end{Verbatim} % This test will produce the following in the output. % \begin{Verbatim} % ========================================== % TEST 8: bool_set, lazy evaluation % ========================================== % TRUE % ========================================== % \end{Verbatim} % (Only if it's the eighth test in the file of course, and assuming \pkg{expl3} % coding conventions are active.) % % \subsection{Showing box content} % % The commands introduced above are only useful for checking algorithmic or logical correctness. % Many packages should be tested based on their typeset output instead; \TeX{} provides a mechanism for this by printing the contents of a box to the log file. % The |regression-test.tex| driver file sets up the relevant \TeX{} parameters to produce as much output as possible when showing box output. % % A plain \TeX{} example of showing box content follows. % \begin{Verbatim}[frame=single,fontsize=\small] % \input regression-test.tex\relax % \START % \setbox0=\hbox{\rm hello \it world $a=b+c$} % \showbox0 % \END % \end{Verbatim} % This produces the output shown in Figure~\ref{fig:box-log} (left side). % It is clear that if the definitions used to typeset the material in the box changes, the log output will differ and the test will no longer pass. % % The equivalent test in \LaTeXe{} using \pkg{expl3} is similar. % \begin{Verbatim}[frame=single,fontsize=\small] % \input{regression-test.tex} % \documentclass{article} % \usepackage{expl3} % \START % \ExplSyntaxOn % \box_new:N \l_tmp_box % \hbox_set:Nn \l_tmp_box {hello~ \emph{world}~ $a=b+c$} % \box_show:N \l_tmp_box % \ExplSyntaxOff % \END % \end{Verbatim} % The output from this test is shown in Figure~\ref{fig:box-log} (right side). % There is marginal difference (mostly related to font selection and different logging settings in \LaTeX) between the plain and \pkg{expl3} versions. % % When examples are not self-contained enough to be typeset into boxes, it is possible to ask \TeX{} to output the entire contents of a page. % Insert \cs{showoutput} for \LaTeX{} or set \cs{tracingoutput} positive for plain \TeX{}; ensure that the test ends with \cs{newpage} or equivalent because \TeX{} waits until the entire page is finished before outputting it. % % TODO: should we add something like \cs{TRACEPAGES} to be format-agnostic here? Should this perhaps even be active by default? % % \begin{figure} % \hspace*{-3cm} % \begin{BVerbatim}[fontsize=\small] % > \box0= % \hbox(6.94444+0.83333)x90.56589 % .\tenrm h % .\tenrm e % .\tenrm l % .\tenrm l % .\tenrm o % .\glue 3.33333 plus 1.66666 minus 1.11111 % .\tenit w % .\tenit o % .\tenit r % .\tenit l % .\tenit d % % .\glue 3.57774 plus 1.53333 minus 1.0222 % .\mathon % .\teni a % .\glue(\thickmuskip) 2.77771 plus 2.77771 % .\tenrm = % .\glue(\thickmuskip) 2.77771 plus 2.77771 % .\teni b % .\glue(\medmuskip) 2.22217 plus 1.11108 minus 2.22217 % .\tenrm + % .\glue(\medmuskip) 2.22217 plus 1.11108 minus 2.22217 % .\teni c % .\mathoff % % ! OK. % l.9 \showbox0 % % % \end{BVerbatim} % \qquad % \begin{BVerbatim}[fontsize=\small] % > \box71= % \hbox(6.94444+0.83333)x91.35481 % .\OT1/cmr/m/n/10 h % .\OT1/cmr/m/n/10 e % .\OT1/cmr/m/n/10 l % .\OT1/cmr/m/n/10 l % .\OT1/cmr/m/n/10 o % .\glue 3.33333 plus 1.66666 minus 1.11111 % .\OT1/cmr/m/it/10 w % .\OT1/cmr/m/it/10 o % .\OT1/cmr/m/it/10 r % .\OT1/cmr/m/it/10 l % .\OT1/cmr/m/it/10 d % .\kern 1.03334 % .\glue 3.33333 plus 1.66666 minus 1.11111 % .\mathon % .\OML/cmm/m/it/10 a % .\glue(\thickmuskip) 2.77771 plus 2.77771 % .\OT1/cmr/m/n/10 = % .\glue(\thickmuskip) 2.77771 plus 2.77771 % .\OML/cmm/m/it/10 b % .\glue(\medmuskip) 2.22217 plus 1.11108 minus 2.22217 % .\OT1/cmr/m/n/10 + % .\glue(\medmuskip) 2.22217 plus 1.11108 minus 2.22217 % .\OML/cmm/m/it/10 c % .\mathoff % % ! OK. % \l_tmp_box % % l.12 \box_show:N \l_tmp_box % \end{BVerbatim} % \caption{Output from displaying the contents of a simple box to the log file, using plain \TeX{} (left) and \pkg{expl3} (right). Some blank lines have been added to the plain \TeX{} version to help with the comparison.} % \label{fig:box-log} % \end{figure} % % % % % \end{documentation} % % \begin{implementation} % % \clearpage % \section{\texttt{regression-test.tex}} % % This section describes the code for setting up the regression test system. % Each test file should start with |\input regression-test.tex\relax|. % % \begin{macrocode} %<*package> % \end{macrocode} % % \subsection{Preliminaries} % % Unlike in the \LaTeXe{} regression test suite, reset catcodes: each test should set these % as appropriate. % \begin{macrocode} \expandafter\edef\csname\detokenize{reset@catcodes}\endcsname{% \catcode`\noexpand\@=\the\catcode`\@\relax } \catcode`\@=11 % % \end{macrocode} % Put \TeX{} into scroll mode, and stop it showing the % implementation details of macros in error messages. % \begin{macrocode} \scrollmode \errorcontextlines=-1 % % \end{macrocode} % % Show all box details: this avoids getting variable results if boxes % have different numbers of lines (\LuaTeX{} adds extra information). % \begin{macrocode} \showboxbreadth=\maxdimen \showboxdepth=\maxdimen % \end{macrocode} % % The |\showoutput| command of \LaTeX{} calls |\loggingoutput| which in % turn calls |\errorstopmode| but we want to continue running without % any stops. % \begin{macrocode} \def\loggingoutput{\tracingoutput1 \showboxbreadth\maxdimen\showboxdepth\maxdimen} % \end{macrocode} % % Set the newline character: \LaTeXe{} does this but plain-based formats % do not. % \begin{macrocode} \newlinechar=`\^^J % \end{macrocode} % % \subsection{Commands in test files} % % A long version of |\typeout|, because tests may contain |\par| tokens. % Besides, with that |\TYPE|, we can do |\TYPE { ... \TRUE ... \NEWLINE ... }|. % \begin{macrocode} \long\def\LONGTYPEOUT#1{% \begingroup \long\def\TYPE##1{##1}% \immediate\write17{#1}% \endgroup } \let\TYPE\LONGTYPEOUT % \end{macrocode} % % Start the test, after the optional |\documentclass| % |\begin{document}| commands with |\START|. All lines in the |.log| file % before this will be ignored. % % It also prints a DocStrip-style % character table in the |.tlg| file. % Is this necessary any more? Probably too late to remove it. % \begin{macrocode} \def\STARTMESSAGE{This is a generated file for the l3build validation system.} \def\START{\LONGTYPEOUT{START-TEST-LOG^^J^^J% \STARTMESSAGE% ^^J^^JDon't change this file in any respect.% ^^J^^J\CTable^^J}} \begingroup \catcode`\^^\=0 \catcode`\^^A=\catcode`\% ^^\catcode`^^\ =11 ^^\catcode`^^\%=11 ^^\catcode`^^\#=11 ^^\catcode`^^\~=11 ^^\endlinechar=`^^\^^J ^^\catcode`^^\\=11^^A ^^\gdef^^\CTable{ %% \CharacterTable %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z %% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z %% Digits \0\1\2\3\4\5\6\7\8\9 %% Exclamation \! Double quote \" Hash (number) \# %% Dollar \$ Percent \% Ampersand \& %% Acute accent \' Left paren \( Right paren \) %% Asterisk \* Plus \+ Comma \, %% Minus \- Point \. Solidus \/ %% Colon \: Semicolon \; Less than \< %% Equals \= Greater than \> Question mark \? %% Commercial at \@ Left bracket \[ Backslash \\ %% Right bracket \] Circumflex \^ Underscore \_ %% Grave accent \` Left brace \{ Vertical bar \| %% Right brace \} Tilde \~} %% }^^A ^^\endgroup{}% % \end{macrocode} % The test should end with |\END| or |\end{document}| % \begin{macrocode} \ifx\@@end\@undefined \let\@@@end\end \else \let\@@@end\@@end \fi \def\END {% \ifnum\currentgrouplevel>0 % \LONGTYPEOUT{Bad grouping: \the\currentgrouplevel!}% \fi \ifnum\currentiflevel>1 % \LONGTYPEOUT{Bad conditionals: \the\numexpr\currentiflevel-1!}% \fi \LONGTYPEOUT{END-TEST-LOG}\@@@end } \let\@@end\END % \end{macrocode} % After the |\START| should come declarations of the format and style % options being used. % \begin{macrocode} \def\FORMAT#1{\LONGTYPEOUT{Format: #1}% \def\@tempa{#1}\ifx\@tempa\@EJ\else \OMIT\TYPE{WARNING: Declared format #1,^^JActual format \@EJ}\TIMO\fi} % \end{macrocode} % The old version got this information from everyjob, % but that does not work with \LaTeXe\ as |\everyjob| is cleared. % \begin{macrocode} \edef\@EJ{\fmtname <\fmtversion>} % \end{macrocode} % Some author info: % \begin{macrocode} \def\AUTHOR#1{\LONGTYPEOUT{Author: #1}} % \end{macrocode} % Surround commands which produce irrelevant lines in the .log file by % |\OMIT|\dots|\TIMO| % \begin{macrocode} \def\OMIT{\LONGTYPEOUT{OMIT}} \def\TIMO{\LONGTYPEOUT{TIMO}} % \end{macrocode} % Not all packages declare themselves to the log file, and we can not % rely on TeX`s output as it includes full path names, and does not % include version numbers etc. % % If the class or package is loaded with options, you may % specify the options in the |\CLASS| (|\PACKAGE|) declaration. eg: % \begin{verbatim} % \CLASS[german,a4page]{article v2.0 1994/01/02} % \PACKAGE{ifthen v2.2 1993/11/12} % \PACKAGE[dvips]{graphics v 3.8 1994/02/02} % \end{verbatim} % \begin{macrocode} \def\CLASS{\@ifnextchar[\OPTCLASS\XCLASS} \def\OPTCLASS[#1]#2{% \TYPE{Main Class: #2^^J\space\space\space\space Options: #1}} \def\XCLASS#1{% \TYPE{Main Class: #1}} \def\PACKAGE{\@ifnextchar[\OPTPACKAGE\XPACKAGE} \def\OPTPACKAGE[#1]#2{% \TYPE{Package: #2^^J\space\space\space\space Options: #1}} \def\XPACKAGE#1{% \TYPE{Package: #1}} % \end{macrocode} % % The commands above require 2e's \verb|\@ifnextchar|, so copy that definition verbatim if necessary: % \begin{macrocode} \ifx\@ifnextchar\@undefined \long\def\@ifnextchar#1#2#3{% \let\reserved@d=#1% \def\reserved@a{#2}% \def\reserved@b{#3}% \futurelet\@let@token\@ifnch} \def\@ifnch{% \ifx\@let@token\@sptoken \let\reserved@c\@xifnch \else \ifx\@let@token\reserved@d \let\reserved@c\reserved@a \else \let\reserved@c\reserved@b \fi \fi \reserved@c} \def\:{\let\@sptoken= } \: % this makes \@sptoken a space token \def\:{\@xifnch} \expandafter\def\: {\futurelet\@let@token\@ifnch} \fi % \end{macrocode} % After the above declarations, and before the main tests, you may % optionally declare' all the commands in the `module' that you are % about to test. These commands will be registered as defined, % undefined or relaxed (i.e.~|\let| to |\relax|). You may wish to declare % commands not currently implemented, so that if they are added at a % later stage, the test will fail, reminding someone to document the % fact that the user interface has changed. % \begin{macrocode} \def\CHECKCOMMAND#1{% \ifx#1\@undefined\LONGTYPEOUT{Undefined \string#1}\else \ifx#1\relax\LONGTYPEOUT{Relaxed \space\space\string#1}\else \LONGTYPEOUT{Defined \space\space\string#1}\fi\fi} % \end{macrocode} % To allow testing of possible changes, we allow extra code to be read % in before the test starts. The necessary code should be placed in a % file |regression-test.cfg|. % \begin{macrocode} \OMIT \ifx\InputIfFileExists\@undefined \newread\@inputcheck \long\def\InputIfFileExists#1#2#3{% \openin\@inputcheck#1\relax \ifeof\@inputcheck \def\reserved@a{#3}% \else \def\reserved@a{#2\input #1\relax}% \fi \closein\@inputcheck \reserved@a} \fi \InputIfFileExists{regression-test.cfg} {\LONGTYPEOUT{^^J***^^Jregression-test.cfg in operation^^J***^^J}}{} \TIMO % \end{macrocode} % % \subsection{Formatting the \texttt{.log} file} % % We are not starved for space in the log file output, so let's make it as % verbose as is useful when reading the |.diff|'s. % \begin{macrocode} \newcount \gTESTint \def\SEPARATOR{% \TYPE{% ============================================================% }% } % \end{macrocode} % \begin{macrocode} \long\def\TEST#1#2{% \advance \gTESTint 1 % \SEPARATOR \LONGTYPEOUT{% TEST \the\gTESTint: \detokenize{#1}}% \SEPARATOR \begingroup \let\TYPE\LONGTYPEOUT #2% \endgroup \SEPARATOR \LONGTYPEOUT{}% } \long\def\TESTEXP#1#2{% \advance \gTESTint 1 % \SEPARATOR \LONGTYPEOUT{% TEST \the\gTESTint: \detokenize{#1}}% \SEPARATOR \begingroup \long\def\TYPE##1{##1}% \LONGTYPEOUT{#2}% \endgroup \SEPARATOR \LONGTYPEOUT{}% } \def \TRUE {\TYPE{TRUE}} \def \FALSE {\TYPE{FALSE}} \def \YES {\TYPE{YES}} \def \NO {\TYPE{NO}} \def \NEWLINE {\TYPE{^^J}} % \end{macrocode} % Finish up. % \begin{macrocode} \reset@catcodes % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \newpage % \section{\texttt{l3build.lua}} % % This section consists of the |l3build.lua| code. % This code is \emph{not} generated from |l3build.dtx| since it needs to already be extracted to build \pkg{l3build} itself! % As Frank says, we don't want to end up with a double M\"unchhausen. % % \lstinputlisting % [ % basicstyle=\ttfamily\scriptsize, % numbers=left, % numberstyle={\tiny\color[gray]{0.4}}, % language={[5.2]Lua}, % procnamekeys=function, % procnamestyle=\color{red}, % ] % {l3build.lua} % % \end{implementation} % % \PrintIndex