SpyGlass 找不到文件路径:cannot open file 速查
更新时间:2026-10-23。FAQ 速查页,属于 EDA 工具排错系列。sg_shell 读工程(
.prj)、读文件列表(-ffilelist)、读 sgdc 约束或 waiver 文件时报「Cannot open file / No such file or directory」,文件十有八九就在磁盘上——工具找不到它的原因集中在六类:工程文件写的是相对路径而启动目录变了、环境变量在 sg_shell 的 shell 里没展开、NFS 挂载点不同机器路径不同、软链指向已删除的旧版本目录、文件名大小写对不上、sgdc/waiver 引用指向旧目录。路径对但权限不够的相邻问题见 SpyGlass 权限被拒 permission denied,同族问题见 PrimeTime 路径/文件不存在。
本文要回答的问题
- 文件明明存在,为什么 SpyGlass 说 Cannot open file?
- 同一个
.prj工程,本地能跑、CI 上就找不到文件,怎么回事? DESIGN_HOME之类的变量在 Makefile 里有值,直接跑 sg_shell 为什么不行?- 换一台机器路径就失效,NFS 与软链各要怎么查?
一、报错原文与现象
Error: Cannot open file '../rtl/chip_top.v': No such file or directory.
Error: Unable to open project file 'spyglass.prj': No such file or directory.
Warning: Search path '$DESIGN_HOME/ip' does not exist, ignored.
Error: Cannot open file 'constraints/top.sgdc': No such file or directory.
Error: Cannot open file 'filelist.f': No such file or directory.先盯住报错里那条路径的原始形态:以 .. 或不带 / 开头的是相对路径(查启动目录);含 $VAR 的是环境变量问题(查当前 shell 里有没有 export);报在软链名上的是链接失效(查链接目标);路径只在某台机器上找不到的是 NFS 挂载差异;报错路径与磁盘上文件名肉眼看着一样的是大小写问题。五种形态五条通道。
二、可能原因总览
| 报错现象 | 可能原因 | 处置 |
|---|---|---|
| 本地能跑、CI 找不到 | CI 启动目录与本地不同 | sg_shell 调用前 cd 固定工程根 |
.prj 里相对路径报错 | 启动目录不是写工程时的目录 | 统一启动目录或改绝对路径 |
| 含 $VAR 路径展开成空 | 当前 shell 没 source env 脚本 | env 单一来源 + echo 验证 |
| Makefile 里行、直接跑不行 | 变量只在 Makefile 作用域定义 | export 进 shell 环境再调 sg_shell |
| 换机器就找不到 | NFS 挂载点不同(/proj vs /nfs/proj) | 核对挂载表与工程检出路径 |
| 昨天能跑今天不行 | 软链指向已删除的旧版本目录 | readlink -f 查链接目标有效性 |
| 文件名看着对就是找不到 | 大小写在 Linux 上对不上 | find 按真实大小写定位 |
| sgdc/waiver 引用报旧目录 | 工程里登记的路径指向历史 run 目录 | 改用相对工程根的稳定路径 |
三、逐条排查展开
相对路径的真相是「相对 sg_shell 启动时的当前目录」。 .prj 里 read_file ../rtl/chip_top.v 没有对错,只有「在哪个目录下启动 sg_shell」才有对错。交互调试时你在工程根目录启动,路径恰好对;CI 流水线(Jenkins/GitLab runner/bsub)从构建工作区或 HOME 启动,同一条路径立刻失效。判别:在报错环境里跑 pwd 与 ls <报错路径>,一秒确认。根治二选一:调用 sg_shell 的包装脚本第一行 cd 到固定工程根目录(相对路径从此稳定),或 .prj 里统一用环境变量拼绝对路径。
含变量的路径先 echo 再谈其他。 $DESIGN_HOME/ip/pll/pll.v 找不到时,先验证变量本身:
echo $DESIGN_HOME
ls $DESIGN_HOME三类高发错法:当前 shell 根本没 source env 脚本(变量为空,路径展开成 /ip/pll/pll.v);变量定义在 Makefile 里(make 子进程里有值,你在终端直接敲 sg_shell 的 shell 里没有——这是 Makefile 作用域最常见的误会);变量在 csh 的 env 脚本里用 setenv 定义而 CI 在 bash 里跑(语法不通,变量为空)。环境变量只在一个 env 脚本里维护、交互与 CI 统一 source,是唯一根治。
NFS 挂载差异是「换台机器就不行」的第一嫌疑人。 开发机上工程挂在 /proj/chip/,CI 节点挂的是 /nfs/proj/chip/,同一份 .prj 里的绝对路径只对其中一台成立。判别不靠记忆:
mount | grep -i proj
ls -ld /proj /nfs/proj根治有两条路:路径里不写挂载点,全部从 DESIGN_HOME 这类变量拼;或各机器用 automounter/统一挂载规范把路径拉齐。EDA 工程跨机器迁移时,任何「写死的 /proj 开头绝对路径」都是定时炸弹。
软链失效是「昨天还好好的」的标准指纹。 工程里常见 ip/current -> ip/pll_v3.2/ 这类活动软链,旧版本目录被清理后链接悬空(dangling),报错形态与文件不存在完全一样。判别:
ls -l <软链路径>
readlink -f <软链路径>ls -l 里链接目标标红(或 readlink -f 解析不出)就是断了。还有一层坑:软链本身有效,但目标目录里文件被挪走——readlink -f 解析成功后再 ls 一次目标目录才算闭环。
大小写问题是 Windows 转 Linux 的必踩坑。 Windows 上不区分大小写,脚本里写 FileList.f、磁盘上实际是 filelist.f,在 Windows 侧一切正常;迁到 Linux 的大小写敏感文件系统立刻 Cannot open file。判别用 find 按忽略大小写找真实文件名:
find . -iname 'filelist.f'找到真实大小写后改引用侧(不要去改文件名——别的脚本可能引用的是现状)。团队规范层面:文件列表与 RTL 文件名全小写,写进工程公约。
sgdc/waiver 引用指向旧目录是版本迭代的遗留伤。 .prj 里登记的 sgdc 约束文件、waiver 文件路径指向某个历史 run 目录(比如别人工程里拷贝来的绝对路径),该目录归档后工程一打开就报错。判别:打开 .prj 搜 sgdc、waiver 关键字,逐条 ls 验证;根治:工程内引用的约束与豁免文件一律放进工程自己的 constraints/、waivers/ 目录,路径写成相对工程根的形式,随工程一起进版本库。
路径找不到 -> 报错路径形态分流
报错路径形态分流 -> 相对路径: pwd实测启动目录
报错路径形态分流 -> 含变量路径: echo变量并ls验证
报错路径形态分流 -> 绝对路径换机失效: mount查NFS挂载点
报错路径形态分流 -> 软链路径: readlink查链接目标
报错路径形态分流 -> 看着一样找不到: find按大小写定位
pwd实测启动目录 -> 修复: cd固定目录或prj用变量拼路径
echo变量并ls验证 -> 修复: env脚本统一source并export
mount查NFS挂载点 -> 修复: 路径走变量或统一挂载规范
readlink查链接目标 -> 修复: 重建软链指向有效交付
find按大小写定位 -> 修复: 引用侧按真实大小写改写
修复: cd固定目录或prj用变量拼路径 -> 路径规范建档防复发
修复: env脚本统一source并export -> 路径规范建档防复发
修复: 路径走变量或统一挂载规范 -> 路径规范建档防复发
修复: 重建软链指向有效交付 -> 路径规范建档防复发
修复: 引用侧按真实大小写改写 -> 路径规范建档防复发
路径找不到.style: { fill: "#FDECEC"; stroke: "#D9534F" }
报错路径形态分流.style: { fill: "#EAF2FE"; stroke: "#3B6FD4" }
相对路径: pwd实测启动目录.style: { fill: "#EAF2FE"; stroke: "#3B6FD4" }
含变量路径: echo变量并ls验证.style: { fill: "#EAF2FE"; stroke: "#3B6FD4" }
绝对路径换机失效: mount查NFS挂载点.style: { fill: "#EAF2FE"; stroke: "#3B6FD4" }
软链路径: readlink查链接目标.style: { fill: "#EAF2FE"; stroke: "#3B6FD4" }
看着一样找不到: find按大小写定位.style: { fill: "#EAF2FE"; stroke: "#3B6FD4" }
修复: cd固定目录或prj用变量拼路径.style: { fill: "#FEF3E2"; stroke: "#E08A1E" }
修复: env脚本统一source并export.style: { fill: "#FEF3E2"; stroke: "#E08A1E" }
修复: 路径走变量或统一挂载规范.style: { fill: "#FEF3E2"; stroke: "#E08A1E" }
修复: 重建软链指向有效交付.style: { fill: "#FEF3E2"; stroke: "#E08A1E" }
修复: 引用侧按真实大小写改写.style: { fill: "#FEF3E2"; stroke: "#E08A1E" }
路径规范建档防复发.style: { fill: "#F1ECFD"; stroke: "#7A5BD4" }颜色按语义分角色:红是报错入口,蓝是排查动作,橙是修复,紫是收尾防复发。主线是「看报错里路径的原始形态分流:相对路径查启动目录、含变量查当前 shell 展开、换机失效查 NFS 挂载、软链查目标、看着一样查大小写」——五条通道的判别动作都是一条命令级(pwd / echo / mount / readlink / find),先花三十秒形态归类,比一头扎进工程目录翻文件快得多。
四、预防与纪律
- 调用 sg_shell 的包装脚本第一行 cd 固定工程根:相对路径只在「工作目录被脚本强制固定」的前提下才允许出现在
.prj里。 - 环境变量单一来源:DESIGN_HOME 等路径变量只在一个 env 脚本定义并 export,交互与 CI 统一 source;Makefile 里需要的变量从 shell 继承,不另起炉灶。
- 路径不写挂载点:工程内所有路径从变量拼起,任何
/proj、/nfs开头的硬编码路径在 review 阶段拦下。 - 启动工具前存在性断言:流程脚本对
.prj、filelist、sgdc、waiver 逐一test -e/test -r,缺哪个报哪个,不把 shell 层的错带进工具日志里。 - 软链指向纳入交付检查:current/latest 类活动链接每次交付后自动验证
readlink -f可达。 - 文件名全小写公约:RTL、filelist、约束文件命名全小写,从命名规范上消灭大小写类问题。
这一篇在知识体系里的位置
本篇是 EDA 排错速查簇中「路径解析」节点的 SpyGlass FAQ 页,与 PrimeTime 路径/文件不存在 同族;路径对但权限不够的相邻问题见 SpyGlass 权限被拒 permission denied,工程配置文件语法层面的另一类读入失败见 SpyGlass 配置解析失败。
一句话总结
SpyGlass 报找不到文件路径时先看报错里路径的形态分流:相对路径用 pwd 实测启动目录、包装脚本第一行 cd 固定工程根根治;含 $VAR 的路径先 echo 再 ls,变量只在单一 env 脚本维护并 export,别指望 Makefile 里的值渗到 sg_shell 的 shell 里;换机器失效查 NFS 挂载差异、路径一律走变量不写挂载点;软链路径用 readlink -f 查悬空;文件名看着一样用 find -iname 按真实大小写定位;最后用「存在性断言 + 软链交付检查 + 文件名全小写公约」三条纪律防复发。