【摘 要】 在 LaTex 中,文章内容、参考文献文件、宏包文件、格式文件是相互分开的。编译过程需要将这些文件拼接起来,形成最终的 pdf 文件。此过程不是一步到位的,而是涉及到一个编译链条:将前一步编译的结果输送到下一步继续编译。

1 Latex 中的各种文件

latex 中的常见文件有如下类型(指参与编译的源文件):

  • .tex:tex 文件是最常见的 latex 文件,也是平时编写文章主要文件
  • .cls:cls 文件是 latex 的格式文件,规定了 tex 源文件的排版格局,称为类文件(class),一般使用 \documentclass{} 导入
  • .sty:sty 文件是一种宏包文件(package),一般使用 \usepackage{} 导入
  • .bst:bst 文件是参考文献的排版格式文件,一般使用 \bibliographystyle{} 导入
  • .bib:存储参考文献数据的库文件,一般使用 \bibliography{} 导入文中使用到的文献
  • 其他文件: 图片、多媒体等其他资源文件

其中 bib 文件一般如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@article{XXX,
title={ABC},
author={A, B},
journal={XX},
year={20XX}
}
@inproceedings{YYY,
title={ABC},
author={A, B, C},
booktitle={YY},
pages={a--b},
year={20YY}
}

2 一个示例

假设在当前目录下有下列文件:main.texA.clsB.styC.bstD.bib

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
%main.tex 文件
\documentclass{A} % 或者不使用自定义的排版文件时,使用最普通的 \documentclass{article}

\usepackage{B} % 以及导入一些其他常用的宏文件,如 amsmath、amssymb、amsthm 等数学相关的宏文件

\begin{document}

XXX % 正文
XXX % 正文
XXX % 正文

\bibliography{D} % 导入正文中引入文献的数据

\bibliographystyle{C} % 导入参考文献的格式文件 C.bst

\end{document}

3 编译过程

类似上例附带参考文献的源文件,整个编译需要完成四步:

【符号说明】:(xe/pdf)latex 表示可以使用 latex, pdflatexxelatex 等工具进行编译。

第一步 (xe/pdf)latex main.tex:

生成 main.auxmain.logmain.pdf 文件。其中 aux 是引用标记记录文件,用于再次编译时生成参考文献和超链接。此时的 pdf 文件中不包含参考文献,文中的引用表现为 [?]

第二步 bibtex main.aux

生成 main.bblmain.blg 文件。其中 blg 为 bibtex 处理过程记录文件,bbl 文件为文中使用的参考文献数据。

第三步 (xe/pdf)latex main.tex 更新了 main.auxmain.logmain.pdf 文件。此时的 pdf 文件的末尾有了参考文献列表,但是正文中的引用仍然表现为 [?]

第四步 (xe/pdf)latex main.tex,更新了 main.auxmain.logmain.pdf 文件。并生成最终的 pdf 文件,此时正文中的引用表现为经标记好的引用方式,如 [1][2] … 等。

上述编译链看起来非常复杂,因此有人开发了一个工具,可以将上述计算流程整合为一个过程,这就是 latexmk

4 PDFLaTeX 和 XeLaTeX 的区别

PDFLaTeX 编译模式与 XeLaTeX 区别如下:

  • PDFLaTeX 使用的是 TeX 的标准字体,所以生成 PDF 时,会将所有的非 TeX 标准字体进行替换,其生成的 PDF 文件默认嵌入所有字体;
  • 使用 XeLaTeX 编译,如果论文中有很多图片或者其他元素没有嵌入字体的话,生成的 PDF 文件也会有些字体没有嵌入。 XeLaTeX 对应的 XeTeX 字体的支持更好,允许用户使用操作系统字体来代替 TeX 的标准字体,而且对非拉丁字体的支持更好。
  • PDFLaTeX 进行编译的速度比 XeLaTeX 快。

5 latexmk 使用常识

已经有人将上述编译过程整合在了一个命令行程序中,那就是 latexmk

5.1 基本命令格式

latexmk 的通用格式为

1
latexmk [options] [file]

