LuaLaTeX:在 CI 上自动对目录、索引、参考书目、词汇表等进行多次编译

LuaLaTeX:在 CI 上自动对目录、索引、参考书目、词汇表等进行多次编译

为了在远程 CI 系统上获得可重现且可靠的文档构建,我希望自动化生成完整文档所需的所有命令行工具和多个编译。无论文档​​中实际使用了哪些插件,此管道都应该可以立即用于任何文档。

据我了解,有一种方法可以让 LaTeX 构建自动执行所有必要的步骤,但到目前为止,我还没有成功使用任何方法。

细节

我当前的设置是这样的:

  • 文档是在我的计算机上使用 LuaLaTeX 和 MiKTeX 编写和编译的
  • CI 由 MiKTeX Docker 镜像组成(看这里)已安装所有自定义字体和资源

在本地,我必须按顺序执行各种操作来编译文档,而作为文档的作者,我必须知道这些操作。但 CI 应该能够构建任何文档,而无需应用特殊的每个文档设置,并且在文档无法正确编译或缺少某些内容时产生错误。

例如:词汇表

当我需要构建一个使用该glossaries包的文档时,本地构建将如下所示

lualatex doc.tex
makeglossaries doc
lualatex doc.tex

现在 CI 不知道文档是否需要此步骤,但仍应能够构建文档。在词汇表文档中提到了参数automake--shell-escape编译文档的选项,我以为这会允许我一次编译所有内容,但这在 CI 上不起作用。同样,我在目录、索引、参考书目等方面也遇到了同样的问题。

概括

有没有一种通用的方法可以自动化不同软件包的复杂编译?(内置于 LuaLaTeX 或一些自定义的通用脚本)

我的设置是否存在问题,导致所有步骤无法自动进行?

我查阅了大量特定软件包或 LaTeX 的资源,但还是找不到有用的。非常感谢您的帮助。

答案1

正如其他人和你自己提到的,latexmk似乎是这项工作的正确工具。为了了解如何实现它,让我从我自己的 LaTeX 文档/模板 CI 管道(在 GitLab 上)中突出显示相关部分。这应该是“针对不同包的复杂编译”的一个可用示例。我将介绍随附的DockerfileGitLab CI 配置除了 LaTeX 特定的/部分之外latexmk,因为所有部分都紧密耦合。

下面详细介绍的所有内容都已实现并且(希望......)有效在这个项目中。我试图让这个答案尽可能独立。项目链接将包含最新状态,最终将取代这个答案。


LaTeX 和分发(Debian)包

