如何获取Haskell项目的文件级递归依赖关系图?
如何用Stack或Cabal提取Haskell文件级递归依赖?
我的Haskell项目包含多个可执行目标,目录结构如下:
... app/ other_app/ src/ package.yaml stack.yaml ...
app/、other_app/和src/目录下有不同的.hs文件。用Stack构建时,若src/中的.hs文件变更,相关可执行文件会重新构建,说明Stack能识别类似GNU make的依赖关系图。我希望像C语言的makedepend工具那样,递归提取Haskell文件的文件级依赖(而非Stack dot提供的包级依赖),比如获取app2的Main.hs对应的文件依赖列表:
- src/Component1/Types.hs
- src/Component1/Utils.hs
- src/CoolLibrary/CoolUtility.hs
...
项目的package.yaml配置片段如下:
............. executables: app1-exe: main: Main.hs source-dirs: app1 ghc-options: - -threaded - -rtsopts - -with-rtsopts=-N dependencies: - app1 app2-exe: main: Main.hs source-dirs: app2 ghc-options: - -threaded - -rtsopts - -with-rtsopts=-N dependencies: - app1 ............
请问能否通过Stack或Cabal工具实现该需求?此前尝试Cabal的v2-freeze命令,发现与需求无关。
可以通过Stack或Cabal结合GHC原生功能实现
方法一:通过Stack调用GHC生成依赖信息
Stack本身没有直接输出文件级依赖的命令,但可以借助GHC的-M参数(生成Makefile风格的依赖规则)来实现:
- 针对目标可执行文件,执行以下命令生成依赖文件:
执行后会生成stack ghc -- --make app2/Main.hs -M -dep-makefile app2.depsapp2.deps文件,里面包含app2/Main.hs递归依赖的所有本地.hs文件路径,格式符合Makefile的依赖规则。 - 如果只需要保留项目内的文件(过滤系统库/外部包依赖),可通过文本工具提取:
grep -E 'src/|app2/' app2.deps | cut -d: -f1 | sort | uniq
方法二:通过Cabal调用GHC生成依赖
Cabal同样可以借助GHC的-M参数实现,步骤类似:
- 执行以下命令生成依赖文件:
同样会生成包含所有递归依赖的cabal exec -- ghc --make app2/Main.hs -M -dep-makefile app2.depsapp2.deps文件。 - 提取项目内依赖文件的命令与Stack方案一致:
grep -E 'src/|app2/' app2.deps | cut -d: -f1 | sort | uniq
补充说明
- GHC的
-M参数会递归解析所有导入模块对应的.hs文件,完全匹配你需要的makedepend类功能。 - 执行命令前确保Stack/Cabal已正确加载项目依赖环境,这样GHC才能找到所有模块的路径。
- 如果需要结构化输出(如JSON格式),可以使用第三方工具
ghc-deps,但仅需基础文件列表的话,上述方法足够满足需求。
内容的提问来源于stack exchange,提问作者RandomB
相关产品推荐
相关产品推荐

