Haskell GHC Dynamic Compliation Only works on firs

2019-04-27 14:11发布

问题:

Following the GHC tutorial posted here and alterations to this code following the advice in a previous stack overflow question I asked, I have created a program which is able to compile and run a module in Test.hs with a function print to print a string to the screen:

import GHC
import GHC.Paths
import DynFlags
import Unsafe.Coerce

main :: IO ()
main =
    defaultErrorHandler defaultLogAction $ do
      func <- runGhc (Just libdir) $ do
        dflags <- getSessionDynFlags
        setSessionDynFlags dflags
        target <- guessTarget "Test.hs" Nothing
        addTarget target
        r <- load LoadAllTargets
        case r of
          Failed -> error "Compilation failed"
          Succeeded -> do
            m <- findModule (mkModuleName "Test") Nothing
            setContext [IIModule m]
            value <- compileExpr ("Test.print")
            do let value' = (unsafeCoerce value) :: String -> IO ()
               return value'
      func "Hello"
      return ()

The problem with this code, as noted in the comments, is that it only seems to work the first time you run it (When Test.hs has not yet been complied). If you attempt to run the code a second time, the following error appears:

mkTopLevEnv: not interpreted main:Test

I believe this has something to do with the fact that the code has already been compiled. If I delete the .hi and .o files and run the program again, the program runs correctly with the correct output. What am I missing? I am currently using ghc version 7.4.1

(Note: I have tried looking through the GHC API but could not find any references to mkTopLevEnv)

回答1:

Simon Marlow suggests here that replacing

guessTarget "Test.hs" Nothing

with

guessTarget "*Test.hs" Nothing

should avoid the error you're getting, on the grounds that it tells GHC not to load the .o file.

See the whole thread on a page via nabble

Of course, you could delete the .hi and .o files each time, but that's an ugly workaround.