添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

用 Codespaces 替代 Overleaf 作为云端 LaTeX 编写编译环境

2024-02-21 · 笔记本

终于终于,学校作业提交可以不用被限制在 Word 格式,且老师鼓励我们使用 LaTeX 写作。被按头用 Word 写了一年半的报告都快给我写出阴影来了,每次调格式都心惊胆战、写公式更是磨练性情……

不过,老师似乎并不打算教我们如何配置 LaTeX 编译环境,毕竟任何时候环境配置都是令人头大的事情,而直接推荐我们使用在线 LaTeX 编辑器 Overleaf。

但是 Overleaf 的免费版有诸多限制,没有文档历史、限制引用检索、限制自定义语法……最让我无法忍受的是不能使用 Git 管理我的文档,和前面不保存文档历史一起就是明摆着没有任何版本管理可言,除非每月向其缴纳百余元的订阅费用。

当然作为服务而非工具,Overleaf 订阅价格也很难说不合理。但我依然花了半天时间将 GitHub Codespaces 配置好 LaTeX 云端编写编译环境,拥有完整命令行和基于文件/文件夹管理的确会更让我踏实一些。

TL;DR

我把折腾配置结果开源在 GitHub:ChrAlpha/LaTeXspaces 上,借助 Dev Container 的配置,你可以在 GitHub Codespaces 上直接打开一个 LaTeX 编译环境(当然第一次生成需要点时间),以及最基本的中文字体(考虑到读这篇文章的绝大多数是中文用户)。

安装 TeX Live

在 VS Code LaTeX 插件 LaTeX-Workshop 文档 中说明需要 LaTeX 包含在环境中,最被推荐的是 TeX Live ,当然也可选用 MiKTeX 或者 TinyTeX

而 Codespaces 默认镜像为 Ubuntu 20.04,直接使用其包管理器 APT 安装 TeX Live 是最简单的方法。

sudo apt update
sudo apt install texlive # texlive-full

但是其默认源的 TeX Live 版本为 2021,而最新版本为 2023(截至本文写作时),在过去很多年 APT 似乎均未积极跟进最新版本的 TeX Live。倘若没有用到较新的特性倒也是能够运行,但好巧不巧我用的某个包需要 2022 版本及以上……

所以跟随 TeX Live 官方文档 的建议手动下载安装程序以安装最新版本的 TeX Live 或许是更好的选择。

