使用Yesod和Darcs库时如何解决重复符号错误? [英] How to work around duplicate symbol error when using Yesod and Darcs library?

查看:200
本文介绍了使用Yesod和Darcs库时如何解决重复符号错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于链接器问题,似乎不可能将Yesod和Darcs库一起使用。我追踪了这个问题,并需要熟悉达尔西内部人员的提示。



使用 darcs library Yesod 应用程序中出现以下错误:

  GHCi运行时链接程序:致命错误:在处理目标文件
时,发现符号
sha256_init
的重复定义/home/sebfisch/.cabal/lib/darcs-2.9.5/ghc-7.4.2/libHSdarcs-2.9.5.a
这可能是由以下原因造成的:
*加载两个不同的目标文件,它们是导出相同的符号
*在GHCi命令行上指定同一个目标文件两次
*一个不正确的`package.conf'条目,导致一些对象被
加载两次。
GHCi在这种情况下无法安全地继续。现在退出。抱歉。

它似乎是由darcs和 cryptohash 图书馆暴露相同的符号,通过搜索各自的目标文件显示:

 #用于`find〜/ .cabal / lib / -name中的文件* .a`; do(readelf -s $ file | grep -i sha256_init)&& (echo $ file; echo);完成
293:0000000000000000 0 NOTYPE GLOBAL DEFAULT UND sha256_init
17:0000000000000690 94 FUNC GLOBAL DEFAULT 1 sha256_init
〜/ .cabal / lib / cryptohash-0.7.5 / ghc-7.4.2 / libHScryptohash-0.7.5.a

10:0000000000000290 45 FUNC GLOBAL DEFAULT 1 sha256_init
〜/ .cabal / lib / darcs-2.8.2 / ghc-7.4.2 / libHSdarcs-2.8 .2.a

我编写了一个测试程序来确认darcs和cryptohash库有冲突:

  import Crypt.SHA256(sha256sum)
import Crypto.Hash.SHA256(hash)
import Data .ByteString(空)
将合格的Data.ByteString.Char8导入为BS
$ b main :: IO()
main = do
BS.putStrLn $ hash empty - - cryptohash
putStrLn $ sha256sum empty - darcs

无法编译时会出现类似的错误:

  /home/sebfisch/.cabal/lib/cryptohash- 0.7.5 / ghc-7.4.2 / libHScryptohash-0.7.5.a(sha256.o):函数`sha256_update':sha256.c :( .text + 0x4b0):`sha256_update'的多重定义
/home/sebfisch/.cabal/lib/darcs-2.8.2/ghc-7.4.2/libHSdarcs-2.8.2.a(sha2.o):sha2.c:(.text+0xf90):首先在这里定义
/home/sebfisch/.cabal/lib/cryptohash-0.7.5/ghc-7.4.2/libHScryptohash-0.7.5.a(sha256.o):在函数`sha224_update'中:sha256.c :(。文本+ 0x640):`sha224_update'的多重定义
/home/sebfisch/.cabal/lib/darcs-2.8.2/ghc-7.4.2/libHSdarcs-2.8.2.a(sha2.o): sha2.c :(。text + 0xbb0):首先在这里定义
/home/sebfisch/.cabal/lib/cryptohash-0.7.5/ghc-7.4.2/libHScryptohash-0.7.5.a(sha256。 o):函数`sha256_init':sha256.c :(。text + 0x690):`sha256_init'的多重定义
/home/sebfisch/.cabal/lib/darcs-2.8.2/ghc-7.4。 2 / libHSdarcs-2.8.2.a(sha2.o):sha2.c(.text + 0x290):此处首先定义
/home/sebfisch/.cabal/lib/cryptohash-0.7.5/ghc- 7.4.2 / libHScryptohash-0.7.5.a(sha256.o):在函数`sha224_ini t':sha256.c :(。text + 0x6f0):`sha224_init'的多重定义
/home/sebfisch/.cabal/lib/darcs-2.8.2/ghc-7.4.2/libHSdarcs-2.8。 2.a(sha2.o):sha2.c(.text + 0x620):首先在这里定义
collect2:ld返回1退出状态

cryptohash库是 yesod-static 所必需的,不能轻易在编写Yesod应用程序时应避免。如何在同一个应用程序中使用Yesod和Darcs(作为库)?



