You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Bazel中解析latex_document构建警告并按需终止构建

拦截Bazel LaTeX构建特定警告并终止构建的最佳实践

针对Bazel 7.4中latex_document规则生成的LaTeX警告,要将其纳入构建流程并拦截特定警告终止构建,核心思路是扩展原生规则,提取沙箱内的log文件并通过自定义脚本检查警告,具体步骤如下:

1. 自定义Bazel规则扩展原生latex_document

原生latex_document不会暴露沙箱内的.log文件,因此需要编写自定义规则,先调用原生规则生成PDF,再将沙箱中的log文件拷贝到可访问路径,最后执行警告检查。

创建latex_rules.bzl文件,添加以下Starlark代码:

load("@bazel_latex//:latex.bzl", "latex_document")

def _strict_latex_document_impl(ctx):
    # 依赖原生latex_document生成的PDF产物
    latex_doc = ctx.attr.latex_doc[DefaultInfo]
    
    # 声明log文件的输出路径,方便后续检查
    log_file = ctx.actions.declare_file(f"{ctx.label.name}.log")
    
    # 从沙箱中拷贝log文件到bazel可访问目录
    ctx.actions.run_shell(
        inputs = [latex_doc.files_to_run.executable],
        outputs = [log_file],
        command = """
            # 定位沙箱内的LaTeX log文件(与主tex文件同名)
            LOG_FILE=$(find $(dirname {exec_path}) -name "{tex_base}.log")
            cp "$LOG_FILE" {output_log}
        """.format(
            exec_path = latex_doc.files_to_run.executable.path,
            tex_base = ctx.attr.main.split(".")[0],
            output_log = log_file.path,
        ),
    )
    
    # 执行警告检查脚本
    check_script = ctx.file._check_script
    ctx.actions.run(
        inputs = [log_file, check_script],
        outputs = [],
        executable = check_script,
        arguments = [log_file.path],
        mnemonic = "LatexWarningCheck",
    )
    
    return DefaultInfo(
        files = depset([latex_doc.files_to_run.executable, log_file]),
        runfiles = latex_doc.runfiles,
    )

strict_latex_document = rule(
    implementation = _strict_latex_document_impl,
    attrs = {
        "latex_doc": attr.label(providers = [DefaultInfo], mandatory = True),
        "main": attr.string(mandatory = True),
        "_check_script": attr.label(
            default = Label("//:check_latex_warnings.py"),
            allow_single_file = True,
        ),
    },
)

在项目BUILD文件中使用自定义规则:

# 原生latex_document目标
latex_document(
    name = "my_pdf",
    main = "main.tex",
    # 其他必要属性(如依赖的tex文件、宏包等)
)

# 带警告检查的严格构建目标
strict_latex_document(
    name = "my_pdf_strict",
    latex_doc = ":my_pdf",
    main = "main.tex",
)

2. 编写LaTeX警告检查脚本

创建check_latex_warnings.py脚本,解析log文件,匹配特定警告并在发现时终止构建:

#!/usr/bin/env python3
import sys
import re

def check_forbidden_warnings(log_path):
    # 定义需要拦截的警告正则,可根据项目需求修改
    forbidden_patterns = [
        r"LaTeX Warning: Reference `.+' on page \d+ undefined",
        r"Font shape `.+' in size `.+' not available",
        r"Overfull \\hbox \(\d+.\d+pt too wide\) in paragraph at lines \d+--\d+",
        r"Underfull \\hbox \(badness \d+\) in paragraph at lines \d+--\d+",
    ]
    
    with open(log_path, "r", encoding="utf-8", errors="ignore") as log_file:
        content = log_file.read()
    
    for pattern in forbidden_patterns:
        matches = re.findall(pattern, content)
        if matches:
            print("ERROR: 发现禁止的LaTeX警告:")
            for match in matches:
                print(f"  - {match}")
            sys.exit(1)
    
    print("INFO: 未发现禁止的LaTeX警告")
    sys.exit(0)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"用法: {sys.argv[0]} <LaTeX日志文件路径>")
        sys.exit(1)
    check_forbidden_warnings(sys.argv[1])

给脚本添加可执行权限:

chmod +x check_latex_warnings.py

3. 关键注意事项

  • 沙箱路径适配:通过find命令定位log文件是通用方案,避免依赖固定的沙箱路径(Bazel沙箱路径会随构建变化)。
  • 缓存机制兼容:log文件作为检查脚本的输入,Bazel会自动识别内容变化并重新检查,符合缓存逻辑。
  • 警告规则定制:根据项目规范调整forbidden_patterns中的正则,比如只拦截严重警告,忽略轻微提示。
  • 依赖顺序保证:自定义规则依赖原生latex_document的产物,确保LaTeX构建完成后再执行警告检查。

4. 验证构建流程

运行严格构建目标:

bazel build //:my_pdf_strict

如果log中存在匹配的警告,构建会立即终止并输出错误信息;无禁止警告时,构建正常完成,同时生成PDF和对应的log文件。

内容的提问来源于stack exchange,提问作者Peder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 09:54:52