【问题标题】:Linking external object files on the fly in GHCi在 GHCi 中动态链接外部对象文件
【发布时间】:2014-07-29 16:20:10
【问题描述】:

我的项目使用 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,我必须以特定顺序链接五个目标文件,这需要在ghci Foo之后超过500个字符。

** 更新 **

以下示例说明了为什么以下 n.m. 的解决方案不适用于 GHC 7.8.2:

mul.c

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

Mul.hs

module Mul where

import Data.Int
import Foreign.Ptr

foreign import ccall unsafe "mulRq" mulRq :: 
  Ptr Int64 -> Ptr Int64 -> Int64 -> Int64 -> IO ()

Dummy.hs 为空。

步骤:

  1. ghci 数

    [找不到标签 mulRq]

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

    [ghci 加载]

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

    [ghci 加载 编译]

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

    [ghci 加载 编译]

  9. nm Dummy.o

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

现在开始 ghci:

$ ghci
GHCi, version 7.8.2: 
...
Prelude> :l Dummy
Ok, modules loaded: Main.
Prelude Main> :l Mul
[1 of 1] Compiling Mul              ( Mul.hs, interpreted )

ByteCodeLink: can't find label
During interactive linking, GHCi couldn't find the following symbol:
  mulRq

【问题讨论】:

  • 使用 shell 脚本而不是 .ghci?
  • 你可以将对象包装在虚拟 Haskell/ghc 模块中吗?
  • 您还可以在per-project basis 上拥有一个.ghci 文件,您可以将其设置为加载该项目所需的目标文件。当你启动 GHCi 时它会全部加载它们,但至少你可以对你正在处理的任何项目进行更多控制,而不必让它们全局化。
  • @n.m.听起来很有趣……我该怎么做?
  • @bheklilr 我确实有一个每个项目的 .ghci 文件。这正是我要问的:如何设置它以在 GHCi 开始时加载目标文件?

标签: haskell ghc cabal ghci


【解决方案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

更新

如果使用 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> 

【讨论】:

  • 这可以正常工作,直到原来的 a.o 发生变化并且我忘记重建 Dummy.o。但它比我现在拥有的要好。
  • 如何让 ghci 不重新编译 Dummy.hs?我首先使用ghc Dummy 编译Dummy.hs,然后使用ghci Dummy,但ghci 仍然再次编译Dummy。
  • 运行一次ghci -fobject-code Dummy 来编译 Dummy。请参阅我的this Q
  • 这使得 GHCi 打印“编译”一次而不是两次,不确定这是否足够。但是,这涉及到我用 args 调用 GHCi。我正在尝试将:l Dummy 放在我的 .ghci 文件中,这不允许这些参数,至少我可以告诉。
  • Ghci 应该能够使用用 ghc 编译的模块。目前不是。我怀疑这是一个 ghc 错误。使用 ghci -fobject-code 是一种解决方法。只需在此模块中使用它而不是 ghc,直到有真正的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
相关资源
最近更新 更多