其中 file 可以直接写文件名, 如果直接写 foo 的话, latexmk 会按照 foo.tex 来处理. 有一些符号在文件名中是不能用的: $, %, \,`(这个东西不能放在代码块里……), &这个符号不能作为文件名的开头, 还有一些控制字符也不可以, 不过我估计没人会闲的用控制字符来做 .tex 的文件名…

5.2 常用命令行选项

(1) -auxdir=FOO 或者 -aux-directory=FOO

设置存放辅助文件的文件夹, 可惜此选项只对 MacOS 的 MiKTeX 版本起作用, linux 的 TeX Live 无法使用。

(2)-bibtex

当源文件需要用 .bbl 文件作为参考文献的时候, 运行 bibtex 或者 biber 来更新 .bbl 文件. 这个选项可以将配置文件 .latexmkrc 中的 $bibtex_use 的值设置为 2 来实现.

(3) -bibtex-

从不运行 bibtex 或者 biber. 同时将 .bbl 文件看做珍贵的 ( 原文为 precious ), 也就是在执行清理命令的时候不会删除 .bbl 文件。如果我们接受到的文件中只有 .bbl 而没有 .bib 的时候会启用此选项。这个选项可以将 .latexmkrc 中的 $bibtex_use 的值设置为 0 来实现.

(4) bibtex-cond

如果源文件中存在 .bib 文件, 则运行 bibtexbiber 来重写 .bbl 文件, 如果没有 .bib 文件, 则不运行 bibtexbiber, 这个选项也会将 .bbl 文件看做珍贵的. 这个选项可以将.latexmkrc 中的 $bibtex_use 的值设置为 1 来实现.

(5) -command

列出 latexmk 在处理文件时可以使用的命令, 然后退出.

(6) -c

清理所有由 latex , bibtex, 以及 biber 生成的可再生的文件, 除了 .dvi, postscript, 和 .pdf 文件. 会删除的文件有 .log, .aux, latexmk 创建的数据文件, 还有 @generated_exts 中指定扩展名的文件, 同时还有 $clean_ext 指定的文件.

(7) -C

清理 -c 选项中的所有文件, 以及 .pdf, .dvi, postscript 文件, 以及 $clean_full_ext 指定的文件.

(8) -cd

在进行处理之前切换到有源程序的文件夹, 并将所有的文件生成在这个文件夹里. 举例: 如果你的文件夹结构为 parent/subfolder/main.tex, 你在 parent 文件夹下, 命令行执行

1
latexmk -cd -xelatex subfolder/main

会进入 subfolder 文件夹进行编译, 并将辅助文件和输出文件生成在 subfolder 文件夹下. 这里注意路径的分隔符要使用 / , 哪怕是 Windows.

(9) -f-interaction=nonstopmode

强制执行 latexmk 哪怕遇到了 error. 一般情况下, 当 latexmk 遇到了 latex 或者其他程序在 接下来的运行中 无法处理的问题的时候, 将不会给出处理结果。

接下来的运行 指的是 如果没有 error 出现, 运行其他程序或者重新运行latex 的时候会编译完成 ( 这段其实我没看懂, 原文是 “Further processing” means the running of other Programs or the rerunning of latex (etc) that would be done if no errors had occurred. ) 额外地, 如果你想让 latex 程序遇到 error 之后不出现给用户处理 error 的暂停 , 你需要使用一些可以传递给程序的选项, 比如 -interaction=nonstopmode。 举例: 当文档里有一个严重的错误, 比如没有定义的命令。此时使用 -f 的命令行为:

1
latexmk -f -xelatex main

此时在遇到错误时,依旧会暂停来等待用户处理。而使用 -interaction=nonstopmode 的话:

1
latexmk -interction=nonstopmode -xelatex main

此时,latexmk 会一气呵成运行到最后, 哪怕没有文件输出。

(10) -g

强制完整地运行一遍 latexmk, 哪怕在 latexmk 觉得源文件自从上次编译之后没有改动

(11) -jobname=STRING

把输出文件中的文件名设置为 STRING, 而不是源文件名, 注意 STRING 中不能带空格。 允许使用占位符 %A , 比如

1
latexmk -xelatex -jobname=%A-xelatex main

此时输出文件名就变成了 main-xelatex.***

(12) -outdir=FOO 或者 -output-directory=FOO

设置存放所有输出文件的文件夹。

(13)编译和预览控制

  • -pdflatex: 使用 pdflatex 作为编译器, 该编译器会关闭 .dvi.ps 文件的生成。
  • -xelatex: 使用 xelatex 作为编译器, 该编译器会关闭 .dvi.ps 文件的生成。
  • -pdf: 使用 pdflatex 编译时,输出 .pdf 文件。
  • -pvc: 是否运行预览。编译中文文档时会使用 xelatex 编译器,此时不生成 .dvi.ps 文件, 所以会直接预览 .pdf 文件。

(14) -r <rcfile>

人工指定配置文件,按照 <rcfile> 中的内容执行 latexmk。 但需注意调用顺序, latexmk 总是会先调用标准初始的 .latexmkrc 文件, 在不存在初始 .latexmkrc 文件时,再去调用 <rcfile>。但如果 <rcfile> 中指定了一个初始 .latexmkrc 文件, 那么此指定会在标准的初始 .latexmkrc 文件之前运行。

5.3 .latexmkmc 配置文件

latexmk 可以通过配置文件来设置一些默认选项,标准的初始文件位置为 ~/.latexmkrc

变量采用如下格式设置:

  • 设置一个值为 字符串型 的变量,如: $bibtex='bibtex %O %B';
  • 设置一个值为 数值型 的变量,如: $preview_mode=1;
  • 设置一个值为 数组型 的变量,如:@default_files=('paper', 'paper1');
  • 用如下语句来给数组变量追加值,如: push @default_files, 'paper2';

可以注意到:简单变量的名字的开头都是 $, 而数组变量的名字的开头是 @, 每个语句都以分号 结尾。 字符串应该用 单引号 括起来, 不建议使用双引号。

5.4 占位符的使用

可以使用一些占位符来辅助设置 latexmk 中的一些命令参数, 例如: 如果想让 latexmkelatex 用作编译器命令, 并且想让其使用 --shell-escape 等选项, 可以写为:

latex='elatex --shell-escape %O %S';

其中,两个前面带 % 的符号就被称为 占位符, 在实际运行命令之前,这些占位符会被替换为实际值. 因此 %S 会被替换为源文件名, %O 会被替换为将作用在此命令上的各种选项,下面列出可用的占位符:

  • %A: 主 .tex 文件的文件名。 不同于 %R, %A 不会被设置别名(jobname) 而受影响;
  • %B: 最近命令中的基础名 (base name)。 比如一个 document.ps 文件从一个 document.dvi 转化得到, 那么这个文件名就是 document
  • %D: 终点 (destination) 文件名。 比如一个 .ps 文件由一个 .dvi 文件转化得到, 那么终点文件名就是这个 .ps 文件。名
  • %O: 例子中提到的选项。
  • %P: 如果变量 $pre_tex_code 不空, 那么 %P 会被替换为 $pre_tex_code\input{SOURCE} 后面的内容, 其中 SOURCE 是资源文件 (source file) 的名字。 这让 TeX 代码可以在资源文件被读入之前就传给 *latex 引擎。 如果 $pre_tex_code 为空, 那么 %P%S等价。
  • %R: 根文件名, 这是主 .tex 文件的基础名, 但是这个值可以被 -jobname 选项或者 $jobname 变量改变。
  • %S: 源文件名。 比如当转化一个 .dvi 文件到 .ps 的时候, .dvi 的文件名就是源文件名。
  • %T: The name of the primary .tex file。
  • %U: 如果变量 $pre_tex_code 不空, 那么这个值就被传递给 %U, 如果为空, 那么它被替换为一个空字符 (null string)。
  • %Y: 辅助文件所在的文件夹名。 如果文件夹名不是以合法符号结束, 那么就会被添加一个文件夹分隔符 /。 注意: 如果设置了 $out_dir 却没设置 $aux_dir, 那么latexmk 就把 $aux_dir 设置为 $out_dir
  • %Z: 输出文件夹名。 如果 $out_dir 不空, 且没以合法符号结束, 那么就会被添加一个文件夹分隔符 /

如果有什么原因你要使用一个 % 字符, 还不是上面标出的情况, 那么用 %%.

注意: 在文件名传递的过程中会被适当地自动添加引号, 所以不需要自行添加引号, 即使文件名中有空格。 如果你的 TeX 文件名中有空格, 那么一些过老版本的 TeX 程序可能不会很好地处理它们。如果 latexmk 的引号不能正确地工作, 你也可以将它关闭, 在变量 $quote_filenames 的设置中。