% \iffalse % % File l3build.dtx Copyright (C) 2014-2024 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> \RequirePackage{expl3} \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 organising files for CTAN} \luavarset{tdsdir} {distribdir .. "/tds"} {Directory for organised 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} {\{"*.pdf", "*.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{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{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{manifestfile} {"MANIFEST.md"} {Filename to use for the manifest file} \luavarseparator \luavarset{tdslocations}{\{ \}}{Map for non-standard file installations} \luavarset{tdsdirs}{\{ \}}{List of 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 test file 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} % % \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 2024-02-08} % % \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 recognises the options % \begin{itemize} % \item |--config| (|-c|) Configuration(s) to use for testing % \item |--date| Date to use when tagging data % \item |--debug| Runs the target in debug mode (not supported by all targets) % \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 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 \texttt{--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{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 to limit % testing to a single engine. 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 command removes all temporary files used for package bundling and regression testing. % In the standard layout, these are all files within the directories defined by \var{localdir}, \var{testdir}, \var{typesetdir} and \var{unpackdir}, as well as all files defined in the \var{cleanfiles} variable in the same directory as the script. % The defaults are |.pdf| files from typesetting (|doc|) and |.zip| files from bundling (|ctan|). % \end{buildcmd} % % % \begin{buildcmd}{ctan} % Creates an archive of the package and its documentation, suitable for uploading to CTAN. % The archive is compiled in \var{distribdir}, and if the results are successful the resultant |.zip| file is moved into the same directory as the build script. % If \var{packtdszip} is set true then the building process includes a |.tds.zip| file containing the `\TeX\ Directory Structure' layout of the package or bundle. % The archive therefore may contain two `views' of the package: % \begin{Verbatim} % abc.zip/ % abc/ % abc.dtx % abc.ins % abc.pdf % README.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 normalising 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{typesetdir} directory. % In the absence of one or more file names, all documentation is typeset; % a file list may be 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 of |pdftex|, |xetex|, or |luatex|), the saved output is stored in \texttt{\meta{name}.\meta{engine}.tlg}. This is necessary if running the test through a different engine produces a different output. % A 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 minimise 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/master/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 list of % configurations to apply, overriding \var{checkconfigs}. For example, in the % directory containing |config-TU.lua|, you can use % |l3build check -cconfig-TU | and |l3build save -cconfig-TU | % 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/master/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 normalised % 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 file dates to \texttt{....-..-..}, and any version % numbers on the same lines to \texttt{v...}. % \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{} to % \texttt{} % \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 normalising % 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} % % When making comparisons between 8-bit and Unicode engines it is useful to % format the top half of the 8-bit range such that it appears in the log as % |^^|\texttt{\meta{char}} (the exact nature of the 8-bit output is otherwise % dependent on the active code page). This may be controlled using the % |asciiengines| option. Any engines named here will use a |.tcx| file to % produce only ASCII chars in the log output, whilst for other engines % normalization is carried out from UTF-8 to ASCII. If the option is set to % an empty table the latter process is skipped: suitable for cases where only % Unicode engines are in use. % % \subsection{Breaking changes} % % Very occasionally, it is necessary to make changes to \pkg{l3build} that % change the \texttt{.tlg} file results. This is typically when additional % normalization is required. When this is the case, you should first verify % that \texttt{.tlg} files pass with the older \pkg{l3build}, then update only % \pkg{l3build}, re-check the files and save the results. Where possible, % we provide a mechanism to run with older setting to allow this process to % take place smoothly. % % \subsubsection{Release 2024-02-08} % % Wrapping of messages by \pkg{l3msg} is now suppressed, aligning with the % approach to \var{maxprintline}. % % \subsubsection{Release 2023-03-22} % % This release changes the standard value of \var{maxprintline} from $79$ to % $9999$, to suppress line wrapping in the log. This makes normalization of % for example file paths more reliable. To check that \texttt{.tlg} files % are correct, you can set \var{maxprintline} in your \texttt{build.lua} file % explicitly to the old default, check that tests pass, then remove this % line and re-check. % % \section{Writing test files} % \label{sec:writing-tests} % % Test files are written in a \TeX{} dialect using the support file |regression-test.tex|, which should be |\input| at the very beginning of each test. % Additional customizations to this driver can be included in a local |regression-test.cfg| file, which will be loaded automatically if found. % % The macros loaded by |regression-test.tex| set up the test system and provide a number of commands to aid the production of a structured test suite. % The basis of the test suite is to output material into the |.log| file, from which a normalised test output (|.tlg|) file is produced by the build command |save|. % A number of commands are provided for this; they are all written in uppercase to help avoid possible conflicts with other package commands. % % \subsection{Metadata and structural commands} % % Any commands that write content to the |.log| file that should be ignored can be surrounded by |\OMIT| \dots\ |\TIMO|. % At the appropriate location in the document where the |.log| comparisons should start (say, after |\begin{document}|), the test suite must contain the |\START| macro. % % The |\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}. % \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} % \usepackage{expl3} % \START % \ExplSyntaxOn % \box_new:N \l_tmp_box % \hbox_set:Nn \l_tmp_box {hello~ \emph{world}~ $a=b+c$} % \box_show:N \l_tmp_box % \ExplSyntaxOff % \END % \end{Verbatim} % The output from this test is shown in Figure~\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. % \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} % \usepackage{expl3} % \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. % 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} enables searching for a \texttt{texmf.cnf} file % by setting the envirnmental variable \texttt{TEXMFCNF}. 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}} % % % % \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 copy the logfile without any normalization % os.execute(string.format("cp %s %s", 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 customised 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 customised 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 availablity 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 } & & \YES & 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. The possible entries in the table are given in the table % below. % \begin{center} % \begin{tabular}{ll} % \toprule % Entry & 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{texmfhome} & String \\ % \bottomrule % \end{tabular} % \end{center} % \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 % modelled 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(,"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{name} 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{Customising 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{Customising 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 % customised 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 customised 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("*all") % 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>2 % \LONGTYPEOUT{Bad conditionals: \the\numexpr\currentiflevel-2!}% \fi \LONGTYPEOUT{^^JEND-TEST-LOG^^J}% \@@@end } \begingroup\expandafter\expandafter\expandafter\endgroup \expandafter\ifx\csname currentgrouplevel\endcsname\relax \def\END{% \LONGTYPEOUT{^^JEND-TEST-LOG^^J}% \@@@end } \fi \ifx\@@end\@undefined \let\end\END \else \let\@@end\END \fi % \end{macrocode} % \end{macro} % % \begin{macro}{\OMIT, \TIMO} % Surround commands which produce irrelevant lines in the |.log| file by % |\OMIT|\dots|\TIMO| % \begin{macrocode} \def\OMIT{\LONGTYPEOUT{OMIT}} \def\TIMO{\LONGTYPEOUT{TIMO}} % \end{macrocode} % \end{macro} % % \begin{macro}{\SHOWFILE} % Load a file (e.g.,| \jobname.toc|) into the .log file with the usual special % characters rendered harmless. Use as |\SHOWFILE{\jobname.aux}|. % \begin{macrocode} \begingroup % within the scope of this groups each line needs to end in % ! \catcode`\^^M\active % \gdef\SHOWFILE#1{% \typeout{-------- #1 (start) ---------}% \IfFileExists{#1}% {\begingroup % \catcode`\^^M\active % \edef^^M{^\string^M^^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{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{! <> setpagedevice} \special{! <> setpagedevice} \else \special{% pdf: docinfo << /Creator (TeX) /CreationDate () /ModDate () /Producer (xdvipdfmx) >> } \fi \fi \fi % \end{macrocode} % Suppress version data in \LaTeX{} runs. % \begin{macrocode} \ifdefined\AddToHook \AddToHook{enddocument/info}[kernel/testmode]{} \DeclareHookRule{enddocument/info}{kernel/testmode}{voids}{kernel/release} \fi % \end{macrocode} % % \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} % % \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