Files
ouc_latex_template/build.sh
T
laoyang 6819d78f29 工作流全部迁到 WSL:新增 WORKFLOW.md,build.sh 改为 WSL 原生 #21
用户要求「全部在 wsl 完成」,原因是 Windows 上工作太多太乱,
WSL 像虚拟环境、坏了能重置、不影响系统。

## 之前为什么乱

分工是「Windows 改代码 + 两端都编」:Windows 侧一份仓库副本装满了
.aux/.log/.toc/.pdf,WSL 侧另一份,靠 scp/git pull 同步维持。
同一项目两份工作副本,漏同步就分叉。

## 实测确认的技术前提

1. **UNC 路径双向读写** —— `\\wsl$\Ubuntu-26.04\home\yongquan\...`
   Read/Write/Edit 三个工具都能直接作用于该路径,读写均落到 WSL 磁盘。
   延迟 6~63ms。⇒ 不需要「本地编辑 → scp」这套中间环节。
   ⚠️ 发行版名是 Ubuntu-26.04,不是常见的 Ubuntu 或 Ubuntu-22.04。

2. **WSL 内 TeX 可完整编译全库** —— `bash build.sh all` 13/13 通过。

3. **WSL 内 git 可推送** —— credential.helper=store 已指向含 token 的
   ~/.git-credentials,fetch 实测通过。

4. **gi.py 可迁** —— 纯标准库,无第三方依赖,复制即用。

5. **Python 依赖** —— 建 ~/.venv-latex,装 pymupdf 2.0 + fonttools 4.68.0,
   不污染系统 Python。

## 本 commit 的改动

### 新增 WORKFLOW.md
写清:为什么在 WSL、目录位置(含 UNC 路径)、日常命令、编辑方式、
PDF 不进版本库的原因、已知排版告警清单、环境重建步骤。

### build.sh 重写为 WSL 原生
原版是「Windows 通过 ssh 远程调 WSL 编译再 scp 取回」,在 WSL 内跑没意义。

新版改动:
- 去掉全部 ssh/scp,直接本地编译
- 两遍编译(目录/页码/LastPage 跨引用第二遍才稳定)
- 自动 cd 到模板目录(.sty 的 ../fonts/ 相对编译目录解析)
- 目录→主文件映射保留:幻灯片/slides、科技报告/report、
  试卷有两个主文件必须显式指定、简历不能拿 ls 第一个 .tex
- `all` 转给 verify_all.sh(那边有完整 TARGETS 清单)
- 新增 SILENT=1 输出紧凑表格,便于脚本消费
- 单目录模式找不到时列出可选目录/主文件,不用去翻源码

### WSL 侧环境(不入库,属个人配置)
- ~/.config/ouc-latex/env.sh 固定 OUC_PY / GI / WB_GITEA_CONFIG / OUC_REPO,
  提供 gi / ouccd / texbuild 别名
- ~/.bashrc 末尾 source
- ~/.local/bin/gi.py + ~/.config/ouc-latex/gitea.json(chmod 600)

## 验证

WSL 内全库编译:

    总数 13 | 通过 13 | 失败 0

逐项:劳务发放说明表 1 / 年度考核登记表 2 / 幻灯片 30(UF1) /
成绩构成说明 1 / 特殊事项说明表 1 / 科技报告 10(UF4) / 简历 3 /
试卷题型示例 6 / 参考答案 3 / 试卷归档封面 1 / 试卷归档目录 1 /
课程执行大纲 5(OF1) / 课程教学日历 2

页数与 Windows 侧历史记录逐个一致。3 处告警均为既有问题,非回归。

WSL 内工单工具:`gi whoami` → token 有效、仓库识别为 ouc_latex_template。
本工单 #21 即由 WSL 内的 gi 创建,工具链已实证可用。

## Windows 侧

备份 D:\Yongquan\backup\ouc_latex_template-win-backup-20261029.tar.gz
(49MB / 244 项 / 不含 .git)。删除前确认两端 HEAD 同为 fb7c76b、
无未推送提交、无 stash。备份保留,不删。

涉及文件:WORKFLOW.md(新增)、build.sh(重写)
2026-10-29 21:50:34 +08:00

