GHCi从不加载编译文件

n. *_* m. 5 haskell ghc ghci

写一个模块:

module Foo where
foo = 3.14
Run Code Online (Sandbox Code Playgroud)

编译它:

ghc -c Foo.hs
Run Code Online (Sandbox Code Playgroud)

加载它:

ghci -ignore-dot-ghci
GHCi, version 7.8.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> :l Foo
[1 of 1] Compiling Foo              ( Foo.hs, interpreted )
Ok, modules loaded: Foo.
Run Code Online (Sandbox Code Playgroud)

为什么GHCi不会选择编译代码?这是GHCi中的错误吗?

我试着跑-v,不太有帮助.

更新

我发现,如果编译模块GHCi -fobject-code Foo,GHCi将随后加载编译版本,即使没有-fobject-code.

更新2

这一切都发生在Linux机器上的Ghc 7.8上.Windows机器上的Ghc 7.6不会出现此问题.

ben*_*ofs 7

来自GHC 7.8.1发行说明

在Linux,FreeBSD和Mac OS X上,GHCi现在默认使用系统动态链接器,而不是内置(静态)对象链接器.这是更强大的跨平台,并修复了许多长期存在的错误(例如:构造函数和析构函数,弱符号等正常工作,并且RTS中的几个边缘情况是固定的.)

因此,GHCi(和模板Haskell)现在必须加载动态对象文件,而不是静态对象文件.为了协助这一点,有一个新的编译标志--dynamic-too,在编译期间使用时会导致GHC同时发出静态和动态目标文件.GHC本身仍默认为静态链接.[...]

目前,Windows(32位或64位)不支持动态GHCi和-dynamic-too.

最后一句解释了为什么这不会影响窗口.

您可以通过比较这些文件看到的问题ghci -fobject-code Fooghc Foo产生:

$ mkdir ghci ghc
$ ghc Foo -odir ghc -hidir ghc
$ ghci -fobject-code Foo -odir ghci -hidir ghci < /dev/null
$ diff -u <(ghc --show-iface ghc/Foo.hi) <(ghc --show-iface ghci/Foo.hi)
--- /proc/self/fd/11    2014-07-30 13:03:34.977845398 +0200
+++ /proc/self/fd/12    2014-07-30 13:03:34.978845419 +0200
@@ -3,13 +3,13 @@
 Version: Wanted [7, 0, 8, 3],
          got    [7, 0, 8, 3]
 Way: Wanted [],
-     got    []
+     got    [d, y, n]
 interface main:Foo 7083
   interface hash: 9aab457c4ecbd2507529fcb479523944
   ABI hash: 375e3124c60d5f4eb51e7e38e71a3be0
   export-list hash: ff40b932e3d14f0fc26fbd56a58e227c
   orphan hash: 693e9af84d3dfcc71e640e005bdc5e2e
-  flag hash: 6c2d0082779adc2bd558d879f3f0fe26
+  flag hash: 82fa613fe97939e6767d853897fe1074
   used TH splices: False
   where
 exports:
Run Code Online (Sandbox Code Playgroud)

这表明GHCi将haskell文件编译为动态目标文件(dyn方式),而GHC编译为静态目标文件.

当GHCi尝试加载Foo时,它注意到Foo没有可用的动态对象文件(因为GHC生成了静态文件),因此它重新编译Foo.如果-fobject-code给出,这将覆盖静态目标文件并生成动态文件,因此下次启动GHCi时不需要重新编译.如果-fobject-code未指定,则不生成任何对象代码,并以解释模式加载文件.

您还可以告诉ghc生成动态对象文件:

$ ghc -dynamic -c Foo
Run Code Online (Sandbox Code Playgroud)

现在ghci Foo不重新编译Foo,而是使用已经编译的动态对象文件.