7

リンカーの問題により、YesodをDarcsライブラリと一緒に使用することは不可能のようです。私は問題を追跡し、Darcsの内部に精通している人々がそれを回避するためのヒントが必要です。

Yesodアプリケーションでdarcsライブラリを使用すると、次のエラーが発生します。

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.

それぞれのオブジェクトファイルを検索すると、次のことが明らかになるため、同じシンボルを公開しているdarcsライブラリとcryptohashライブラリが原因であると思われます。

# 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アプリケーションを作成するときに簡単に回避することはできません。同じアプリケーションで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 ()

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

4

1 に答える 1

4

darcsハッシュ出力は、cryptohash出力のbase16エンコードバージョンにすぎません。base16 -bytestringは、そのギャップを埋める1つの方法のようです。私はそれを試しましたが、Crypt.SHA256は次のように単純になります。

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

実際、ハッシュストレージパッケージにもsha2.cのコピーがあり、シンボルの名前を変更することで問題を修正しました。したがって、darcs 2.8の最も簡単な簡単な修正は、ハッシュストレージからsha2.hsha2.chashed_storage_をコピーしdarcs_、両方のファイルで置き換え、darcsのsrc / Crypt/SHA256.hsのFFIインポートを次のように変更することです。

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

よろしければ、この変更でdarcs2.8.3をリリースできれば幸いです。2.10では、ローカルCバージョンを使い続ける理由が見当たらないため、上記のように暗号ハッシュを使用するように切り替えます。一般に、darcsでは、一般的なコードのプライベート実装を削除しようとしています。

編集:私は当初、ハッシュストレージにも同じ問題があると思っていましたが、間違っていました(振り返ってみると、名前の変更がなければ、darcs自体と衝突していたことは明らかです)。

于 2012-11-02T00:46:59.083 に答える