% \iffalse % % File l3build.dtx (C) Copyright 2014-2018 The LaTeX3 Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this % license or (at your option) any later version. The latest version % of this license is in the file % % http://www.latex-project.org/lppl.txt % % This file is part of the "l3build bundle" (The Work in LPPL) % and all files in that bundle must be distributed together. % % ----------------------------------------------------------------------- % % The 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}{\$} texlua build.lua #1}% \nopagebreak\smallskip\nopagebreak\par\nopagebreak\noindent\ignorespaces } {} \makeatletter \newcommand\luavar[1]{\@ifundefined{lua_#1}{\ERROR}{\texttt{\@nameuse{lua_#1}}}} \newcommand\luavarset[3]{\@namedef{lua_#1}{#2}} \newcommand\luavarseparator{} \makeatother \def\allluavars{ \luavarset{module}{""}{The name of the module} \luavarset{bundle}{""}{The name of the bundle in which the module belongs (where relevant)} \luavarset{ctanpkg}{module/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{sourcfiledir}{"."} {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} \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{testdir} {builddir .. "/test"} {Directory for running tests} \luavarset{typesetdir}{builddir .. "/doc"} {Directory for building documentation} \luavarset{unpackdir} {builddir .. "/unpack"} {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~"\}}{Files to ignore entirely (default for Emacs backup files)} \luavarset{installfiles} {\{"*.sty","*.cls"\}}{Files to install to the \texttt{text} 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{bakext}{".bak"}{Extension of backup files} \luavarset{dviext}{".dvi"}{Extension of DVI files} \luavarset{lvtext}{".lvt"}{Extension of test files} \luavarset{tlgext}{".tlg"}{Extension of test file 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{pdfext}{".pdf"}{Extension of PDF file for checking and saving} \luavarset{psext} {".ps"} {Extension of PostScript files} \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} {"pdftex"}{Engine to generate \texttt{.tlg} file from} \luavarset{checkformat} {"latex"} {Format to use for tests} \luavarseparator \luavarset{checkconfigs}{\{\}}{Configurations to use for tests} \luavarseparator \luavarset{typesetexe}{"pdflatex"}{Executable for compiling \texttt{doc(s)}} \luavarset{unpackexe} {"tex"} {Executable for running \texttt{unpack}} \luavarset{zipexe} {"zip"} {Executable for creating archive with \texttt{ctan}} \luavarseparator \luavarset{checkopts} {"-interaction=nonstopmode"}{Options based to engine when running checks.} \luavarset{typesetopts}{"-interaction=nonstopmode"}{Options based to engine when typesetting.} \luavarset{unpackopts} {""} {Options based to engine when unpacking.} \luavarset{zipopts} {"-v -r -X"} {Options based to zip program.} \luavarseparator \luavarset{checksearch} {true}{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} \luavarseparator \luavarseparator \luavarset{biberexe} {"biber"} {Biber executable} \luavarset{biberopts} {""} {Biber options} \luavarset{bibtexexe} {"bibtex8"} {\BibTeX{} executable} \luavarset{bibtexopts} {"-W"} {\BibTeX{} options} \luavarset{makeindexexe} {"makeindex"}{MakeIndex executable} \luavarset{makeindexopts}{""} {MakeIndex options} \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 sure ASCII} \luavarset{checkruns} {1} {Number of runs to complete for a test before comparing the log} \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{maxprintline}{79} {Length of line to use in log files} \luavarset{packtdszip} {false} {Switch to build a TDS-style zip file for CTAN} \luavarset{typesetcmds} {""} {Instructions to be passed to \TeX{} when doing typesetting.} \luavarset{typsetcycles}{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.} } \allluavars \newcommand\luavartypeset{% \begingroup \frenchspacing \renewcommand\luavarset[3]{ \texttt{##1} & \texttt{##2} & ##3 \\ } \renewcommand\luavarseparator{\midrule} \setlength\LTleft{-0.21\linewidth} \begin{longtable}{@{}% >{\small} p{0.18\linewidth} @{\hspace{0.03\linewidth}} >{\footnotesize\hangindent=1em} p{0.34\linewidth} @{\hspace{0.03\linewidth}} >{\small\raggedright\arraybackslash} p{0.63\linewidth} @{}} \toprule Variable & Default & Description \\ \midrule\endhead \allluavars \bottomrule \end{longtable} \endgroup } \newcommand\code{\texttt} \newcommand\var{\texttt} \usepackage[procnames]{listings} \lstset{ basicstyle=\ttfamily\small, numbers=left, numberstyle={\tiny\color[gray]{0.4}}, } \usepackage{shortvrb} \usepackage{enumitem} \usepackage{longtable} \MakeShortVerb\| \begin{document} \DocInput{\jobname.dtx} \end{document} % % \fi % % \title{^^A % The \pkg{l3build} package\\ Checking and building packages^^A % } % % \author{^^A % The \LaTeX3 Project\thanks % {^^A % E-mail: % \href{mailto:latex-team@latex-project.org} % {latex-team@latex-project.org}^^A % }^^A % } % % \date{Released 2018-05-10} % % \maketitle % \tableofcontents % % \begin{documentation} % % \section{The \pkg{l3build} system} % % \subsection{Introduction} % % The \pkg{l3build} system is a Lua script for building \TeX{} packages, with particular emphasis on regression testing. % It is written in cross-platform Lua code, so can be used by any modern \TeX{} distribution with the |texlua| interpreter. % A package for building with \pkg{l3build} can be written in any \TeX\ dialect; its defaults are set up for \LaTeX\ packages written in the DocStrip style. (Caveat: minimal testing has yet been performed for non-\LaTeX{} packages.) % % Test files are written as standalone \TeX{} documents using the |regression-test.tex| setup file; documentation on writing these tests is discussed in Section~\ref{sec:writing-tests}. % % 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 \LaTeX3 project we have the \textsf{l3packages} bundle which contains the \textsf{xparse}, \textsf{xtemplate}, etc., modules. % These are all built and distributed as one bundle for installation, distribution \emph{via} CTAN and so forth. % % Each module in a bundle will have its own build script, and a bundle build script brings them all together. % A standard bundle layout would contain the following structure. % \begin{Verbatim} % mybundle/ % build.lua % support/ % yyy/ zoo/ % build.lua build.lua % README.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 safety deleted; all material within is re-generated for each command of the \pkg{l3build} system. % % \subsection{Main build commands} % % In the working directory of a bundle or module, the following commands can be executed: % \begin{itemize}[noitemsep]\ttfamily % \item check % \item check \meta{name(s)} % \item cmdcheck % \item clean % \item ctan % \item doc \meta{name(s)} % \item install % \item save \meta{name(s)} % \item tag % \item unpack % \end{itemize} % These commands are described below. % % As well as these commands, 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 |--dry-run| Runs the \texttt{install} target but does not copy % any files: simply lists those that would be installed % \item |--engine| (|-e|) Sets the engine to use for % testing % \item |--epoch| Sets the epoch for typesetting and testing % \item |--first| Name of the first test to run % \item |--force| (|-f|) Force checks to run even if sanity % checks fail, \emph{e.g.}~when |--engine| is not given in % \luavar{checkengines} % \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 |--pdf| (|-p|) Test PDF file against a reference % version rather than using a log comparison % \item |--quiet| (|-q|) Suppresses output from unpacking % \item |--rerun| Run tests without unpacking/set up % \item |--shuffle| Shuffle the order in whichs tests run % \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} % This range of possibilities allow sensible defaults but significant flexibility for defining your own test setups. % % Checking can be performed with any or all of the `engines' \texttt{pdftex}, \texttt{xetex}, and \texttt{luatex}. % By default, each test is executed with all three, being compared against the \texttt{.tlg} file produced from the \var{pdftex} engine (these defaults are controlled by the |checkengines| and |stdengine| variable respectively). % The format used for tests can be altered by setting \var{checkformat}: the default setting \texttt{latex} means that tests are run using \emph{e.g.}~\texttt{pdflatex}, whereas setting to \texttt{plain} will run tests using \emph{e.g.}~\texttt{pdftex}. % (Currently, this should be one of \texttt{latex} or \texttt{plain}.) % To perform the check, the engine typesets each test up to \var{checkruns} times. % More detail on this in the documentation on |save|. % Options passed to the binary are defined in the variable \var{checkopts}. % % By default, |texmf| trees are searched for input files when checking. This can be disabled by setting \var{checksearch} to |false|: isolation provides confidence that the tests cannot accidentally be running with incorrect files installed in the main distribution or |hometexmf|. % \end{buildcmd} % % % \begin{buildcmd}{check \meta{name(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 |-s| option. % \end{buildcmd} % % \begin{buildcmd}{check -p} % Rather than the log-based checking carried out by the standard % |check| target, running with the |-p| option carries out a binary % comparison of the PDF files produced by typesetting against those % saved in \var{testfiledir}. % % This functionality requires \TeX{} Live 2016 or later as it needs support % from the engines not available in earlier releases. % \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}. % % Files that should always be excluded from the archive are matched against the \var{excludefiles} variable; by default this is \luavar{excludefiles}, which match Emacs' autosave files. % % Binary files should be specified with the \var{binaryfiles} variable (default \luavar{binaryfiles}); these are added to the zip archive without normalising line endings (text files are automatically converted to Unix-style line endings). % % To create the archive, by default the binary \var{zipexe} is used (\luavar{zipexe}) with options \var{zipopts} (|-v -r -X|). The intermediate build directories \var{ctandir} and \var{tdsdir} are used to construct the archive. % \end{buildcmd} % % % \begin{buildcmd}{doc} % Compiles 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/local| directory (|localdir|) 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 % root name 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| swtich: % 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 normalisation process is performed when checking to avoid common differences such as register allocation; full details are listed in section~\ref{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}{save -p \meta{name(s)}} % This version of |save| will store the PDF files produced from % \texttt{\meta{name(s)}.lvt} in addition to the |.tlg| file, and thus allows % binary comparison of the result of typesetting. % % This functionality requires \TeX{} Live 2016 or later as it needs support % from the engines not available in earlier releases. % \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~\ref{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} % Modifies the content of files specified by |tagfiles| to allow % automatic updating of the release tag and date. The tag is given as a % command line option, whilst the optional date should be passed using % |--date| (|-d|); if not given, the date will default to the current date in % ISO format (YYYY-MM-DD). As detailed below, the standard set up has no search % pattern defined for this target and so no action will be taken \emph{unless} % tag substitution is set up. % \end{buildcmd} % % \begin{buildcmd}{unpack} % This is an internal target that is normally not needed on user level. % It unpacks all files into the directory defined by \var{unpackdir}. This occurs before other build commands such as |doc|, |check|, etc. % % The unpacking process is performed by executing the \var{unpackexe} (default \texttt{tex}) with options \var{unpackopts} on all files defined by the \var{unpackfiles} variable; by default, all files that match \luavar{unpackfiles}. % % If additional support files are required for the unpacking process, these can be enumerated in the \var{unpacksuppfiles} variable. % Dependencies for unpacking are defined with \var{unpackdeps}. % % By default this process allows files to be accessed in all standard |texmf| trees; this can be disabled by setting \var{unpacksearch} to |false|. % \end{buildcmd} % % \subsection{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} additionally custom code to change the build % process. A number of example scripts are given in Section~\ref{sec:examples}. % % \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 Figure~\ref{fig:breqn}. % Here, the |module| only is defined, and since it doesn't use |.ins| files so the variable \var{unpackfiles} is redefined to run |tex| on the |.dtx| files instead to generate the necessary |.sty| files. % There are some PDFs in the repository that shouldn't be part of a CTAN submission, so they're explicitly excluded, and here unpacking is done `quietly' to minimise console output when building the package. % % \begin{figure}[!b] % \begin{lstlisting}[frame=single,language={[5.2]Lua},gobble = 6] % -- Build configuration for breqn % % module = "breqn" % % unpackfiles = {"*.dtx"} % excludefiles = {"*/breqn-abbr-test.pdf", % "*/eqbreaks.pdf"} % unpackopts = "-interaction=batchmode" % \end{lstlisting} % \caption{The build configuration for the \pkg{breqn} package.} % \label{fig:breqn} % \end{figure} % % An example of a bundle build script for \pkg{l3packages} is shown in Figure~\ref{fig:bundle}. % Note for \LaTeX3 we use a common file to set all build variables in one place, and the path to the |l3build.lua| script is hard-coded so we always use our own most recent version of the script. % An example of an accompanying module build script is shown in Figure~\ref{fig:module}. % % \begin{figure}[p] % \begin{lstlisting}[frame=single,language={[5.2]Lua},gobble = 6] % -- Build script for LaTeX3 "l3packages" files % % -- Identify the bundle: there is no module as this is the "driver" % bundle = "l3packages" % % -- Location of main directory: use Unix-style path separators % maindir = ".." % \end{lstlisting} % \caption{The build script for the \pkg{l3packages} bundle.} % \label{fig:bundle} % \end{figure} % % \begin{figure}[p] % \begin{lstlisting}[frame=single,language={[5.2]Lua},gobble = 6] % -- Build script for LaTeX3 "xparse" files % % -- Identify the bundle and module: % bundle = "l3packages" % module = "xparse" % % -- Location of main directory: use Unix-style path separators % -- Should match that defined by the bundle. % maindir = "../.." % \end{lstlisting} % \caption{The build script for the \pkg{xparse} module.} % \label{fig:module} % \end{figure} % % \subsection{Backward compatibly} % % Earlier releases of \pkg{l3build} required that the last line of % \texttt{build.lua} ran the main script, \emph{i.e.}~ that \texttt{build.lua} % was what the user called rather than \texttt{l3build.lua}. To allow scripts % to support both forms \emph{for the transition}, a simple test may be % included as showing in Figure~\ref{fig:build-compat}. % \begin{figure} % \begin{lstlisting}[frame=single,language={[5.2]Lua},gobble = 6] % if not release_date then % dofile(kpse.lookup("l3build.lua")) % end % \end{lstlisting} % \caption{Final lines for a \texttt{build.lua} script usable with both older % and newer releases of \pkg{l3build}.} % \label{fig:build-compat} % \end{figure} % % Note that in time support for loading \pkg{l3build} by calling the % \texttt{build.lua} script \emph{may} be removed: the recommended approach for % new scripts is to run \pkg{l3build}. % % \subsection{Variables} % % This section lists all variables defined in the |l3build.lua| script that are available for customisation. % % \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. % % \luavartypeset % % \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 the short % |build-TU.lua| file shown in Figure~\ref{fig: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{figure} % \begin{lstlisting}[frame=single,language={[5.2]Lua},gobble = 6] % -- Special config for these tests % checksearch = true % checkengines = {"xetex","luatex"} % testfiledir = "testfiles-TU" % \end{lstlisting} % \caption{Example of using additional (or overriding) settings for configuring tests in a different subdirectory.} % \label{fig:configs} % \end{figure} % % To allow selection of a 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}. % % \subsection{Dependencies} % % If you have multiple packages that are developed separately but still interact in some way, it's often desirable to integrate them when performing regression tests. % For \LaTeX3, for example, when we make changes to \pkg{l3kernel} it's important to check that the tests for \pkg{l3packages} still run correctly, so it's necessary to include the \pkg{l3kernel} files in the build process for \pkg{l3packages}. % % In other words, \pkg{l3packages} is \emph{dependent} on \pkg{l3kernel}, and this is specified in \pkg{l3build} by setting appropriately the variables \texttt{checkdeps}, \texttt{typesetdeps}, and \texttt{unpackdeps}. % The relevant parts of the \LaTeX3 repository is structured as the following. % \Needspace{3\baselineskip} % \begin{Verbatim} % l3/ % l3kernel/ % build.lua % expl3.dtx % expl3.ins % ... % testfiles/ % l3packages/ % build.lua % xparse/ % build.lua % testfiles/ % xparse.dtx % xparse.ins % support/ % \end{Verbatim} % For \LaTeX3 build files, |maindir| is defined as top level folder |l3|, so all support files are located here, and the build directories will be created there. % To set \pkg{l3kernel} as a dependency of \pkg{l3package}, within |l3packages/xparse/build.lua| the equivalent of the following is set: % \begin{Verbatim} % maindir = "../.." % checkdeps = {maindir .. "/l3kernel"} % \end{Verbatim} % This ensures that the \pkg{l3kernel} code is included in all processes involved in unpacking and checking and so on. % The name of the script file in the dependency is set with the |scriptname| variable; by default these are |"build.lua"|. % % \subsection{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} and \var{docfiledir} % 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. % % A series of example layouts and matching |build.lua| files are available from % \url{https://github.com/latex3/l3build/tree/master/examples}. % % \subsection{Output normalisation} % \label{sec:norm} % % To allow test files to be used between different systems (\emph{e.g.}~when % multiple developers are involved in a project), the log files are normalised % before comparison during checking. This removes some system-dependent % data but also some variations due to different engines. This normalisation % consists of two parts: removing (\enquote{ignoring}) some lines and modifying % others to give consistent test. Currently, the following types of line are % ignored: % \begin{itemize} % \item Lines before the \cs{START}, after the \cs{END} and within % \cs{OMIT}/\cs{TIMO} blocks % \item Entirely blank lines, including those consisting only of spaces. % \item Lines containing file dates in format % \texttt{\meta{yyyy}/\meta{mm}/\meta{dd}}. % \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 Standardisation 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 Standardisation of \verb*|\csname\endcsname | to |\csname\endcsname| % (the former is formally correct, but the latter was produced for many % years due to a \TeX{} bug). % \item Conversion of \texttt{on line \meta{number}} to \texttt{on line ...} % to allow flexibility in changes to test files. % \item 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 Removal of some (u)p\TeX{} data where it is equivalent to % \pdfTeX{} (|yoko direction|, |\displace 0.0|) % \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 % normalisation is undertaken. On the other hand, for cross-engine comparison % the following normalisation is applied: % \begin{itemize} % \item Removal of additional (unused) |\discretionary| points. % \item Normalisation 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 % normalisation 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. % % \section{Writing test files} % \label{sec:writing-tests} % % Test files are written in a \TeX{} dialect using the support file |regression-test.tex|, which should be |\input| at the very beginning of each test. % Additional customisations to this driver can be included in a local |regression-test.cfg| file, which will be loaded automatically if found. % % The macros loaded by |regression-test.tex| set up the test system and provide a number of commands to aid the production of a structured test suite. % The basis of the test suite is to output material into the |.log| file, from which a normalised test output (|.tlg|) file is produced by the build command |save|. % A number of commands are provided for this; they are all written in uppercase to help avoid possible conflicts with other package commands. % % \subsection{Metadata and structural commands} % % Any commands that write content to the |.log| file that should be ignored can be surrounded by |\OMIT| \dots\ |\TIMO|. % At the appropriate location in the document where the |.log| comparisons should start (say, after |\begin{document}|), the test suite must contain the |\START| macro. % The test should then include \cs{AUTHOR}\marg{authors details} in case a test file fails in the future and needs to be re-analysed. % % Some additional diagnostic information can then be included as metadata for the conditions of the test. % The desired format can be indicated with \cs{FORMAT}\marg{format name}, and any packages or classes loaded can be indicated with % % \noindent\hspace*{2\parindent} \cs{CLASS}\oarg{options}\marg{class name, version}\par % \noindent\hspace*{2\parindent} \cs{PACKAGE}\oarg{options}\marg{package name, version} % % \noindent These do not provide information that is useful for automated checking; after all, packages change their version numbers frequently. % Rather, including this information in a test indicates the conditions under which the test was definitely known to pass at a certain time in the past. % % The |\END| command signals the end of the test (but read on). % Some additional diagnostic information is printed at this time to debug if the test did not complete `properly' in terms of mismatched brace groups or \cs{if}\dots\cs{fi} groups. % % In a \LaTeX{} document, |\end{document}| will implicitly call |\END| at the very end of the compilation process. % If |\END| is used directly (replacing |\end{document}| in the test), the compilation will halt almost immediately, and various tasks that |\end{document}| usually performs will not occur (such as potentially writing to the various |.toc| files, and so on). This can be an advantage if there is additional material printed to the log file in this stage that you wish to ignore, but it is a disadvantage if the test relies on various auxiliary data for a subsequent typesetting run. % (See the \var{checkruns} variable for how these tests would be test up.) % % \subsection{Commands to help write tests} % % A simple command \cs{CHECKCOMMAND}\cs{\meta{macro}} is provided to check whether a particular \cs{\meta{macro}} is defined, undefined, or equivalent to \cs{relax}. % This is useful to flag either that internal macros are remaining local to their definitions, or that defined commands definitely are defined, or even as a reminder that commands you intend to define in a future package need to be tested once they appear. % % \cs{TYPE} is used to write material to the \texttt{.log} file, like \LaTeX's \cs{typeout}, but it allows `long' input. % The following commands are defined to use \cs{TYPE} to output strings to the \texttt{.log} file. % \begin{itemize} % \item % \cs{SEPARATOR} inserts a long line of \texttt{=} symbols to break up the log output. % \item % \cs{NEWLINE} inserts a linebreak into the log file. % \item % \cs{TRUE}, \cs{FALSE}, \cs{YES}, \cs{NO} output those strings to the log file. % \item % \cs{ERROR} is \emph{not} defined but is commonly used to indicate a code path that should never be reached. % \item % The \cs{TEST}\marg{title}\marg{contents} command surrounds its \meta{contents} with some \cs{SEPARATOR}s and a \meta{title}. % \item % \cs{TESTEXP} surrounds its contents with \cs{TYPE} and formatting to match \cs{TEST}; this can be used as a shorthand to test expandable commands. % \item % TODO: would a \cs{TESTFEXP} command (based on \cs{romannumeral} expansion) be useful as well? % \item % \cs{BEGINTEST}\marg{title} \dots \cs{ENDTEST} is an environment form of % \cs{TEST}, allowing verbatim material, \emph{etc.} to appear. % \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~\ref{fig:box-log} (left side). % It is clear that if the definitions used to typeset the material in the box changes, the log output will differ and the test will no longer pass. % % The equivalent test in \LaTeXe{} using \pkg{expl3} is similar. % \begin{Verbatim}[frame=single,fontsize=\small] % \input{regression-test.tex} % \documentclass{article} % \usepackage{expl3} % \START % \ExplSyntaxOn % \box_new:N \l_tmp_box % \hbox_set:Nn \l_tmp_box {hello~ \emph{world}~ $a=b+c$} % \box_show:N \l_tmp_box % \ExplSyntaxOff % \END % \end{Verbatim} % The output from this test is shown in Figure~\ref{fig:box-log} (right side). % There is marginal difference (mostly related to font selection and different logging settings in \LaTeX) between the plain and \pkg{expl3} versions. % % When examples are not self-contained enough to be typeset into boxes, it is possible to ask \TeX{} to output the entire contents of a page. % Insert \cs{showoutput} for \LaTeX{} or set \cs{tracingoutput} positive for plain \TeX{}; ensure that the test ends with \cs{newpage} or equivalent because \TeX{} waits until the entire page is finished before outputting it. % % TODO: should we add something like \cs{TRACEPAGES} to be format-agnostic here? Should this perhaps even be active by default? % % \begin{figure} % \hspace*{-3cm} % \begin{BVerbatim}[fontsize=\small] % > \box0= % \hbox(6.94444+0.83333)x90.56589 % .\tenrm h % .\tenrm e % .\tenrm l % .\tenrm l % .\tenrm o % .\glue 3.33333 plus 1.66666 minus 1.11111 % .\tenit w % .\tenit o % .\tenit r % .\tenit l % .\tenit d % % .\glue 3.57774 plus 1.53333 minus 1.0222 % .\mathon % .\teni a % .\glue(\thickmuskip) 2.77771 plus 2.77771 % .\tenrm = % .\glue(\thickmuskip) 2.77771 plus 2.77771 % .\teni b % .\glue(\medmuskip) 2.22217 plus 1.11108 minus 2.22217 % .\tenrm + % .\glue(\medmuskip) 2.22217 plus 1.11108 minus 2.22217 % .\teni c % .\mathoff % % ! OK. % l.9 \showbox0 % % % \end{BVerbatim} % \qquad % \begin{BVerbatim}[fontsize=\small] % > \box71= % \hbox(6.94444+0.83333)x91.35481 % .\OT1/cmr/m/n/10 h % .\OT1/cmr/m/n/10 e % .\OT1/cmr/m/n/10 l % .\OT1/cmr/m/n/10 l % .\OT1/cmr/m/n/10 o % .\glue 3.33333 plus 1.66666 minus 1.11111 % .\OT1/cmr/m/it/10 w % .\OT1/cmr/m/it/10 o % .\OT1/cmr/m/it/10 r % .\OT1/cmr/m/it/10 l % .\OT1/cmr/m/it/10 d % .\kern 1.03334 % .\glue 3.33333 plus 1.66666 minus 1.11111 % .\mathon % .\OML/cmm/m/it/10 a % .\glue(\thickmuskip) 2.77771 plus 2.77771 % .\OT1/cmr/m/n/10 = % .\glue(\thickmuskip) 2.77771 plus 2.77771 % .\OML/cmm/m/it/10 b % .\glue(\medmuskip) 2.22217 plus 1.11108 minus 2.22217 % .\OT1/cmr/m/n/10 + % .\glue(\medmuskip) 2.22217 plus 1.11108 minus 2.22217 % .\OML/cmm/m/it/10 c % .\mathoff % % ! OK. % \l_tmp_box % % l.12 \box_show:N \l_tmp_box % \end{BVerbatim} % \caption{Output from displaying the contents of a simple box to the log file, using plain \TeX{} (left) and \pkg{expl3} (right). Some blank lines have been added to the plain \TeX{} version to help with the comparison.} % \label{fig:box-log} % \end{figure} % % \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{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 one argument, the name % of the current test (this is equivalent to \TeX{}'s \cs{jobname}, % \emph{i.e.}~it lacks an extension). The function |runtest_tasks| % is is into a call to the system to run the engine. As such, it % should take return a string with the appropriate command(s) % and option(s). 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~\ref{fig:test-tasks}. % \begin{figure} % \begin{lstlisting}[frame=single,language={[5.2]Lua},gobble = 6] % function runtest_tasks(name) % return "biber " .. name % end % \end{lstlisting} % \caption{Example \texttt{runtest_tasks} function.} % \label{fig:test-tasks} % \end{figure} % % \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 \luavar{epoch} variable may % be given as a raw value (a simple integer) or as a date in ISO format. % The two flags \luavar{forcecheckepoch} and \luavar{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. % % \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 \ref{fig:expect-dtx} exemplary tests % \TeX{}s counters. Listing \ref{fig:expect-ins} shows the relevant part of an % \texttt{.ins} file to generate it. % % \begin{figure} % \begin{lstlisting}[frame=single,language={TeX},gobble = 6] % \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{lstlisting} % \caption{Test and expectation can be specified side-by-side in a single % \texttt{.dtx} file.} % \label{fig:expect-dtx} % \end{figure} % %\begin{figure} % \begin{lstlisting}[frame=single,language={TeX},gobble = 6] % \generate{\file{\jobname.lvt}{\from{\jobname.dtx}{test}} % \file{\jobname.lve}{\from{\jobname.dtx}{expect}}} % \end{lstlisting} % \caption{Test and expectation are generated from a \texttt{.dtx} file of % the same name.} % \label{fig:expect-ins} % \end{figure} % % \section{Release-focussed features} % % \subsection{Automatic tagging} % % As detailed above, the |tag| target will automatically edit % source files to modify date and release tag. As standard, no automatic % replacement takes place, but setting up a |updae_tag()| function % will allow this to happen. This takes four arguments: % \begin{itemize} % \item The file name % \item The full content of the file % \item The tag name % \item The tag date % \end{itemize} % and should return the (modified) contents for writing to disk. % For example, the function used by |l3build| itself is % shown in Figure~\ref{fig:update-tag}. % \begin{figure} % \begin{lstlisting}[frame=single,language={[5.2]Lua},gobble = 6] % -- 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 contents % end % \end{lstlisting} % \caption{Example \texttt{update_tag} function.} % \label{fig:update-tag} % \end{figure} % % 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 during tagging (for example, % setting 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 \luavar{biberexe}, \luavar{bibtexexe} % and \luavar{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 % customisation. 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, Figure~\ref{fig: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_hook()| 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). % % \begin{figure}[!b] % \begin{lstlisting}[frame=single,language={[5.2]Lua},gobble = 6] % #!/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{lstlisting} % \caption{A customised PDF creation script.} % \label{fig:PDF} % \end{figure} % % % \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{date} & String \\ % \var{engine} & Table \\ % \var{force} & Boolean \\ % \var{halt} & Boolean \\ % \var{help} & Boolean \\ % \var{names} & Table \\ % \var{pdf} & Boolean \\ % \var{quiet} & Boolean \\ % \var{rerun} & Boolean \\ % \var{testfiledir} & Table \\ % \var{version} & 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; 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}{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} % A command to generate a series of $200$ lines each containing the % character |y|: this is useful as the Unix |yes| command cannot be % used inside |os.execute| (it does not terminate). % \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} % % \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 (\S\ref{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 (\S\ref{sec:manifest-sorting}), % the inclusion of one-line descriptions for each file (\S\ref{sec:manifest-desc}), % and the details of the formatting of each entry (\S\ref{sec:manifest-formatting}). % % To perform such customisations, 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 Table~\ref{tab:manifest-setup} and Table~\ref{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} % \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. % % % \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{}. % \begin{macrocode} \begingroup\expandafter\expandafter\expandafter\endgroup \expandafter\ifx\csname eTeXversion\endcsname\relax \errmessage{e-TeX is required to use regression-test.tex}% \expandafter\endinput \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} \ifnum\interactionmode>1 \scrollmode\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 } \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} % % 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 % } % 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{% ============================================================% }% } \protected\long\def\BEGINTEST#1{% \global\advance\gTESTint by 1 % \SEPARATOR \LONGTYPEOUT{TEST \the\gTESTint: \detokenize{#1}}% \SEPARATOR \begingroup \let\TYPE\LONGTYPEOUT } \protected\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}} % \end{macrocode} % \end{macro} % % \subsection{Suppressing variable data in output} % % 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). We are % somewhat stuck if \texttt{dvips} is being used so just hope for the best! % 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. % \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 \pdfinfo{/Producer (\ifx\directlua\@undefined pdf\else Lua\fi TeX)} \ifx\pdfinfoomitdate\@undefined\else \pdfinfoomitdate = 1 % \pdfsuppressptexinfo = 1 % \pdftrailerid{} \fi \else \pdfextension info{/Producer (LuaTeX)} \pdfvariable suppressoptionalinfo \numexpr 0 + 1 % PTEX.Fullbanner + 32 % CreationDate + 64 % ModDate \relax \fi \else \special{% pdf: docinfo << /Creator (TeX) /CreationDate () /ModDate () /Producer (\ifx\XeTeXversion\@undefined\else x\fi dvipdfmx) >> } \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