Skip to content

Commit

Permalink
Merge pull request ProdriveTechnologies#84 from solsjo/organize_tool_…
Browse files Browse the repository at this point in the history
…wrapper

Refactor run_latex.py
  • Loading branch information
Kernald authored Aug 30, 2022
2 parents 87bc3c1 + 5c6b172 commit 73852bd
Show file tree
Hide file tree
Showing 7 changed files with 193 additions and 119 deletions.
2 changes: 1 addition & 1 deletion .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ container:
image: l.gcr.io/google/bazel:latest
task:
name: Build the example document
build_script: bazel build //example:my_report
build_script: bazel build //example:all
task:
name: Build all package tests
build_script: bazel build //packages:all
9 changes: 5 additions & 4 deletions BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
load(":toolchain.bzl", "latex_toolchain")

exports_files([
"run_lualatex.py",
"tool_wrapper.py",
"view_pdf.sh",
])

Expand Down Expand Up @@ -37,7 +37,7 @@ latex_toolchain(
filegroup(
name = "core_dependencies",
srcs = [
"@bazel_latex//:run_lualatex.py",
"@bazel_latex//:tool_wrapper_py",
"@texlive_extra__tlpkg__TeXLive",
"@texlive_texmf__texmf-dist__fonts__enc__dvips__base",
"@texlive_texmf__texmf-dist__fonts__enc__dvips__cm-super",
Expand Down Expand Up @@ -66,7 +66,8 @@ filegroup(
)

py_binary(
name = "run_lualatex",
srcs = ["run_lualatex.py"],
name = "tool_wrapper_py",
srcs = ["tool_wrapper.py"],
main = "tool_wrapper.py",
visibility = ["//visibility:public"],
)
1 change: 1 addition & 0 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ register_toolchains(
load("@bazel_latex//:repositories.bzl", "latex_repositories")

latex_repositories()

14 changes: 14 additions & 0 deletions example/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,17 @@ latex_document(
cmd_flags = ["--bibtex-cmd=biber"],
main = "my_report.tex",
)

latex_document(
name = "my_dvi_report",
format = "dvi",
srcs = glob([
"chapters/*.tex",
]) + [
"@bazel_latex//packages:biblatex",
"references.bib",
"//example/example_class:example_class",
],
cmd_flags = ["--bibtex-cmd=biber"],
main = "my_report.tex",
)
98 changes: 61 additions & 37 deletions latex.bzl
Original file line number Diff line number Diff line change
@@ -1,26 +1,38 @@
def _latex_pdf_impl(ctx):
LatexOutputInfo = provider(fields = ['format', 'file'])

def _latex_impl(ctx):
toolchain = ctx.toolchains["@bazel_latex//:latex_toolchain_type"].latexinfo
custom_dependencies = []
for srcs in ctx.attr.srcs:
for file in srcs.files.to_list():
if file.dirname not in custom_dependencies:
custom_dependencies.append(file.dirname)
custom_dependencies = ','.join(custom_dependencies)

flags = ["--flag=--latex-args=--output-format={}".format(ctx.attr.format)]
for value in ctx.attr.cmd_flags:
if "output-format" in value and ctx.attr.format not in value:
fail("Value of attr format ({}) conflicts with value of flag {}".format(ctx.attr.format, value))
flags.append("--flag=" + value)

ctx.actions.run(
mnemonic = "LuaLatex",
use_default_shell_env = True,
executable = ctx.executable.tool,
executable = ctx.executable._tool,
arguments = [
toolchain.kpsewhich.files.to_list()[0].path,
toolchain.luatex.files.to_list()[0].path,
toolchain.bibtex.files.to_list()[0].path,
toolchain.biber.files.to_list()[0].path,
ctx.files._latexrun[0].path,
ctx.label.name,
ctx.files.main[0].path,
ctx.outputs.out.path,
custom_dependencies,
] + ctx.attr.cmd_flags,
"--dep-tool=" + toolchain.kpsewhich.files.to_list()[0].path,
"--dep-tool=" + toolchain.luatex.files.to_list()[0].path,
"--dep-tool=" + toolchain.bibtex.files.to_list()[0].path,
"--dep-tool=" + toolchain.biber.files.to_list()[0].path,
"--tool=" + ctx.files._latexrun[0].path,
"--flag=--latex-cmd=lualatex",
"--flag=--latex-args=-shell-escape -jobname=" + ctx.label.name,
"--flag=-Wall",
"--input=" + ctx.file.main.path,
"--tool-output=" + ctx.file.main.basename.rsplit(".", 1)[0] + ".{}".format(ctx.attr.format),
"--output=" + ctx.outputs.out.path,
"--inputs=" + custom_dependencies,
] + flags,
inputs = depset(
direct = ctx.files.main + ctx.files.srcs + ctx.files._latexrun,
transitive = [
Expand All @@ -31,19 +43,29 @@ def _latex_pdf_impl(ctx):
],
),
outputs = [ctx.outputs.out],
tools = [ctx.executable.tool],
tools = [ctx.executable._tool],
)
latex_info = LatexOutputInfo(file = ctx.outputs.out, format=ctx.attr.format)
return [latex_info]

_latex_pdf = rule(
_latex = rule(
attrs = {
"main": attr.label(allow_files = True),
"main": attr.label(
allow_single_file = [".tex"],
mandatory = True,
),
"srcs": attr.label_list(allow_files = True),
"cmd_flags": attr.string_list(
allow_empty = True,
default = [],
),
"tool": attr.label(
default = Label("//:run_lualatex"),
"format": attr.string(
doc = "Output file format",
default = "pdf",
values = ["dvi", "pdf"],
),
"_tool": attr.label(
default = Label("@bazel_latex//:tool_wrapper_py"),
executable = True,
cfg = "host",
),
Expand All @@ -52,34 +74,36 @@ _latex_pdf = rule(
default = "@bazel_latex_latexrun//:latexrun",
),
},
outputs = {"out": "%{name}.pdf"},
outputs = {"out": "%{name}.%{format}"},
toolchains = ["@bazel_latex//:latex_toolchain_type"],
implementation = _latex_pdf_impl,
implementation = _latex_impl,
)

def latex_document(name, main, srcs = [], tags = [], cmd_flags = []):
# PDF generation.
_latex_pdf(
def latex_document(name, main, srcs = [], tags = [], cmd_flags = [], format="pdf"):

_latex(
name = name,
srcs = srcs + ["@bazel_latex//:core_dependencies"],
main = main,
tags = tags,
cmd_flags = cmd_flags,
format = format,
)

# Convenience rule for viewing PDFs.
native.sh_binary(
name = name + "_view_output",
srcs = ["@bazel_latex//:view_pdf.sh"],
data = [name + ".pdf"],
tags = tags,
)
if "pdf" in format:
# Convenience rule for viewing PDFs.
native.sh_binary(
name = "{}_view_output".format(name),
srcs = ["@bazel_latex//:view_pdf.sh"],
data = [":{}".format(name)],
tags = tags,
)

# Convenience rule for viewing PDFs.
native.sh_binary(
name = name + "_view",
srcs = ["@bazel_latex//:view_pdf.sh"],
data = [name + ".pdf"],
args = ["None"],
tags = tags,
)
# Convenience rule for viewing PDFs.
native.sh_binary(
name = "{}_view".format(name),
srcs = ["@bazel_latex//:view_pdf.sh"],
data = [":{}".format(name)],
args = ["None"],
tags = tags,
)
77 changes: 0 additions & 77 deletions run_lualatex.py

This file was deleted.

111 changes: 111 additions & 0 deletions tool_wrapper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#!/usr/bin/env python

import argparse
import glob
import os
import shutil
import subprocess
import sys

from pathlib import Path


def setup_dependencies():
# Walk through all externals. If they start with the special prefix
# texlive_{extra,texmf}__ prefix, it means they should be part of the
# texmf directory. LaTeX utilities don't seem to like the use of
# symlinks, so move the externals into the texmf directory.
#
# Externals that do not start with the special prefix should be added to
# TEXINPUTS, so that inclusions of external resources works.
texinputs = [""] + glob.glob("bazel-out/*/bin")
for external in sorted(os.listdir("external")):
src = os.path.abspath(os.path.join("external", external))
if external.startswith("texlive_extra__") or external.startswith(
"texlive_texmf__"):
dst = os.path.join("texmf", "/".join(external.split("__")[1:]))
try:
os.makedirs(os.path.dirname(dst))
except OSError:
pass
os.rename(src, dst)
else:
texinputs.append(src)
return texinputs


def setup_env(env, texinputs, tools):
env["OPENTYPEFONTS"] = ":".join(texinputs)
env["PATH"] = "%s:%s" % (os.path.abspath("bin"), env["PATH"])
env["SOURCE_DATE_EPOCH"] = "0"
env["TEXINPUTS"] = ":".join(texinputs)
env["TEXMF"] = os.path.abspath("texmf/texmf-dist")
env["TEXMFCNF"] = os.path.abspath("texmf/texmf-dist/web2c")
env["TEXMFROOT"] = os.path.abspath("texmf")
env["TTFONTS"] = ":".join(texinputs)

os.mkdir("bin")
for tool in tools:
if "luatex" in tool:
shutil.copy(tool, "bin/lualatex")
os.link("bin/lualatex", "bin/luatex")
else:
shutil.copy(tool, "bin/" + os.path.basename(tool))

shutil.copy("texmf/texmf-dist/scripts/texlive/fmtutil.pl", "bin/mktexfmt")
return env


def setup_argparse():
parser = argparse.ArgumentParser()
parser.add_argument('--dep-tool', default=[], action='append')
parser.add_argument('--tool')
parser.add_argument('--env', default=[], action='append')
parser.add_argument('--input')
parser.add_argument('--inputs')
parser.add_argument('--tool-output')
parser.add_argument('--output')
parser.add_argument('--flag', default=[], action='append')
return parser


def main():
parser = setup_argparse()
args = parser.parse_args()

tools = args.dep_tool + [args.tool]

env = dict(os.environ)
for en in args.env:
key, value = en.split(":")
value = os.path.abspath(value)
env[key] = value
texinputs = setup_dependencies()
# Add custom dependencies to TEXINPUTS
dependency_list = args.inputs.split(',')
texinputs.extend([os.path.abspath(path) for path in dependency_list])
env = setup_env(env, texinputs, tools)
cmd_args = [
os.path.basename(args.tool),
] + args.flag + [args.input]

result = subprocess.check_output(
args=cmd_args,
env=env,
stderr=subprocess.STDOUT,
)

if not os.path.exists(args.tool_output):
raise SystemExit(
"""{} exited with: {}
The following arguments were provided:
{}
content in dir:
{}""".format(args.tool, result, cmd_args, os.listdir("."))
)

os.rename(args.tool_output, args.output)


if __name__ == "__main__":
main()

0 comments on commit 73852bd

Please sign in to comment.