在链接的管道中,有几个包需要在设置中特别注意。您不太可能有完全相同的要求,但为了完整性,我在这里列出它们。

  1. glossaries-extra,建立在之上glossaries,需要bib2gls转换并处理要使用的*.bib文件。lualatex

    这在设置中体现为双重:

    1. Docker 镜像需要 Java 运行时环境bib2gls
    2. latexmk需要被告知bib2gls文件的存在。
  2. pgfplotscontour选项为\addplot3例子)需要外部gnuplot计划。同样,这体现在两个方面:

    1. lualatex(或者您选择的引擎)需要外部写访问权限才能gnuplot将其计算结果写入文件以供pgfplots读取:--shell-escape需要,必须latexmk告知。
    2. gnuplot,因为分发包(而不是 LaTeX 包)必须存在,例如apt-get install gnuplot在 Debian 主机上。
  3. LaTeX 本身无法嵌入*.svg文件。嵌入此类文件需要先转换为 PDF(或其他可嵌入格式)。这可以使用Inkscape和它的*.pdf_tex常规。但是,这导致每个 SVG 文件有两个额外的文件:*.pdf*.pdf_tex。SVG 文件中的每次更改都必须更新派生文件。这会导致潜在的冲突,在版本控制(git等)的背景下也是如此:要保留哪些版本?

    svgLaTeX 软件包通过自动化转换过程解决了这些问题。生成的*.pdf*.pdf_tex文件可以作为临时/派生文件处理并自由丢弃。只有 SVG 保留下来,作为单一事实来源. 作为奖励,基于文本 (XML),它们也适用于 VCS git(二进制 PDF 实际上不适合)。

    与以前一样,这在下面的两个地方的设置中反映出来:

    1. 为了调用 CLI inkscape(而不是 GUI;要使其工作,inkscape必须在您的 上$PATH)进行读写,LaTeX 引擎需要--shell-escape
    2. inkscape需要在构建环境(Docker 镜像)中可用。
  4. 使用tcolorbox及其\newtcolorbox命令,我创建了一个新的环境例子

    \newtcolorbox[%
      auto counter,%
      number within=chapter,%
      % Set cleveref, see https://tex.stackexchange.com/a/126023/120853:
      crefname={Example}{Examples},
      % List of Examples. *.loe file ending could clash with package thmtools,
      % careful if that is used!
      list inside=loe,
    ]{example}% Name of environment itself
        [2]% Number of arguments for the environment
        []% Default of optional argument, which is the first one. Use it for label
        {%
            beforeafter skip=18pt plus 4pt minus 4pt,%
            width=0.95\linewidth,%
            % Center box; see https://tex.stackexchange.com/a/273111/120853:
            enlarge left by=0.025\linewidth,
            title=Example\ \thetcbcounter: #2,%
            fonttitle=\sffamily,%
            leftrule=1mm,%
            arc is angular,%
            parbox,% Allows regular paragraph breaks
            breakable,% Breaks across pages
            enhanced,% Hands drawing to tikz
            rightrule=0mm,%
            bottomrule=0mm,%
            % Setting what ends up in 'list of' so that '<Title>' is not shown:
            list text=#2,
            #1,%
            colback=black!05,%
            colframe=black!70,%
            % float,
        }%
    

    这看起来像:

    tcolorbox 示例框

    这是相关的,因为它与komascript使用list inside=loe指令,使我们能够获取并打印示例列表,就像标准图片列表

    % Declare a new list of contents, with the file suffix in brackets.
    % This will give access to \listof<name>s
    \DeclareNewTOC[%
        type=example,% This also creates types=example+s, that is by appending an s
        % Listname is "List of <Type>s" by default
        % listname={...},
    ]{loe}
    

    最后,latexmk需要告知这个新创建的*.loe文件。这很重要,因为latexmk它通过检查辅助文件的变化来衡量编译进度和完成情况。

  5. 与上一点类似,使用listings包将允许我们打印列表列表从生成的*.lol文件中获取。和以前一样,latexmk会想了解它。

最后,生成以下.latexmkrc文件:

# Contents of .latexmkrc

# PERL latexmk config file

# PDF-generating modes are:
# 1: pdflatex, as specified by $pdflatex variable (still largely in use)
# 2: postscript conversion, as specified by the $ps2pdf variable (useless)
# 3: dvi conversion, as specified by the $dvipdf variable (useless)
# 4: lualatex, as specified by the $lualatex variable (best)
# 5: xelatex, as specified by the $xelatex variable (second best)
$pdf_mode = 4;

# --shell-escape option (execution of code outside of latex) is required for the
#'svg' package.
# It converts raw SVG files to the PDF+PDF_TEX combo using InkScape.
$lualatex = "lualatex --shell-escape";

# option 2 is same as 1 (run biber when necessary), but also deletes the
# regeneratable bbl-file in a clenaup (`latexmk -c`). Do not use if original
# bib file is not available!
$bibtex_use = 2;  # default: 1

# Let latexmk know about generated files, so they can be used to detect if a
# rerun is required, or be deleted in a cleanup.
# loe: List of Examples (KOMAScript)
# lol: List of Listings (listings package)
push @generated_exts, 'loe', 'lol';

# Also delete the *.glstex files from package glossaries-extra. Problem is,
# that that package generates files of the form "basename-digit.glstex" if
# multiple glossaries are present. Latexmk looks for "basename.glstex" and so
# does not find those. For that purpose, use wildcard.
# Also delete files generated by gnuplot/pgfplots contour plots
# (.dat, .script, .table),
# and XML file generated by biber runs.
$clean_ext = "%R-*.glstex %R_contourtmp*.* %R.run.xml";

# Grabbed from latexmk CTAN distribution:
# Implementing glossary with bib2gls and glossaries-extra, with the
# log file (.glg) analyzed to get dependence on a .bib file.
# !!! ONLY WORKS WITH VERSION 4.54 or higher of latexmk

# Push new file endings into list holding those files
# that are kept and later used again (like idx, bbl, ...):
push @generated_exts, 'glstex', 'glg';

# Add custom dependency.
# latexmk checks whether a file with ending as given in the 2nd
# argument exists ('toextension'). If yes, check if file with
# ending as in first argument ('fromextension') exists. If yes,
# run subroutine as given in fourth argument.
# Third argument is whether file MUST exist. If 0, no action taken.
add_cus_dep('aux', 'glstex', 0, 'run_bib2gls');

