Idea
你好!我想创建一个程序,这将生成Haskell核心,并将使用GHC API来进一步编译成一个可执行文件。但在我开始之前,我想构建一个非常基本的示例,展示如何将Haskell源代码编译成核心,然后再编译成二进制文件。
The problem
我已经阅读了大量的文档,并尝试了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
另一个令人担忧的事情是文档中compileCoreToObj
函数旁边的注释:
...到目前为止,这只是用一个自包含的模块进行了测试。
但我希望它不会带来任何进一步的问题。
question
创建此解决方案的最佳方法是什么?中间步骤是由自定义核心进一步替换所需的。
作为一个次要问题-目前是否可以为GHC提供外部核心文件,或者此功能尚未实现,我将不得不使用GHC.Api手动构建核心(相关:Compiling to GHC Core)
更新
我终于能够创建一个小示例,允许加载模块并将其编译为.hi
和.o
文件。这不是问题的解决方案,因为它不允许我替换核心,并且它还没有将目标文件链接到可执行文件中:
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 ()
发布于 2015-01-30 21:31:00
生成核心的文本表示在这里不是问题,因为它可以通过多种方式生成。您可以使用-fext-core
标志来生成.hcr
文件,并使用extcore等工具处理这些文件。还有其他可以转储核心的包,比如ghc-core或ghc-core-html。
这里的主要问题是将ghc-core加载到ghc
中。据我所知,它得到了支持,但现在不支持了,因为人们对使用它的兴趣很低,随着时间的推移,它变得过时了。
我们在这里可以尝试的最好的事情是深入挖掘ghc
的内部结构,找到使用ghc-core的地方,并尝试在那里修改它。也许我们也可以尝试创建一个ghc plugin并用它来修改内核。
发布于 2015-01-29 04:52:27
简而言之:一旦你必须对象化文件,你就可以使用你选择的c编译器来编译一个主存根并链接到一个可执行文件中。
如果你有目标文件,那么GHC要做的最后几步是在链接器和C编译器中完成的。例如,通过为一个简单的文件设置-verbose标志和- hello_world -tmp-files,我在构建对象后的最后三个步骤是:
'/usr/bin/gcc' '-fno-stack-protector' '-Wl,--hash-size=31' '-Wl,--reduce-memory-overheads' '-c' '/tmp/ghc29076_0/ghc29076_0.c' '-o' '/tmp/ghc29076_0/ghc29076_0.o' '-DTABLES_NEXT_TO_CODE' '-I/usr/lib/ghc/include'
*** C Compiler:
'/usr/bin/gcc' '-fno-stack-protector' '-Wl,--hash-size=31' '-Wl,--reduce-memory-overheads' '-c' '/tmp/ghc29076_0/ghc29076_0.s' '-o' '/tmp/ghc29076_0/ghc29076_1.o' '-DTABLES_NEXT_TO_CODE' '-I/usr/lib/ghc/include'
*** Linker:
'/usr/bin/gcc' '-fno-stack-protector' '-Wl,--hash-size=31' '-Wl,--reduce-memory-overheads' '-o' 'hello' 'hello.o' '-L/usr/lib/ghc/base-4.6.0.1' '-L/usr/lib/ghc/integer-gmp-0.5.0.0' '-L/usr/lib/ghc/ghc-prim-0.3.0.0' '-L/usr/lib/ghc' '/tmp/ghc29076_0/ghc29076_0.o' '/tmp/ghc29076_0/ghc29076_1.o' '-lHSbase-4.6.0.1' '-lHSinteger-gmp-0.5.0.0' '-lgmp' '-lHSghc-prim-0.3.0.0' '-lHSrts' '-lffi' '-lm' '-lrt' '-ldl' '-u' 'ghczmprim_GHCziTypes_Izh_static_info' '-u' 'ghczmprim_GHCziTypes_Czh_static_info' '-u' 'ghczmprim_GHCziTypes_Fzh_static_info' '-u' 'ghczmprim_GHCziTypes_Dzh_static_info' '-u' 'base_GHCziPtr_Ptr_static_info' '-u' 'ghczmprim_GHCziTypes_Wzh_static_info' '-u' 'base_GHCziInt_I8zh_static_info' '-u' 'base_GHCziInt_I16zh_static_info' '-u' 'base_GHCziInt_I32zh_static_info' '-u' 'base_GHCziInt_I64zh_static_info' '-u' 'base_GHCziWord_W8zh_static_info' '-u' 'base_GHCziWord_W16zh_static_info' '-u' 'base_GHCziWord_W32zh_static_info' '-u' 'base_GHCziWord_W64zh_static_info' '-u' 'base_GHCziStable_StablePtr_static_info' '-u' 'ghczmprim_GHCziTypes_Izh_con_info' '-u' 'ghczmprim_GHCziTypes_Czh_con_info' '-u' 'ghczmprim_GHCziTypes_Fzh_con_info' '-u' 'ghczmprim_GHCziTypes_Dzh_con_info' '-u' 'base_GHCziPtr_Ptr_con_info' '-u' 'base_GHCziPtr_FunPtr_con_info' '-u' 'base_GHCziStable_StablePtr_con_info' '-u' 'ghczmprim_GHCziTypes_False_closure' '-u' 'ghczmprim_GHCziTypes_True_closure' '-u' 'base_GHCziPack_unpackCString_closure' '-u' 'base_GHCziIOziException_stackOverflow_closure' '-u' 'base_GHCziIOziException_heapOverflow_closure' '-u' 'base_ControlziExceptionziBase_nonTermination_closure' '-u' 'base_GHCziIOziException_blockedIndefinitelyOnMVar_closure' '-u' 'base_GHCziIOziException_blockedIndefinitelyOnSTM_closure' '-u' 'base_ControlziExceptionziBase_nestedAtomically_closure' '-u' 'base_GHCziWeak_runFinalizzerBatch_closure' '-u' 'base_GHCziTopHandler_flushStdHandles_closure' '-u' 'base_GHCziTopHandler_runIO_closure' '-u' 'base_GHCziTopHandler_runNonIO_closure' '-u' 'base_GHCziConcziIO_ensureIOManagerIsRunning_closure' '-u' 'base_GHCziConcziSync_runSparks_closure' '-u' 'base_GHCziConcziSignal_runHandlers_closure'
查看前两个文件会发现c文件只是:
#include "Rts.h"
extern StgClosure ZCMain_main_closure;
int main(int argc, char *argv[])
{
RtsConfig __conf = defaultRtsConfig;
__conf.rts_opts_enabled = RtsOptsSafeOnly;
return hs_main(argc, argv, &ZCMain_main_closure,__conf);
}
这似乎不应该在项目之间有太大的变化。
部件文件为:
.section .debug-ghc-link-info,"",@note
.ascii "([\"-lHSbase-4.6.0.1\",\"-lHSinteger-gmp-0.5.0.0\",\"-lgmp\",\"-lHSghc-prim-0.3.0.0\",\"-lHSrts\",\"-lffi\ ",\"-lm\",\"-lrt\",\"-ldl\",\"-u\",\"ghczmprim_GHCziTypes_Izh_static_info\",\"-u\",\"ghczmprim_GHCziTypes_Czh_static _info\",\"-u\",\"ghczmprim_GHCziTypes_Fzh_static_info\",\"-u\",\"ghczmprim_GHCziTypes_Dzh_static_info\",\"-u\",\"bas e_GHCziPtr_Ptr_static_info\",\"-u\",\"ghczmprim_GHCziTypes_Wzh_static_info\",\"-u\",\"base_GHCziInt_I8zh_static_info \",\"-u\",\"base_GHCziInt_I16zh_static_info\",\"-u\",\"base_GHCziInt_I32zh_static_info\",\"-u\",\"base_GHCziInt_I64z h_static_info\",\"-u\",\"base_GHCziWord_W8zh_static_info\",\"-u\",\"base_GHCziWord_W16zh_static_info\",\"-u\",\"base _GHCziWord_W32zh_static_info\",\"-u\",\"base_GHCziWord_W64zh_static_info\",\"-u\",\"base_GHCziStable_StablePtr_stati c_info\",\"-u\",\"ghczmprim_GHCziTypes_Izh_con_info\",\"-u\",\"ghczmprim_GHCziTypes_Czh_con_info\",\"-u\",\"ghczmpri m_GHCziTypes_Fzh_con_info\",\"-u\",\"ghczmprim_GHCziTypes_Dzh_con_info\",\"-u\",\"base_GHCziPtr_Ptr_con_info\",\"-u\ ",\"base_GHCziPtr_FunPtr_con_info\",\"-u\",\"base_GHCziStable_StablePtr_con_info\",\"-u\",\"ghczmprim_GHCziTypes_Fal se_closure\",\"-u\",\"ghczmprim_GHCziTypes_True_closure\",\"-u\",\"base_GHCziPack_unpackCString_closure\",\"-u\",\"b ase_GHCziIOziException_stackOverflow_closure\",\"-u\",\"base_GHCziIOziException_heapOverflow_closure\",\"-u\",\"base _ControlziExceptionziBase_nonTermination_closure\",\"-u\",\"base_GHCziIOziException_blockedIndefinitelyOnMVar_closur e\",\"-u\",\"base_GHCziIOziException_blockedIndefinitelyOnSTM_closure\",\"-u\",\"base_ControlziExceptionziBase_neste dAtomically_closure\",\"-u\",\"base_GHCziWeak_runFinalizzerBatch_closure\",\"-u\",\"base_GHCziTopHandler_flushStdHan dles_closure\",\"-u\",\"base_GHCziTopHandler_runIO_closure\",\"-u\",\"base_GHCziTopHandler_runNonIO_closure\",\"-u\" ,\"base_GHCziConcziIO_ensureIOManagerIsRunning_closure\",\"-u\",\"base_GHCziConcziSync_runSparks_closure\",\"-u\",\" base_GHCziConcziSignal_runHandlers_closure\"],[],Nothing,RtsOptsSafeOnly,False,[],[])"
好吧,这有点糟糕,但看起来这些是一个链接器标志列表,带有一些官样文章,最后被传递到GHC中。我不确定链接器没有定义的所有东西,查看链接器标志将是您最大的家庭作业。您需要修改这些标志吗?也许,也许只有在依赖关系改变的情况下。
https://stackoverflow.com/questions/28059669
复制相似问题