它能帮助从一个库中删除重复的符号吗?这两个软件包都通过FFI访问哈希函数,但使用不同的文件。



From darcs / Crypt.SHA256

 国外进口ccall不安全sha2.h sha256c_sha256 
:: Ptr CChar - > CSize - > Ptr Word8 - > IO()

From cryptohash / Crypto.Hash.SHA256

  foreign import ccall unsafesha256.h sha256_init
c_sha256_init :: Ptr Ctx - > IO()

foreign import ccallsha256.h sha256_update
c_sha256_update :: Ptr Ctx - > CString - > Word32 - > IO()

国外进口ccall不安全sha256.h sha256_finalize
c_sha256_finalize :: Ptr Ctx - > CString - > IO()

另一个想法是将Darcs重写为不使用自己的哈希函数。我怎样才能重新实现Darcs的 SHA256 模块来使用cryptohash?我测试程序的 main 函数中的两个语句没有提供相同的输出(通过注释掉其他语句来测试),所以在Darcs中使用cryptohash似乎并不直接。

解决方案

darcs散列输出只是cryptohash输出的base16编码版本。看起来像是弥合这种差距的一种方法。我试过了,Crypt.SHA256变得如此简单:

 模块Crypt.SHA256(sha256sum)其中

import Crypto.Hash.SHA256(hash)
import Data.ByteString(ByteString)
import Data.ByteString.Base16(encode)
import Data.ByteString.Char8(unpack)

sha256sum :: ByteString - >字符串
sha256sum =解包。编码。哈希

事实上, hashed-storage 包也有一个sha2.c的副本,并通过重命名这些符号来解决问题。因此,darcs 2.8最简单的快速修复方法是复制 sha2.h 和来自散列存储的 sha2.c ,将 hashed_storage _ darcs _ ,并将drc中的src / Crypt / SHA256.hs中的FFI导入更改为:

  foreign import ccall unsafesha2.h darcs_sha256c_sha256 
:: Ptr CChar - > CSize - > Ptr Word8 - > IO()

如果它有帮助,我很乐意发布darcs 2.8.3您。对于2.10,我将切换到使用cryptohash,因为我没有看到任何理由继续使用本地C版本,并且通常在darcs中我们试图摆脱普通代码的私有实现。



编辑:我原本以为散列存储会有同样的问题,但我错了(回想起来很显然它会与darcs本身发生冲突,如果不是重命名的话)。


It seems impossible to use Yesod together with the Darcs library due to a linker problem. I tracked down the problem and need hints to work around it by people familiar with Darcs internals.

When using the darcs library in a Yesod application, I get the following error:

GHCi runtime linker: fatal error: I found a duplicate definition for symbol
   sha256_init
whilst processing object file
   /home/sebfisch/.cabal/lib/darcs-2.9.5/ghc-7.4.2/libHSdarcs-2.9.5.a
