2

I have been making a Haskell project that I want to continue on in C at some point through the FFI. I wanted to create a makefile to compile all the source with Clang for C and GHC for Haskell.

The make file is pictured below:

#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)/*

I keep trying to run make, and this is the result I get:

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

For the first step, I am just compiling to all the interface files first or the files in the hi format. Because I thought the issue was that I needed all those files before compiling into object files. But anyway, even though CalcLangParser compiles first, the import is not working correctly in the CalcLangInterpreter file. If I am missing some flag or doing something wrong, I would like to know. I am not super experienced with Haskell yet.

2
  • In principle, I support your effort to understand the tools from the ground up. I've found that instinct invaluable in my career. But, once you get this working, I strongly recommend migrating to cabal and letting it sort out these kinds of low-level details for you. Commented Aug 18 at 20:04
  • @DanielWagner I took your advice and switched over to Cabal. I was running into an issue with Make, where it was saying I had two Main methods. One was in a file in my tmp directory because apparently GHC makes temp files. Kind of annoying but whatever. I couldn't find a way around that; I even tried to delete the contents tmp directory. But it didn't work. So like I said I just switched over to Cabal. And to be honest, it is way more user-friendly than Make. The only problem is I can't get the cabal install command to work. It won't detect my include header files or directories. Commented Aug 24 at 21:58

1 Answer 1

1

If I'm reading the documentation correctly, instead of

-c -o foo.hi -fno-code

you will need:

-ohi foo.hi -fno-code -fwrite-interface

Optionally, I believe you can omit the -ohi foo.hi part. The file to write will be computed from your -hidir flag and the module name.

I think the command you tried created an object file, not an interface, and gave it a name ending in .hi. More details in the separate compilation section of the GHC manual.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.