做排版这行久了,绕不开一个现实:文档一旦上了规模——几十页的报告、上百条公式的讲义、带交叉引用和自动编号的论文——Word 那套“所见即所得”就开始拖后腿了。编号错乱、图表移位、参考文献手动核对,改一处崩三处。LaTeX 就是在这个节点进入视野的,而 TeX Live 则是绝大多数人最终会落脚的发行版。这篇内容聊的就是从零把 TeX Live 装好、配好、调到顺手为止的完整过程,包括安装器的每个选项到底在干什么、中文环境为什么老是出问题、编辑器怎么配才能一键编译、以及那些文档里不写但会让人卡半天的坑。不管你是第一次接触 LaTeX 的学生,还是已经用了几年但一直靠“能跑就行”混过来的老用户,下面这些内容应该都能抠出点东西。
1. 发行版选型:为什么最终落在 TeX Live 上
1.1 三个主流发行版的横向对比
LaTeX 本身只是一套宏包格式,真正干活的是底层的 TeX 引擎,而把引擎、宏包、字体、工具链打包在一起的整包,就叫发行版。市面上能打的其实就三个:TeX Live、MiKTeX、MacTeX。MacTeX 严格来说不是独立发行版,它就是 TeX Live 在 macOS 上的定制封装,底层完全一致。
MiKTeX 的特点是“按需安装”,编译时缺什么宏包就弹窗问你要不要装,初次安装包体很小。听起来很美,但实际用起来,在无网络环境、批量编译、CI 流水线里就会变成灾难——你永远不知道下一次编译会不会突然卡在一个下载对话框上。TeX Live 走的是另一条路:一次装全,之后离线也能跑。这个取舍对个人电脑可能无所谓,但对“明天要交稿今晚断网”的场景,就是生死问题。
还有一个容易被忽略的点是版本一致性。TeX Live 每年发一个大版本,版本号就是年份,同年内只做宏包更新不做底层变更。这意味着你把文档发给同学、同事,只要年份对得上,编译结果基本一致。MiKTeX 是滚动更新,两边宏包版本错开一点点,就可能出现“我这边好好的,你那边报错”的经典场面。
| 维度 | TeX Live | MiKTeX | MacTeX |
|---|---|---|---|
| 安装体积 | 完整版 5~7 GB | 初始 200 MB 左右 | 4~5 GB |
| 宏包策略 | 一次性全量 | 按需下载 | 同 TeX Live |
| 跨平台 | Windows/macOS/Linux | Windows 为主 | 仅 macOS |
| 版本可复现性 | 强(按年份锁定) | 弱(滚动) | 强 |
| 离线可用 | 是 | 需预装 | 是 |
我自己的判断标准很简单:如果这台机器要长期用来写正式文档,选 TeX Live;如果只是临时改个别人的模板、装完就删,MiKTeX 更省事。但考虑到现在硬盘动辄 500 GB 起步,那几 GB 的空间实在算不上成本。
1.2 完整版与精简版的容量账
TeX Live 安装器提供几档 scheme,选错了后面要么天天补包,要么白占几个 G。常见的有 scheme-basic、scheme-small、scheme-medium、scheme-full,还有一堆按用途划分的(scheme-context、scheme-games 之类,普通人不用管)。
先把账算清楚。scheme-full 安装完大约 7 GB,其中相当一部分是宏包自带的 PDF 文档——每个宏包都配一份几百页的说明书。如果你勾选了“安装宏包文档”,体积会明显上去;不勾的话能省下接近 2 GB。我的建议是初次安装不要勾,等真正需要查某个宏包的用法时,用texdoc 宏包名在线的或者后续单独装都行。
scheme-medium 大约 1.5 GB,覆盖了绝大多数常见宏包:graphicx、amsmath、hyperref、booktabs 这些都在,中文的 ctex 也在。问题在于你迟早会撞上一个“差一个包”的时刻——比如用 tikz 画个复杂图,里面调了 pgfplots 或者某个冷门的库;或者投某个期刊,模板依赖一个你听都没听过的 .sty。这时候tlmgr install能补,但如果当时在没网的环境,就只能干瞪眼。
提示:如果硬盘空间不是极度紧张,直接 scheme-full。省下来的那点空间,抵不过后面反复补包浪费的时间,而且全量安装最大的价值是“离线可交付”——拷到 U 盘里带到任何一台机器上都能直接编译。
顺带说一句,完整安装不是把所有东西都塞进系统目录就完事。TeX Live 支持“安装到便携介质”,安装时选择便携模式,整个发行版可以放在移动硬盘里,插到别的电脑上改一下 PATH 就能用。这个功能在需要给机房统一环境、或者要给评审现场演示的时候非常实用。
2. 安装前的环境盘点与方案定型
2.1 磁盘、权限与路径的三项检查
装 TeX Live 之前有三件事必须先确认,这三件事任何一件出问题,后面都会以各种奇怪的形式报错。
第一是磁盘空间。别只看“还剩多少”,要看“装在哪个盘”。Windows 上默认装到 C 盘,很多人 C 盘就剩十来个 G,装到一半空间不足中断,残留一堆半截文件,清理起来比重装系统还烦。我一般建议把 TeX Live 装到非系统盘,路径形如D:\texlive\2024。但要注意,路径里绝对不能有中文和空格——这不是 TeX Live 矫情,是底层一堆脚本对路径转义处理得很粗糙。D:\我的文档\texlive这种路径,出问题的时候你连报错都看不懂。
第二是权限。Windows 上安装器需要管理员权限来写 PATH 和注册文件关联。如果你用的是公司或学校的受控机器,装到一半提示无权限,那就是组策略限制,得先跟管理员沟通,别硬试。
第三是残留版本。如果之前装过旧年份的 TeX Live,比如 2022 版还躺在那里,新版本装完后两个版本的二进制文件可能同时出现在 PATH 里,pdflatex --version输出的年份和你以为的不一样。这种情况的排查成本极高,因为编辑器调用的可能是一个版本,命令行里which出来的是另一个。稳妥做法是新装之前把旧的卸干净,或者装完之后手动检查 PATH 顺序。
再说一个容易被忽视的:Windows 的用户名如果是中文,某些宏包在写临时文件时会出问题。这不是 TeX Live 的锅,是部分脚本对非 ASCII 路径支持不到位。如果实在改不了用户名,可以把工作目录设在纯英文路径下,TEXMFVAR和TEXMFCACHE这两个环境变量单独指到英文目录。
2.2 安装包获取与校验
官方提供两种获取方式:网络安装器(install-tl-windows.exe,几百 KB 到几 MB)和完整 ISO 镜像(几 GB)。网络安装器体积小,但安装过程中要持续下载,网络不稳的话容易断在中间;ISO 镜像下载一次,之后完全离线安装,速度稳定。
我的经验是:网络条件好、能挂着慢慢装,用网络安装器;网络时断时续、或者要装多台机器,下 ISO。ISO 挂载后里面有个 install-tl-windows.bat,双击即可。下载完记得做一次校验,官方会给出 SHA-512 校验值,Windows 上用certutil -hashfile 文件名 SHA512,Linux/macOS 上用shasum -a 512 文件名。校验这步很多教程都跳过,但镜像下载不完整导致安装到 80% 报 CRC 错误的案例,我见过不止一次。
网络安装器还有个隐藏好处:它自带镜像测速,启动后会列出一堆镜像源并测延迟,你可以手动挑一个快的。国内访问官方主站速度一般,切换到家附近的高校镜像源通常能快十倍以上。安装器界面里有个“Change”按钮可以手动指定,也可以在命令行里用-repository参数直接指定。
安装路径规划上,我习惯这样组织:
# Windows 示例 D:\texlive\2024\ # 发行版本体 D:\texlive\texmf-local\ # 自己的宏包和字体,独立于版本 E:\work\latex\ # 项目文档目录texmf-local这个目录很关键,它是留给用户的“不被升级覆盖”的区域。自己写的 .sty、下载的字体、公司统一的模板,全放这里,以后换年份升级,这部分原封不动。
3. Windows 下的安装实录
3.1 安装器交互项逐条拆解
双击安装器进入图形界面,第一屏是欢迎页,直接下一步。第二屏是许可协议,TeX Live 用的是自由许可,接受即可。第三屏开始就是真正要做决策的地方了,这一屏很多人一路“下一步”点过去,装完才发现选错了。
第一组选项是“安装 scheme”。下拉框里默认是 scheme-full,如果不是,手动改成 full。旁边有个“自定义”按钮,点进去能看到按语言、按用途分类的宏包集合,比如“中文”“日文”“数学”“出版”。理论上你可以只勾中文+基础,但我不建议——依赖关系是网状的,你以为只要中文,结果某个模板链式依赖了三个你没想到的包。
第二组是“安装路径”。这里分两个:根目录和用户目录。根目录就是刚才说的D:\texlive\2024。用户目录(TEXMFHOME)默认在C:\Users\用户名\texmf,这个也建议改到非系统盘,原因同上——重装系统的时候不会丢。
第三组容易被忽略:“为所有用户安装”还是“仅为当前用户”。选前者会写系统级 PATH,需要管理员权限,但装完之后任何账户都能用命令行调 latex。选后者只写当前用户的 PATH。个人电脑选前者,共享机器选后者更干净。
第四组是“创建文件关联”。勾上之后 .tex 文件双击会用 TeXworks 打开。TeXworks 是 TeX Live 自带的极简编辑器,能用来验证环境是否装好,但日常不会用它写东西。这个关联勾不勾无所谓,后面装了 VS Code 会接管。
最后确认页会显示一个“安装计划”,包括磁盘占用量、预计下载量。这里有一个“调整”按钮,能改端口和代理设置——如果你在公司网络后面,需要走内网代理,就在这里填。确认后点安装,接下来就是等待。scheme-full 从国内镜像拉,20 分钟到 1 小时不等,取决于带宽和硬盘速度。
3.2 安装后的目录结构与命令行验证
装完之后先别急着打开编辑器,先在命令行做三件事验证。
第一件事,确认版本和路径唯一。
where pdflatex pdflatex --versionwhere会列出所有匹配的可执行文件。如果输出两行,说明有多个版本共存,PATH 里有残留,需要手动清理。--version输出的第一行会写明 TeX Live 的年份和引擎版本,比如pdfTeX 3.141592653-2.6-1.40.25 (TeX Live 2024),年份对不上就是装错了。
第二件事,确认包数据库完整。
tlmgr --version tlmgr info collection-langchinese第二条命令会列出中文支持集合的信息,能看到包名、版本、安装状态。如果提示“tlmgr: command not found”,说明 PATH 没写进去,需要手动加,或者重新运行安装器里的“添加 PATH”选项。
第三件事,跑一个最小样例。新建一个 test.tex:
\documentclass{article} \begin{document} Hello, \LaTeX. \end{document}然后pdflatex test.tex。顺利的话会生成 test.pdf。这一步能过,说明引擎、格式文件、基础宏包都在位。
目录结构上,装完之后值得认识几个路径:
| 路径 | 作用 |
|---|---|
texlive/2024/bin/windows | 所有可执行文件(pdflatex、xelatex、tlmgr 等) |
texlive/2024/texmf-dist | 发行版自带的宏包和字体,只读,升级会覆盖 |
texlive/texmf-local | 用户自己的宏包、字体,升级不覆盖 |
texlive/2024/tlpkg | 包管理数据库,别手动动 |
想快速定位某个文件到底在哪,用kpsewhich:
kpsewhich ctex.sty kpsewhich article.cls输出的是完整路径。这个命令在排查“到底加载的是哪个版本的宏包”时几乎是唯一可靠的手段。
3.3 卸载与重装的干净做法
TeX Live 的卸载不像普通软件那样在控制面板里点一下就行。正确做法是运行安装目录下的tlmgr uninstall或者uninstall-tl.bat(Windows)。但即便这样,仍有三处残留需要手动清:
一是 PATH 环境变量里那两条路径,卸载程序有时不会删;二是用户目录下的.texlive2024之类的配置文件夹;三是 TeXworks 等关联程序留下的注册表项。这三处不清,重装时可能出现“检测到已有安装”的奇怪提示。
我的建议是:能不重装就不重装。TeX Live 的包管理器很稳,缺什么补什么,绝大多数问题都能通过tlmgr install和tlmgr update解决。真要重装,先把整个安装目录重命名(比如改成2024_old),装完新版确认没问题再删旧的。这样万一新版出问题,改回 PATH 就能回退。
4. macOS 与 Linux 的差异化处理
4.1 macOS:完整包与精简包的分界
macOS 上的官方方案是 MacTeX,它其实就是 TeX Live 加了一个图形化的 TeXShop 编辑器和一些 macOS 特有的字体配置。完整版 pkg 大约 4~5 GB,装完直接用,中文、字体、路径全都配好了,几乎不需要额外折腾。对不想折腾的人来说,这是最省心的路。
但如果你用的是 256 GB 的 MacBook Air,装 5 GB 进去确实肉疼。这时候可以用 BasicTeX,一百多 MB,只带最基础的引擎和宏包。代价是后面每次遇到缺包都要手动sudo tlmgr install 包名。注意这里必须加 sudo,因为 BasicTeX 装在了系统目录/usr/local/texlive下,写权限需要提权。
BasicTeX 用户最常踩的坑是:tlmgr报 “Local TeX Live (2024) is older than remote repository”,意思是你本地版本比镜像上的旧。这时候别急着 update,先确认镜像指向对不对,然后sudo tlmgr update --self更新管理器本身,再更新其他包。如果不按这个顺序,容易出现管理器版本太老、无法解析新索引的情况。
macOS 还有个特殊点:系统自带的字体管理和 TeX 的字体查找是两套机制。用fontspec指定系统字体(比如某个中文字体)时,XeLaTeX 走的是 macOS 的字体服务,理论上能直接找到。但有些字体装在用户目录~/Library/Fonts下,某些版本的 XeLaTeX 扫描不到,需要把字体移到/Library/Fonts或者~/texmf/fonts/opentype/下再用fc-cache重建缓存。这种问题在 Linux 上同样存在,本质是字体缓存机制不统一。
4.2 Linux:系统包管理器与官方安装的取舍
Linux 这边存在两条路线,选错了后面很别扭。
路线一是发行版仓库:apt install texlive-full、dnf install texlive-scheme-full。优点是省心,跟系统包管理统一,升级的时候一起升。缺点有两个:一是版本往往落后一年甚至更久,仓库里还挂在上一个年份;二是分发版会把 tlmgr 的功能切掉或限制,因为它不希望用户绕开包管理器自己去装包。表现出来就是tlmgr install要么报错,要么装了之后系统包管理器不知道,容易冲突。
路线二是官方 ISO 或安装脚本,跟 Windows 流程基本一致,装到/usr/local/texlive/2024,然后手动加 PATH。这条路线的好处是版本新、tlmgr 功能完整、跟 Windows 环境一致(团队协作时这一点很重要)。
我个人的选择是路线二。理由很实际:如果你需要在多个平台上编译同一个文档,版本不一致带来的排查成本远高于安装时多花的那半小时。PATH 加在~/.bashrc或~/.zshrc里:
export PATH=/usr/local/texlive/2024/bin/x86_64-linux:$PATH export MANPATH=/usr/local/texlive/2024/texmf-dist/doc/man:$MANPATH export INFOPATH=/usr/local/texlive/2024/texmf-dist/doc/info:$INFOPATH注意一定要放在 PATH 的最前面,否则系统仓库里如果也装了 texlive,会优先命中旧的。
Linux 下还有个细节:中文字体。TeX Live 自带的 fandol 是一套开源中文字体,够用但字形偏朴素。如果想用系统里的思源、文泉驿之类的字体,先把字体文件放进~/texmf/fonts/opentype/,然后执行:
mktexlsr fc-cache -fv前一条命令重建 TeX 的文件名数据库,后一条重建系统字体缓存。两条都执行完,XeLaTeX 才能通过字体名找到它。顺序不能反,只执行第二条也没用——TeX 不认系统字体缓存,它有自己的 ls-R 数据库。
5. 中文排版配置的核心逻辑
5.1 引擎、宏包、字体三者的关系
中文排版之所以让新手头疼,是因为它涉及三层:引擎、宏包、字体。这三层任何一层没对齐,都会报出让人看不懂的错误。
引擎层面,pdflatex 对中文支持很差,虽然能用 CJK 宏包凑合,但字体、断行、标点挤压都很原始。现在主流方案是 xelatex 或 lualatex,它们原生支持 Unicode 和系统字体。lualatex 更现代,但某些宏包兼容性不如 xelatex;xelatex 生态最成熟,中文场景下是我的默认选择。记住一条铁律:只要文档里有中文,就别用 pdflatex。
宏包层面,ctex 是事实标准。它不是单一宏包,而是一整套:ctexart、ctexrep、ctexbook、ctexbeamer 几个文档类,加上 ctex 宏包供在 article 等标准类里调用。它内部调用了 xeCJK 处理中文断行和标点,还预置了字体配置和字号方案。用 ctex 的好处是它替你处理了大量琐碎设置——中文首行缩进两字符、中英文混排的间距、章节标题的中文化。
字体层面,方案有三种:用 ctex 默认的 fandol(随发行版分发,无需额外配置,跨平台一致性好);用系统字体(需要 fontspec 显式指定);用自己放在 texmf 目录里的字体。默认方案最省事,但字形一般;系统字体好看,但换台机器可能就找不到。我的建议是:投稿、协作、代码仓库里的文档,用 fandol 保证可复现;自己看的讲义、内部文档,用系统字体提升观感。
5.2 一份可以直接用的中文模板
下面这份模板覆盖了绝大多数日常场景,可以直接抄走改:
\documentclass[12pt, a4paper]{ctexart} % 页面与版心 \usepackage[margin=2.5cm]{geometry} % 数学 \usepackage{amsmath, amssymb, amsthm} % 图表 \usepackage{graphicx} \usepackage{booktabs} \usepackage{caption} \captionsetup{font=small, labelsep=quad} % 超链接与书签 \usepackage[colorlinks=true, linkcolor=blue, citecolor=blue, urlcolor=blue]{hyperref} % 代码 \usepackage{listings} \lstset{basicstyle=\ttfamily\small, breaklines=true} % 字体设置:默认用 fandol,无需额外操作 % 若想用系统字体,取消下面注释并替换字体名 % \setCJKmainfont{Noto Serif CJK SC} % \setCJKsansfont{Noto Sans CJK SC} % \setCJKmonofont{Noto Sans Mono CJK SC} \title{文档标题} \author{作者} \date{\today} \begin{document} \maketitle \begin{abstract} 这里是摘要。 \end{abstract} \section{第一节} 正文内容。 \subsection{小节} 公式示例: \begin{equation} E = mc^2 \end{equation} 表格示例见表~\ref{tab:demo}。 \begin{table}[htbp] \centering \caption{示例表格} \label{tab:demo} \begin{tabular}{lcr} \toprule 项目 & 数量 & 备注 \\ \midrule A & 10 & 说明 \\ B & 20 & 说明 \\ \bottomrule \end{tabular} \end{table} \end{document}注意几个点:用ctexart而不是article加\usepackage{ctex},前者省心得多;geometry一定要在 ctex 之后加载,否则版心设置会被覆盖;hyperref放最后加载,它跟很多宏包有加载顺序要求,放早了容易冲突。
编译命令是:
xelatex main.tex xelatex main.tex中文文档至少要编译两次,因为 ctex 会写辅助文件来记录断行位置和交叉引用。第一次编译生成的 .aux 里可能还有未解析的引用,第二次才稳定。如果用了 bibtex 或 biber,流程变成 xelatex → bibtex → xelatex → xelatex,四步。这就是为什么强烈建议用 latexmk 自动化,手动敲太容易漏。
5.3 字体缺失与断行异常的处理
字体缺失的典型报错长这样:
! Package fontspec Error: The font "Noto Serif CJK SC" cannot be found.意思是 fontspec 在系统里找不到这个字体名。排查三步:一是确认字体确实装了,Windows 在“设置-字体”里搜,macOS 用“字体册”,Linux 用fc-list :lang=zh;二是确认字体名写对了,注意是“字体族名”不是文件名,fc-list输出的冒号前面那段才是;三是确认缓存刷新了,Linux/macOS 需要fc-cache -fv。
还有个隐蔽的情况:系统里装了字体,fc-list也能看到,但 XeLaTeX 就是报找不到。这多半是因为字体装在用户目录,而 TeX 的查找路径没覆盖到。解决办法是把字体复制到~/texmf/fonts/opentype/下,然后mktexlsr && fc-cache -fv。
断行异常是另一个高频问题。表现是中文段落里某一行的字间距被拉得很开,或者英文单词被硬生生拆开。前者通常是因为两端对齐时找不到合适的断点,TeX 只能拉伸间距;后者是连字符规则没配好。
对中文来说,最常见的原因是用了 pdflatex 编译。pdflatex 不认识中文断行规则,把每个汉字当成一个字符,自然排不好。换成 xelatex 基本就好了。如果换引擎后还有问题,检查是不是在 ctex 之外又手动加载了 CJK 或 xeCJK 并改了参数——双重配置经常互相打架。
还有一种情况是长英文单词或 URL 撑破了行宽。\usepackage{xurl}能让 URL 在任意位置断行,比 hyperref 自带的breaklinks更彻底。这个包很小,但解决的是真痛点,建议所有带链接的文档都加上。
6. 编辑器与编译链的工程化配置
6.1 VS Code 的 recipes 与 tools 怎么写
TeXworks 能验证环境,但生产力工具还得看 VS Code 加 LaTeX Workshop 扩展。装完扩展之后,默认配置基本能用,但有几个地方值得改。
LaTeX Workshop 的核心概念是“工具(tool)”和“配方(recipe)”。工具是单条命令,比如运行一次 xelatex;配方是工具的序列,比如“xelatex 跑两遍”。配置文件在 VS Code 的 settings.json 里,或者项目根目录的.vscode/settings.json(推荐后者,跟着项目走)。
一份实用的配置:
{ "latex-workshop.latex.tools": [ { "name": "xelatex", "command": "xelatex", "args": [ "-synctex=1", "-interaction=nonstopmode", "-file-line-error", "-output-directory=%OUTDIR%", "%DOC%" ] }, { "name": "bibtex", "command": "bibtex", "args": ["%DOCFILE%"] }, { "name": "biber", "command": "biber", "args": ["%DOCFILE%"] } ], "latex-workshop.latex.recipes": [ { "name": "xelatex x2", "tools": ["xelatex", "xelatex"] }, { "name": "xelatex + biber", "tools": ["xelatex", "biber", "xelatex", "xelatex"] } ], "latex-workshop.latex.recipe.default": "first", "latex-workshop.view.pdf.viewer": "tab", "latex-workshop.latex.autoBuild.run": "onSave" }几个参数值得解释。-synctex=1生成同步文件,支持 PDF 和源码双向跳转,写长文档时是刚需。-interaction=nonstopmode让编译遇到错误不暂停等输入,否则在编辑器里会卡死。-file-line-error把报错格式改成“文件名:行号:错误”,点击能直接跳转。-output-directory把中间文件(.aux、.log、.toc)都扔进指定目录,保持源码目录干净——这个参数有坑,见下一节。
autoBuild.run: onSave是保存即编译。方便,但文档大了会很卡,因为每次保存都全量编译。这种情况下改成never,需要时手动点编译按钮,或者用后面的 latexmk 增量方案。
6.2 latexmk 与 .latexmkrc
latexmk 是个脚本,它能自动判断需要编译几遍、什么时候该跑 bibtex。你只管敲一次latexmk,它自己循环到结果稳定。这比手动数遍数靠谱得多,尤其是文档里交叉引用多的时候。
基本用法:
latexmk -xelatex main.tex # 编译 latexmk -xelatex -pvc main.tex # 监视模式,文件变动自动编译 latexmk -C # 清理所有中间文件-pvc是预览持续模式,配合 PDF 阅读器能实现改一行看一眼。但这模式下 latexmk 会一直占着一个进程,长时间用建议单独开终端跑。
项目根目录放一个.latexmkrc能做更细的控制:
# .latexmkrc $xelatex = 'xelatex -synctex=1 -interaction=nonstopmode -file-line-error %O %S'; $pdf_mode = 5; # 5 表示用 xelatex 生成 pdf $out_dir = 'build'; # 中间文件统一放 build 目录 $aux_dir = 'build'; $clean_ext = 'synctex.gz run.xml bbl fdb_latexmk';$out_dir和$aux_dir指向同一个目录是个好习惯,源码目录里只会剩下 .tex 和图片。但这里有坑:\includegraphics找图片时,搜索路径是相对主文件所在目录的,跟输出目录无关,所以图片引用照常写相对路径就行;而\input引入的子文件如果也用相对路径,某些情况下会因为工作目录变化而找不到。稳妥做法是子文件用相对于主文件的路径写,或者干脆用import宏包显式指定。
还有一点:用-output-directory的时候,如果文档里有\write18调用外部程序(比如某些绘图宏包生成图片),工作目录变了会导致相对路径失效。遇到这类报错,把输出目录去掉,或者改用绝对路径。
6.3 目录结构与输出隔离
文档一旦超过二十页,源码堆在一个目录里就开始难受了。我习惯这样组织:
project/ ├── main.tex ├── .latexmkrc ├── chapters/ │ ├── 01-intro.tex │ ├── 02-method.tex │ └── 03-result.tex ├── figures/ │ ├── fig1.pdf │ └── fig2.png ├── refs.bib └── build/ # 中间文件和最终 PDF主文件里用\input{chapters/01-intro}引入。这样改哪章就开哪个文件,编辑器不卡。配合\includeonly还能实现只编译某几章:
\includeonly{chapters/02-method}注意\include和\input有区别:\include会强制分页并生成独立的 .aux,适合章一级;\input是纯文本插入,适合小节或表格。用\includeonly必须是\include引入的文件才生效。
图表目录统一放 figures,命名用语义化的名字(pipeline-overview.pdf而不是fig1.pdf),后期维护会感谢自己。图片格式上,矢量图优先用 PDF,位图用 PNG,别用 JPG 放带文字的图——压缩伪影在打印时非常明显。
7. 包管理与版本维护
7.1 tlmgr 高频命令
tlmgr 是 TeX Live 的包管理器,日常用得上的命令其实就十来条,但每一条都值得记住。
# 更新包数据库(不装东西,只刷新索引) tlmgr update --self # 更新所有已安装的包 tlmgr update --all # 安装单个包 tlmgr install pgfplots # 卸载 tlmgr remove 包名 # 查包信息 tlmgr info ctex # 列出已安装的包 tlmgr list --only-installed # 搜索包(按关键词) tlmgr search --global --keyword 关键词 # 切换镜像源 tlmgr option repository https://某镜像站/texlive/tlmgr search特别有用。有时候报错说缺某个 .sty,你不知道它属于哪个包,直接tlmgr search --global --file 文件名.sty就能反查出来。这个功能在补包时能省下大量瞎猜的时间。
镜像源切换是提速的关键。默认源在国外,tlmgr update --all可能要跑半小时。切到国内镜像后通常几分钟搞定。切换后建议先跑一次tlmgr update --self,再--all,顺序反了可能因为管理器版本旧而解析不了新索引。
注意:
tlmgr update --all不要无脑天天跑。TeX Live 同一年内的更新一般是安全的,但偶尔会有宏包更新引入不兼容改动。如果你手上有一个正在赶工期的文档,编译通过了就别动它。我的习惯是项目开工前更新一次,交付前不碰。
7.2 升级时机与回滚策略
TeX Live 的年份升级(比如 2023 到 2024)不是增量更新,是装一套全新的。官方建议是新旧共存一段时间,确认没问题再删旧的。两套共存的代价是磁盘,好处是随时能切回去。
切换的方式就是改 PATH。写个脚本或者别名:
# ~/.bashrc alias tl2023='export PATH=/usr/local/texlive/2023/bin/x86_64-linux:$PATH' alias tl2024='export PATH=/usr/local/texlive/2024/bin/x86_64-linux:$PATH'出问题的时候开个新终端,切到旧版本,先保证活儿能干完,再慢慢排查新版本的问题。
单个包的版本回滚比较麻烦,tlmgr 不直接支持降级。可行的方法是去历史仓库(texlive 的 tlnet 有历史快照)手动下载对应版本的包,用tlmgr install --file 包文件装上。这个操作不常用,但真遇到“新版宏包把某个命令改了名”的情况,是唯一的救命稻草。
还有个小技巧:tlmgr支持--dry-run参数,先看看会改什么,不实际执行。升级前跑一遍,心里有数:
tlmgr update --all --dry-run8. 报错排查速查
8.1 编译中断的三类根因
LaTeX 的报错信息出了名的不友好,但绝大多数中断可以归到三类。
第一类是“找不到文件”。典型信息是! LaTeX Error: File 'xxx.sty' not found.或者! I can't find file 'yyy.tex'。前者是缺宏包,tlmgr install补上;后者是路径写错,或者文件名大小写不对(Linux 下大小写敏感,Windows 不敏感,这个差异在跨平台协作时坑过无数人)。排查用kpsewhich xxx.sty,能输出路径就是装了,只是没被正确加载。
第二类是“语法错误”。典型信息是! Missing $ inserted.或者! Undefined control sequence.。前者通常是数学符号写在了文本模式里,比如下划线、尖括号、百分号没转义;后者是命令名拼错,或者用了没加载的宏包里的命令。定位靠行号,但 LaTeX 报的行号经常比实际出错位置晚几行——因为它是读到“觉得不对”的地方才报错。所以看报错时往上翻两三行,往往能找到真凶。
第三类是“资源耗尽”。典型信息是! TeX capacity exceeded, sorry [main memory size=...]。这在大文档、复杂 tikz 图、或者死循环的宏里出现。TeX Live 的默认内存设置其实挺大了,真遇到多半是代码有问题,比如递归宏没写终止条件。少数情况是 tikz 图画得太复杂,可以调大main_memory(需要改 texmf.cnf 并重建格式文件),但这个操作有门槛,优先考虑拆分图形。
8.2 常见问题速查表
把踩过的坑整理成表,出问题时先对照一遍,能省不少时间:
| 现象 | 大概率原因 | 处理方式 |
|---|---|---|
File 'ctex.sty' not found | 没装中文支持集合 | tlmgr install collection-langchinese |
| 中文全是方框 | 字体没找到 | 换 xelatex 引擎,或用 fandol |
Font ... not found | 字体名写错或未刷新缓存 | fc-list核对名字,fc-cache -fv |
引用显示为?? | 编译次数不够 | 用 latexmk 或手动多跑一遍 |
| 参考文献不显示 | 没跑 bibtex/biber | 检查编译链,biber 需 .bcf 文件 |
Emergency stop | 前面有更早的错误 | 往上翻日志找第一个 Error |
| 编译超时无响应 | 死循环或等输入 | 加-interaction=nonstopmode |
| PDF 里中文复制乱码 | 字体未嵌入或编码问题 | 用 xelatex + 完整字体 |
Too many open files | 图片或子文件过多 | 合并图片,或调系统 fd 上限 |
| 编译速度越来越慢 | 中间文件堆积 | latexmk -c清理 |
日志文件(.log)是排查的主要依据。VS Code 的 LaTeX Workshop 会把错误提取出来显示在问题面板,但有时提取不全,直接打开 .log 搜!更可靠。搜到的第一个!往往就是真正的起点,后面的报错大多是连锁反应。
再补一个容易被忽略的:中文文档编译后 PDF 里文字复制出来是乱码。这不是编码问题,是字体没有正确嵌入或者用了 Type3 字体。检查方法是用pdffonts命令(Windows 上随 poppler 提供)看字体列表,如果出现 Type3 就说明有问题。解决办法是确保用 xelatex 编译,并且字体是 TrueType 或 OpenType 格式。
9. 提速与工程化实践
9.1 编译时间都花在哪
文档大了之后,一次全量编译可能要几十秒甚至几分钟,改一个字等半天,体验极差。先搞清楚时间花在哪:字体加载、图片处理、tikz 绘图、交叉引用解析,这四项占大头。
字体加载是一次性的,但 xelatex 每次启动都要重新扫描字体,如果有几十个字体变体,启动就要好几秒。精简办法是只加载真正用到的字重,别一股脑\setCJKfamilyfont定义七八个。
tikz 是最耗时的。一张复杂图编译十秒很正常,如果文档里有二十张,那就是三分多钟。解决方案是tikzexternalize,把每张图编译成独立的 PDF 缓存起来,主文档只负责插入。配置如下:
\usetikzlibrary{external} \tikzexternalize[prefix=build/tikz-]第一次编译会慢,之后只要图没改,就直接复用缓存。注意这个功能对\ref之类的交叉引用支持有限,图里如果引用了文档中的标签,外部化后会失效,需要\tikzexternaldisable单独处理。
分章编译是另一个大杀器。前面提到的\includeonly能把编译范围限制在一两章,时间立省 80%。配合 VS Code 的任务配置,可以做成“只编译当前文件所在章”的快捷命令。
draft模式也值得一提。文档类加draft选项后,图片会变成方框占位,不实际加载图片文件,编译速度明显提升。写文字阶段用 draft,排版阶段再切回来。
9.2 大型文档的目录结构组织
最后聊点工程化的东西。一个人写十页文档无所谓结构,但如果是团队协作、或者一本书级别的项目,目录组织直接决定后期维护成本。
核心原则是“一个文件一个职责”。主文件只管导言区和章节引入,不写正文;每章一个文件;每张复杂图表单独一个文件用\input引入;参考文献、自定义命令、字体配置各自独立成 .tex 或 .sty。
自定义命令建议单独放一个commands.tex,主文件里\input{commands}。这样换项目的时候整个文件拷过去就能复用。里面放什么?常用的数学符号简写、单位命令、固定格式的表格环境。举个简单的例子:
% commands.tex \newcommand{\R}{\mathbb{R}} \newcommand{\dd}{\mathrm{d}} \newcommand{\figref}[1]{图~\ref{#1}} \newcommand{\tabref}[1]{表~\ref{#1}}这类小命令看着不起眼,但写几百个公式之后,\R比\mathbb{R}省的手腕不是一点半点。而且格式统一,后期想改风格只改一处。
版本控制方面,.gitignore 要写对。中间文件(.aux、.log、.out、.toc、.synctex.gz、.bbl)都不该进仓库,只提交 .tex、.bib、图片和 .latexmkrc。PDF 视情况,如果仓库要给非技术同事看,可以提交最终版;纯代码仓库就别提交了,二进制文件会让仓库迅速膨胀。
团队协作时还有一个必做项:在 README 里写清楚 TeX Live 的年份、编译命令、需要的额外字体。这三条信息能省掉新人上手时 90% 的沟通成本。我见过太多项目,接手的人折腾一整天环境,最后发现只是年份差了一年。
踩过几次坑之后,我个人的体会是:TeX Live 的安装本身其实不难,难的是中文环境和编译链这两块,而这两块的坑大多源于“版本不一致”和“路径不干净”。所以我现在给别人的建议永远是那三条:装完整版别省空间,路径全用英文别图省事,年份锁定别乱升级。至于编辑器配置,一开始用默认的能跑就行,等真正觉得哪一步烦了再去改,比照着教程一次性配一大堆用不上的功能要实在得多。