# PERL subroutine. $_[0] is the argument (filename in this case).
# File from author from here: https://tex.stackexchange.com/a/401979/120853
sub run_bib2gls {
    if ( $silent ) {
    #    my $ret = system "bib2gls --silent --group '$_[0]'"; # Original version
        my $ret = system "bib2gls --silent --group $_[0]"; # Runs in PowerShell
    } else {
    #    my $ret = system "bib2gls --group '$_[0]'"; # Original version
        my $ret = system "bib2gls --group $_[0]"; # Runs in PowerShell
    };

    my ($base, $path) = fileparse( $_[0] );
    if ($path && -e "$base.glstex") {
        rename "$base.glstex", "$path$base.glstex";
    }

    # Analyze log file.
    local *LOG;
    $LOG = "$_[0].glg";
    if (!$ret && -e $LOG) {
        open LOG, "<$LOG";
    while (<LOG>) {
            if (/^Reading (.*\.bib)\s$/) {
        rdb_ensure_file( $rule, $1 );
        }
    }
    close LOG;
    }
    return $ret;
}

latexmk将选取此文件并自动从中提取配置,如果它被命名为.latexmkrc。因此,如果该文件存在于 中,则无需明确指定其位置pwd

构建环境(Docker 镜像)

最容易获得所需的 Docker 映像的方式是使用debian基础映像并进行安装texlive-full(以及上述任何所需软件包,或您需要的任何软件包)。这可以像下面这样简单Dockerfile

FROM debian:testing

RUN apt-get update --yes \
    && apt-get install --yes --no-install-recommends \
        texlive-full

为了我自己的需要,我准备了更加复杂的 Dockerfile(由于字数限制,评论被删除):

ARG BASE_OS
ARG OS_VERSION

FROM ${BASE_OS}:${OS_VERSION} as BASE

RUN apt-get update && \
    apt-get install --yes --no-install-recommends \
        wget \
        ca-certificates \
        perl


FROM BASE as PREPARE

ARG TL_VERSION
ARG TL_INSTALL_ARCHIVE="install-tl-unx.tar.gz"
ARG EISVOGEL_ARCHIVE="Eisvogel.tar.gz"
ARG INSTALL_TL_DIR="install-tl"

COPY texlive.sh .

RUN \
    ./texlive.sh get ${TL_VERSION} && \
    wget https://github.com/Wandmalfarbe/pandoc-latex-template/releases/latest/download/${EISVOGEL_ARCHIVE}

RUN \
    mkdir ${INSTALL_TL_DIR} && \
    tar --extract --file=${TL_INSTALL_ARCHIVE} --directory=${INSTALL_TL_DIR} --strip-components 1 && \
    \
    tar --extract --file=${EISVOGEL_ARCHIVE}


FROM BASE as MAIN

ARG BUILD_DATE="n/a"
ARG VCS_REF="n/a"

ARG TL_VERSION
ARG TL_PROFILE="texlive.profile"

LABEL \
    maintainer="Alex Povel <[email protected]>" \
    org.label-schema.build-date=${BUILD_DATE} \
    org.label-schema.description="TeXLive with most packages, JavaRE, Inkscape, pandoc and more" \
    org.label-schema.url="https://collaborating.tuhh.de/alex/latex-git-cookbook" \
    org.label-schema.vcs-url="https://github.com/alexpovel/latex-extras-docker" \
    org.label-schema.vcs-ref=${VCS_REF} \
    org.label-schema.schema-version="1.0"

ARG INSTALL_DIR="/install/"
WORKDIR ${INSTALL_DIR}

COPY ${TL_PROFILE} .
COPY --from=PREPARE /install-tl/ /texlive.sh ./

COPY --from=PREPARE /eisvogel.tex /usr/share/pandoc/data/templates/eisvogel.latex

ARG TEXLIVE_INSTALL_PREFIX="/usr/local/texlive"
ARG TEXLIVE_INSTALL_TEXDIR="${TEXLIVE_INSTALL_PREFIX}/${TL_VERSION}"
ARG TEXLIVE_INSTALL_TEXMFCONFIG="~/.texlive${TL_VERSION}/texmf-config"
ARG TEXLIVE_INSTALL_TEXMFVAR="~/.texlive${TL_VERSION}/texmf-var"
ARG TEXLIVE_INSTALL_TEXMFHOME="~/texmf"
ARG TEXLIVE_INSTALL_TEXMFLOCAL="${TEXLIVE_INSTALL_PREFIX}/texmf-local"
ARG TEXLIVE_INSTALL_TEXMFSYSCONFIG="${TEXLIVE_INSTALL_TEXDIR}/texmf-config"
ARG TEXLIVE_INSTALL_TEXMFSYSVAR="${TEXLIVE_INSTALL_TEXDIR}/texmf-var"

