Quartus 命令行退出码非零速查:quartus_sh/quartus_fit 报错但屏幕看不出原因怎么办
更新时间:2026-10-23。FAQ 速查页,属于 FPGA 工具报错排错系列。Quartus 命令行在 CI/脚本里最气人的故障形态是:
quartus_sh --flow compile跑完,shell 拿到非零退出码,可滚屏输出里一眼看不到 Error——到底是编译真挂了、license 没了,还是脚本自己把原因吞掉了?本篇把「Quartus 命令行退出码非零」的六类真实病因排成速查表。license 拉取本身的深水区分诊见 Quartus license 取不出来,进程不是退出而是直接崩掉(段错误、core dump)的那类见 Quartus 崩溃段错误速查。
本文要回答的问题
- CI 日志里只有
Error: Quartus Prime ... was unsuccessful. N errors, M warnings,原因藏在哪? - 没有任何 Error,只有一堆 Critical Warning,为什么也算失败、怎么让它不算?
-c <revision>指定的 revision 不存在、flow 跳步跑(没 map 直接 fit),退出码长什么样?- 脚本里用管道或重定向之后,真正的报错怎么就「消失」了?
- 退出码 130、137、143、144 各自是谁杀了我的编译?
一、现象与报错原文
现场通常有三层输出,原因往往藏在最底层那层:
1. make / CI 封装层看到的,只有一个干巴巴的退出码:
quartus_sh --flow compile demo -c demo
make: *** [Makefile:12: compile] Error 1
ERROR: Job failed: exit code 1Error 1 是 make 转述的子进程退出码,不含任何 Quartus 语义。真正的信息在上一步 Quartus 自己写的日志里。
2. Quartus stdout 的尾部,常常只有汇总没有明细:
Info (293000): Quartus Prime Full Compilation was successful. 0 errors, 7 warnings
...
Error (293000): Quartus Prime Full Compilation was unsuccessful. 3 errors, 42 warnings
Error: Quartus Prime Fitter was unsuccessful. 1 error, 18 warningswas unsuccessful 这行只告诉你「失败 + 数量」,具体那 3 个 error 在几百行之前的滚动输出里,CI 界面默认折叠后就看不到了。
3. 报告文件里的真相。 每个阶段都有对应的报告:.map.rpt、.fit.rpt、.sta.rpt、.asm.rpt,失败阶段的 .rpt 尾部与 Error/Critical Warning 段落才是第一手现场。
二、现象 → 区分点 → 处置速查表
| 现象 | 区分点 / 最常见原因 | 处置 |
|---|---|---|
| 有 Error 但在滚屏里找不到 | CI 折叠输出,Error 行在几百行之前 | 直接 grep -n "^Error" compile.out 或翻对应阶段 .rpt 的 Error 段 |
| 0 errors 但仍失败 | Critical Warning 被工程/Tcl 流程当作失败判据 | 看流程脚本是否检查 CW 计数;确认 CW 内容后修复或用消息抑制降级 |
报错 Can't find design file 或 revision 相关提示 | -c <revision> 指定的 revision 在 .qsf 里不存在 | quartus_sh --tcl_eval project_open demo; get_all_revisions 列出现有 revision 对名 |
| fit/sta 报错「需要先运行上一阶段」 | flow 跳步:没跑 map 就直接 fit/sta | 按 map → fit → asm → sta 顺序串行跑,或直接用 --flow compile |
| 屏幕干净但退出码非零 | stderr 被管道/重定向吞掉,或日志落到了别处 | 命令尾部加 `2>&1 |
| 无 Error、日志中途戛然而止 | license 静默失效:只体现为流程中止 | 看日志尾部是否有 license 相关 Info;按 Quartus license 取不出来 分诊 |
| 退出码 137 / 144 | OOM killer 或系统杀了进程(137 = SIGKILL) | dmesg 查 OOM 记录;降并行度或加内存,别当 Quartus bug 排 |
| 退出码 130 / 143 | 130 = Ctrl-C(SIGINT),143 = SIGTERM(CI 超时杀) | 查是谁发的信号;CI 侧分级超时见下文 |
三、排查决策树
分诊只问两个问题:失败阶段的 .rpt/stdout 里有没有真 Error;退出码是不是外部信号给的。两条答案把现场切成「Quartus 自己拒绝」和「进程被外力终止」两条通道:
读这张图抓住两条主线:Quartus 自己拒绝的路径——grep 总能捞出 Error 或 CW 痕迹,顺着 Error 编号修就行;外力终止的路径——退出码落在 128 以上的信号区间(130/137/143/144),那不是 Quartus 的意见,是有人杀了它,排错方向要换成「谁发的信号」。 红色是入口现象与被外力终止这一病态态,蓝色是排查动作,绿色表示「原因已经捞到手」,橙色是修复,紫色是收口防复发。最忌讳的是不 grep 就直接重跑:Error 行在滚屏里沉底,肉眼翻十次不如一条 grep。
四、逐条排查展开
先把真错捞出来,再谈排查。 失败任务的输出里定位全部 Error 与 Critical Warning 只要一行:
grep -nE "^(Error|Critical Warning)" compile.out
# 或直接看失败阶段报告的尾部
tail -n 60 output_files/demo.fit.rpt.rpt 文件里每个 Error 都带编号(如 Error (170048)),拿编号去搜比拿自然语言描述去搜准得多。
Critical Warning 也会「算失败」。 默认流程下 CW 本身不置退出码,但两条常见路径会让它变成失败:一是工程 Tcl/CI 脚本显式检查 CW 计数(比如要求时序类 CW 为 0),二是某些高严重度 CW(如时序不收敛、引脚未分配落在关键配置脚)被上层流程判为不可发布。遇到 0 errors 但流程判失败,先翻脚本里有没有对 warning 计数的断言,再决定是修 CW 本体还是用消息抑制(Message Suppression)把确认无害的条目降级——不要图省事全局关掉 CW 显示。
revision 不存在是脚本拼写事故的高发区。 -c demo_v2 而工程里只有 demo,Quartus 会报找不到 revision 并非零退出,但提示行在大量 Info 里一闪而过。跑命令前列一遍现有 revision 对名:
quartus_sh --tcl_eval project_open demo; get_all_revisionsflow 前置依赖不能跳。 单独跑 quartus_fit 要求 map 阶段的数据库已存在;没跑过 map 直接 fit,会因缺前置结果失败。CI 里各阶段拆开跑时,顺序固定为 quartus_map → quartus_fit → quartus_asm → quartus_sta,不确定就老老实实 quartus_sh --flow compile 一把梭。
stderr 被吞是脚本自己的锅。 quartus_fit demo | grep -i error 这种写法,一旦 grep 没匹配到还会让管道返回非零,把「编译其实成功了」变成「脚本说失败了」。规范写法是让 Quartus 输出原样落盘:
quartus_sh --flow compile demo > compile.out 2>&1
echo "exit=$?"拿到原始退出码与完整日志,再谈后面所有分析。
license 静默失效:只体现在「流程中止 + 非零退出」。 网络抖动导致 license 断开时,部分版本的命令行进程不打印显眼 Error,日志停在与 license 相关的 Info 附近就结束。确认方法:单独跑一次拿干净日志,看尾部;license 服务器可达性、席位占用、心跳超时的完整分诊走 Quartus license 取不出来。
退出码 ≥128 的全部按「信号死亡」处理。 130 是 Ctrl-C,137 是 SIGKILL(Linux 下头号嫌疑是 OOM killer,dmesg | grep -i oom 石锤),143 是 SIGTERM(CI 超时机制最爱发这个),144 多为封装层转述的 137 变体。这类失败的修复对象是内存配额、并行度(NUM_PARALLEL_PROCESSORS)与超时配置,不是 Quartus 工程本身。进程是被杀到连日志都来不及写完的,和 Quartus 崩溃段错误速查 里「自己崩出 core」的形态相邻但根因不同,别混在一起排。
五、预防与纪律
- 日志先行:所有 CI 调用固定
> compile.out 2>&1落盘并归档,失败任务的第一动作是 grep 不是重跑。 - revision 名入变量:脚本里 revision 名只定义一处,改工程时同步改脚本。
- flow 不跳步:拆阶段跑就按 map → fit → asm → sta 固定顺序,或整段
--flow compile。 - CW 治理:时序类 Critical Warning 清零进 CI 判据,确认无害的逐条抑制,禁止全局屏蔽。
- 内存留裕量 + 分级超时:编译机内存按峰值留 30%;map/fit 分开限时,超时杀进程前保留日志现场。
- license 超时化:心跳与重连设上限,断连快速失败并打印明确原因。
这一篇在知识体系里的位置
本篇是 FPGA 排错速查簇中「Quartus 命令行退出码」节点的 FAQ 页:退出码背后的 license 分诊展开见 Quartus license 取不出来;进程不是非零退出而是直接崩出 core dump 的形态见 Quartus 崩溃段错误速查。三篇合起来覆盖命令行失败的三种终态:有错的失败、无声的失败、被外力终止的失败。
一句话总结
Quartus 命令行退出码非零的分诊起点是把「封装层转述的 exit code」还原成「失败阶段的真实输出」:grep Error 与 Critical Warning、看 .rpt 尾部。有 Error 按编号修;0 error 查 CW 判据、revision 名与 flow 顺序;什么都查不到就先去掉管道单独复跑拿原始退出码;退出码落在 130/137/143/144 区间一律按外部信号(Ctrl-C、OOM killer、CI 超时)处理。根治靠日志落盘归档、flow 不跳步、CW 治理与分级超时,让每一次失败都自带可回溯的现场。