理念
你好!我想创建一个程序,它将生成 Haskell Core 并使用 GHC API 将其进一步编译成可执行文件。但在我开始之前,我想构建一个非常基本的示例,展示我们如何将 Haskell 源代码编译成 CORE,然后编译成二进制文件。
问题
我已经阅读了很多文档并尝试了 GHC Api 的许多方法,但现在没有成功。我从 Official GHC Api introduction 开始并成功编译了示例。示例显示了以下函数的用法:parseModule
, typecheckModule
, desugarModule
, getNamesInScope
和 getModuleGraph
但不包括最后的编译步骤。另一方面,api中有一些函数,其名称看起来与问题有关,如HscMain.{hscCompileOneShot, hscCompileBatch}或 GHC.{compileToCoreModule, compileCoreToObj} .我尝试使用它们,但出现运行时错误,如下例所示:
import GHC
import GHC.Paths ( libdir )
import DynFlags
targetFile = "Test.hs"
main :: IO ()
main = do
res <- example
return ()
example =
defaultErrorHandler defaultFatalMessager defaultFlushOut $ do
runGhc (Just libdir) $ do
dflags <- getSessionDynFlags
let dflags' = foldl xopt_set dflags
[Opt_Cpp, Opt_ImplicitPrelude, Opt_MagicHash]
setSessionDynFlags dflags'
coreMod <- compileToCoreModule targetFile
compileCoreToObj False coreMod "foo" "bar"
return ()
可以用
ghc -package ghc Main.hs
编译并在运行时导致以下错误:Main: panic! (the 'impossible' happened)
(GHC version 7.8.3 for x86_64-unknown-linux):
expectJust mkStubPaths
这当然可能是错误 API 使用的结果,特别是因为行
compileCoreToObj False coreMod "foo" "bar"
,其中字符串只是随机字符串,因为文档没有太多关于它们的说明。如果我们查看来源,似乎第一个是输出名称,第二个是“extCore_filename”,无论它可能是什么。另一个令人担忧的事情是
compileCoreToObj
旁边的文档中的注释。功能:[...] This has only so far been tested with a single self-contained module.
但我希望它不会带来任何进一步的问题。
问题
创建此解决方案的最佳方法是什么?我们如何创建一个最小的工作示例,它将加载 haskell 源,将它们编译到 CORE 中,然后将核心编译为最终的可执行文件(使用 GHC API)。需要中间步骤来进一步替换自定义 CORE。
作为一个附带问题 - 目前是否可以为 GHC 提供外部核心文件,或者此功能尚未实现,我将不得不使用 GHC.Api 手动构建核心(相关:Compiling to GHC Core)
更新
我终于能够创建一个小示例,允许加载模块并将其编译为
.hi
和 .o
文件。这不是问题的解决方案,因为它不允许我替换 CORE 并且它还没有将目标文件链接到可执行文件中:import GHC
import GHC.Paths ( libdir )
import DynFlags
import Linker
import Module
targetFile = "Test.hs"
main :: IO ()
main = do
res <- example
return ()
example =
defaultErrorHandler defaultFatalMessager defaultFlushOut $ do
runGhc (Just libdir) $ do
dflags <- getSessionDynFlags
let dflags2 = dflags { ghcLink = LinkBinary
, hscTarget = HscAsm
}
let dflags' = foldl xopt_set dflags2
[Opt_Cpp, Opt_ImplicitPrelude, Opt_MagicHash]
setSessionDynFlags dflags'
setTargets =<< sequence [guessTarget "Test.hs" Nothing]
load LoadAllTargets
return ()
最佳答案
在这里生成核心的文本表示不是问题,因为它可以通过多种方式进行。您可以使用 -fext-core
生成标志.hcr
文件并使用例如extcore .还有其他可以转储核心的软件包,例如 ghc-core或 ghc-core-html .
这里的主要问题是将 ghc-core 加载到 ghc
中。 .据我所知,它受到支持,但现在不支持,因为人们对使用它的兴趣不大,而且随着时间的推移它变得过时了。
我们可以在这里尝试的最好的事情是深入挖掘 ghc
内部,找到使用 ghc-core 的地方并尝试在那里修改它。也许我们也可以尝试创建一个 ghc plugin并用它修改核心。
关于haskell - 使用 GHC API 将 Haskell 源代码编译为 CORE 和 CORE 为二进制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28059669/