129 lines
4.7 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# 在 WSL 内编译模板(WSL 原生版,无需 ssh/scp)
#
# 这套仓库的全部工作都在 WSL 内完成:编辑、编译、查看、提交、提工单。
# Windows 侧只通过 \\wsl$\<发行版>\... 这个 UNC 路径读取文件(只读浏览)。
#
# 用法:
# bash build.sh 特殊事项说明表 # 编译该目录下默认主文件
# bash build.sh 试卷 试卷题型示例 # 显式指定主文件(不带 .tex 也行)
# bash build.sh all # 全库所有主文件,逐个编译
# bash build.sh all 2>&1 | tee /tmp/v.log # 想留完整日志
#
# 可用环境变量:
# TEXBIN 默认 xelatex
# SILENT 非空时只打印结论行(给批量脚本用)
#
# ⚠️ 三条务必注意
#
# 1) **PDF 不要提交**。同源码编两次,页面一致但内嵌 CreationDate 不同,
# git 会认为文件变了(全库 13 个 PDF 全变 M)。提交前:
# git checkout -- '*.pdf'
# 或者用 git status 确认只 add 了源码。
#
# 2) **每个模板都要在它自己的目录里编**。.sty 里的 Path=../fonts/ 是相对
# 编译时工作目录解析的,从仓库根调用会找不到字体,报一堆
# "The font ... cannot be found"。本脚本已自动 cd,不用手动。
#
# 3) **两遍编译**。目录、页码、LastPage 跨引用要第二遍才稳定。
# 只编一遍会看到「第 ? 页」或者目录页码错位。
set -u
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TEXBIN="${TEXBIN:-xelatex}"
SILENT="${SILENT:-}"
die() { echo "$1" >&2; exit 2; }
# 目录 → 主文件。目录名与主文件名不一致的必须在这里登记。
# 简历/ 下有 fontawesomesymbols-*.tex 等宏包片段,不能拿 ls 第一个 .tex 当主文件。
mainfile_of() {
case "$1" in
幻灯片) echo "slides" ;;
科技报告) echo "report" ;;
简历) echo "简历" ;;
试卷) echo "" ;; # 有两个主文件,必须显式指定
*) echo "$1" ;;
esac
}
# 编一个:$1=目录 $2=主文件名(不带 .tex)
build_one() {
local dir="$1" name="$2"
local log="/tmp/oucbuild.$$.log"
local log1="/tmp/oucbuild.$$.1.log"
# 第一遍:产出 .aux/.toc,允许非致命错误(TOC 还没生成时会警告)
( cd "$ROOT/$dir" && $TEXBIN -interaction=nonstopmode "$name.tex" ) > "$log1" 2>&1
local rc1=$?
# 第二遍:交叉引用稳定后的最终结果,统计以这一遍为准
( cd "$ROOT/$dir" && $TEXBIN -interaction=nonstopmode "$name.tex" ) > "$log" 2>&1
local rc2=$?
local err over under pages
err=$(grep -c '^!' "$log" 2>/dev/null || :)
over=$(grep -c 'Overfull' "$log" 2>/dev/null || :)
under=$(grep -c 'Underfull' "$log" 2>/dev/null || :)
pages=$(grep -o 'Output written on .*' "$log" 2>/dev/null | tail -1)
if [ -z "$SILENT" ]; then
echo "=== $dir / $name ==="
echo " error : $err"
echo " Overfull : $over"
echo " Underfull : $under"
echo " ${pages:-(无输出,见 $log)}"
else
printf '%-24s err=%-2s over=%-2s under=%-2s %s\n' \
"$dir" "$err" "$over" "$under" "$(echo "$pages" | sed 's/Output written on .*(\([0-9]*\) page.*/\1页/')"
fi
if [ "$rc2" -ne 0 ]; then
echo "--- 错误片段($log)---" >&2
grep -A6 '^!' "$log" 2>/dev/null | head -20 | sed 's/^/ /' >&2
# 保留失败日志,方便排查;成功时删掉
return "$rc2"
fi
rm -f "$log" "$log1"
return 0
}
[ $# -eq 0 ] && die "用法: bash build.sh <目录名|all> [主文件名]"
DIR="$1"; TEX="${2:-}"
#----------------------------------------------------------------------
# 全库模式:直接转给 verify_all.sh(那边有完整的 TARGETS 清单)
#----------------------------------------------------------------------
if [ "$DIR" = "all" ]; then
exec bash "$ROOT/verify_all.sh"
fi
#----------------------------------------------------------------------
# 单目录模式
#----------------------------------------------------------------------
if [ ! -d "$ROOT/$DIR" ]; then
echo "没有这个目录:$DIR" >&2
echo "可选:" >&2
( cd "$ROOT" && ls -d */ 2>/dev/null | sed 's|/$||' | sed 's/^/ /' ) >&2
exit 2
fi
if [ -z "$TEX" ]; then
TEX="$(mainfile_of "$DIR")"
if [ -z "$TEX" ]; then
echo "$DIR/ 有多个主文件,请显式指定:" >&2
( cd "$ROOT/$DIR" && ls *.tex 2>/dev/null | grep -v fontawesome | sed 's/\.tex$//' | sed 's/^/ /' ) >&2
echo "例: bash build.sh $DIR $(cd "$ROOT/$DIR" && ls *.tex 2>/dev/null | grep -v fontawesome | head -1 | sed 's/\.tex$//')" >&2
exit 2
fi
fi
# 允许用户写带 .tex 的
TEX="${TEX%.tex}"
if [ ! -f "$ROOT/$DIR/$TEX.tex" ]; then
echo "找不到 $DIR/$TEX.tex" >&2
exit 2
fi
build_one "$DIR" "$TEX"