% \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{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-07-10}
%
% \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.
%
% \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.
%
% Note that for technical reasons, any information printed during \cs{everyjob}
% is suppressed by \pkg{l3build}. \LaTeX{} version information is also printed
% at the end of documents, and is visible in the raw \texttt{.log} files but
% is automatically omitted from \texttt{.tlg} files. This information may be
% useful for debugging: to ensure it prints, you need to use |\end{document}|
% rather than \cs{END}.
%
% \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{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.
%
% 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}{\gOMITint}
% \begin{macro}{\OMIT, \TIMO}
%   Surround commands which produce irrelevant lines in the |.log| file by
%   |\OMIT|\dots|\TIMO|
%    \begin{macrocode}
\newcount\gOMITint
\def\OMIT{%
  \ifnum\gOMITint=0 %
    \LONGTYPEOUT{OMIT}%
  \fi
  \global\advance\gOMITint1 %
}
\def\TIMO{%
  \ifnum\gOMITint=0 \else
    \LONGTYPEOUT{TIMO}%
    \ifnum\gOMITint>0 %
      \global\advance\gOMITint-1 %
    \fi
  \fi
}
%    \end{macrocode}
% \end{macro}
% \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
%   }
%   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
%    \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}[l3build/before]{\OMIT}
  \AddToHook{enddocument/info}[l3build/after]{\TIMO}
  \DeclareHookRule{enddocument/info}{l3build/before}{before}{kernel/release}
  \DeclareHookRule{enddocument/info}{l3build/after}{after}{kernel/release}
  \DeclareHookRule{enddocument/info}{l3build/after}{before}{kernel/filelist}
\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
