在GHCi中动态链接外部对象文件

时间:2014-07-29 16:20:10

标签: haskell ghc cabal ghci

我的项目使用FFI,所以我总是要链接到使用GHCi进行测试的预编译对象文件:

ghci Foo a.o

我的问题是:一旦GHCi正在运行而不是GHCi启动,有没有办法做到这一点? 我试过这个:

$ ghci
> :l Foo a.o

但我收到错误a.o is not a module name or a source file

我的目标是能够启动 GHCi会话,其中包含通过.ghci文件链接的外部符号。我的动机是cabal将目标文件编译成dist/build/my-tests/my-tests-tmp/src/../../../../a.o,最终长度为92个字符。这一次打字很糟糕(最后用*,o),但是由于regression in GHC 7.8,我必须按照特定的顺序链接五个目标文件,这需要超过500个字符{ {1}}。

**更新**

以下示例说明了为什么n.m.的解决方案在GHC 7.8.2上对我不起作用:

mul.c

ghci Foo

Mul.hs

#include <inttypes.h>
void mulRq (int64_t* a, int64_t* b, int32_t totm, int64_t q) { }

Dummy.hs是空的。

步骤:

  1. ghci Mul

    [找不到标签mulRq]

  2. gcc -c -o mul.o mul.c
  3. ghci Mul mul.o

    [ghci loads]

  4. ghci -fobject-code Dummy
  5. ghci Dummy

    [ghci加载没有编译]

  6. ld -r Dummy.o mul.o -o temp.o
  7. mv temp.o Dummy.o
  8. ghci Dummy

    [ghci加载没有编译]

  9. nm Dummy.o

    [验证Dummy.o包含符号mulRq]

  10. 现在开始ghci:

    module Mul where
    
    import Data.Int
    import Foreign.Ptr
    
    foreign import ccall unsafe "mulRq" mulRq :: 
      Ptr Int64 -> Ptr Int64 -> Int64 -> Int64 -> IO ()
    

1 个答案:

答案 0 :(得分:1)

  1. 将Haskell模块Dummy.hs编译为Dummy.o。它可以是完全空的,或包含任何有用的Haskell代码。
  2. 确保ghci Dummy加载Dummy的现有编译版本(加载时不会打印Compiling)。
  3. 合并Dummy.oa.o

    ld -r Dummy.o a.o -o temp.o
    mv temp.o Dummy.o

  4. 现在您有一个可加载的Haskell模块Dummy,它还包含所有a.o

  5. <强>更新

    如果将使用 a.o/Dummy.o的模块编译为目标代码,并且在解释它们时不起作用,则此方案有效。

    始终使用已编译代码的一种简单方法是使用-fobject-code运行GHCi。使用您的示例,

    ghci -fobject-code
    Prelude> :l Dummy
    Ok, modules loaded: Dummy.
    Prelude Dummy> :l Mul
    [1 of 1] Compiling Mul              ( Mul.hs, Mul.o )
    Ok, modules loaded: Mul.
    Prelude Mul>