GHCi从不加载编译文件

时间:2014-07-29 21:07:06

标签: haskell ghc ghci

写一个模块:

module Foo where
foo = 3.14

编译:

ghc -c Foo.hs

加载它:

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.

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

我尝试使用-v运行,但没有太大帮助。

更新

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

更新2

这一切都发生在Linux机器上的Ghc 7.8上。 Windows机器上的Ghc 7.6没有出现此问题。

1 个答案:

答案 0 :(得分:7)

来自GHC 7.8.1 Release Notes

  

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

     

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

     

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

最后一句解释了为什么这不影响窗户。

您可以通过比较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:

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

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

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

$ ghc -dynamic -c Foo

现在ghci Foo不会重新编译Foo,但会使用已编译的动态对象文件。