Using GHC API to compile Haskell file

Neil Mitchell ndmitchell at gmail.com
Tue Aug 25 20:27:35 UTC 2015


So after all the linking bugs, I decided to give up on the linking
step (for now), as it's not essential to my use case. I can compile
two files with:

      forM_ ["Test1.hs","Test.hs"] $ \file -> do
        runGhc (Just libdir) $ do
          liftIO $ print file
          dflags <- getSessionDynFlags
          (dflags, _, _) <- parseDynamicFlags dflags []
          setSessionDynFlags dflags{ghcMode=OneShot, hscTarget =
HscAsm, ghcLink=NoLink}
          setTargets [Target (TargetFile file Nothing) True Nothing]
          load LoadAllTargets

And assuming Test.hs imports Test1.hs then everything is fine.
However, if I switch the runGhc and forM lines, so I compile both in
the same Ghc session, then I get an error about "Can't find
interface-file declaration for variable test1" when compiling Test.hs,
and when compiling Test.hs it does a fresh dependency check on Test1
and would compile it if I hadn't done so already.

The motivation for using a single Ghc session is that I'd like to
share things like loading the Prelude and not have to repeat that
work. Is there any way of doing that with two compiles which other
than sharing a cache I'd like to be separate?

Thanks, Neil


On Mon, Aug 24, 2015 at 8:42 AM, Neil Mitchell <ndmitchell at gmail.com> wrote:
> Thanks Edward, that fixed the issue with GHC 7.8.3. While trying to
> replicate with 7.10.2 to submit a bug report, I got a different error,
> even with your fix included:
>
> C:\Users\NDMIT_~1\AppData\Local\Temp\ghc2428_1\ghc_4.o:ghc_3.c:(.text+0x55):
> undefined reference to `ZCMain_main_closure'
>
> Doing another diff of the command lines, I see ghc --make includes
> "Test.o" on the Link line, but the API doesn't.
>
> Thanks, Neil
>
>
> On Mon, Aug 24, 2015 at 12:00 AM, Edward Z. Yang <ezyang at mit.edu> wrote:
>> The problem is that the default code is trying to build a dynamically
>> linked executable, but the Windows distributions don't come with dlls
>> by default.
>>
>> Why doesn't the GHC API code pick this up?  Based on snooping
>> ghc/Main.hs, it's probably because you need to call parseDynamicFlags*
>> which will call updateWays which will turn off -dynamic-too if the
>> platform doesn't support it.
>>
>> GHC bug? Absolutely! Please file a ticket.
>>
>> Edward
>>
>> Excerpts from Neil Mitchell's message of 2015-08-23 05:43:28 -0700:
>>> Hi,
>>>
>>> Is this the right place for GHC API queries? If not, is there anywhere better?
>>>
>>> I want to compile a Haskell module, much like `ghc --make` or `ghc -c`
>>> does. The sample code on the Haskell wiki
>>> (https://wiki.haskell.org/GHC/As_a_library#A_Simple_Example),
>>> StackOverflow (http://stackoverflow.com/a/5631338/160673) and in GHC
>>> API slides (http://sneezy.cs.nott.ac.uk/fplunch/weblog/wp-content/uploads/2008/12/ghc-api-slidesnotes.pdf)
>>> says:
>>>
>>>     import GHC
>>>     import GHC.Paths ( libdir )
>>>     import DynFlags
>>>
>>>     main =
>>>         defaultErrorHandler defaultFatalMessager defaultFlushOut $ do
>>>           runGhc (Just libdir) $ do
>>>             dflags <- getSessionDynFlags
>>>             setSessionDynFlags dflags
>>>             target <- guessTarget "Test.hs" Nothing
>>>             setTargets [target]
>>>             load LoadAllTargets
>>>
>>> However, given a `Test.hs` file with the contents `main = print 1`, I
>>> get the error:
>>>
>>>     C:/Program Files (x86)/MinGHC-7.8.3/ghc-7.8.3/mingw/bin/ld.exe:
>>> cannot find -lHSbase-4.7.0.1-ghc7.8.3
>>>     C:/Program Files (x86)/MinGHC-7.8.3/ghc-7.8.3/mingw/bin/ld.exe:
>>> cannot find -lHSinteger-gmp-0.5.1.0-ghc7.8.3
>>>     C:/Program Files (x86)/MinGHC-7.8.3/ghc-7.8.3/mingw/bin/ld.exe:
>>> cannot find -lHSghc-prim-0.3.1.0-ghc7.8.3
>>>     C:/Program Files (x86)/MinGHC-7.8.3/ghc-7.8.3/mingw/bin/ld.exe:
>>> cannot find -lHSrts-ghc7.8.3
>>>     C:/Program Files (x86)/MinGHC-7.8.3/ghc-7.8.3/mingw/bin/ld.exe:
>>> cannot find -lffi-6
>>>     collect2: ld returned 1 exit status
>>>
>>> Has the recipe changed?
>>>
>>> By turning up the verbosity, I was able to compare the command line
>>> passed to the linker. The failing GHC API call contains:
>>>
>>>     "-lHSbase-4.7.0.1-ghc7.8.3" "-lHSinteger-gmp-0.5.1.0-ghc7.8.3"
>>> "-lHSghc-prim-0.3.1.0-ghc7.8.3" "-lHSrts-ghc7.8.3" "-lffi-6"
>>>
>>> While the succeeding ghc --make contains:
>>>
>>>     "-lHSbase-4.7.0.1" "-lHSinteger-gmp-0.5.1.0"
>>> "-lHSghc-prim-0.3.1.0" "-lHSrts" "-lCffi-6"
>>>
>>> Should I be getting DynFlags differently to influence those link variables?
>>>
>>> Thanks, Neil


More information about the ghc-devs mailing list