Recently, I found that there was some interest in latex rules for bazel. Moreover, I found increased hits on my old blog entry on timestamps with pdflatex, possibly because it is referenced from Ed's latex rules. So I decided, that there should be a more accessible place for my latex rules that an old mail thread.
So, here's an archive of (only) the relevant parts of my personal bazel repository containing my bazel latex rules. There are a few things to keep in mind in comparison to Ed's rules.
As thinking about latex rules for bazel step by step leads through all features of bazel's rule system, I used them as an example on how to extend bazel in my FrOSCon 2017 talk. The video recording is still online, and the relevant part starts at 0:16:45. The slides are also available online.
Let's have a look on how to use these rules.
The most simple, but still most typical, use case is to define a filegroup for each reusable part and combine them to a larger document by including the entry points and declaring the file groups as sources (for a latex document) or dependencies (for another filegroup forming a larger reusable part).
So, assume you have the following main.tex.
\documentclass{beamer} \begin{document} \input{example/slides_triangle} \input{example/slides_square} \end{document}
load("//aehlig_rules/latex:latex.bzl", "latex") filegroup( name = "slides_triangle", srcs = [ "slides_triangle.tex", "triangle.eps", ], ) filegroup( name = "slides_square", srcs = [ "slides_square.tex", "square.eps", ], ) latex( name = "example", main = "main.tex", srcs = [ ":slides_triangle", ":slides_square", ], )
I often need several variants of the same latex document, e.g., a full mathematical script, as well as an outline (say, without proofs). To avoid duplication, those should come from the same sources; the only thing I need is to include a single short file to switch between the variants. So there is a single exception to the rule that each file is included by its canonical path: the file specified by the optional flavor argument will always be visible at the location flavor.tex in the working directory of the latex invocation (i.e., no module path needed). In this way, I can conveniently define my variants by a BUILD file like the following.
load("//aehlig_rules/latex:latex.bzl", "latex") [ latex( name="main_%s" % (flavor,), main="main.tex", flavor = "%s.tex" % (flavor,) ) for flavor in ["full", "outline"]]
\documentclass{article} \usepackage{amsthm} \input{flavor} \newtheorem{theorem}{Theorem} \begin{document} \begin{theorem} $(a+b)^2=a^2 + 2ab + b^2$ \end{theorem} \begin{proof} $(a+b)^2=(a+b)(a+b)=a(a+b)+b(a+b)= a^2+ab+ba+b^2=a^2+ab+ab+b^2=a^2+2ab+b^2$ \end{proof} \end{document}
\renewenvironment{proof}% {\bgroup\setbox0=\vbox\bgroup}% {\egroup\egroup}
Another typical siutation when writing larger latex documents is that each part brings in its own contribution to the part of the document before the \begin{document}. Packages have to be included, macros for all the notations used have to be defined (so that I have a single place to change my notation, and in this way don't get inconsistencies in my document, if I chose to change my notation), etc.
Collecting all those with nested file groups is a great way to get the right collection of files to be included in preamble—due to the set-like semantics already in deduplicated form. To include all the files of that file group, I use the latex_include rule. It generates a .tex file with one \input for each member of the file group (in iteration order). Additionally, it passes via the appropriate provider, that every latex target using this file also, implicitly, has the whole file group as input.
So, in my main.tex I simply have one \input{path/to/module/preamble} just after the \begin{document} and use a BUILD file like the following.
load("//aehlig_rules/latex:latex.bzl", "latex", "latex_include") filegroup( name = "local_preamble", srcs = [ "//latex/shared:use_amssymb.tex", "notation.tex", # ... ], ) latex_include( name = "preamble", srcs = [ ":local_preamble", # likely also file groups from dependencies ], ) latex( name = "main", main = "main.tex", srcs = [ ":preamble", # other dependencies ], )
It is often useful to include files verbatim in a document, e.g., console "screen shots" generated via script(1). If that interaction is sufficiently reproducible, that often is itself a generated artifact. To conveniently include those files, the rules come with a macro latex_verbatim that generates a new .tex file from the source file by prepending it with \begin{verbatim} and appending \end{verbatim} at the end. Yes, this is technically unsound as it assumes that the string \end{verbatim} does not occur in the file to be quoted. But in practce, that simple macro just works too well.
While technically not a latex problem, something I frequently have to do when generating slides with latex is to have diagrams developped step by step. Of course, I want to maintain the whole diagram with all its stages in a single file, in my case a postscript file. Also, while the diagram can be reused, the stages of the development I want to include in a presentation are differnt at different occasions.
So, my approach is to have a file, that is parametric in the variable stage defined at the beginning of the document; for debugging positioning problems it is also useful to optionally draw the bounding box.
%! %%BoundingBox: -1 -1 101 151 gsave /stage { 9 } bind def /drawbb { true } bind def drawbb { gsave 5 setlinewidth newpath 0 0 moveto 100 0 rlineto 0 150 rlineto -100 0 rlineto closepath stroke grestore } if newpath 0 0 moveto stage 1 ge { 0 100 rlineto } if stage 2 ge { 50 50 rlineto } if stage 3 ge { 50 -50 rlineto } if stage 4 ge { -100 0 rlineto } if stage 5 ge { 100 -100 rlineto } if stage 6 ge { 0 100 rlineto } if stage 7 ge { -100 -100 rlineto } if stage 8 ge { 100 0 rlineto } if stroke grestore
load("//aehlig_rules/latex:latex.bzl", "latex") load("//aehlig_rules/ps:psfamily.bzl", "ps_family") ps_family( name = "drawing", src = "drawing.eps", stages = [0, 1, 2, 3, 4, 5, 6, 7, 8], ) latex( name = "main", main = "main.tex", srcs = [ ":drawing" ], )
\documentclass{beamer} \begin{document} \begin{frame}{A drawing} This is how you draw that image as one line. \only<1>{\includegraphics[height=0.7\textheight]{ps_example/drawing_0}}% \only<2>{\includegraphics[height=0.7\textheight]{ps_example/drawing_1}}% \only<3>{\includegraphics[height=0.7\textheight]{ps_example/drawing_2}}% \only<4>{\includegraphics[height=0.7\textheight]{ps_example/drawing_3}}% \only<5>{\includegraphics[height=0.7\textheight]{ps_example/drawing_4}}% \only<6>{\includegraphics[height=0.7\textheight]{ps_example/drawing_5}}% \only<7>{\includegraphics[height=0.7\textheight]{ps_example/drawing_6}}% \only<8>{\includegraphics[height=0.7\textheight]{ps_example/drawing_7}}% \only<9>{\includegraphics[height=0.7\textheight]{ps_example/drawing_8}}% \end{frame} \end{document}