RUN ./texlive.sh install ${TL_VERSION}

RUN luaotfload-tool --update || echo "luaotfload-tool not found, skipping."

RUN apt-get update && \
    apt-get install --yes --no-install-recommends \
    default-jre-headless \
    inkscape \
    gnuplot-nox \
    ghostscript

RUN apt-get update && \
    apt-get install --yes --no-install-recommends \
    librsvg2-bin \
    pandoc

WORKDIR /tex/

RUN rm --recursive ${INSTALL_DIR}

CMD [ "--lualatex" ]

ENTRYPOINT [ "latexmk" ]

它允许用户指定要构建的 TeXLive(从其档案中提取)和 Debian 版本。为此,它需要以下texlive.sh脚本。它在latest(Docker)标签和一些历史版本(例如 Debian 9、TeXLive 2018)之间进行选择,在这种情况下,它会从TUG 档案

#!/bin/bash

# Script to fetch `install-tl` script from different sources, depending on argument
# given.

# Error out of any of the variables used here are unbound, e.g. no CLI arg given.
set -u

usage() {
    echo "Usage: $0 get|install latest|version (YYYY)"
}

if [[ $# != 2 ]]; then
    echoerr "Unsuitable number of arguments given."
    usage
    # From /usr/include/sysexits.h
    exit 64
fi

# From: https://stackoverflow.com/a/2990533/11477374
echoerr() { echo "$@" 1>&2; }

# Bind CLI arguments to explicit names:
ACTION=${1}
VERSION=${2}

# Download the `install-tl` script from the `tlnet-final` subdirectory, NOT
# from the parent directory. The latter contains an outdated, non-final `install-tl`
# script, causing this exact problem:
# https://tug.org/pipermail/tex-live/2017-June/040376.html
HISTORIC_URL="ftp://tug.org/historic/systems/texlive/${VERSION}/tlnet-final"
REGULAR_URL="http://mirror.ctan.org/systems/texlive/tlnet"

case ${ACTION} in
    "get")
        if [[ ${VERSION} == "latest" ]]
        then
            # Get from default, current repository
            wget ${REGULAR_URL}/${TL_INSTALL_ARCHIVE}
        else
            # Get from historic repository
            wget ${HISTORIC_URL}/${TL_INSTALL_ARCHIVE}
        fi
    ;;
    "install")
        if [[ ${VERSION} == "latest" ]]
        then
            # Install using default, current repository
            perl install-tl \
                --profile=${TL_PROFILE}
        else
            # Install using historic repository (`install-tl` script and repository
            # versions need to match)
            perl install-tl \
                --profile=${TL_PROFILE} \
                --repository=${HISTORIC_URL}
        fi

        # For `command` usage, see:
        # https://www.gnu.org/software/bash/manual/html_node/Bash-Builtins.html#Bash-Builtins.
        # The following test assumes the most basic program, `tex`, is present.
        if command -v tex &> /dev/null
        then
            # If automatic `install-tl` process has already adjusted PATH, we are happy.
            echo "PATH and installation seem OK."
        else
            # Try and make installation available on path manually.
            #
            # The first wildcard expands to the architecture (should be 'x86_64-linux',
            # which might change in TeXLive upstream, so do not hardcode here),
            # the second one expands to all binaries found in that directory.
            # Only link if directory exists, else we end up with a junk symlink.
            EXPECTED_INSTALL_TEXDIR=${TEXLIVE_INSTALL_TEXDIR}/bin/*

            # `ls` found to be more robust than `[ -d ... ]`.
            if ls ${EXPECTED_INSTALL_TEXDIR} 1>/dev/null 2>&1
            then
                SYMLINK_DESTINATION="/usr/local/bin"

                # "String contains", see: https://stackoverflow.com/a/229606/11477374
                if [[ ! ${PATH} == *${SYMLINK_DESTINATION}* ]]
                then
                    # Should never get here, but make sure.
                    echoerr "Symlink destination ${SYMLINK_DESTINATION} not in PATH (${PATH}), exiting."
                    exit 1
                fi

                echo "Symlinking TeXLive binaries in ${EXPECTED_INSTALL_TEXDIR}"
                echo "to a directory (${SYMLINK_DESTINATION}) found on PATH (${PATH})"

                # Notice the wildcard:
                ln --symbolic --verbose ${EXPECTED_INSTALL_TEXDIR}/* ${SYMLINK_DESTINATION}

                if command -v tex &> /dev/null
                then
                    echo "PATH and installation seem OK."
                else
                    echoerr "Manual symlinking failed and TeXLive did not modify PATH automatically."
                    echoerr "Exiting."
                    exit 1
                fi
            else
                echoerr "Expected TeXLive installation dir not found and TeXLive installation did not modify PATH automatically."
                echoerr "Exiting."
                exit 1
            fi
        fi
    ;;
    *)
        echoerr "Input not understood."
        usage
        # From /usr/include/sysexits.h
        exit 64
esac

此外,TeXLive 的安装是使用其install-tl脚本。对于无人值守安装,它需要轮廓文件,如下所示texlive.profile(由于字符限制,评论被删除):

selected_scheme scheme-custom

collection-basic 1
collection-bibtexextra 1
collection-binextra 1
collection-fontsextra 1
collection-fontsrecommended 1
collection-fontutils 1
collection-formatsextra 1
collection-langenglish 1
collection-langeuropean 1
collection-langgerman 1
collection-latex 1
collection-latexextra 1
collection-latexrecommended 1
collection-luatex 1
collection-mathscience 1
collection-pictures 1
collection-plaingeneric 1
collection-publishers 1
collection-xetex 1

collection-context 0
collection-games 0
collection-humanities 0
collection-langarabic 0
collection-langchinese 0
collection-langcjk 0
collection-langcyrillic 0
collection-langczechslovak 0
collection-langfrench 0
collection-langgreek 0
collection-langitalian 0
collection-langjapanese 0
collection-langkorean 0
collection-langother 0
collection-langpolish 0
collection-langportuguese 0
collection-langspanish 0
collection-metapost 0
collection-music 0
collection-pstricks 0
collection-texworks 0
collection-wintools 0

instopt_adjustpath 1
instopt_adjustrepo 0
instopt_letter 0
instopt_portable 0
instopt_write18_restricted 1
tlpdbopt_autobackup 0
tlpdbopt_backupdir tlpkg/backups
tlpdbopt_create_formats 1
tlpdbopt_desktop_integration 0
tlpdbopt_file_assocs 0
tlpdbopt_generate_updmap 0
tlpdbopt_install_docfiles 0
tlpdbopt_install_srcfiles 0
tlpdbopt_post_code 1

如果您愿意,此文件是映像构建过程的核心。它指定要下载和安装哪些 LaTeX 包。您可以在此处修改您的构建,也许最重要的是精简构建。例如,此处明确省略了安装/下载文档文件,这是在简单运行 时无法实现的apt-get install texlive-full,从而节省了数 GB 的空间。

请注意,这些图像已经构建并可用(以持续集成的方式:git push源存储库上的每个图像都将触发构建)DockerHub。使用这些将获得与自己构建相同的图像,不会对 TUG 档案服务器造成压力。这些镜像是使用 DockerHub 的构建钩子,其中设置页面看起来有点像(另请参阅这里):

DockerHub 设置页面

CI 配置

这是 GitLab 特有的。我还没有为 GitHub/Travis 实现此功能。

在给定的存储库中,*.tex根目录中有一个或多个文件以及README.md,下面的 CI YAML 配置(由于字符限制没有注释)将:

  1. 从上面的 DockerHub 存储库中拉取镜像,将所有ENTRYPOINT指令替换为空(即普通 shell)。这对于script部件的正常工作很重要,而这ENTRYPOINT对于在桌面上运行容器很方便。
  2. n.a.将 LaTeX 类文件(位于项目根目录中)中的in\newcommand*{\GitVersion}{n.a.}\newcommand*{\GitShortHash}{n.a.}from替换*.cls为该构建的实际当前值。这允许将 VCS 元数据打印在 PDF 中。
  3. 只需发出 即可将 LaTeX 构建为 PDF latexmk。它将从 中提取说明.latexmkrc,见上文。
  4. README.md使用从 编译 PDF pandoc,再次使用lualatex进行转换。这是使用模板来获得更漂亮的输出。此步骤更像是 的噱头/展示pandoc

生成的 PDF 为文物CI 管道,运行成功后即可下载。

default:
    image:
        name: alexpovel/latex
        entrypoint: [ "" ]
    retry:
        max: 1
        when: runner_system_failure
    artifacts:
        name: "$CI_COMMIT_REF_NAME"
        paths:
            - "*.pdf"
stages:
    - prepare
    - build

insert_git_metadata:
    stage: prepare
    script:
        - |
            declare -A GITINFO=(
                [GitVersion]=$CI_COMMIT_REF_NAME
                [GitShortHash]=$CI_COMMIT_SHORT_SHA
            )
        - |
            for k in "${!GITINFO[@]}"
                do
                    sed -i "s~\(newcommand\*{\\\\$k}\){.*}~\1{${GITINFO[$k]}}~" *.cls
                done
    artifacts:
        paths:
            - "*.cls"
    needs: []

build_latex:
    stage: build
    script:
        - latexmk
    dependencies:
        - insert_git_metadata

build_pandoc:
    stage: build
    script:
        - 'sed -i "s~\(^date: \)\".*\"~\1\"$(date +"%B %-d, %Y")\"~" README.md'
        - |
            pandoc README.md \
            --template eisvogel --pdf-engine=lualatex --number-sections \
            -o README.pdf
    needs: []

答案2

抱歉,我不知道 CI 代表什么,但如果您的机器上有 GNU make,您可以编写一个如下的小型 makefile:

FILE=yourfilename


.PHONY: clean cleanall

all:$(FILE).pdf

clean:  -rm *.aux *.blg *.out *.bbl *.lot *.lof *.glo *.ist *.acn *.acr *.alg *.glg *.gls *.toc *.bcf *.run.xml

cleanall:  -rm *.aux *.blg *.out *.bbl *.log *.lot *.lof *.glo *.ist *.acn *.acr *.alg *.glg *.gls *.toc *.bcf *.run.xml #report#.pdf



$(FILE).pdf: *.tex
    E:\miktex-portable\texmfs\install\miktex\bin\x64\lualatex.exe $(FILE)
    E:\miktex-portable\texmfs\install\miktex\bin\x64\biber.exe $(FILE)
    E:\miktex-portable\texmfs\install\miktex\bin\x64\makeglossaries.exe $(FILE)
    E:\miktex-portable\texmfs\install\miktex\bin\x64\lualatex.exe $(FILE)
    E:\miktex-portable\texmfs\install\miktex\bin\x64\lualatex.exe $(FILE)

该示例针对 Windows 操作系统。不要使用 E:\miktex-portable...\,请调整适合您安装的路径。如果您使用的是 GNU/Linux,则可以设置 $PATH,这样就不需要指定可执行文件的完整路径(即只需说“lualatex $(FILE)”等)。据了解,参考列表是使用 biber 和 biblatex 创建的。makefile(相同文件名)应放在 *.tex 文件所在的同一目录中。然后,您只需在命令行终端中输入“make”。同样,“make clean”和“make cleanall”可以帮助您整理目录。

答案3

我最终做的是申请latexmkCI 并应用额外的规则来latexmk帮助打包glossaries

设置构建环境和 miktex docker 镜像后,自动构建执行以下操作:

mpm --install=latexmk

构建文档时使用以下命令:

latexmk -r "<path-to-rc-file>/.latexmkrc" -lualatex -latexoption="-interaction=nonstopmode"

.latexmkrc文件位于我们所有文档存储库之间共享的 Git 子模块中,我们在其中还有共享的文档类等。

以下是.latexmkrc

# This shows how to use lualatex (http://en.wikipedia.org/wiki/LuaTeX)
# with latexmk.  
#
#   WARNING: The method shown here is suitable only for ver. 4.51 and
#            later of latexmk, not for earlier versions.
#

$pdf_mode = 4;
$postscript_mode = $dvi_mode = 0;

# This shows how to use the glossaries package
# (http://www.ctan.org/pkg/glossaries) and the glossaries-extra package
# (http://www.ctan.org/pkg/glossaries-extra) with latexmk.

add_cus_dep( 'acn', 'acr', 0, 'makeglossaries' );
add_cus_dep( 'glo', 'gls', 0, 'makeglossaries' );
$clean_ext .= " acr acn alg glo gls glg";
sub makeglossaries {
   my ($base_name, $path) = fileparse( $_[0] );
   pushd $path;
   my $return = system "makeglossaries", $base_name;
   popd;
   return $return;
}

取自这里

无论文档及其内容如何,​​最终结果都能确保一致的构建体验。这种方法还具有灵活性和可扩展性,可以在编写时使用来自本地 Docker 容器的完全相同的工具链。

相关内容