This could be caused by:
   * Loading two different object files which export the same symbol
   * Specifying the same object file twice on the GHCi command line
   * An incorrect `package.conf' entry, causing some object to be
     loaded twice.
GHCi cannot safely continue in this situation.  Exiting now.  Sorry.

It appears to be caused by the darcs and cryptohash libraries exposing the same symbol, as searching through the respective object files reveals:

# for file in `find ~/.cabal/lib/ -name "*.a"`; do (readelf -s $file | grep -i sha256_init) && (echo $file; echo); done
   293: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND sha256_init
    17: 0000000000000690    94 FUNC    GLOBAL DEFAULT    1 sha256_init
~/.cabal/lib/cryptohash-0.7.5/ghc-7.4.2/libHScryptohash-0.7.5.a

    10: 0000000000000290    45 FUNC    GLOBAL DEFAULT    1 sha256_init
~/.cabal/lib/darcs-2.8.2/ghc-7.4.2/libHSdarcs-2.8.2.a

I wrote a test program to confirm that the darcs and cryptohash libraries are in conflict:

import           Crypt.SHA256          (sha256sum)
import           Crypto.Hash.SHA256    (hash)
import           Data.ByteString       (empty)
import qualified Data.ByteString.Char8 as BS

main :: IO ()
main = do
    BS.putStrLn $ hash empty    -- cryptohash
    putStrLn $ sha256sum empty  -- darcs

It fails to compile with a similar error:

/home/sebfisch/.cabal/lib/cryptohash-0.7.5/ghc-7.4.2/libHScryptohash-0.7.5.a(sha256.o): In function `sha256_update': sha256.c:(.text+0x4b0): multiple definition of `sha256_update'
/home/sebfisch/.cabal/lib/darcs-2.8.2/ghc-7.4.2/libHSdarcs-2.8.2.a(sha2.o):sha2.c:(.text+0xf90): first defined here
/home/sebfisch/.cabal/lib/cryptohash-0.7.5/ghc-7.4.2/libHScryptohash-0.7.5.a(sha256.o): In function `sha224_update': sha256.c:(.text+0x640): multiple definition of `sha224_update'
/home/sebfisch/.cabal/lib/darcs-2.8.2/ghc-7.4.2/libHSdarcs-2.8.2.a(sha2.o):sha2.c:(.text+0xbb0): first defined here
/home/sebfisch/.cabal/lib/cryptohash-0.7.5/ghc-7.4.2/libHScryptohash-0.7.5.a(sha256.o): In function `sha256_init': sha256.c:(.text+0x690): multiple definition of `sha256_init'
/home/sebfisch/.cabal/lib/darcs-2.8.2/ghc-7.4.2/libHSdarcs-2.8.2.a(sha2.o):sha2.c (.text+0x290): first defined here
/home/sebfisch/.cabal/lib/cryptohash-0.7.5/ghc-7.4.2/libHScryptohash-0.7.5.a(sha256.o): In function `sha224_init': sha256.c:(.text+0x6f0): multiple definition of `sha224_init'
/home/sebfisch/.cabal/lib/darcs-2.8.2/ghc-7.4.2/libHSdarcs-2.8.2.a(sha2.o):sha2.c (.text+0x620): first defined here
collect2: ld returned 1 exit status

The cryptohash library is required by yesod-static and cannot easily be avoided when writing a Yesod application. How can I use Yesod and Darcs (as a library) in the same application?

Would it help to delete the duplicate symbols from one library? Both packages access hashing functions via FFI but using different files.

From darcs/Crypt.SHA256:

foreign import ccall unsafe "sha2.h sha256" c_sha256
    :: Ptr CChar -> CSize -> Ptr Word8 -> IO ()

From cryptohash/Crypto.Hash.SHA256:

foreign import ccall unsafe "sha256.h sha256_init"
    c_sha256_init :: Ptr Ctx -> IO ()

foreign import ccall "sha256.h sha256_update"
    c_sha256_update :: Ptr Ctx -> CString -> Word32 -> IO ()

foreign import ccall unsafe "sha256.h sha256_finalize"
    c_sha256_finalize :: Ptr Ctx -> CString -> IO ()

Another idea is to rewrite Darcs to not use its own hashing function. How can I reimplement Darcs's SHA256 module to use cryptohash? The two statements in the main function of my test program do not give the same output (tested by commenting out the other statement), so using cryptohash in Darcs does not seem entirely straightforward.

解决方案

The darcs hash output is just the base16 encoded version of the cryptohash output. Looks like base16-bytestring is one way to bridge that gap. I tried it and Crypt.SHA256 becomes as simple as:

module Crypt.SHA256 ( sha256sum ) where

import Crypto.Hash.SHA256 ( hash )
import Data.ByteString ( ByteString )
import Data.ByteString.Base16 ( encode )
import Data.ByteString.Char8 ( unpack )

sha256sum :: ByteString -> String
sha256sum = unpack . encode . hash

In fact the hashed-storage package also has a copy of sha2.c and fixed the problem by renaming the symbols. So the simplest quick fix for darcs 2.8 is to copy sha2.h and sha2.c from hashed-storage, replace hashed_storage_ with darcs_ in both files, and change the FFI import in src/Crypt/SHA256.hs in darcs to:

foreign import ccall unsafe "sha2.h darcs_sha256" c_sha256
    :: Ptr CChar -> CSize -> Ptr Word8 -> IO ()

I'd be happy to release darcs 2.8.3 with this change if it would help you. For 2.10 I'll switch to using cryptohash as above as I don't see any reason to keep using the local C version and in general in darcs we are trying to get rid of private implementations of common code.

EDIT: I originally thought hashed-storage would have the same problem, but I was wrong (in retrospect it's obvious that it would have clashed with darcs itself if not for the renaming).

这篇关于使用Yesod和Darcs库时如何解决重复符号错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