mkdir -p ~/tmp/texlive
cd ~/tmp/texlive
wget https://mirror.ctan.org/systems/texlive/tlnet/install-tl-unx.tar.gz
zcat < install-tl-unx.tar.gz | tar xf -
cd $(ls -d install-tl-* | head -n 1)
sudo perl ./install-tl --scheme=small --no-interaction
  • --scheme=small 选项决定安装精简版的 TeX Live,毕竟完整版的 TeX Live 有不小于 8GB 的体积,而我在日常使用中也未察觉精简版的不足。
  • --no-interaction 选项决定安装过程不需要人工干预,直接安装默认配置。
  • 如果后续运行起来有缺失也可以在终端运行 tlmgr install <package> 安装缺失的包。当然更建议在 USERMODE 下安装,以免权限问题。只需要在初次通过 tlmgr init-usertree 初始化用户模式后,再于每次安装加上 --usermode 即可。

    例如安装 ctex 宏包:

    tlmgr install ctex --usermode

    倘若一直无法编译且确定不是某单个包的问题,最后也可尝试安装完整版的 TeX Live。完整版 TeX Live 占据 7GB+ 的空间,倘若你的 GitHub 是免费账户需要留意 Codespaces Storage 额度。

    TeX Live 在 Codespaces 上的环境配置还有点诡异。在使用 install-tl 手动安装完毕后,会提醒你添加到 PATH,一般都是在 ~/.bashrc / ~/.zshrc 中添加:

    export PATH="/usr/local/texlive/2023/bin/x86_64-linux:$PATH"

    此时重启 Terminal 或者 source ~/.bashrc / source ~/.zshrc 已经生效,通过 which tex 可以检验。但是无论我重启 VS Code Window 还是重启整个 Codespacces 乃至重装插件都无法让 LaTeX Workshop 识别到 TeX Live 路径。这个问题困扰我许久,且通过 VS Code OUTPUT 看到 PATH 中依旧没有明明我在所有 Shell 的配置文件都 export 过的路径。而这个问题在本地(macOS、WSL2)均不存在——只要重启 VS Code Window 就能无论在终端抑或在插件中识别到 TeX Live 路径。

    最后还是通过 tlmgr 通过软链接的方式将 TeX Live 的路径链接到了 /usr/local/bin 目录下,而这个目录默认就在环境中的 PATH 中,这样 LaTeX Workshop 就能识别到 TeX Live 路径了。

    sudo env PATH=$PATH tlmgr path add

    tlmgr path 命令 在文档深处且几乎没人提及,在用 install-tl 脚本安装如果不添加 --no-interaction 参数安装前便会有选项通过 create symlinks 添加到 PATH,但是这个选项默认是不勾选的,进一步搜索才发现 tlmgr 可以在安装后实现同样的效果。

    env PATH=$PATH 也是为了让 sudo 使用当前终端的 PATH ,我怀疑这里和插件的不识别路径是同样的问题,但是暂时没有深究。

    配置中文字体

    这算是 LaTeX 在中文环境下本地化的内容了。其实在 GitHub 上也有过开源的仓库诸如 WebLaTeX ,但是一是其使用 Docker 安装 TeX Live 应该还不是最新版导致我某个包一直报错,二是自然没有考虑中文字体使用的情况。

    最方便安装的含 CJK 的字体自然是思源 Noto 系列字体,在 Ubuntu 下可以直接通过 APT 安装:

    sudo apt install fonts-noto-cjk # fonts-noto

    然后通过 XeTeX 引擎可以不用额外配置直接 fallback 调用系统字体,在多语言使用中更为方便。

    不过字体这个我确实也没办法完全帮你搞定,一种字体往往倾注了设计师大量心血,也是版权问题的重灾区。更何况不同学校、不同老师、不同期刊对于字体的要求都不尽相同。例如我们学校毕业论文的要求是中文宋体(SimSun)、英文 Times New Roman,而这两者均无法通过 APT 安装,请自行合理获取你所需要的字体文件手动安装。

    这里介绍一种简单的、不需要 root 权限的仅为当前用户安装字体文件(.ttf/.otf)的方法——将字体文件放在 ~/.fonts 目录下即可。

    mkdir -p ~/.fonts  # If the directory does not exist
    cp /path/to/your/font.ttf ~/.fonts

    另一个较为暴力的方法是直接将 Windows 字体目录软链接到 WSL 内的字体目录下:

    # 先获取宿主机目录在 WSL 内的挂在位置
    wslpath 'C:\Windows\Fonts'
    # Output: /mnt/c/Windows/Fonts
    # 然后再将该目录链接到用户字体目录等位置
    ln -s /mnt/c/Windows/Fonts ~/.fonts
    # 确认创建成功
    ls -l ~/.fonts
    # lrwxrwxrwx  1 <name> <name>   20 May 14 11:45 .fonts -> /mnt/c/Windows/Fonts

    这样,你就可以在 WSL 中使用 Windows 的字体了。

    如果没有立即生效,可以运行 fc-cache -f -v 强制刷新字体缓存。你也可以使用 fc-list :lang=zh 命令检查是否已经新增了相应的中文字体。

    然后就可以在 LaTeX 文档中使用这些字体了,例如:

    \usepackage{xeCJK}
    \setCJKmainfont{SimSun}
    \setmainfont{Times New Roman}

    你也可以把这些配置统一写进你自定义的 .cls 文件里,以便在每个文档中引用。

    更新异常

    后续使用过程中逐步探索更复杂的模板、类的用法,进一步的借助 Beamer 直接将 TeX 编译成 Slides 也有尝试。其中有个模板用到 l3build 自动化 LaTeX3 项目的构建、测试和发布。考虑到当前环境已经安装了一两年,在用 l3build 将项目源码在本地编译成 TeX Live 可以识别的组织形式之前,我先尝试将 TeX Live 更新:

  • 将 TeX Live 路径(默认 /usr/local/texlive )以版本年份为名的目录复制或移动到最新版本年份,例如 2021 目录移动到 2023 目录
  • update-tlmgr-latest.sh 更新 tlmgr 包管理器
  • 再用更新好的 tlmgr 更新所有包
    tlmgr update --self --all
  • 刚更新完还没编译新模板,旧版 TeX Live 可以编译的文档直接报错:

    ! LaTeX3 Error: Mismatched LaTeX support files detected.
    (LaTeX3)        Loading 'expl3.sty' aborted!

    简单 Google 一下,靠前的回答让 fmtutil-user / fmtutil-sys ──与 TeX Live 相关的命令行工具,用于管理用户级(对于后者,系统级)的格式文件──完全重新建立格式文件,避免旧版残留。

    fmtutil-user --all
    fmtutil-sys --all

    这个命令会花费一些时间,然而在我的环境中并没有解决问题,无论重置用户级抑或是系统级格式文件。后来我也尝试了用 tlmgr 重新安装 l3build 包,依然无济于事。最后甚至完全重装了 TeX Live 均无补。

    好在看到 StackExchange - TeX 的一个回答 提到解决方案:

  • kpsewhich 可被用于查找各种 TeX 文件(如 .sty , .cls , .tex , .bib 等)的路径
  • 若检索出多个格式文件路径
    • 通过 fmtutil-sys --byfmt <fmt> 选择在最新路径(如 /usr/local/texlive/2024 )下的
    • 或者干脆删掉一般在 ~/.texlive 下的旧格式文件
    • kpsewhich --all --engine=xetex xelatex.fmt

      前文提到,我主要使用更适合中文环境的 XeTeX,所以 kpsewhich 针对检索了它的格式文件。而该命令输出确实额外多出一条在家目录下的路径,甚至还排在 /usr/local/texlive 下的路径之前。这个家目录下的 TeX Live 路径在旧版本生成,估计不会被包管理器更新。回答中提到「或许总是在更新 l3kernel 时遇到(这个问题)」也和我的情况相符。删除整个 ~/.texlive<year> 目录后再次运行建立格式文件的命令,问题得以解决。

      rm -rf ~/.texlive<year>
      fmtutil-user --all
      
  •