2012-11-01 11 views
7

リンカの問題のために、Darcsライブラリと一緒にYesodを使用することは不可能です。私はこの問題を追跡し、Darcs社の内部に精通した人たちがその問題を回避するためのヒントを必要としています。YesodとDarcsライブラリを使用しているときに重複するシンボルエラーを回避するにはどうすればよいですか?

Yesodアプリケーションでdarcs libraryを使用して、私は次のエラーを取得する:

それぞれのオブジェクトファイルを検索するよう、darcsのと同じシンボルを暴露 cryptohashライブラリに起因すると思わ
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. 

明らかに:

# 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 

は私がdarcsのとcryptohashライブラリが競合していることを確認するためのテストプログラムを書いた:

これは、同様のエラーでコンパイルに失敗し
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 

/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 

cryptohashライブラリがyesod-staticによって要求されたとイェソドアプリケーションを書くときに容易に回避することはできません。同じアプリケーションでYesodとDarcs(ライブラリとして)を使用するにはどうすればよいですか?

重複するシンボルを1つのライブラリから削除すると便利ですか?どちらのパッケージも、FFIを介して異なるファイルを使用してハッシュ関数にアクセスします。 darcs/Crypt.SHA256から

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

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() 

もう一つのアイデアは、独自のハッシュ関数を使用しないようにDarcsのを書き換えることです。どうすればDarcsのSHA256モジュールをcryptohashを使って再実装できますか?私のテストプログラムのmain機能の2つのステートメントは、同じ出力(他のステートメントをコメントアウトすることによってテストされています)を与えないので、Darcsでcryptohashを使用することは全く単純ではありません。

+0

この関数のDarcsバージョンの名前を 'darcs_sha256_init'のように変更することはできませんか? –

+1

私が正しく理解していれば、シンボルはFFI経由で使用される2つの異なるCファイルで定義されているため、Haskell関数の名前を変更しても効果がありません。 –

+0

しかし、C関数の名前を変更すると助けになります。私の改訂版の回答を参照してください。 –

答えて

4

darcsハッシュ出力は、cryptohash出力のbase16でエンコードされたバージョンです。そのギャップを埋める一つの方法はbase16-bytestringのようです。私はそれを試してみましたが、Crypt.SHA256は同じくらい簡単になる:hashed-storageパッケージもsha2.cのコピーを持っているし、シンボルの名前を変更することで問題を修正実際に

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 

foreign import ccall unsafe "sha2.h darcs_sha256" c_sha256 
    :: Ptr CChar -> CSize -> Ptr Word8 -> IO() 
:だからdarcsの2.8のための最も簡単なクイックフィックスは、ハッシュ化されたストレージから sha2.hsha2.cをコピー両方のファイルで darcs_hashed_storage_を交換し、にdarcsの中のsrc /墓所/ SHA256.hsでFFIインポートを変更することです

ダルク2.8.3をリリースすれば、この変更があればうれしいでしょう。 2.10では、上記のようにcryptohashを使用するように変更します。ローカルCのバージョンを使用し続ける理由はなく、一般的なコードの私的実装を取り除こうとしているdarcsでは一般的です。

EDIT:もともとハッシュストレージには同じ問題があると思っていましたが、私は間違っていました(名前を変更しないとdarcs自体と衝突することは間違いありません)。

+0

私は、cryptohashの使用が長期的には好ましいことに同意しますが、2.8のほうが望ましい場合には、もっと簡単な修正で暮らすことができます。 Hackageへのアップロードは素晴らしいので、リリース版を使用することができます。ありがとう! –

+1

アップロードされました:http://hackage.haskell.org/package/darcs-2.8.3 –