% \iffalse
%
% File l3build.dtx Copyright (C) 2014-2026 The LaTeX 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
%
%    https://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 development version of the bundle can be found at
%
%    https://github.com/latex3/l3build
%
% for those people who are interested.
%
%<*driver>
\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}{\$} l3build #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 (where relevant)}
\luavarset{ctanpkg}{bundle == "" and module or bundle}{Name of the CTAN package matching this module}
\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}     {"."}                      {Top level directory for the module/bundle}
\luavarset{docfiledir}  {"."}                 {Directory containing documentation files}
\luavarset{sourcefiledir}{"."}                 {Directory containing source files}
\luavarset{supportdir} {maindir .. "/support"}    {Directory containing general support files}
\luavarset{testfiledir}{"./testfiles"}  {Directory containing test files}
\luavarset{testsuppdir}{testfiledir .. "/support"}{Directory containing test-specific support files}
\luavarset{texmfdir}{maindir .. "/texmf"}{Directory containing support files in tree form}
\luavarset{textfiledir}{"."}                 {Directory containing plain text files}
\luavarseparator
\luavarset{builddir}  {maindir .. "/build"}   {Directory for building and testing}
\luavarset{distribdir}{builddir .. "/distrib"}{Directory for generating distribution structure}
\luavarset{localdir}  {builddir .. "/local"}  {Directory for extracted files in \enquote{sandboxed} \TeX{} runs}
\luavarset{resultdir} {builddir .. "/result"} {Directory for PDF files when using PDF-based tests}
\luavarset{testdir}   {builddir .. "/test"}   {Directory for running tests}
\luavarset{typesetdir}{builddir .. "/doc"}    {Directory for building documentation}
\luavarset{unpackdir} {builddir .. "/unpacked"}{Directory for unpacking sources}
\luavarseparator
\luavarset{ctandir}{distribdir .. "/ctan"}{Directory for organizing files for CTAN}
\luavarset{tdsdir} {distribdir .. "/tds"} {Directory for organized files into TDS structure}
\luavarset{tdsroot}{"latex"}{Root directory of the TDS structure for the bundle/module to be installed into}
\luavarseparator
\luavarset{auxfiles}          {\{"*.aux", "*.lof", "*.lot", "*.toc"\}}{Secondary files to be saved as part of running tests}
\luavarset{bibfiles}          {\{"*.bib"\}}{\BibTeX{} database files}
\luavarset{binaryfiles}       {\{"*.otf", "*.pdf", "*.pfb", "*.pfm", "*.tfm", "*.ttf", "*.vf", "*.zip"\}}{Files to be added in binary mode to zip files}
\luavarset{bstfiles}          {\{"*.bst"\}}{\BibTeX{} style files}
\luavarset{checkfiles}        {\{~\}}{Extra files unpacked purely for tests}
\luavarset{checksuppfiles}    {\{ \}}{Files needed for performing regression tests}
\luavarset{cleanfiles}        {\{"*.log", "*.pdf", "*.zip"\}}{Files to delete when cleaning}
\luavarset{demofiles}         {\{ \}}{Files which show how to use a module}
\luavarset{docfiles}          {\{ \}}{Files which are part of the documentation but should not be typeset}
\luavarset{dynamicfiles}      {\{ \}}{Secondary files to cleared before each test is run}
\luavarset{excludefiles}      {\{"*\string~","build.lua","config-*.lua"\}}{Files to ignore entirely (default for Emacs backup files)}
\luavarset{installfiles}      {\{"*.sty","*.cls"\}}{Files to install to the \texttt{tex} area of the \texttt{texmf} tree}
\luavarset{makeindexfiles}    {\{"*.ist"\}}{MakeIndex files to be included in a TDS-style zip}
\luavarset{scriptfiles}       {\{ \}}{Files to install to the \texttt{scripts} area of the \texttt{texmf} tree}
\luavarset{scriptmanfiles}    {\{ \}}{Files to install to the \texttt{doc/man} area of the \texttt{texmf} tree}
\luavarset{sourcefiles}       {\{"*.dtx", "*.ins", "*-????-??-??.sty"\}}{Files to copy for unpacking}
\luavarset{tagfiles}          {\{"*.dtx"\}}{Files for automatic tagging}
\luavarset{textfiles}         {\{"*.md", "*.txt"\}}{Plain text files to send to CTAN as-is}
\luavarset{typesetdemofiles}  {\{ \}}{Files to typeset before the documentation for inclusion in main documentation files}
\luavarset{typesetfiles}      {\{"*.dtx"\}}{Files to typeset for documentation}
\luavarset{typesetsuppfiles}  {\{ \}}{Files needed to support typesetting when \enquote{sandboxed}}
\luavarset{typesetsourcefiles}{\{ \}}{Files to copy to unpacking when typesetting}
\luavarset{unpackfiles}       {\{"*.ins"\}}{Files to run to perform unpacking}
\luavarset{unpacksuppfiles}   {\{ \}}{Files needed to support unpacking when \enquote{sandboxed}}
\luavarseparator
\luavarset{includetests}{\{"*"\}}{Test names to include when checking}
\luavarset{excludetests}{\{ \}}   {Test names to exclude when checking}
\luavarseparator
\luavarset{checkdeps}  {\{ \}}{List of dependencies for running checks}
\luavarset{typesetdeps}{\{ \}}{List of dependencies for typesetting docs}
\luavarset{unpackdeps} {\{ \}}{List of dependencies for unpacking}
\luavarseparator
\luavarset{checkengines}{\{"pdftex", "xetex", "luatex"\}}{Engines to check with \texttt{check} by default}
\luavarset{stdengine}    {checkengines[1] or "pdftex"}{Engine to generate \texttt{.tlg} file from}
\luavarset{checkformat}  {"latex"} {Format to use for tests}
\luavarset{specialformats}{\meta{table}} {Non-standard engine/format combinations}
\luavarset{\detokenize{test_types}}        {\meta{table}} {Custom test variants}
\luavarset{\detokenize{test_order}}        {\{"log", "pdf"\}} {Which kinds of tests to evaluate}
\luavarseparator
\luavarset{checkconfigs}{\{ \}}{Configurations to use for tests}
\luavarseparator
\luavarset{typesetexe}   {"pdflatex"} {Executable for compiling \texttt{doc(s)}}
\luavarset{unpackexe}    {"pdftex"}   {Executable for running \texttt{unpack}}
\luavarset{biberexe}     {"biber"}    {Biber executable}
\luavarset{bibtexexe}    {"bibtex8"}  {\BibTeX{} executable}
\luavarset{makeindexexe} {"makeindex"}{MakeIndex executable}
\luavarset{curlexe}      {"curl"}     {Curl executable for \texttt{upload}}
\luavarseparator
\luavarset{checkopts}  {"-interaction=nonstopmode"}{Options passed to engine when running checks}
\luavarset{typesetopts}{"-interaction=nonstopmode"}{Options passed to engine when typesetting}
\luavarset{unpackopts} {""}                        {Options passed to engine when unpacking}
\luavarset{biberopts}    {""}         {Biber options}
\luavarset{bibtexopts}   {"-W"}       {\BibTeX{} options}
\luavarset{makeindexopts}{""}         {MakeIndex options}
\luavarseparator
\luavarset{checksearch}  {true}{Switch to search the system \texttt{texmf} for during checking}
\luavarset{typesetsearch}{true}{Switch to search the system \texttt{texmf} for during typesetting}
\luavarset{unpacksearch} {true}{Switch to search the system \texttt{texmf} for during unpacking}
\luavarseparator
\luavarset{glossarystyle}{"gglo.ist"}{MakeIndex style file for glossary/changes creation}
\luavarset{indexstyle}   {"gind.ist"}{MakeIndex style for index creation}
\luavarset{specialtypesetting}{\meta{table}} {Non-standard typesetting combinations}
\luavarseparator
\luavarset{forcecheckepoch}{true}     {Force epoch when running tests}
\luavarset{forcedocepoch}  {false}    {Force epoch when typesetting}
\luavarseparator
\luavarset{asciiengines}{\{"pdftex"\}}{Engines which should log as pure ASCII}
\luavarset{checkruns}   {1}           {Number of runs to complete for a test before comparing the log}
\luavarset{forcecheckruns}{false}     {Always run \texttt{checkruns} runs and never stop early}
\luavarset{versionpatterns}{\{ \}}    {Additional file version patterns to normalize when comparing logs}
\luavarset{ctanreadme}{"README.md"}   {Name of the file to send to CTAN as \texttt{README.\meta{ext}}}
\luavarset{ctanzip}{ctanpkg ... "-ctan"}{Name of the zip file (without extension) created for upload to CTAN}
\luavarset{epoch}       {1463734800}  {Epoch (Unix date) to set for test runs}
\luavarset{flatten}     {true}        {Switch to flatten any source structure when sending to CTAN}
\luavarset{flattentds}  {true}        {Switch to flatten any source structure when creating a TDS structure}
\luavarset{maxprintline}{9999}        {Length of line to use in log files}
\luavarset{errorline}{79}            {Length of line to use for error line}
\luavarset{halferrorline}{50}        {Links to the above: see standard \TeX{} documentation}
\luavarset{packtdszip}  {false}       {Switch to build a TDS-style zip file for CTAN}
\luavarset{ps2pdfopts}  {""}          {Options for \texttt{ps2pdf}}
\luavarset{typesetcmds} {""}          {Instructions to be passed to \TeX{} when doing typesetting}
\luavarset{typesetruns}{3}            {Number of cycles of typesetting to carry out}
\luavarset{typesetwarnings}{false}    {Switch to fail typesetting when the log reports overfull/underfull boxes}
\luavarset{recordstatus}{false}       {Switch to include error level from test runs in \texttt{.tlg} files}
\luavarset{xetexnopdf}{true}          {Disable generation of PDF using \texttt{xetex} engine, for log-based tests}
\luavarset{manifestfile}        {"MANIFEST.md"} {Filename to use for the manifest file}
\luavarseparator
\luavarset{tdslocations}{\{ \}}{List of non-standard file installations}
\luavarset{tdsdirs}{\{ \}}{Map for ready-to-use source locations}
\luavarseparator
\luavarset{uploadconfig}        {\meta{table}} {Metadata to describe the package for CTAN (see Table~\vref{tab:upload-setup})}
\luavarset{uploadconfig.pkg}{ctanpkg}{Name of the CTAN package}
\luavarseparator
\luavarset{bakext}{".bak"}{Extension of backup files}
\luavarset{dviext}{".dvi"}{Extension of DVI files}
\luavarset{lvtext}{".lvt"}{Extension of log-based test files}
\luavarset{tlgext}{".tlg"}{Extension of log-based test output}
\luavarset{tpfext}{".tpf"}{Extension of PDF-based test output}
\luavarset{lveext}{".lve"}{Extension of auto-generating test file output}
\luavarset{logext}{".log"}{Extension of checking output, before processing it into a \texttt{.tlg}}
\luavarset{pvtext}{".pvt"}{Extension of PDF-based test files}
\luavarset{pdfext}{".pdf"}{Extension of PDF file for checking and saving}
\luavarset{psext} {".ps"} {Extension of PostScript files}
}
\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.20\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\var{\texttt}
\usepackage[procnames]{listings}
\lstset{
    basicstyle=\ttfamily\small,
    numbers=left,
    numberstyle={\tiny\color[gray]{0.4}},
    language={[5.2]Lua},
    gobble=4,
}
\lstnewenvironment{floating-listing}[1][]
{%
  \lstset{
    frame=single,
    float,
    captionpos=b,
    abovecaptionskip=\bigskipamount,
    floatplacement=htb,
    #1
  }%
}
{}
\usepackage{shortvrb}
\usepackage{enumitem}
\usepackage[nospace]{varioref}
\usepackage{longtable}
\MakeShortVerb\|
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
% \title{^^A
%   The \pkg{l3build} package\\ Checking and building packages^^A
% }
%
% \author{^^A
%  The \LaTeX{} Project\thanks
%    {^^A
%      E-mail:
%        \href{mailto:latex-team@latex-project.org}
%          {latex-team@latex-project.org}^^A
%    }^^A
% }
%
% \date{Released 2026-08-02}
%
% \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.
% Wrapper functions/binaries are distributed in the standard \TeX{} distributions so that the script can be called using
% \texttt{l3build} on the command line; run without arguments it prints a brief synopsis of its usage.
%
% The \pkg{l3build} system is designed for packages 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~\vref{sec:writing-tests}.
%
% Each package will define its own |build.lua| configuration file which both sets variables (such as the name of the package) and may also provide custom functions.
%
% \pagebreak[2]
% A standard package layout might look something like the following:
% \begin{Verbatim}[fontsize=\small]
%  abc/
%      abc.dtx
%      abc.ins
%      build.lua
%      README.md
%      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 \LaTeX{} 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.md               README.md
%              testfiles/              testfiles/
%              yyy.dtx                 zoo.dtx
%              yyy.ins                 zoo.ins
% \end{Verbatim}
% All modules within a bundle must use the same build script name.
%
% In a small number of cases, the name used by CTAN for a module or bundle is
% different from that used in the installation tree. For example, the \LaTeXe{}
% kernel is called \pkg{latex-base} by CTAN but is located inside
% \texttt{\meta{texmf}/tex/latex/base}. This can be handled by using
% \var{ctanpkg} for the name required by CTAN to override the standard
% value.
%
% 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 safely deleted; all material within is re-generated for each command of the \pkg{l3build} system.
%
% \subsection{The \texttt{build.lua} file}
%
% The \texttt{build.lua} file used to control \pkg{l3build} is a simple Lua file
% which is read during execution. In the current release of \pkg{l3build},
% \texttt{build.lua} is read automatically and can access all of the global
% functions provided by the script. Thus it may contain a simple list of
% variable settings \emph{or} additional code to customize the build
% process.
%
%The example scripts given in Section~\vref{sec:examples} largely cover the required knowledge in Lua programing.
% For a more advanced usage, one may consult general Lua documentations including \url{https://www.lua.org/manual/5.3/manual.html} and for the few |texlua| specific additions see section 4.2 of the \LuaTeX{} manual available locally with |texdoc luatex| command line or at \url{https://www.pragma-ade.com/general/manuals/luatex.pdf}.
%
% \subsection{Main build targets}
%
% In the working directory of a bundle or module, \pkg{l3build} is run by executing
% \begin{center}
% \texttt{l3build \meta{target} [\meta{option(s)}]}
% \end{center}
% where \texttt{\meta{target}} can be one of the following:
% \begin{itemize}[noitemsep]\ttfamily
% \item check
% \item check \meta{name(s)}
% \item clean
% \item ctan
% \item doc
% \item doc \meta{name(s)}
% \item install
% \item manifest
% \item save \meta{name(s)}
% \item tag [\meta{tag name}]
% \item uninstall
% \item unpack
% \item upload [\meta{version}]
% \end{itemize}
% These targets are described below.
%
% As well as these targets, the system recognizes the options
% \begin{itemize}
% \item |--config| (|-c|) Configuration(s) to use for testing
% \item |--date| (|-d|) Date to use when tagging data
% \item |--debug| Runs the target in debug mode (not supported by all targets)
% \item |--dev| Runs \LaTeX{} checks using the development format
% \item |--dirty| Skips cleaning up of the test area
% \item |--dry-run| Runs the \texttt{install} target but does not copy
%   any files: simply lists those that would be installed
% \item |--email| Sets the email address for CTAN upload
% \item |--engine| (|-e|) Sets the engine(s) to use for testing
% \item |--epoch| Sets the epoch for typesetting and testing
% \item |--file| (|-F|) Takes the upload announcement from the given file
% \item |--first| Name of the first test to run
% \item |--full| Instructs the \texttt{install} target to include the
%   \texttt{doc} and \texttt{source} trees
% \item |--halt-on-error| (|-H|) Specifies that checks
%   should stop as soon as possible, rather than running all requested
%   tests; the difference file is printed in the terminal directly in the case of failure
% \item |--last| Name of the last test to run
% \item |--message| (|-m|) Text for upload announcement
% \item |--quiet| (|-q|) Suppresses output from unpacking
% \item |--rerun| Runs tests without unpacking/set up
% \item |--show-log-on-error| To be used in addition to |--halt-on-error| and results
%   in the full \texttt{.log} file of a failed test to be shown on the console
% \item |--show-saves| (|-S|) When tests fail, prints the \texttt{l3build save} commands needed
%   to regenerate the tests assuming that the failures were false negatives.
% \item |--shuffle| Shuffles the order in which tests run
% \item |--stdengine| (|-s|) Run tests only with the standard engine (which can vary between
%   configurations)
% \item |--texmfhome| Sets the location of the user tree for installing
% \end{itemize}
%
% \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}).
%
% On Windows, the |diff| program is not available and so |fc| is used instead
% (generating an |.fc| file). Setting the environmental variables |diffexe|
% and |diffext| can be used to adjust the choice of comparison made: the standard
% values are
% \begin{itemize}
%   \item[Windows] |diffext = .fc|, |diffexe = fc /n|
%   \item[*nix] |diffext = .diff|, |diffexe = diff -c --strip-trailing-cr|
% \end{itemize}
%
% 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}
% The \var{texmfdir} is also made available to the tests (if defined and
% non-empty).
% 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 standard engine to use is typically chosen automatically as the first entry in
% \var{checkengines}, but may be set manually using \var{stdengine}. Where multiple
% configurations are used and need adjustment to the standard engine, this does
% need to be given explicitly using \var{stdengine}.
% 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{tex} will run tests using \emph{e.g.}~\texttt{pdftex}.
% (Currently, this should be one of \texttt{latex}, \texttt{latex-dev}, \texttt{tex}, or
% \texttt{context}.)
% To perform the check, the engine typesets each test up to \var{checkruns} times.
% More detail on this in the documentation on |save|.
% Options passed to the binary are those defined in the variable
% \var{checkopts}, followed by the engine-specific ones for the current
% \var{checkformat} (stored in table \var{specialformats}), if exist.
%
% 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|.
%
% The \var{texmfdir} variable sets a directory which is made available for
% recursive searching \emph{in addition} to any files copied from
% \var{supportdir}. No subdivison of \var{texmfdir} is attempted, thus it
% should not contain multiple files with the same name. The \var{texmfdir}
% is made available both to checking and typesetting.
% \end{buildcmd}
%
%
% \begin{buildcmd}{check \meta{name(s)}}
% Checks only the test \texttt{\meta{name(s)}.lvt}.
% All engines specified by \var{checkengines} are tested unless the command
% line option |--engine| (or |-e|) has been given a comma-separated list to
% limit testing to selected |checkengines|.
% Normally testing is preceded by unpacking
% source files and copying the result plus any additional support to the
% test directory: this may be skipped using the |--rerun| (|-r|) option.
% \end{buildcmd}
%
% \begin{buildcmd}{clean}
% This target is meant as preparation for other targets, for example |ctan|.
% It removes the contents of \var{distribdir} and all temporary files used for package bundling and regression testing.
% These are all files within the directories \var{unpackdir}, \var{testdir}, \var{typesetdir} and \var{localdir}.
% In addition, all the files in \var{maindir} (the directory of |build.lua| in the standard layout),
% \var{sourcefiledir} and \var{docfiledir} are removed when matched by \var{cleanfiles}
% but not by \var{sourcefiles}.
% In a standard way are removed |.log| and |.pdf| files from the |doc| target and
% |.zip| files from the |ctan| target.
%
% When applied to a bundle, the |clean| target is first applied to each
% embedded modules (listed in |modules|). 
% In addition, all the files in the directory of |build.lua| are removed
% when matched by \var{cleanfiles}, while ignoring \var{sourcefiles}. Finally |ctandir| and |tdsdir| are removed.
% \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.md
%         abc.tds.zip/
%                     doc/latex/abc/
%                                   abc.pdf
%                                   README.md
%                  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 placed inside the |tex|
% tree in a single directory, as shown above. If the module includes any
% \BibTeX{} or MakeIndex styles these will be placed in the appropriate
% subtrees.
%
% \pagebreak[2]
% The |doc| tree is constructed from:
% \begin{itemize}
% \item all files matched by \var{demofiles},
% \item all files matched by \var{docfiles},
% \item all files matched by \var{typesetfiles} with their extension replaced with |.pdf|,
% \item all files matched by \var{textfiles},
% \item all files matched by \var{bibfiles}.
% \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}.
%
% The special case \var{ctanreadme} is used to allow renaming of a local
% |foo.xyz| file to |README.xyz|. The local |foo.xyz| should be listed in
% \var{textfiles}, and will be renamed as part of constructing the CTAN
% structure. The file extension will be unchanged by this process.
%
% 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 normalizing line endings (text files are automatically converted to Unix-style line endings).
%
% The intermediate build directories \var{ctandir} and \var{tdsdir} are used to construct the archive.
% \end{buildcmd}
%
%
% \begin{buildcmd}{doc}
% Compiles documentation files in the \var{docfiledir}, using \var{typesetdir}
% as the working directory.
% In the absence of one or more file names, all documentation is typeset;
% a file list may be specified in \var{typesetfiles} or given at the command line for selective typesetting.
% 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/doc| directory (|typesetdir|) for the typesetting compilation process.
% Additional dependencies listed in the \var{typesetdeps} variable (empty by default) will also be installed.
%
% Source files specified in \var{sourcefiles} and \var{typesetsourcefiles}
% are unpacked before the typesetting takes place. (In most cases
% \var{typesetsourcefiles} will be empty, but may be used where there are
% files to unpack \emph{only} for typesetting.)
%
% 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.
%
% If \var{typesetwarnings} is set to \code{true} (it is \code{false} by default), the |.log| of each typeset file is searched for overfull and underfull box warnings once compilation has finished, and typesetting is reported as failed if any are present. These boxes are announced by the \TeX{} engine itself rather than by a macro, so they cannot be promoted to errors at the \TeX{} level (other than under \LuaTeX{}, using the \texttt{hpack\_quality} and \texttt{vpack\_quality} callbacks): the builder is therefore the only place able to catch them for \pdfTeX{} and \XeTeX{}. The check reads the standard \LaTeX{} log format and so has no effect when typesetting with \texttt{context}, whose log uses different wording.
%
% \end{buildcmd}
%
% \begin{buildcmd}{doc \meta{name(s)}}
%   Typesets only the files with the \meta{name(s)} given, which should be the
%   basename without any extension.
% \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.
% The location of the user tree can be adjusted using the |--texmfhome| switch:
% the standard setting is the location set as |TEXMFHOME|.
% \end{buildcmd}
%
% \begin{buildcmd}{save \meta{name(s)}}
% This command runs through the same execution as |check| for a specific test(s) \texttt{\meta{name(s)}.lvt}.
% 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 |--engine| (or |-e|) is specified (one or more comma-separated engines
% in |checkengines|), the saved output is stored in
% \texttt{\meta{name}.\meta{engine}.tlg} for non-standard engines.
% This is necessary if running the test through a different engine produces
% a different output. A normalization process is performed when checking to
% avoid common differences such as register allocation; full details are listed
% in Section~\vref{sec:norm}.
%
% If the \var{recordstatus} variable is set \var{true}, additional information
% will be added to the \texttt{.tlg} to record the \enquote{exit status} of the
% typesetting compilation of the \texttt{.lvt} file. If the typesetting compilation
% completed without throwing an error (due to \TeX\ programming errors, for example),
% the \enquote{exit status} is zero, else non-zero.
% \end{buildcmd}
%
% \begin{buildcmd}{manifest}
% Generates a `manifest' file which lists the files of the package as known to \pkg{l3build}.
% The filename of this file (by default \luavar{manifestfile}) can be set with the variable \var{manifestfile}.
%
% The intended purpose of this manifest file is to include it within a package as metadata.
% This would allow, say, for the copyright statement for the package to refer to the
% manifest file rather than requiring the author to manually keep a file list up-to-date
% in multiple locations. The manifest file can be structured and documented with a degree
% of flexibility. Additional information is described in Section~\vref{sec:manifest}.
%
% In order for \texttt{manifest} to detect derived and typeset files, it should be run
% \emph{after} running \texttt{unpack} and \texttt{doc}. If \texttt{manifest}
% is run after also running \texttt{ctan} it will include the files included
% in the CTAN and TDS directories as well.
%
% Presently, this means that if you wish to include an up-to-date manifest file
% as part of a \texttt{ctan} release, you must run
%   \texttt{ctan} / \texttt{manifest} / \texttt{ctan}.
% Improvements to this process are planned for the future.
% \end{buildcmd}
%
% \begin{buildcmd}{tag [\meta{tag name}]}
% Applies the Lua |update_tag()| function to modify the contents of all the files
% specified by |tagfiles|; this function updates the `release tag' (or package version)
% and date.
% The tag is given as the optional command line argument \meta{tag name} and the date using
% |--date| (or |-d|). If not given, the date will default to the current date in
% ISO format (YYYY-MM-DD). If no \meta{tag name} is given, the tag will default to |nil|.
% Both are passed as arguments to the |update_tag()| function.
%
% The standard setup does nothing unless tag update is set up by defining a custom |update_tag()| function. See Section~\vref{sec:tagging} for full details on this feature.
% \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{pdftex}) 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}
%
% \begin{buildcmd}{upload [\meta{version}]}
% This target uses \texttt{curl} to upload the package zip file (created using \texttt{ctan}) to CTAN.
% To control the metadata used to upload the package, the \texttt{uploadconfig} table should be populated with a number of fields.
% These are documented in Table~\vref{tab:upload-setup}.
% Missing required fields will result in an interactive prompt for manual entry. When given, \meta{version} overrides \texttt{uploadconfig.version}.
%
% See Section~\vref{sec:upload} for full details on this feature.
% \end{buildcmd}
%
% \subsection{Example build scripts}
% \label{sec:examples}
%
% An example of a standalone build script for a package that uses self-contained |.dtx| files is shown in Listing~\vref{lst: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 minimize console output when building the package.
%
% \begin{floating-listing}[caption=The build configuration for the \pkg{breqn} package.,label=lst:breqn]
%   -- Build configuration for breqn
%
%   module = "breqn"
%
%   unpackfiles = {"*.dtx"}
%   excludefiles = {"*/breqn-abbr-test.pdf",
%                   "*/eqbreaks.pdf"}
%   unpackopts  = "-interaction=batchmode"
% \end{floating-listing}
%
% An example of a bundle build script for \pkg{l3packages} is shown in Listing~\vref{lst:bundle}.
% Note for \LaTeX{} 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 Listing~\vref{lst:module}.
%
% \begin{floating-listing}[caption={The build script for the \pkg{l3packages} bundle.},label={lst:bundle}]
%   -- Build script for LaTeX "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 = ".."
% \end{floating-listing}
%
% \begin{floating-listing}[caption={The build script for the \pkg{xparse} module.},label={lst:module}]
%   -- Build script for LaTeX "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 = "../.."
% \end{floating-listing}
%
% A collection of full examples (source files in various layouts) are available
% at \url{https://github.com/latex3/l3build/tree/main/examples}.
%
% \subsection{Variables}
%
% This section lists all variables defined in the |l3build.lua| script that are available for customization.
%
% \luavartypeset
%
% \subsection{Interaction between tests}
%
% Tests are run in a single directory, so whilst they are may be isolated from
% the system \TeX{} tree they do share files. This may be significant if
% installation-type files are generated during a test, for example by a
% |filecontents| environment in \LaTeX{}. Typically, you should set up your
% tests such that they do not use the same names for such files: this may lead
% to variable outcomes depending on the order in which tests are run.
%
% Where files need to be removed between different engine tests, they should
% be listed in |dynamicfiles|. If the files are generated in a directory
% structure, e.g.~by \pkg{minted}, then a recursive glob will be needed,
% for example
% \begin{Verbatim}
%   dynamicfiles = {"_minted-*/**"}
% \end{Verbatim}
%
% \subsection{Selective running of tests}
%
% The variables |includetests| and |excludetests| may be used to select which
% tests are run: these variables take raw test \emph{names} not full file names.
% The list of tests in |excludetests| overrides any matches in |includetests|,
% meaning that tests can be disabled selectively. It also makes it possible
% to disable test on for example a platform basis: the |texlua| specific variable
% |os.type| may be used to set |excludetests| only on some systems.
%
% \subsection{Multiple sets of tests}
%
% In most cases, a single set of tests will be appropriate for the module, with
% a common set of configuration settings applying. However, there are
% situations where you may need entirely independent sets of tests which have
% different setting values, for example using different formats or where the
% entire set will be engine-dependent. To support this, \pkg{l3build} offers
% the possibility of using multiple configurations for tests. This is supported
% using the \var{checkconfigs} table. This is used to list the names of each
% configuration (|.lua| file) which will be used to run tests.
%
% For example, for the core \LaTeXe{} tests the main test files are contained
% in a directory |testfiles|. To test font loading for \XeTeX{} and \LuaTeX{}
% there are a second set of tests in |testfiles-TU| which use a short
% |config-TU.lua| file similar to the one shown in Listing~\vref{lst:configs}.
% To run both sets of tests, the main |build.lua| file contains the setting
% |checkconfigs = {"build", "config-TU"}|. This will cause \pkg{l3build} to run
% first using no additional settings (\emph{i.e.}~reading the normal
% |build.lua| file alone), then running \emph{also} loading the settings from
% |config-TU.lua|.
% \begin{floating-listing}[caption={Example of using additional (or overriding) settings for configuring tests in a different subdirectory.},label={lst:configs}]
%   -- Special config for these tests
%   stdengine    = "xetex"
%   checkengines = {"xetex","luatex"}
%   checksearch  = true
%   testfiledir  = "testfiles-TU"
% \end{floating-listing}
%
% To allow selection of one or more configurations, and to allow saving of
% |.tlg| files in non-standard configurations, the |--config| (|-c|) option may
% be used. This works in the same way as |--engine|: it takes a comma-separated
% list of configurations to apply, overriding \var{checkconfigs}. For example,
% in the directory containing |config-TU.lua|, you can use
% |l3build check -cconfig-TU <name(s)>| and |l3build save -cconfig-TU <name(s)>|
% to check and save tests in |testfiles-TU| directory.
%
% \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 \LaTeX{}, 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 \LaTeX{} 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 \LaTeX{} 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{Non-standard source layouts}
%
% A variety of source layouts are supported. In general, a \enquote{flat}
% layout with all source files \enquote{here} is most convenient. However,
% \pkg{l3build} supports placement of both code and documentation source
% files in other locations using the \var{sourcefiledir}, \var{docfiledir}
% and \var{textfiledir}
% variables. For pre-built trees, the glob syntax \texttt{**/*.\meta{ext}} may
% be useful in these cases: this enables recursive searching in the appropriate
% tree locations. With the standard settings, this structure will be removed
% when creating a CTAN release: the variable \var{flatten} may be
% used to control this behavior. The \var{flattentds} setting controls
% the same concept for TDS creation.
%
% Notice that text files are treated separately from documentation files when
% splitting trees: this is to allow for the common case where files such
% as |README| and |LICENSE| are at the top level even when other documentation
% files are in a sub-directory.
%
% A series of example layouts and matching |build.lua| files are available from
% \url{https://github.com/latex3/l3build/tree/main/examples}.
%
% For more complex layouts in which sources are laid out in TDS format and
% should be used directly, the table \var{tdsdirs} is available. Each entry
% is a source directory and the matching installation target, for example
% \begin{Verbatim}
%   tdsdirs = {sources = "tex"}
% \end{Verbatim}
%  This would enable a directory \texttt{sources} in the development area to
%  be used for testing and typesetting, and for it to be installed into the
%  \texttt{tex} tree when building a release. When this method is used, the
%  sources are \emph{not} copied into the local tree: like \var{texmfdir},
%  they are added directly to the areas accessible during a testing or
%  typesetting run. When using this approach, the files listed in
%  \var{typesetfiles} \emph{must} still be included in \var{docfiles}:
%  they have to be directly visible to \pkg{l3build}, not found by
%  \texttt{kpsewhich} searching.
%
% \subsection{Non-standard formats/binaries}
%
% The standard approach used by \pkg{l3build} is to use a combination
% of \var{engine} and \var{checkformat} to generate the \emph{binary} and
% \emph{format} combination used for tests. For example, when |pdftex| is
% the \var{engine} and |latex| is the \var{checkformat}, the system call
% used is
% \begin{verbatim}
%   pdftex --fmt=pdflatex
% \end{verbatim}
% \emph{i.e.}~the binary names is the same as the \var{engine}, and the format
% is a simple substitution of the \var{checkformat} into \var{engine}, replacing
% |tex|.
%
% For more complex set ups, \var{specialformats} should be used. This is a
% table with one entry per \var{checkformat}. Each entry is itself a table,
% and these contain a list of engines and settings for |binary|, |format|
% and |options|. For example, the set up for Con\TeX{}t in \pkg{l3build} 2023-07-17 is
% \begin{verbatim}
% specialformats.context = {
%   luametatex = {binary = "context", format = ""},
%   luatex     = {binary = "context", format = "", options = "--luatex"},
%   pdftex     = {binary = "texexec", format = ""},
%   xetex      = {binary = "texexec", format = "", options = "--xetex"}
% }
% \end{verbatim}
% Additional tokens can also be injected before the loading of a test file using
% the |tokens| entry: this might for example be used to select a graphics driver
% with a DVI-based route.
%
% \subsection{Output normalization}
% \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 normalized
% before comparison during checking. This removes some system-dependent
% data but also some variations due to different engines. This normalization
% 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 related to loading |.fd| files (from \texttt{(\meta{name}.fd}
%     to the matching \texttt{)}).
%  \item Lines starting \cs{openin} or \cs{openout}.
% \end{itemize}
% Modifications made in lines are:
% \begin{itemize}
%   \item Removal spaces at the start of lines.
%   \item Removal of |./| at start of file names.
%   \item Standardization of the list of units known to \TeX{} (\pdfTeX{}
%     and \LuaTeX{} add a small number of additional units which are not
%     known to \TeX90 or \XeTeX{}, (u)p\TeX{} adds some additional non-standard
%     ones)
%   \item Standardization 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 Conversion of \texttt{at lines \meta{number}}|--|\texttt{\meta{number}} to 
%     \texttt{at lines ...} for overfull and underfull boxes.
%   \item Conversion of file dates to \texttt{....-..-..}, and any version
%     numbers on the same lines to \texttt{v...}.
%     If specified, extra version patterns in \var{versionpatterns} are applied 
%     before builtin patterns.
%   \item Conversion of register numbers in assignment lines
%     \texttt{\cs{\meta{register}}=\cs{\meta{type}}\meta{number}} to
%     \texttt{\cs{\meta{type}}\meta{...}}
%   \item Conversion of box numbers in |\show| lines
%     \texttt{>~\cs{box}\meta{number}=} to \texttt{>~\cs{box}...=}
%   \item Conversion of Lua data reference ids
%     \texttt{<lua data reference \meta{number}>} to
%     \texttt{<lua data reference ...>}
%   \item Removal of some (u)p\TeX{} data where it is equivalent to
%     \pdfTeX{} (|yoko direction|, |\displace 0.0|)
%   \item Removal of various |\special| lines inserted due to the build
%     process
% \end{itemize}
%
% \LuaTeX{} makes several additional changes to the log file. As normalizing
% these may not be desirable in all cases, they are handled separately.
% When creating \LuaTeX{}-specific test files (either with \LuaTeX{} as
% the standard engine or saving a \LuaTeX{}-specific |.tlg| file) no further
% normalization is undertaken. On the other hand, for cross-engine comparison
% the following normalization is applied:
% \begin{itemize}
%   \item Removal of additional (unused) |\discretionary| points.
%   \item normalization of some |\discretionary| data to a \TeX{}90 form.
%   \item Removal of |U+...| notation for missing characters.
%   \item Removal of |display| for display math boxes
%     (included by \TeX90/\pdfTeX{}/\XeTeX).
%   \item Removal of Omega-like |direction TLT| information.
%   \item Removal of additional whatsit containing local paragraph information
%     (|\localinterlinepenalty|, \emph{etc.}).
%   \item Rounding of glue set to four decimal places (glue set may be
%     slightly different in \LuaTeX{} compared to other engines).
%   \item Conversion of low chars ($0$ to $31$) to |^^| notation.
% \end{itemize}
% This involves making an additional \texttt{.tlg} file in the \var{testdir}
% location, which is generated dynamically during the testing process.
%
% When making comparisons between 8-bit and Unicode engines it is useful to
% format the top half of the 8-bit range such that it appears in the log as
% |^^|\texttt{\meta{char}} (the exact nature of the 8-bit output is otherwise
% dependent on the active code page). This may be controlled using the
% |asciiengines| option. Any engines named here will use a |.tcx| file to
% produce only ASCII chars in the log output, whilst for other engines
% normalization is carried out from UTF-8 to ASCII. If the option is set to
% an empty table the latter process is skipped: suitable for cases where only
% Unicode engines are in use.
%
% \subsection{Breaking changes}
%
% Very occasionally, it is necessary to make changes to \pkg{l3build} that
% change the \texttt{.tlg} file results. This is typically when additional
% normalization is required. When this is the case, you should first verify
% that \texttt{.tlg} files pass with the older \pkg{l3build}, then update only
% \pkg{l3build}, re-check the files and save the results. Where possible,
% we provide a mechanism to run with older setting to allow this process to
% take place smoothly.
%
% \subsubsection{Release 2024-02-08}
%
% Wrapping of messages by \pkg{l3msg} is now suppressed, aligning with the
% approach to \var{maxprintline}.
%
% \subsubsection{Release 2023-03-22}
%
% This release changes the standard value of \var{maxprintline} from $79$ to
% $9999$, to suppress line wrapping in the log. This makes normalization of
% for example file paths more reliable. To check that \texttt{.tlg} files
% are correct, you can set \var{maxprintline} in your \texttt{build.lua} file
% explicitly to the old default, check that tests pass, then remove this
% line and re-check.
%
% \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 customizations 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 normalized 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 |\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}
%
% \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 runs its \meta{contents}
% in a group and surrounds the generated log lines with some \cs{SEPARATOR}s
% and a \meta{title}.
% \item
% \cs{TESTEXP}\marg{title}\marg{contents} surrounds its \meta{contents} with
% \cs{TYPE} and formatting to match \cs{TEST}; this can be used as a shorthand
% to test expandable commands.
% \item
% \cs{BEGINTEST}\marg{title} \dots \cs{ENDTEST} is an environment form of
% \cs{TEST}, allowing verbatim material, \emph{etc.} to appear.
% \item
% \cs{BEGINBOXTEST}\marg{title} \dots \cs{ENDBOXTEST} is a wrapper around
% \cs{BEGINTEST}\marg{title} \dots \cs{ENDTEST} that typesets the content in an
% |\hbox| with the name \cs{TESTBOX} and prints the box contents to the log file
% using \cs{SHOWBOX}.
% \item
% \cs{SHOWBOX}\marg{box} is a wrapper around the |\showbox| with local
% adjustment of parameters to print the full \marg{box} details to the log.
% \item
% \cs{SHOWFILE}\marg{filename} (\eTeX{} only) shows the content of
% \meta{filename}.
% \item
% \cs{ASSERT}\marg{arg_1}\marg{arg_2} and \cs{ASSERTSTR}\marg{arg_1}\marg{arg_2}
% Test if the full expansion of \meta{arg_1} and \meta{arg_2} are the same:
% on a token basis in \cs{ASSERT} and on a string basis in \cs{ASSERTSTR}.
% Depending on the outcome, record either \texttt{PASSED} or \texttt{FAILED}
% in the \texttt{.log}.
% \item
% \cs{SHOWPDFTAGS} generates a test block in the log file containing
% the XML generated by applying \texttt{show-pdf-tags --xml} to PDF output
% of the current test file. This allows any changes in the tagged PDF structure
% to be detected. The \pkg{show-pdf-tags} package is required.
% \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_lazy_any_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~\vref{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}
% \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~\vref{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.
%
% As an alternative to avoid repeating the box setup all the time there is the
% \cs{BEGINBOXTEST}\marg{title} \dots \cs{ENDBOXTEST} environment which is a
% wrapper around \cs{BEGINTEST}\marg{title} \dots \cs{ENDTEST} that encloses its
% content in an |\hbox| with the name \cs{TESTBOX} and prints that into the log
% using |\showbox|.
% \begin{Verbatim}[frame=single,fontsize=\small]
% \input{regression-test.tex}
% \documentclass{article}
% \START
% \BEGINBOXTEST{hello world}
% hello~ \emph{world}~ $a=b+c$
% \ENDBOXTEST
% \END
% \end{Verbatim}
% This is equivalent to the example above with the small difference that
% \cs{ENDBOXTEST} uses \cs{SHOWBOX} which locally resets the box printing
% parameter to override any local settings which could truncate long PDF specials
% otherwise.  Also the presence of the |TEST| environment will print labels and
% separators around the log output.
%
% 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.
% <argument> \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}
%
% \subsection{Testing entire pages}
%
% There may be occasions where creating entire test pages is necessary
% to observe the test output required. That is best achieved by applying
% \cs{showoutput} and forcing a complete page to be produced, for example
% \begin{Verbatim}[frame=single,fontsize=\small]
% \input{regression-test.tex}
% \documentclass{article}
% \START
% \showoutput
% % Test content here
% \vfil\break
% \END
% \end{Verbatim}
%
% \subsection{Pre-check hook}
%
% To allow complex set up for tests, a hook |checkinit_hook()| is available
% to be executed once all standard set up is complete but before any tests
% are run. This should return an integer value: $0$ indicates no error.
%
% \subsection{Additional test tasks}
%
% A standard test will run the file \texttt{\meta{name}.lvt} using one
% or more engines, but will not carry out any additional processing. For
% some tests, for example bibliography generation, it may be desirable to
% call one or more tools in addition to the engine. This can be arranged
% by defining |runtest_tasks|, a function taking two arguments, the name
% of the current test (this is equivalent to \TeX{}'s \cs{jobname},
% \emph{i.e.}~it lacks an extension) and the current run number.
% The function |runtest_tasks| is run after the main call to the
% engine for a test cycle. It should return a string consists of task(s),
% i.e., the CLI command(s) to execute.
% If more than one task is required, these should be separated
% by use of |os_concat|, a string variable defined by \pkg{l3build} as the
% correct concatenation marker for the system. An example of |runtest_tasks|
% suitable for calling Biber is shown in Listing~\vref{lst:test-tasks}.
% \begin{floating-listing}[caption={Example \texttt{runtest_tasks} function.},label={lst:test-tasks}]
%   function runtest_tasks(name,run)
%     if run == 1 then
%       return "biber " .. name
%     else
%       return ""
%     end
%   end
% \end{floating-listing}
%
% \subsection{Instructions for rebuilding test output}
%
% Sometimes changes to fundamental parts of the code can cause a lot of tests
% to fail even though the actually tested systems are still working correctly.
% This is especially common when the logging and error reporting systems
% changes and therefore all log file based tests using the component fail with
% these changes.
%
% In these cases, the option |--show-saves| can be passed to
% |l3build check| in order to generate a list of |l3build save| commands which
% can be executed to regenerate the expected output of all tests which fail.
% Additionally it sometimes prints a list of |l3build check| commands for tests
% which might still fail due to engine differences after running the |save|
% commands. After running all these |l3build check| commands and all
% |l3build save| commands listed by them, all tests will succeed.
%
% When bundles are used |l3build check --show-saves| has to be executed
% separately for every module in the bundle.
%
% This option is potentially dangerous and therefore should only be used with
% care. It can easily hide valid test failures between a bunch of spurious
% changes. Therefore you should always take a close look at the difference
% files generated by |l3build check| before running the generated
% |l3build save| commands. Additionally it should only be used when you are
% aware of the reason why a large number of tests failed and the change
% causing the failures has been tested separately to have no unintended
% side effects.
%
% \subsection{Epoch setting}
%
% To produce predictable output when using dates, the test system offers the
% ability to set the epoch to a known value. The \var{epoch} variable may
% be given as a raw value (a simple integer) or as a date in ISO format
% (YYYY-MM-DD).
% The two flags \var{forcecheckepoch} and \var{forcedocepoch} then
% determine whether this is applied in testing and typesetting, respectively.
%
% The epoch may also be given as a command line option, |-E|, which again
% takes either a date or raw epoch. When given, this will automatically
% activate forcing of the epoch in both testing and typesetting.
%
% \subsection{Settings in \texttt{texmf.cnf}}
%
% To allow application of non-standard \TeX{} trees or similar non-standard
% settings, \pkg{l3build} sets the environment variable \texttt{TEXMFCNF}
% to allow reading of any \texttt{texmf.cnf} file present in the support folder.
% This might for example be used with a file containing
% \begin{verbatim}
% TEXMFAUXTREES = ../../texmf,
% \end{verbatim}
% for adding a local tree within the development repository (assuming the
% typical \pkg{l3build} layout).
%
% \section{Alternative test formats}
%
% \subsection{Generating test files with \pkg{DocStrip}}
%
% It is  possible to pack tests inside source files. Tests generated during the
% unpacking process will be available to the \texttt{check} and \texttt{save}
% commands as if they were stored in the \texttt{testfiledir}. Any explicit
% test files inside \texttt{testfiledir} take priority over generated ones
% with the same names.
%
% \subsection{Specifying expectations}
%
% Regression tests check whether changes introduced in the code modify the test
% output. Especially while developing a complex package there is not yet a
% baseline to save a test goal with. It might then be easier to formulate the
% expected effects and outputs of tests directly. To achieve this, you may
% create an \texttt{.lve} instead of a \texttt{.tlg}
% file.\footnote{Mnemonic: \texttt{lv\textbf{t}}: \textbf{t}est,
% \texttt{lv\textbf{e}}: \textbf{e}xpectation} It is processed exactly like
% the \texttt{.lvt} to generate the expected outcome. The test fails when both
% differ.
%
% Combining both features enables contrasting the test with its expected
% outcome in a compact format. Listing~\vref{lst:expect-dtx} exemplary tests
% \TeX{}s counters. Listing~\vref{lst:expect-ins} shows the relevant part of an
% \texttt{.ins} file to generate it.
%
% \begin{floating-listing}[language={TeX},caption={Test and expectation can be specified side-by-side in a single \texttt{.dtx} file.},label={lst:expect-dtx}]
%   \input regression-test.tex\relax
%   \START
%   \TEST{counter-math}{
%   %<*test>
%     \OMIT
%     \newcounter{numbers}
%     \setcounter{numbers}{2}
%     \addtocounter{numbers}{2}
%     \stepcounter{numbers}
%     \TIMO
%     \typeout{\arabic{numbers}}
%   %</test>
%   %<expect>  \typeout{5}
%   }
%   \END
% \end{floating-listing}
%
% \begin{floating-listing}[language={TeX},caption={Test and expectation are generated from a \texttt{.dtx} file of the same name.},label={lst:expect-ins}]
%    \generate{\file{\jobname.lvt}{\from{\jobname.dtx}{test}}
%              \file{\jobname.lve}{\from{\jobname.dtx}{expect}}}
% \end{floating-listing}
%
% \subsection{PDF-based tests}
%
% In most cases, testing is best handled by using the text-based methods
% outlined above. However, there are cases where the detail of output structure
% is important. This can only be fully tested by comparing PDF structure.
% To support this, \pkg{l3build} can be instructed to build and compare
% PDF files by setting up tests in \texttt{.pvt} files. The following
% normalization takes place:
% \begin{itemize}
%   \item Replacement of binary streams by the marker |[BINARY STREAM]|
%   \item Replacement of \texttt{/ID} values by |ID-STRING|
%   \item Removal of blank lines
%   \item Removal of comment (|%%|) lines
% \end{itemize}
%
% After this normalization takes place, the file can not usually be rendered
% properly. To check if the build system has produced a correct PDF, the
% pre-normalization PDF can be found in the \texttt{build} folder.
%
% To allow platform-independence, PDF-based tests must use only Type~1 or
% OpenType fonts: Type3 fonts are system-dependent. PDF files are
% engine-specific, thus one |.tpf| file should be stored per engine to be
% tested.
%
% \subsection{Custom tests}
%
% If neither the text-based methods nor PDF-based tests are sufficient,
% there is the additional option of defining custom variants with individual
% normalization rules.
%
% For this, the variant has to be registered in the \texttt{test_types} table
% and then activated in \texttt{test_order}.
%
% Every element in \texttt{test_types} is a table with fields \texttt{test}
% (the extension of the test file), \texttt{reference} (the extension of the
% file the output is compared with), \texttt{generated} (extension of the
% analyzed \LaTeX{} output file) and \texttt{rewrite} (A Lua function for
% normalizing the output file, taking as parameters the name of the unnormalized
% \LaTeX{} output file to be read, the name of the normalized file to be written,
% the engine name and a potential errorcode).
%
% For example:
% \begin{verbatim}
% test_types = {
%   mytest = {
%     test = ".mylvt",
%     reference = ".mytlg",
%     generated = ".log",
%     rewrite = function(source, normalized, engine, errorcode)
%       -- In this example we just rename the logfile without any normalization
%       ren(testdir,source,normalized)
%     end,
%   },
% }
% test_order = {"mylvt", "log", "pdf"}
% \end{verbatim}
%
% \section{Release-focussed features}
%
% \subsection{Installation structure}
%
% With the standard settings, \pkg{l3build} will install files within
% the \TeX{} directory structure (TDS) as follows
% \begin{itemize}
%   \item \var{installfiles} within a \texttt{\meta{bundle}/\meta{module}}
%     (or \texttt{\meta{module}}) directory inside \texttt{tex/\meta{format}}
%   \item \var{sourcefiles} within a \texttt{\meta{bundle}/\meta{module}}
%     (or \texttt{\meta{module}}) directory inside \texttt{source/\meta{format}}
%   \item Typeset PDFs within a \texttt{\meta{bundle}/\meta{module}}
%     (or \texttt{\meta{module}}) directory inside \texttt{doc/\meta{format}}
%   \item \var{bstfiles} within a \texttt{\meta{bundle}/\meta{module}}
%     (or \texttt{\meta{module}}) directory inside \texttt{bibtex/bst}
%   \item \var{bibfiles} within a \texttt{\meta{bundle}/\meta{module}}
%     (or \texttt{\meta{module}}) directory inside \texttt{bibtex/bib}
%   \item \var{makeindexfiles} within a \texttt{\meta{bundle}/\meta{module}}
%     (or \texttt{\meta{module}}) directory inside \texttt{makeindex}
% \end{itemize}
%
% For more complex set ups, this can be customized using the
% \var{tdslocations} table. Each entry there should be a glob specifying the
% TDS position of a file or files. Any files not specified in the table
% will use the standard locations above. For example, to place some files
% in the generic tree, some in the plain \TeX{} tree and some in the \LaTeX{}
% tree, one might use the set up shown in Listing~\vref{lst:tds}.
% \begin{floating-listing}[caption={Example \texttt{tdslocations} table.},label={lst:tds}]
%   tdslocations =
%     {
%       "tex/generic/mypkg/*.generic.tex" ,
%       "tex/plain/mypkg/*.plain.tex"    ,
%       "tex/latex/mypkg/*.latex.tex"
%     }
% \end{floating-listing}
%
% The table is read in order, and thus specific file names should come before
% potential wild-card matches.
%
% \subsection{Automatic tagging}
% \label{sec:tagging}
%
% The |tag| target can automatically edit
% source files to modify date and release tag name. As standard, no automatic
% replacement takes place, but setting up a |update_tag()| function
% will allow this to happen. This function takes four input arguments:
% \begin{enumerate}[nosep]
%   \item file name
%   \item full content of the file
%   \item tag name
%   \item tag date
% \end{enumerate}
% The |update_tag()| function should return the (modified) contents
% for writing to disk.
% For example, the function used by |l3build| itself is
% shown in Listing~\vref{lst:update-tag}.
%
% \begin{floating-listing}[caption={Example \texttt{update_tag} function.},label={lst:update-tag}]
%   -- Detail how to set the version automatically
%   function update_tag(file,content,tagname,tagdate)
%     if string.match(file, "%.dtx$") then
%       return string.gsub(content,
%         "\n%% \\date{Released %d%d%d%d/%d%d/%d%d}\n",
%         "\n%% \\date{Released " .. tagname .. "}\n")
%     elseif string.match(file, "%.md$") then
%       return string.gsub(content,
%         "\nRelease %d%d%d%d/%d%d/%d%d\n",
%         "\nRelease " .. tagname .. "\n")
%     elseif string.match(file, "%.lua$") then
%       return string.gsub(content,
%         '\nrelease_date = "%d%d%d%d/%d%d/%d%d"\n',
%         '\nrelease_date = "' .. tagname .. '"\n')
%     end
%     return content
%   end
% \end{floating-listing}
%
% To allow more complex tasks to take place, a hook |tag_hook()| is also
% available. It will receive the tag name and date as arguments, and
% may be used to carry out arbitrary tasks after all files have been updated.
% For example, this can be used to set a version control tag for an entire repository.
%
%
% \subsection{Typesetting documentation}
%
% As part of the overall build process, \pkg{l3build} will create PDF
% documentation as described earlier. The standard build process for PDFs
% will attempt to run Biber, \BibTeX{} and MakeIndex as appropriate
% (the exact binaries used are defined by \var{biberexe}, \var{bibtexexe}
% and \var{makeindexexe}). However, there is no attempt to create an entire
% PDF creation system in the style of \texttt{latexmk} or similar.
%
% For package authors who have more complex requirements than those covered
% by the standard set up, the Lua script offers the possibility for
% customization. The Lua function \texttt{typeset} may be defined before
% reading \texttt{l3build.lua} and should take one argument, the name of
% the file to be typeset. Within this function, the auxiliary Lua
% functions \texttt{biber}, \texttt{bibtex}, \texttt{makeindex} and
% \texttt{tex} can be used, along with custom code, to define a PDF
% typesetting pathway. The functions \texttt{biber} and \texttt{bibtex}
% take a single argument: the name of the file to work with \emph{minus}
% any extension. The \texttt{tex} takes as an argument the full name
% of the file. The most complex function \texttt{makeindex} requires the
% name, input extension, output extension, log extension and style name.
% For example, Listing~\vref{lst:PDF} shows a simple script which might
% apply to a case where multiple \BibTeX{} runs are needed (perhaps where
% citations can appear within other references).
%
% Where there are complex requirements for pre-compiled demonstration
% files, the hook |typeset_demo_tasks()| is available: it runs after
% copying files to the typesetting location but before the main typesetting
% run. This may be used for example to script a very large number of
% demonstrations using a single source (see the \pkg{beamer} package
% for an example of this). Note that this hook is intended for use files
% \emph{not} listed in \var{typesetfiles} or \var{typesetdemofiles}.
%
% \begin{floating-listing}[caption={A customized PDF creation script.},label={lst:PDF}]
%   #!/usr/bin/env texlua
%
%   -- Build script with custom PDF route
%
%   module = "mymodule"
%
%   function typeset(file)
%     local name = jobname(file)
%     local errorlevel = tex (file)
%     if errorlevel == 0 then
%       -- Return a non-zero errorlevel if anything goes wrong
%       errorlevel =(
%         bibtex(name) +
%         tex(file)    +
%         bibtex(name) +
%         tex(file)    +
%         tex(file)
%       )
%     end
%     return errorlevel
%   end
% \end{floating-listing}
%
% \subsection{Pre-typesetting hook}
%
% To allow complex set up for typesetting, a hook |docinit_hook()| is available
% to be executed once all standard set up is complete but before any typesetting
% is run.
%
% \subsection{Non-standard typesetting}
%
% To allow non-standard typesetting combinations, for example per-file
% choice of engines, the table \var{specialtypesetting} may be used.
% This is a table with one entry per file. Each entry is itself a table,
% and these contain a list of engines and settings for |cmd| and |func|.
% For example, to choose to use \LuaTeX{} for one file when \var{typesetexe}
% is |pdftex|
% \begin{verbatim}
% specialtypesetting = specialtypesetting or {}
% specialtypesetting["foo.tex"] = {cmd = "luatex -interaction=nonstopmode"}
% \end{verbatim}
% or to select an entirely different typesetting function
% \begin{verbatim}
% specialtypesetting = specialtypesetting or {}
% specialtypesetting["foo.tex"] = {func = typeset_foo}
% \end{verbatim}
%
% \subsection{Automated upload to CTAN}
% \label{sec:upload}
%
% The CTAN upload process is backed by an API, which \pkg{l3build} can use
% to send zip files for release. Along with the file, a variety of metadata
% must be specified about the package, including the version, license, and so on, explained at \url{https://www.ctan.org/upload}.
% A description of this metadata is outlined in Table~\vref{tab:upload-setup},
% and a simple example of an extract from a \texttt{build.lua} file using this is shown
% in Listing~\vref{lst:uploadconfig}.
%
% Note that the \texttt{upload} target will \emph{not} execute the
% \texttt{ctan} target first.
%
% This upload facility assumes availability of |curl| on your
% system. In the case of Windows, the system curl will not be
% available if you are using a 32 bit \TeX\ implementation. Curl
% executables are available for a variety of operating systems from
% \url{https://curl.haxx.se/download.html}.
%
% \paragraph{Announcement text}
% It can be convenient not to include the announcement text within the |build.lua| file
% directly. The command line argument |--message| (|-m|) allows the announcement to be
% included as part of the |l3build| arguments, and |--file| (|-F|) reads the announcement
% from a specified file. The \texttt{build.lua} file may also specify that this text is to
% be taken from the file specified by
% |uploadconfig.announcement_file|, this allows the release-specific announcement to be
% specified outside the main |build.lua| file. If
% |uploadconfig.announcement_file| is |nil| or specifies a file that
% can not be read, and no announcement is provided by the
% |announcement| field or commandline arguments, |l3build| will
% interactively prompt for text (which may be empty).
%
% Note that if the announcement text is empty a `silent update'
% is performed; this should usually be performed for minor bug or documentation fixes only.
%
% \paragraph{Note text}
% This optional field is for passing notes to the CTAN maintainers. As
% for announcements, the text may be set in |uploadconfig.note| or
% perhaps more usefully, if |uploadconfig.note_file| is the filename of a
% readable file the file text is used as the note.
%
% \paragraph{Uploader details}
% The CTAN team use the uploader email address as a form of low-security sanity
% check that the upload is coming from a reputable source. Therefore, it is advisable not
% to store this information within a public |build.lua| file. It can be set on the command
% line with the |--email| option to \texttt{l3build}; alternatively, a private
% configuration file could be used to add this information at upload time.
%
% \paragraph{The \texttt{update} field}
% In most scenarios the |update| field does not need to be explicitly set. By default
% \pkg{l3build} assumes that the package being uploaded already exists on CTAN
% (|update=true|). If it does not, this is caught in the validation process before
% uploading and automatically corrected. If you set |update| explicitly this will be passed
% directly to CTAN in all circumstances, leading to errors if you attempt to update a
% non-existing package or if you attempt to upload a new package with the same name as a
% pre-existing one.
%
% \paragraph{The \texttt{curl} options file}
%
% The \pkg{l3build} upload options are passed to |curl| by writing the
% fields to a text file with a default name being
% \meta{package}|-ctan.curlopt|. This is then passed to curl using its
% |--config| commandline option.  (Using an intermediate file helps
% keep \pkg{l3build} portable between systems using different
% commandline quoting conventions. Any backslashes are doubled when writing
% to this file, so they do not need to be doubled in announcement and note texts.)
%
% By default the file is written into the current directory alongside
% the zip file to be uploaded. You may wish to specify that this file
% is ignored by any version control in that directory (using
% |.gitignore| or similar). Or alternatively you can use the
% |uploadconfig.curlopt_file| field in the |build.lua| file to specify an
% alternative name or location for this file.
%
% \paragraph{Validating}
%  To validate your upload but not actually submit to CTAN, you may use
%  the |--dry-run| command-line option.
%
% \paragraph{Debugging}
% If you have have difficulty with the upload process, add the option |--debug| to divert
% the request from CTAN to a service that redirects the input back
% again so it can be examined.
% It can also be useful to check the contents of the |curlopts| file which has a
% record of the options passed to curl.
%
% \begin{table}[p]
%   \def\YES{\textbullet}
%   \caption{Fields used in the \texttt{uploadconfig} setup table. The
%   first section of fields are \emph{required} and if they are
%   omitted the user will be interactively prompted for further
%   input. Most commands take string input, but those that are
%   indicated with `Multi' accept more than one entry using an array
%   of strings.  Most of the fields correspond directly to the fields
%   in the CTAN upload API, the last group relate to file use by
%   \pkg{l3build}.}
%   \label{tab:upload-setup}
% \medskip
%   \begin{minipage}{\linewidth}
%   \begin{tabular}{@{}lccp{8cm}@{}}
%     \toprule
%     Field & Req. & Multi & Description \\
%     \midrule
%  \texttt{announcement} & \YES &      & Announcement text                      \\
%  \texttt{author      } & \YES &      & Author name (semicolon-separated for multiple) \\
%  \texttt{ctanPath    } & \YES &      & CTAN path                              \\
%  \texttt{email       } & \YES &      & Email address of uploader              \\
%  \texttt{license     } & \YES & \YES & Package license(s)\footnote{See \url{https://ctan.org/license}} \\
%  \texttt{pkg         } & \YES &      & Package name                           \\
%  \texttt{summary     } & \YES &      & One-line summary                       \\
%  \texttt{uploader    } & \YES &      & Name of uploader                       \\
%  \texttt{version     } & \YES &      & Package version                        \\
%  \midrule
%  \texttt{bugtracker  } &      & \YES & URL(s) of bug tracker                  \\
%  \texttt{description } &      &      & Short description/abstract             \\
%  \texttt{development } &      & \YES & URL(s) of development channels         \\
%  \texttt{home        } &      & \YES & URL(s) of home page                       \\
%  \texttt{note        } &      &      & Internal note to CTAN                  \\
%  \texttt{repository  } &      &      & URL(s) of source repositories          \\
%  \texttt{support     } &      & \YES & URL(s) of support channels             \\
%  \texttt{topic       } &      & \YES & Topic(s)\footnote{See \url{https://ctan.org/topics/highscore}} \\
%  \texttt{update      } &      &      & Boolean \texttt{true} for an update, \texttt{false} for a new package   \\
% \midrule
%  \texttt{announcement\_file} &  &      & Announcement text  file                    \\
%  \texttt{note\_file} &  &      & Note text file              \\
%  \texttt{curlopt\_file} &  &      & The filename containing the options passed to curl    \\
%     \bottomrule
%   \end{tabular}
%   \end{minipage}
% \end{table}
%
%
% \begin{floating-listing}[caption={Example of \texttt{uploadconfig} from the \pkg{vertbars} package.},label={lst:uploadconfig}]
%   uploadconfig = {
%     pkg         = "vertbars",
%     version     = "v1.0c",
%     author      = "Peter R Wilson; Will Robertson",
%     license     = "lppl1.3c",
%     summary     = "Mark vertical rules in margin of text",
%     ctanPath    = "/macros/latex/contrib/vertbars",
%     repository  = "https://github.com/wspr/herries-press/",
%     update      = true,
%   }
% \end{floating-listing}
%
% \section{Lua interfaces}
%
% Whilst for the majority of users the simple variable-based control methods
% outlined above will suffice, for more advanced applications there will be
% a need to adjust behavior by using interfaces within the Lua code. This
% section details the global variables and functions provided.
%
% \subsection{Global variables}
%
% \begin{variable}{options}
%   The |options| table holds the values passed to \pkg{l3build} at the
%   command line. Each possible \meta{entry} given below corresponds to
%   |--|\meta{entry} given at the command line, except the |target| entry
%   which is self explanatory and the |names| entry which corresponds to \meta{name(s)}
%   for |check|, |doc|, |save| and |tag| targets.  
%   \begin{center}
%   \begin{tabular}{ll}
%     \toprule
%     Entry & Lua type \\
%     \midrule
%       \var{config}        & |table|   \\
%       \var{date}          & |string|  \\
%       \var{dirty}         & |boolean| \\
%       \var{dry-run}       & |boolean| \\
%       \var{email}         & |string|  \\
%       \var{engine}        & |table|   \\
%       \var{epoch}         & |string|  \\
%       \var{file}          & |string|  \\
%       \var{first}         & |boolean| \\
%       \var{full}          & |boolean| \\
%       \var{halt-on-error} & |boolean| \\
%       \var{help}          & |boolean| \\
%       \var{message}       & |string|  \\
%       \var{names}         & |table|   \\
%       \var{quiet}         & |boolean| \\
%       \var{rerun}         & |boolean| \\
%       \var{shuffle}       & |boolean| \\
%       \var{stdengine}     & |boolean| \\
%       \var{target}        & |string|  \\
%       \var{texmfhome}     & |string|  \\
%     \bottomrule
%     \end{tabular}
%   \end{center}
%   The Lua tables mentioned here are in fact arrays of strings.
%   From the |build.lua| file, one can modify the string and boolean values,
%   add or remove entries in arrays. But it is not recommended to affect a
%   whole new Lua table to |options| nor to its array entries.
% \end{variable}
%
% \subsection{Utility functions}
%
% The utility functions are largely focussed on file operations, though a small
% number of others are provided. File paths should be given in Unix style
% (using |/| as a path separator). File operations take place relative to the
% path from which \pkg{l3build} is called. File operation syntax is largely
% modeled on Unix command line commands but reflect the need to work on
% Windows in a flexible way.
%
% \begin{function}{abspath()}
%   \begin{syntax}
%     |abspath(|\meta{target}|)|
%   \end{syntax}
%   Returns a string which gives the absolute location of the
%   \meta{target} directory.
% \end{function}
%
% \begin{function}{dirname()}
%   \begin{syntax}
%     |dirname(|\meta{file}|)|
%   \end{syntax}
%   Returns a string comprising the path to a \meta{file} with the name removed
%   (\emph{i.e.}~up to the last |/|). Where the \meta{file} has no path data,
%   |"."| is returned.
% \end{function}
%
% \begin{function}{basename()}
%   \begin{syntax}
%     |basename(|\meta{file}|)|
%   \end{syntax}
%   Returns a string comprising the full name of the \meta{file} with the
%   path removed (\emph{i.e.}~from the last |/| onward).
% \end{function}
%
% \begin{function}{cleandir()}
%   \begin{syntax}
%     |cleandir(|\meta{dir}|)|
%   \end{syntax}
%   Removes any content within the \meta{dir}; returns an error level.
% \end{function}
%
% \begin{function}{cp()}
%   \begin{syntax}
%     |cp(|\meta{glob}, \meta{source}, \meta{destination}|)|
%   \end{syntax}
%   Copies files matching the \meta{glob} from the \meta{source} directory
%   to the \meta{destination}; returns an error level.
% \end{function}
%
% \begin{function}{direxists()}
%   \begin{syntax}
%     |direxists(|\meta{dir}|)|
%   \end{syntax}
%   Tests if the \meta{dir} exists; returns a boolean value.
% \end{function}
%
% \begin{function}{fileexists()}
%   \begin{syntax}
%     |fileexists(|\meta{file}|)|
%   \end{syntax}
%   Tests if the \meta{file} exists and is readable; returns a boolean value.
% \end{function}
%
% \begin{function}{filelist()}
%   \begin{syntax}
%     |filelist(|\meta{path}, \oarg{glob}|)|
%   \end{syntax}
%   Returns a table containing all of the files with the \meta{path}
%   which match the \meta{glob}; if the latter is absent returns a list of
%   all files in the \meta{path}.
% \end{function}
%
% \begin{function}{ordered_filelist()}
%   \begin{syntax}
%     |ordered_filelist(|\meta{path}, \oarg{glob}|)|
%   \end{syntax}
%   Like |filelist()| but returning a sorted table.
% \end{function}
%
% \begin{function}{glob_to_pattern()}
%   \begin{syntax}
%     |glob_to_pattern(|\meta{glob}|)|
%   \end{syntax}
%   Returns the \meta{glob} converted to a Lua pattern.
% \end{function}
%
% \begin{function}{jobname()}
%   \begin{syntax}
%     |jobname(|\meta{file}|)|
%   \end{syntax}
%   Returns a string comprising the jobname of the file with the
%   path and extension removed (\emph{i.e.}~from the last |/| up to the
%   last |.|).
% \end{function}
%
% \begin{function}{mkdir()}
%   \begin{syntax}
%     |mkdir(|\meta{dir}|)|
%   \end{syntax}
%   Creates the \meta{dir}; returns an error level.
% \end{function}
%
% \begin{function}{ren()}
%   \begin{syntax}
%     |ren(|\meta{dir}, \meta{source}, \meta{destination}|)|
%   \end{syntax}
%   Renames the \meta{source} file to the \meta{destination} name within
%   the \meta{dir}; returns an error level.
% \end{function}
%
% \begin{function}{rm()}
%   \begin{syntax}
%     |rm(|\meta{dir}, \meta{glob}|)|
%   \end{syntax}
%   Removes files in the \meta{dir} matching the \meta{glob}; returns an
%   error level.
% \end{function}
%
% \begin{function}{run()}
%   \begin{syntax}
%     |run(|\meta{dir}, \meta{cmd}|)|
%   \end{syntax}
%   Executes the \meta{cmd}, starting it in the \meta{dir}; returns an
%   error level.
% \end{function}
%
% \begin{function}{splitpath()}
%   \begin{syntax}
%     |splitpath(|\meta{file}|)|
%   \end{syntax}
%   Returns two strings split at the last |/|: the \texttt{dirname()} and
%   the |basename()|.
% \end{function}
%
% \begin{function}{normalize_path()}
%   \begin{syntax}
%     |normalize_path(|\meta{path}|)|
%   \end{syntax}
%   When called on Windows, returns a string comprising the \meta{path} with
%   |/| characters replaced by |\|. In other cases returns the path unchanged.
% \end{function}
%
% \subsection{System-dependent strings}
%
% To support creation of additional functionality, the following low-level
% strings are exposed by \pkg{l3build}: these all have system-dependent
% definitions and avoid the need to test |os.type| during the construction
% of system calls.
%
% \begin{variable}{os_concat}
%   The concatenation operation for using multiple commands in one
%   system call, \emph{e.g.}
%   \begin{verbatim}
%     os.execute("tex " .. file .. os_concat .. "tex " .. file)
%   \end{verbatim}
% \end{variable}
%
% \begin{variable}{os_null}
%   The location to redirect commands which should produce no output
%   at the terminal: almost always used preceded by |>|, \emph{e.g.}
%   \begin{verbatim}
%     os.execute("tex " .. file .. " > " .. os_null)
%   \end{verbatim}
% \end{variable}
%
% \begin{variable}{os_pathsep}
%   The separator used when setting an environment variable to multiple
%   paths, \emph{e.g.}
%   \begin{verbatim}
%     os.execute(os_setenv .. " PATH=../a" .. os_pathsep .. "../b")
%   \end{verbatim}
% \end{variable}
%
% \begin{variable}{os_setenv}
%   The command to set an environmental variable, \emph{e.g.}
%   \begin{verbatim}
%     os.execute(os_setenv .. " PATH=../a")
%   \end{verbatim}
% \end{variable}
%
% \begin{variable}{os_yes}
%   \textbf{DEPRECATED}
%   A command to generate a series of $300$ lines each containing the
%   character |y|: this is useful as the Unix |yes| command cannot be
%   used inside |os.execute| (it does not terminate).
%
%  Rather than use this function, we recommend the replacement construct
%  \begin{verbatim}
%    io.popen(<cmd>,"w"):write(string.rep("y\n", 300)):close()
%  \end{verbatim}
% \end{variable}
%
% \subsection{Components of \texttt{l3build}}
%
% \begin{function}{call()}
%   \begin{syntax}
%     |call(|\meta{dirs}, \meta{target}, \oarg{options}|)|
%   \end{syntax}
%   Runs the \texttt{l3build} \meta{target} (a string) for each directory in the
%   \meta{dirs} (a table). This will pass command line options for the parent
%   script to the child processes. The \meta{options} table should take the
%   same form as the global \meta{options}, described above. If it is
%   absent then the global list is used. Note that any entry for the
%   |target| in this table is ignored.
% \end{function}
%
% \begin{function}{install_files()}
%   \begin{syntax}
%     |install_files(|\meta{target},\meta{full},\meta{dry-run}|)|
%   \end{syntax}
%   Installs the files from the module into the TDS root \meta{target}.
%   If \meta{full} is \texttt{true}, all files are copied: if it is
%   \texttt{false}, the \texttt{doc} and \texttt{source} trees are skipped.
%   If \meta{dry-run} is \texttt{true}, no files are copied, but instead the
%   files which would be copied are reported.
% \end{function}
%
% \subsection{Typesetting functions}
%
% All typesetting functions return $0$ on a successful completion.
%
% \begin{function}{biber()}
%   \begin{syntax}
%     |biber(|\meta{name},\meta{dir}|)|
%   \end{syntax}
%   Runs Biber on the \meta{name} (\emph{i.e.}~a jobname lacking any
%   extension) inside the \meta{dir}. If there is no |.bcf| file then
%   no action is taken with a return value of $0$.
% \end{function}
%
% \begin{function}{bibtex()}
%   \begin{syntax}
%     |bibtex(|\meta{name},\meta{dir}|)|
%   \end{syntax}
%   Runs Bib\TeX{} on the \meta{name} (\emph{i.e.}~a jobname lacking any
%   extension) inside the \meta{dir}. If there are no |\citation| lines in
%   the |.aux| file then no action is taken with a return value of $0$.
% \end{function}
%
% \begin{function}{makeindex()}
%   \begin{syntax}
%     |makeindex(|\meta{name},\meta{dir},\meta{inext},\meta{outext},\meta{logext},\meta{style}|)|
%   \end{syntax}
%   Runs MakeIndex on the \meta{name} (\emph{i.e.}~a jobname lacking any
%   extension) inside the \meta{dir}. The various extensions and the \meta{style}
%   should normally be given as it standard for MakeIndex.
% \end{function}
%
% \begin{function}{tex()}
%   \begin{syntax}
%     |tex(|\meta{file},\meta{dir},\meta{cmd}|)|
%   \end{syntax}
%   Runs \meta{cmd} (by default \luavar{typesetexe} \luavar{typesetopts}) on the
%   \meta{file} inside the \meta{dir}.
% \end{function}
%
% \begin{function}{runcmd()}
%   \begin{syntax}
%     |runcmd(|\meta{cmd},\meta{dir},|{|\meta{envvars}|})|
%   \end{syntax}
%   A generic function which runs the \meta{cmd} in the \meta{dir}, first
%   setting up all of the environmental variables specified to
%   point to the |local| and |working| directories. This function is useful
%   when creating non-standard typesetting steps.
% \end{function}
%
% \subsection{Customizing the target and option lists}
%
% The targets known to \pkg{l3build} are stored in the global table
% |target_list|. Each entry should have at least a |func|, pointing to the
% function used to implement the target. This function will receive the
% list of names given at the command line as a table argument.
% In most cases, targets will also have a |desc|, used to construct |help()|
% automatically. In addition, the following may also be used:
% \begin{itemize}
%   \item |bundle_func| A variant of |func| used when at the top level of
%     a bundle
%   \item |bundle_target| A boolean to specify that when passing the target
%     name in a bundle, it should have |bundle| prepended.
%   \item |pre| A function executed before the main function, and receiving
%     the |names| as an argument; this allows checking of the |name| data
%     without impact on the main |func|.
% \end{itemize}
% The functions |func|, |bundle_func| and |pre| must return 0 on success.
%
% The list of options (switches) is controlled by the |option_list| table.
% The name of each entry in the table is the \enquote{long} version of the
% option. Each entry requires a |type|, one of |boolean|, |string| or
% |table|. As for targets, each entry should have a |desc| to construct
% the |help()|. It is also possible to provide a |short| name for the option:
% this should be a single letter.
%
% \subsection{Customizing the manifest file}
% \label{sec:manifest}
%
% The default setup for the manifest file creating with the \texttt{manifest}
% target attempt to reflect the defaults for \pkg{l3build} itself.
% The groups (and hence the files) displayed can be completely
% customized by defining a new setup function which creates a Lua table with
% the appropriate settings (Section~\vref{sec:manifest-groups}).
%
% The formatting within the manifest file can be customized by redefining a number
% of Lua functions. This includes
% how the files are sorted within each group (Section~\vref{sec:manifest-sorting}),
% the inclusion of one-line descriptions for each file (Section~\vref{sec:manifest-desc}),
% and the details of the formatting of each entry (Section~\vref{sec:manifest-formatting}).
%
% To perform such customizations, either include the re-definitions directly within your
% package's |build.lua| file, or make a copy of |l3build-manifest-setup.lua|, rename it,
% and load it within your |build.lua| using |dofile()|.
%
%
% \subsubsection{Custom manifest groups}
% \label{sec:manifest-groups}
%
% The setup code for defining each group of files within the manifest looks something like
% the following:
% \begin{verbatim}
% manifest_setup = function()
%   local groups = {
%     {
%        subheading = "Repository files",
%        description = [[
% Files located in the package development repository.
%        ]],
%     },
%     {
%        name    = "Source files",
%        description = [[
% These are source files generating the package files.
%        ]],
%        files   = {sourcefiles},
%     },
%     {
%        name    = "Typeset documentation source files",
%        description = [[
% These files are typeset using LaTeX to produce the PDF documentation for the package.
%        ]],
%        files   = {typesetfiles,typesetsourcefiles,typesetdemofiles},
%     },
%     ...
%   }
%   return groups
% end
% \end{verbatim}
%
% The |groups| variable is an ordered array of tables which contain the metadata about each
% `group' in the manifest listing.
% The keys supported in these tables are outlined in
% Tables~\vref{tab:manifest-setup} and~\vref{tab:manifest-subheadings}.
% See the complete setup code in |l3build-manifest-setup.lua| for examples of these in use.
%
% \begin{table}
%   \caption{Table entries used in the manifest setup table for a group.}
%   \label{tab:manifest-setup}
%   \centering
%   \begin{tabular}{lp{8cm}}
%     \toprule
%     Entry & Description \\
%     \midrule
%       \var{name}               & The heading of the group                             \\
%       \var{description}        & The description printed below the heading            \\
%       \var{files}              & Files to include in this group                       \\
%       \var{exclude}            & Files to exclude (default |{excludefiles}|)          \\
%       \var{dir}                & The directory to search (default |maindir|)          \\
%       \var{rename}             & An array with a |gsub| redefinition for the filename \\
%       \var{skipfiledescription} & Whether to extract file descriptions from these files (default |false|) \\
%     \bottomrule
%     \end{tabular}
% \end{table}
%
% \begin{table}
%   \caption{Table entries used in the manifest setup table for a subheading.}
%   \label{tab:manifest-subheadings}
%   \centering
%   \begin{tabular}{lp{8cm}}
%     \toprule
%     Entry & Description \\
%     \midrule
%       \var{subheading}         & The subheading                                       \\
%       \var{description}        & The description printed below the subheading         \\
%     \bottomrule
%     \end{tabular}
% \end{table}
%
%
% \subsubsection{Sorting within each manifest group}
% \label{sec:manifest-sorting}
%
% Within a single group in the manifest listing, files can be matched against multiple variables.
% For example, for |sourcefiles={*.dtx,*.ins}| the following (unsorted) file listing might result:
% \begin{itemize}[nosep]
% \item foo.dtx
% \item bar.dtx
% \item foo.ins
% \item bar.ins
% \end{itemize}
% This listing can be sorted using two separate functions by the default manifest code.
% The first, default, is to sort alphabetically within a single variable match.
% This keeps all files of a single extension contiguous in the listing.
% To edit how this sort is performed, redefine the |manifest_sort_within_match| function.
%
% The second approach to sorting is to apply a sorting function to the entire set of matched files.
% (This happens \emph{after} any sorting is applied for each match.)
% By default this is a no-op but can be edited by redefining the |manifest_sort_within_group|
% function. For example:
% \begin{verbatim}
% manifest_sort_within_group = function(files)
%   local f = files
%   table.sort(f)
%   return f
% end
% \end{verbatim}
% This will produce an alphabetical listing of files:
% \begin{itemize}
% \item bar.dtx
% \item bar.ins
% \item foo.dtx
% \item foo.ins
% \end{itemize}
%
%
% \subsubsection{File descriptions}
% \label{sec:manifest-desc}
%
% By default the manifest contains lists of files, and with a small addition these
% lists can be augmented with a one-line summary of each file.
% If the Lua function |manifest_extract_filedesc| is defined, it will be used to search
% the contents of each file to extract a description for that file.
% For example, perhaps you are using multiple |.dtx| files for a project and the argument
% to the first |\section| in each can be used as a file description:
% \begin{verbatim}
% manifest_extract_filedesc = function(filehandle,filename)
%
%   local all_file = filehandle:read("a")
%   local matchstr = "\\section{(.-)}"
%
%   filedesc = string.match(all_file,matchstr)
%
%   return filedesc
% end
% \end{verbatim}
% (Note the |matchstr| above is only an example and doesn't handle nested braces.)
%
%
% \subsubsection{Custom formatting}
% \label{sec:manifest-formatting}
%
% After the manifest code has built a complete listing of files to print, a series of
% file writing operations are performed which create the manifest file.
% The following functions can be re-defined to change the formatting of the manifest file:
% \begin{itemize}
% \item |manifest_write_opening|: Write the heading of the manifest file and its opening paragraph.
% \item |manifest_write_subheading|: Write a subheading and description
% \item |manifest_write_group_heading|: Write the section heading of the manifest group and the group description
% \item |manifest_write_group_file|: Write the filename (when not writing file descriptions)
% \item |manifest_write_group_file_descr|: Write the filename and the file description
% \end{itemize}
% Full descriptions of their usage and arguments can be found within the |l3build-manifest-setup.lua|
% code itself.
%
% \section{Known limitations}
%
% \subsection{Non-\textsc{ascii} filenames}
%
% On Windows, support for non-\textsc{ascii} filenames is limited by the way
% that Lua handles system calls. While calling \TeX{} engines should work with
% any name, general file operations will only success if the filename falls
% within the codepage currently in use by the operating system.
%
% \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}
%
% We require \eTeX{} for some features.
%    \begin{macrocode}
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname eTeXversion\endcsname\relax
  \message{e-TeX is required by some regression-test.tex features}%
\fi
%    \end{macrocode}
%
% \begin{macro}{\reset@catcodes}
%   Unlike in the \LaTeXe{} regression test suite, reset catcodes: each test
%   should set these as appropriate. There's also a quick test for Con\TeX{}t:
%   it defines |\unprotect| which should be a reasonable marker (and is
%   needed as some catcodes are otherwise wrong).
%    \begin{macrocode}
\ifx\unprotect\undefined
  \expandafter\edef\csname reset\string @catcodes\endcsname{%
    \catcode`\noexpand\@=\the\catcode`\@\relax
  }%
  \catcode`\@=11 %
\else
  \unprotect
  \def\reset@catcodes{\protect}%
\fi
%    \end{macrocode}
% \end{macro}
%
% Put \TeX{} into scroll mode, and stop it showing the
% implementation details of macros in error messages.
%    \begin{macrocode}
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname interactionmode\endcsname\relax
\else
  \ifnum\interactionmode>1 \scrollmode\fi
\fi
\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}
%
% \begin{macro}{\logginoutput}
%   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{%
  \tracingoutput=1 %
  \showboxbreadth=\maxdimen
  \showboxdepth=\maxdimen
}
%    \end{macrocode}
% \end{macro}
%
% Set the newline character: \LaTeXe{} does this but plain-based formats do
% not.
%    \begin{macrocode}
\newlinechar=`\^^J
%    \end{macrocode}
%
% \subsection{Commands in test files}
%
% \begin{macro}{\LONGTYPEOUT, \TYPE}
%   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\write128{#1}%
  \endgroup
}
\let\TYPE\LONGTYPEOUT
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\STARTMESSAGE, \START}
%   Start the test, after the optional |\documentclass|
%   |\begin{document}| commands with |\START|.  All lines in the |.log| file
%   before this will be ignored.
%    \begin{macrocode}
\def\STARTMESSAGE{This is a generated file for the l3build validation system.}
\def\START{%
  \LONGTYPEOUT{^^JSTART-TEST-LOG^^J}%
  \LONGTYPEOUT{^^J%
     \STARTMESSAGE%
     ^^J^^JDon't change this file in any respect.%
     ^^J^^J%
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@@end, \END}
% The test should end with |\END| or |\end{document}|
% or |\bye| in plain \TeX{}.
%    \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{^^JEND-TEST-LOG^^J}%
  \@@@end
}
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname currentgrouplevel\endcsname\relax
  \def\END{%
    \LONGTYPEOUT{^^JEND-TEST-LOG^^J}%
    \@@@end
  }
\fi
\ifx\@@end\@undefined
  \let\end\END
\else
  \let\@@end\END
\fi
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\OMIT, \TIMO}
%   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}
% \end{macro}
%
%  \begin{macro}{\SHOWFILE}
%     Load a file (e.g.,| \jobname.toc|) into the .log file with the usual special
%     characters rendered harmless. Use as |\SHOWFILE{\jobname.aux}|.
%    \begin{macrocode}
\begingroup       % within the scope of this groups each line needs to end in % !
\catcode`\^^M\active %
\gdef\SHOWFILE#1{%
     \typeout{-------- #1 (start) ---------}%
\IfFileExists{#1}%
  {\begingroup %
     \catcode`\^^M\active %
     \edef^^M{[nl]^^J}%
     \everyeof{\noexpand}%
     \obeyspaces %
     \@sanitize %
     \message{\@@input #1 }%
   \endgroup }%
  {\message{Not found}}%
     \typeout{-------- #1 (end) -----------}%
}%
\endgroup
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname everyeof\endcsname\relax
  \def\SHOWFILE#1{\TYPE{FEATURE UNAVAILABLE}}
\fi
%    \end{macrocode}
%  \end{macro}
%
% 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}
\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}}{}
%    \end{macrocode}
%
% \subsection{Showing PDF Tag Tree}
%
% \begin{macro}{\SHOWPDFTAGS}
% Insert a marker in the log. The normalized log will have
% The output from \texttt{show-pdf-tags} inserted at that point.
%    \begin{macrocode}
\gdef\SHOWPDFTAGS{%
  \BEGINTEST{Show PDF Tags}%
  \TYPE{^^J^^J%
    -------- \jobname.xml (start) ---------^^J%
    --INSERT-PDF-TAGS \jobname.pdf ^^J%
    -------- \jobname.xml (end) -----------^^J%
    ^^J}%
  \ENDTEST
}
%    \end{macrocode}
% \end{macro}
% \subsection{Formatting the \texttt{.log} file}
%
% \begin{macro}{\gTESTint}
%   For tracking the total number of tests.
%    \begin{macrocode}
\newcount\gTESTint
%     \end{macrocode}
% \end{macro}
%
% \begin{macro}
%   {
%     \SEPARATOR,
%     \BEGINTEST,
%     \ENDTEST,
%     \TEST,
%     \TESTEXP,
%     \TRUE,
%     \FALSE,
%     \YES,
%     \NO,
%     \NEWLINE,
%     \ASSERT,
%     \ASSERTSTR,
%     \TESTBOX,
%     \BEGINBOXTEST,
%     \ENDBOXTEST,
%     \SHOWBOX
%   }
%   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}
\def\SEPARATOR{%
  \TYPE{%
    ============================================================%
  }%
}
\csname protected\endcsname\long\def\BEGINTEST#1{%
  \global\advance\gTESTint by 1 %
  \SEPARATOR
  \LONGTYPEOUT{TEST \the\gTESTint: \detokenize{#1}}%
  \SEPARATOR
  \begingroup
    \let\TYPE\LONGTYPEOUT
}
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname detokenize\endcsname\relax
  \long\def\BEGINTEST#1{%
    \global\advance\gTESTint by 1 %
    \SEPARATOR
    \begingroup
      \toks0={#1}%
      \LONGTYPEOUT{TEST \the\gTESTint: \the\toks0 }%
    \endgroup
    \SEPARATOR
    \begingroup
      \let\TYPE\LONGTYPEOUT
  }
\fi
\csname protected\endcsname\long\def\ENDTEST{%
  \endgroup
  \SEPARATOR
  \LONGTYPEOUT{}%
}
\long\def\TEST#1#2{%
  \BEGINTEST{#1}%
  #2%
  \ENDTEST
}
\long\def\TESTEXP#1#2{%
  \BEGINTEST{#1}%
  \LONGTYPEOUT{#2}%
  \ENDTEST
}
\def \TRUE  {\TYPE{TRUE}}
\def \FALSE {\TYPE{FALSE}}
\def \YES   {\TYPE{YES}}
\def \NO    {\TYPE{NO}}
\def \NEWLINE {\TYPE{^^J}}
\csname protected\endcsname\long\def\ASSERT#1#2{%
  \begingroup
    \edef\@tempa{#1}%
    \edef\@tempb{#2}%
    \ifx\@tempa\@tempb
      \TYPE{PASSED}%
    \else
      \TYPE{FAILED}%
    \fi
  \endgroup
}
\csname protected\endcsname\long\def\ASSERTSTR#1#2{%
  \begingroup
    \edef\@tempa{#1}%
    \edef\@tempb{#2}%
    \edef\@tempa{\meaning\@tempa}%
    \edef\@tempb{\meaning\@tempb}%
    \ifx\@tempa\@tempb
      \TYPE{PASSED}%
    \else
      \TYPE{FAILED}%
    \fi
  \endgroup
}
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname detokenize\endcsname\relax
  \long\def\ASSERTSTR#1#2{%
    \TYPE{FEATURE UNAVAILABLE}%
  }
\fi
\csname newbox\endcsname\TESTBOX% newbox is \outer in plain
\csname protected\endcsname\long\def\BEGINBOXTEST#1{%
  \BEGINTEST{#1}%
    \setbox\TESTBOX=\hbox\bgroup
      \ignorespaces
}
\csname protected\endcsname\long\def\ENDBOXTEST{%
      \ifhmode\unskip\fi
    \egroup
    \SHOWBOX{\TESTBOX}%
  \ENDTEST
}
\csname protected\endcsname\long\def\SHOWBOX#1{%
  \begingroup
    \long\def\use##1{##1}%
    \showboxbreadth=\maxdimen
    \showboxdepth=\maxdimen
    \tracingonline=0 %
    \errorcontextlines=-1 %
    \showbox\use{#1}%
  \endgroup
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Suppressing variable data in output}
%
% Disable compression in PDF output.
%    \begin{macrocode}
\ifnum 0%
  \ifx\pdfoutput\@undefined\else\ifnum\pdfoutput>0 1\fi\fi
  \ifx\outputmode\@undefined\else\ifnum\outputmode>0 1\fi\fi
  >0 %
  \ifx\pdfvariable\@undefined
    \pdfcompresslevel=0 %
    \pdfobjcompresslevel=0 %
  \else
    \pdfvariable compresslevel=0 %
    \pdfvariable objcompresslevel=0 %
  \fi
\else
  \ifx\XeTeXversion\@undefined
  \special{%
      ps: /setdistillerparams
      where
        {pop << /CompressPages false /CompressStreams false >> setdistillerparams}
      if
    }%
  \else
    \special{dvipdfmx:config z 0}% Compress level
    \special{dvipdfmx:config C 0x40}% Object compression
  \fi
\fi
%    \end{macrocode}
%
%
%    \begin{macrocode}
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname protected\endcsname\relax
  \reset@catcodes
  \let\protected\undefined
  \expandafter\endinput
\fi
%    \end{macrocode}
%
% Load the map file early so it does not appear in the log.
%    \begin{macrocode}
\ifx\pdfoutput\@undefined
  \ifx\outputmode\@undefined
  \else
    \ifnum\outputmode>0 %
      \pdfextension mapfile{pdftex.map}%
    \fi
  \fi
\else
  \ifnum\pdfoutput>0 %
    \pdfmapfile{pdftex.map}%
  \fi
\fi
%    \end{macrocode}
%
% To make any PDF file produced comparable we need to suppress various
% pieces of data. This works in concert with setting the epoch from the
% environment side (as not all output can be controlled here).
% There is a limit to what can be done with the underlying PDF structure so
% there is no point entirely suppressing \texttt{Producer}: simply avoid
% any version numbers. If the pdfmanagement is loaded we use its function
% if it exists.
%    \begin{macrocode}
\ifcsname pdfmeta_set_regression_data:\endcsname
   \csname pdfmeta_set_regression_data:\endcsname
\else
  \ifnum 0%
    \ifx\pdfoutput\@undefined\else\ifnum\pdfoutput>0 1\fi\fi
    \ifx\outputmode\@undefined\else\ifnum\outputmode>0 1\fi\fi
    >0 %
    \ifx\pdfvariable\@undefined
      \pdfinfo{/Producer (\ifx\directlua\@undefined pdf\else Lua\fi TeX)}
      \ifx\pdfinfoomitdate\@undefined\else
        \pdfinfoomitdate     = 1 %
        \pdfsuppressptexinfo = \numexpr
              0
            + 1 % PTEX.Fullbanner
            + 2 % PTEX.FileName
          \relax
        \pdftrailerid{}
      \fi
    \else
      \pdfextension info{/Producer (LuaTeX)}
      \pdfvariable suppressoptionalinfo \numexpr
            0
          +   1 % PTEX.Fullbanner
          +   2 % PTEX.FileName
          +  32 % CreationDate
          +  64 % ModDate
          + 512 % ID
        \relax
    \fi
  \else
    \ifx\XeTeXversion\@undefined
      \special{! <</DocumentUUID (DocumentUUID)>> setpagedevice}
      \special{! <</InstanceUUID (InstanceUUID)>> setpagedevice}
    \else
      \special{%
        pdf: docinfo
          <<
            /Creator        (TeX)
            /CreationDate   ()
            /ModDate        ()
            /Producer       (xdvipdfmx)
          >>
      }
    \fi
  \fi
\fi
%    \end{macrocode}
%  Suppress version data in \LaTeX{} runs.
%    \begin{macrocode}
\ifdefined\AddToHook
  \AddToHook{enddocument/info}[kernel/testmode]{}
  \DeclareHookRule{enddocument/info}{kernel/testmode}{voids}{kernel/release}
\fi
%    \end{macrocode}
% And write the information up-front.
%    \begin{macrocode}
\ifdefined\LaTeXReleaseInfo
  \begingroup
    \let\show@release@info\wlog
    \show@release@info{ ***********}
    \the\LaTeXReleaseInfo
    \show@release@info{ ***********}
  \endgroup
\fi
%    \end{macrocode}
%
%    \begin{macrocode}
\ifcsname\detokenize{l_iow_line_count_int}\endcsname
  \csname \detokenize{l_iow_line_count_int}\endcsname=9999 %
\fi
%    \end{macrocode}
%
% Finish up.
%    \begin{macrocode}
\reset@catcodes
%    \end{macrocode}
%
%    \begin{macrocode}
%</package>
%    \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
