You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GHC无法识别Makefile中导入模块的问题求助

问题

开发Haskell项目时计划通过FFI用C扩展功能,编写了Makefile用Clang编译C代码、GHC编译Haskell代码,但执行make时,CalcLangInterpreter.hs无法找到已编译的CalcLangParser模块,尽管已先生成了接口文件。

Makefile内容:

#Directory Definitions
SRCDIR:=./src
HDIR:=$(SRCDIR)/haskell
CDIR:=$(SRCDIR)/c
LDIR:=./lib
HLDIR:=$(LDIR)/haskell
CLDIR:=$(LDIR)/c
ODIR:=./obj
CODIR:=$(ODIR)/c
HODIR:=$(ODIR)/haskell
INTDIR:=./interface/haskell
INCDIR:=./include
BDIR:=./bin
ITARGET:=CalcLang.exe
# Toolchain definitions
CLANG:=clang
GHC:=ghc
# C compilation directives
CFLAGS += -fPIC
CFLAGS += -std=c99
CFLAGS += -g
CFLAGS += -I$(INCDIR)
# Haskell generate interface file Flags
HIFLAGS += -hidir $(INTDIR)
HIFLAGS += -fno-code
HIFLAGS += -i$(HDIR)
# Haskell compilation directives
HFLAGS += -XForeignFunctionInterface
HFLAGS += -fPIC
HFLAGS += -flink-rts
HFLAGS += -hidir $(INTDIR)
#Here is a specification of the Src
HISRC:=$(HDIR)/CalcLangParser.hs $(HDIR)/CalcLangInterpreter.hs $(HDIR)/CalcLangMain.hs
HIINT:=$(HISRC:$(HDIR)/%.hs=$(INTDIR)/%.hi)
HIOBJS:=$(HISRC:$(HDIR)/%.hs=$(HODIR)/%.o)

$(INTDIR)/%.hi: $(HDIR)/%.hs
    $(GHC) -c $< -o $@ $(HIFLAGS)
$(HODIR)/%.o: $(HDIR)/%.hs $(HIINT)
    $(GHC) -c $< -o $@ $(HFLAGS)
$(BDIR)/$(ITARGET): $(HIOBJS)
    $(GHC) $^ -o $@

.PHONY: clean
clean:
    rm -f $(HIOBJS) $(HIINT) ./*~ ./*# ./*/*/*~ ./*/*/*#  $(BDIR)/*

执行make后的错误信息:

ghc -c src/haskell/CalcLangParser.hs -o interface/haskell/CalcLangParser.hi -hidir ./interface/haskell -fno-code -i./src/haskell
ghc -c src/haskell/CalcLangInterpreter.hs -o interface/haskell/CalcLangInterpreter.hi -hidir ./interface/haskell -fno-code -i./src/haskell
src\haskell\CalcLangInterpreter.hs:3:1: error: [GHC-87110]
    Could not find module `CalcLangParser'.
    Use -v to see a list of the files searched for.
  |
3 | import CalcLangParser
解决方案

问题核心是GHC在生成接口文件和编译目标文件时,找不到依赖模块的接口路径,同时模块间的依赖关系未明确声明。

1. 补充接口文件搜索路径

生成接口文件的HIFLAGS仅指定了源码目录,未包含接口文件所在的INTDIR,导致编译CalcLangInterpreter.hi时找不到已生成的CalcLangParser.hi。修改HIFLAGS:

# Haskell generate interface file Flags
HIFLAGS += -hidir $(INTDIR)
HIFLAGS += -fno-code
HIFLAGS += -i$(HDIR)
HIFLAGS += -i$(INTDIR)  # 添加接口文件搜索路径

同时,编译目标文件的HFLAGS也需要补充这两个路径,否则后续编译.o文件时同样会找不到模块:

# Haskell compilation directives
HFLAGS += -XForeignFunctionInterface
HFLAGS += -fPIC
HFLAGS += -flink-rts
HFLAGS += -hidir $(INTDIR)
HFLAGS += -i$(HDIR)  # 添加源码搜索路径
HFLAGS += -i$(INTDIR)  # 添加接口文件搜索路径

2. 明确模块依赖关系

原Makefile中,.hi文件的生成规则仅依赖对应的.hs文件,未声明模块间的依赖,可能导致make并行编译时顺序错误。手动添加依赖规则:

# 声明模块间的依赖关系
$(INTDIR)/CalcLangInterpreter.hi: $(HDIR)/CalcLangInterpreter.hs $(INTDIR)/CalcLangParser.hi
$(INTDIR)/CalcLangMain.hi: $(HDIR)/CalcLangMain.hs $(INTDIR)/CalcLangParser.hi $(INTDIR)/CalcLangInterpreter.hi

完成上述修改后重新执行make,即可正确解析模块依赖。

内容的提问来源于stack exchange,提问作者Jacob Bauer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 12:12:29