Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GHCi never loads compiled files

Tags:

haskell

ghc

ghci

Write a module:

module Foo where
foo = 3.14

Compile it:

ghc -c Foo.hs

Load it:

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.

Why won't GHCi pick up compiled code? Is it a bug in GHCi?

I tried to run with -v, not too helpful.

Update

I have found that If the module is compiled with GHCi -fobject-code Foo, GHCi will subsequently load the compiled version, even without -fobject-code.

Update 2

This all happens with Ghc 7.8 on a Linux machine. Ghc 7.6 on a Windows machine does not exhibit this problem.

like image 232
n. 1.8e9-where's-my-share m. Avatar asked Jul 29 '14 21:07

n. 1.8e9-where's-my-share m.


1 Answers

From the GHC 7.8.1 Release Notes

On Linux, FreeBSD and Mac OS X, GHCi now uses the system dynamic linker by default, instead of its built in (static) object linker. This is more robust cross-platform, and fixes many long-standing bugs (for example: constructors and destructors, weak symbols, etc work correctly, and several edge cases in the RTS are fixed.)

As a result of this, GHCi (and Template Haskell) must now load dynamic object files, not static ones. To assist this, there is a new compilation flag, -dynamic-too, which when used during compilation causes GHC to emit both static and dynamic object files at the same time. GHC itself still defaults to static linking. [...]

Currently, Dynamic GHCi and -dynamic-too are not supported on Windows (32bit or 64bit.)

The last sentence explains why this doesn't affect windows.

You can see the problem by comparing the files that ghci -fobject-code Foo and ghc Foo generates:

$ 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:

This shows that GHCi compiles haskell files to dynamic object files (dyn way), while GHC compiles to static object files.

When GHCi tries to load Foo, it notices that there is no dynamic object file for Foo available (because GHC generated a static one), and thus it recompiles Foo. If -fobject-code is given, this will now override the static object file and generate a dynamic one, so that no recompilation is needed the next time GHCi is started. If -fobject-code is not specified, no object code is generated and the file is loaded in interpreted mode.

You can also tell ghc to generate dynamic object files:

$ ghc -dynamic -c Foo

Now ghci Foo doesn't recompile Foo, but uses the already-compiled dynamic object file.

like image 112
bennofs Avatar answered Nov 10 '22 00:11

bennofs