NextPDF Backport Builder 故障排查
构建工具,而不是运行时依赖包。本页列出的每个症状都属于维护者或 CI 主机上的构建期状况。这些状况不会出现在下游应用程序中。
构建会按顺序执行五个阶段。它会在第一个失败点停止,并输出阶段名称和信息。先查看对应阶段,再到下方定位原因。五个阶段分别是合并来源、执行 Rector 降级、生成 composer.json、复制静态资产和验证输出。已对照 scripts/build.php(run() 与 step())验证。
阶段:合并来源
标题为“阶段:合并来源”的章节「找不到来源仓库 '',位置:」
标题为“「找不到来源仓库 '',位置:」”的章节合并阶段会在复制之前验证每个预期的来源仓库。若有仓库缺失,它会带着缺失仓库的名称和路径中止。PHP 8.1 目标预期包含 nextpdf、nextpdf-Artisan、nextpdf-compat-legacy、nextpdf-Laravel、nextpdf-Symfony、nextpdf-CodeIgniter;纳入 Pro 时还包括 nextpdf-Pro。PHP 7.4 目标仅预期 nextpdf。已对照 scripts/merge-sources.php(run() 验证循环、__construct() 仓库映射表)验证。
解决方式:将这些仓库以同级目录的形式检出到传入 --source-dir 的路径下,并使用上述确切的目录名称。试运行(dry-run)会列出它将读取的每个仓库。可以先用它确认布局,再执行完整构建。
阶段:执行 Rector 降级
标题为“阶段:执行 Rector 降级”的章节Rector 以非零码结束
标题为“Rector 以非零码结束”的章节协调器会报告 Rector failed on <label> (exit code: N) 并停止。该标签会指出失败发生在哪个阶段——public package、pro package、enum pre-processing 或 full downgrade。已对照 scripts/build.php(runRectorPass())验证。
枚举默认值触发默认参数解析器崩溃(PHP 7.4)
标题为“枚举默认值触发默认参数解析器崩溃(PHP 7.4)”的章节这也是 PHP 7.4 目标采用两遍处理的原因。Rector 的默认参数值解析器在遇到作为构造函数提升默认值的枚举 case 时会崩溃。第 1 阶段(rector-php74-enums.php)会先把枚举转换为常量列表类。这样第 2 阶段的完整流程就永远不会看到枚举 case 默认值。如果你绕过协调器,直接对带有枚举的源代码执行完整的 PHP 7.4 配置,就会触发这个崩溃。已对照 scripts/build.php(runRector() 注解与两遍顺序)与 rector/config/rector-php74-enums.php 验证。
基准测试脚本使 Rector 崩溃
标题为“基准测试脚本使 Rector 崩溃”的章节rector-php81.php 与 rector-php74.php 会跳过 */tests/Benchmark/*。那些脚本引用了 Rector 无法解析的外部 PDF 函数库,因而使默认参数解析器崩溃。如果某个基准测试路径被处理,说明跳过用的通配符模式缺失,或路径不同。已对照 withSkip() 调用验证。
MHASH_XXH* 崩溃(PHP 7.4)
标题为“MHASH_XXH* 崩溃(PHP 7.4)”的章节rector-php74.php 会跳过 DowngradeHashAlgorithmXxHashRector。那条内置规则在遇到 xxHash 常量时会崩溃。源代码并未使用 xxHash,因此跳过是安全的。已对照 rector/config/rector-php74.php(withSkip())验证。
阶段:Rector 后续修正(仅 PHP 7.4)
标题为“阶段:Rector 后续修正(仅 PHP 7.4)”的章节这些修正会在两个阶段之间执行。它们会改写枚举转类规则留下的模式。如果 PHP 7.4 输出中仍出现涉及 EnumClass::Case->value、->name、以实例方法调用的原枚举方法,或在未解析类型上使用命名实参的解析错误,说明修正没有匹配到该模式。clone-with 的限制同样适用:实参匹配并非递归,因此带有嵌套括号的覆盖值不会被改写。已对照 scripts/build.php(postProcessFixups()、fixEnumMethodCallSites()、applyFixups())与 rector/rules/DowngradeCloneWithRector.php(记载于文件的限制)验证。
阶段:产生 composer.json
标题为“阶段:产生 composer.json”的章节这个阶段会把处理后的 src/ 与 tests/ 从构建临时目录移动到输出目录。随后写入生成的 composer.json。此处的失败几乎都属于文件系统问题:输出目录不可写,或因为 Rector 没有产出任何内容而导致构建临时树缺失。已对照 scripts/build.php(adjustComposer()、moveTree())验证。
阶段:复制静态资产
标题为“阶段:复制静态资产”的章节这个阶段会从核心来源仓库复制 LICENSE,并写入生成的 CHANGELOG.md。当授权文件不存在时,复制会被静默跳过,构建继续进行;变更记录则始终会写入。此处的失败表示输出目录在构建过程中变为不可写。已对照 scripts/build.php(copyStaticAssets())验证。
阶段:验证输出
标题为“阶段:验证输出”的章节「找不到输出的 src/ 目录」/「在输出中找不到 PHP 文件」
标题为“「找不到输出的 src/ 目录」/「在输出中找不到 PHP 文件」”的章节验证需要一个非空的 output/src。空目录树表示合并没有复制任何内容,或文件移动失败。已对照 scripts/build.php(validateOutput())验证。
「语法验证:已略过(需要 PHP 运行时)」
标题为“「语法验证:已略过(需要 PHP 运行时)」”的章节这是预期内的情况,并非错误。构建主机运行的是现代版 PHP,而非目标版本,因此本机阶段只会统计文件数量,并输出用于真正语法检查的 Docker 指令。具权威性的语法门禁是发行工作流中构建后的 php -l 步骤,它会在实际的目标运行时下执行。已对照 scripts/build.php(validateOutput())与 .github/workflows/build.yml(PHP 8.1/PHP 7.4 语法检查步骤)验证。
已知限制
标题为“已知限制”的章节这些限制是降级方案本身固有的。已对照各规则和项目 README.md 中的「Known Limitations」验证:
- 只读属性会被移除。
readonly会被去掉,以便 clone-with 展开的显式属性赋值在较旧的运行时上合法。降级后的输出中,运行时不再强制不可变性。 - 在 PHP 8.1 上不会强制应用
#[Override]。 该属性可能仍会保留,但较旧的运行时不会对其执行任何操作。 - PHP 7.4 目标仅包含核心。 框架适配器、tcpdf 兼容层及 Pro 并不属于 PHP 7.4 分发版的一部分,这由构建脚本的结构决定。
- Pro 是独立包且仅限 PHP 8.1。 没有 PHP 7.4 的 Pro 构建。
- clone-with 实参匹配并非递归。 包含嵌套括号的覆盖值不会被转换,并且只有字符串数组键会被解析为属性名称。
- /integrations/backport/configuration/ — 规则与标志参考。
- /integrations/backport/production-usage/ — CI 门禁与发布通道。