nextpnr 找不到文件或路径:Failed to open input file 速查
更新时间:2026-10-23。FAQ 速查页,面向用 Yosys + nextpnr 开源流程做 iCE40 / ECP5 / Gowin 开发的同学。典型场景:照抄网上的 Makefile 一把
make下去,综合那步明明过了,nextpnr 一启动就报打不开文件——.json网表、.pcf引脚约束、--chipdb数据库总有一个找不到。这类报错九成不是工具坏了,而是传给 nextpnr 的路径字符串解析出来的位置,和文件实际落盘的位置对不上。本篇只收「文件系统层面打不开」一族;文件能打开但模块找不到的(ERROR: module not found 类),见 nextpnr 找不到模块速查;上游综合阶段的同类问题见 Yosys 路径不存在速查。
本文要回答的问题
- nextpnr 的 Failed to open input file / No such file or directory 报错原文长什么样?
- Makefile 里 yosys 的产物路径和 nextpnr 的读取路径为什么会对不上?
- 在子目录里跑 make、约束文件没生成、文件名有空格,各是怎么把路径搞断的?
--chipdb显式指定数据库时路径怎么查?符号链接失效怎么确认?
一、报错原文与一句话根因
以下文案按 nextpnr(ice40/ecp5/gowin 各后端措辞基本一致)的真实输出风格整理,路径与工程名均占位:
1. 输入网表打不开(最高频):
ERROR: Failed to open input file 'build/demo.json'.
0 warnings, 1 error2. 引脚约束文件打不开:
ERROR: Failed to open PCF file 'constraints/demo.pcf'.3. 显式指定的 chipdb 数据库打不开:
ERROR: Failed to open chipdb file '/opt/fpga/share/nextpnr/ice40/chipdb-5k.bin'.4. shell 层就断(工具根本没被调起来):
nextpnr-ice40: No such file or directory
make: *** [build/demo.asc] Error 1一句话根因:nextpnr 是命令行工具,它拿到的每个路径要么来自 Makefile 变量,要么来自命令行参数,全部按「你敲命令时所在的目录」做相对路径解析;一旦 Makefile 里写死的产物目录名和 yosys 实际输出目录名不一致、你在错误的子目录里跑 make、约束文件根本没生成、或符号链接指向已被删掉的目标,这条路径就指向空处。 排查总原则只有一句:把 nextpnr 实际收到的路径原样拿去 ls 一下,对了再往下猜,不对就先修路径。
二、排查决策图
先用这张图定方向,再照第三节病因表对号入座。读图方式:红色是入口报错,蓝色是排查动作,绿色是「目标真实存在」的通过判定,橙色是各分支的修复动作,紫色是收尾的防复发约定。每修一步都回到蓝色检查节点重验。
direction: down
err: "报错:Failed to open input file / No such file or directory"
chk: "把报错里的路径原样 ls 一下\nrealpath 看解析结果"
gen: "yosys 产物没生成或目录名对不上?"
cwd: "是在 Makefile 所在目录跑的 make?"
pcf: "缺的是 .pcf/.lpf 约束文件?"
link: "路径里有符号链接?"
db: "显式指定了 --chipdb?"
fixgen: "先单独跑 yosys 看报错\n统一 build 目录变量"
fixcwd: "回到工程根目录重跑 make"
fixpcf: "补写约束文件或修正文件名"
fixlink: "重拷真实文件替换失效软链"
fixdb: "改指真实 chipdb 路径或去掉参数"
pass: "nextpnr 正常读入继续布线"
prev: "防复发:Makefile 变量集中定义\nCI 里加 ls 预检,路径纯英文无空格"
err -> chk
chk -> gen: "文件不存在"
gen -> fixgen: "是"
gen -> cwd: "否,文件其实在"
cwd -> fixcwd: "工作目录不对"
cwd -> pcf: "目录对仍打不开"
pcf -> fixpcf: "约束没生成/名不对"
pcf -> link: "不是约束问题"
link -> fixlink: "链接目标已删"
link -> db: "链接正常"
db -> fixdb: "数据库路径错"
db -> pass: "全部路径有效"
fixgen -> chk
fixcwd -> chk
fixpcf -> chk
fixlink -> chk
fixdb -> chk
pass -> prev
err.style: { fill: "#FDECEC"; stroke: "#D9534F" }
chk.style: { fill: "#EAF2FE"; stroke: "#3B6FD4" }
gen.style: { fill: "#EAF2FE"; stroke: "#3B6FD4" }
cwd.style: { fill: "#EAF2FE"; stroke: "#3B6FD4" }
pcf.style: { fill: "#EAF2FE"; stroke: "#3B6FD4" }
link.style: { fill: "#EAF2FE"; stroke: "#3B6FD4" }
db.style: { fill: "#EAF2FE"; stroke: "#3B6FD4" }
fixgen.style: { fill: "#FEF3E2"; stroke: "#E08A1E" }
fixcwd.style: { fill: "#FEF3E2"; stroke: "#E08A1E" }
fixpcf.style: { fill: "#FEF3E2"; stroke: "#E08A1E" }
fixlink.style: { fill: "#FEF3E2"; stroke: "#E08A1E" }
fixdb.style: { fill: "#FEF3E2"; stroke: "#E08A1E" }
pass.style: { fill: "#E9F8F0"; stroke: "#2E9E6B" }
prev.style: { fill: "#F1ECFD"; stroke: "#7A5BD4" }这张图覆盖六大根因:产物路径不一致、工作目录漂移、约束文件缺失、符号链接失效、chipdb 路径错,以及收口前的「文件其实存在」确认;特殊字符截断一类在第三节表里单独给验证方法。
三、病因处置表
| 报错现象 | 根因 | 快速验证 | 处置 |
|---|---|---|---|
| make 一把跑、nextpnr 报 .json 打不开 | Makefile 里 yosys 输出路径(如 build/)与 nextpnr 读取路径写成了两个变量/两个目录名 | ls build/ 看 .json 在不在;make -n 看实际命令 | 统一用一个 BUILD 变量;先单独跑 yosys 确认产物落盘 |
| 在工程根目录能跑,进子目录跑就断 | 相对路径按当前工作目录解析,make 在子目录里找不到上一级文件 | pwd 对比 Makefile 所在目录 | 回到 Makefile 所在目录跑;或用 make -C 指定 |
| 报 .pcf/.lpf 打不开但约束文件明明写过 | 约束文件没纳入版本管理、换了目录名,或模板工程引用的是示例名 | ls constraints/ 逐字符核对文件名(含大小写) | 按磁盘真实文件名改 Makefile 的 PCF 变量 |
| 报错路径在空格处断成两截 | 路径含空格/中文/括号,shell 分词或工具内部拼接时被截断 | ls 带引号看完整路径名 | 工程整体迁到纯英文无空格路径,Makefile 里变量引用加引号 |
| 工程从别处拷来后所有路径都失效 | 目录里是符号链接,目标在源机器上,拷过来只拷了链接本身 | ls -l 看箭头指向,readlink -f 看解析结果是否悬空 | 重新拷真实文件;或修复链接指向本机实际路径 |
只有显式 --chipdb 的脚本报错,默认跑没事 | 指定的数据库文件路径错(版本升级后目录变了、装在了别的前缀下) | ls 报错里那条绝对路径;find / -name 'chipdb*.bin' 定位真身 | 改指真实路径;或去掉 --chipdb 让 nextpnr 用内置默认 |
文件在、ls 能开、nextpnr 仍报打不开 | 文件名大小写与 Makefile 引用不一致(Linux 大小写敏感) | ls 输出与 Makefile 里的写法逐字符 diff | 统一大小写,以磁盘真实名为准 |
四、三个最高频根因的修法
根因一:Makefile 里产物路径与读取路径不一致。 开源 FPGA 教程的 Makefile 五花八门,最常见的断法是 yosys 那步输出到 build/demo.json,nextpnr 那步却引用 out/demo.json——两个变量、两个目录名,综合过了、布线找不到。标准写法是一个变量管到底:
BUILD := build
TOP := demo
$(BUILD)/$(TOP).json: rtl/$(TOP).v
yosys -p "synth_ice40 -top $(TOP) -json $@" $^
$(BUILD)/$(TOP).asc: $(BUILD)/$(TOP).json constraints/$(TOP).pcf
nextpnr-ice40 --hx1k --json $< --pcf constraints/$(TOP).pcf --asc $@排查时先 make -n 把将要执行的命令打印出来(不真跑),逐条看每个 -o/-json/--json 参数指向的路径,再拿 ls 对。也可以加一行调试目标 @echo yosys 输出到 $(BUILD)/$(TOP).json 让变量展开显形。
根因二:相对路径的工作目录漂移。 nextpnr 自己不认识 Makefile,它只看调用瞬间的当前目录。在工程根目录 ./constraints/demo.pcf 是对的,在 rtl/ 子目录里跑同一条命令就指向 rtl/constraints/demo.pcf——不存在。GUI 脚本、IDE 终端、tmux 分屏各开在不同目录时尤其容易中招。修法很机械:所有命令固定在 Makefile 所在目录执行;团队协作时在 README 第一句写明「在工程根目录跑 make」。跨目录脚本必须用路径时,用 $(abspath ...) 或 $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) 把基准钉死在 Makefile 自己身上。
根因三:约束文件没生成或符号链接失效。 .pcf(iCE40)/.lpf(ECP5)约束文件常被当成「配置文件」不入库,模板工程里引用的又是 blinky.pcf 这种示例名,clone 下来一改顶层名就断。另一族更隐蔽:工程目录里 chipdb-5k.bin 是个符号链接,指向源机器 /opt/fpga/... 下的真身,用 cp -r 或压缩包拷过来时只拷了链接(cp 不带 -L),ls -l 一看箭头指向一个不存在的绝对路径。确认方法:
ls -l chipdb-5k.bin # 看是不是 l 开头的符号链接
readlink -f chipdb-5k.bin # 看解析后的最终路径
test -e chipdb-5k.bin && echo OK || echo BROKEN链接失效就重拷真身;约束文件缺了就按磁盘上真实文件名改 Makefile 的 PCF 变量,或者干脆补一份进版本库。
最后提醒 --chipdb 一族:绝大多数场景不需要显式指定,nextpnr 启动时会按编译时的安装前缀自动找数据库。只有自编译安装、多版本并存时才需要它,而升级工具链后旧脚本里的绝对路径常常指向已被覆盖的目录——报错的措辞同样是 Failed to open chipdb file,按表里第六行定位真身后改指即可。
五、修复后验证与防复发
修完不要只看「这次 make 过了」。先 make clean 清掉旧产物全量重跑一遍(增量可能掩盖路径问题),再把 make -n 的输出里所有路径参数挑出来逐条 ls 确认,最后确认 .asc/.bin 比特流真实生成——nextpnr 静默产空文件的情况虽少,但路径问题修错方向时会出现「没报错也没产物」。
防复发三件事:其一,Makefile 里所有目录名集中到开头变量区(BUILD :=、RTL :=、CONSTRAINTS :=),正文只引用变量,杜绝同一个目录在多处拼写;其二,在 CI 或 pre-build 钩子加一行预检,test -f 把网表、约束、chipdb 三个关键路径全查一遍,缺哪个直接报人话而不是让 nextpnr 抛英文错;其三,工程路径规范写进约定:纯英文、无空格、约束文件随 RTL 一起入库、跨机器传工程打 tar 时加 -h(跟随符号链接拷真身)。
养成一个肌肉记忆:接到别人的工程或换台机器,第一件事不是 make,而是 make -n | grep -E 'json|pcf|chipdb' 把所有文件路径参数打出来,对着 ls 扫一遍。三十秒预检,省掉对着 Failed to open input file 反推半小时。文件在、编译器却看不见模块定义的另一族问题,对照 nextpnr 找不到模块速查;上游综合阶段的同族路径问题,见 Yosys 路径不存在速查。
一句话总结
nextpnr 找不到文件或路径的本质是「传给 nextpnr 的路径字符串」与「文件实际位置」脱节:Makefile 里 yosys 产物目录名与 nextpnr 读取路径写成两套、相对路径按当前工作目录解析导致换目录即断、.pcf/.lpf 约束文件没生成或文件名对不上、路径含空格中文被截断、工程拷贝时符号链接目标没跟过来、显式 --chipdb 指向已失效的数据库路径;先用 make -n 加 ls/realpath 让实际要找的路径显形,再按统一变量、固定工作目录、补齐约束、替换失效软链、改指真实 chipdb 逐条修复,Makefile 变量集中定义加 CI 路径预检是防复发的闭环。