2012-11-01 6 views
7

Sembra impossibile utilizzare Yesod insieme alla libreria Darcs a causa di un problema del linker. Ho rintracciato il problema e ho bisogno di suggerimenti per aggirare il problema da persone che hanno familiarità con gli interni di Darcs.Come aggirare l'errore di simbolo duplicato quando si utilizza la libreria Yesod e Darcs?

Quando si utilizza il darcs library in un'applicazione Yesod, ottengo il seguente errore:

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. 

Sembra essere causato dalle darcs e cryptohash librerie che espongono lo stesso simbolo, come la ricerca attraverso i rispettivi file oggetto rivela :

# 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 

ho scritto un programma di test per confermare che i darcs e le biblioteche cryptohash sono in conflitto:

0.123.516,410617 millions
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 

Non riesce a compilare con un errore simile:

/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 

La biblioteca cryptohash è richiesto dalla yesod-static e non può facilmente essere evitato quando si scrive un'applicazione Yesod. Come posso usare Yesod e Darcs (come libreria) nella stessa applicazione?

Potrebbe essere utile eliminare i simboli duplicati da una libreria? Entrambi i pacchetti accedono alle funzioni di hashing tramite FFI ma utilizzando file diversi.

Da darcs/Crypt.SHA256:

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

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

Un'altra idea è quella di riscrivere Darcs non utilizzare la propria funzione di hashing. Come posso reimplementare il modulo SHA256 di Darcs per utilizzare cryptohash? Le due dichiarazioni nella funzione main del mio programma di test non danno lo stesso risultato (testate commentando l'altra istruzione), quindi l'uso di cryptohash in Darcs non sembra del tutto semplice.

+0

Non puoi semplicemente rinominare la versione Darcs di questa funzione in qualcosa come "darcs_sha256_init'? –

+1

Se ho capito bene, il problema è che il simbolo è definito in due diversi file C utilizzati tramite FFI, quindi non è utile rinominare la funzione Haskell, giusto? –

+0

Tuttavia, la rinomina della funzione C è d'aiuto. Vedi la mia risposta rivista. –

risposta

4

L'output di hash di darcs è solo la versione codificata base16 dell'output di cryptohash. Sembra che base16-bytestring sia un modo per colmare questa lacuna. Ho provato e Crypt.SHA256 diventa semplice come:

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 

Infatti il ​​pacchetto hashed-storage ha anche una copia di sha2.c e risolto il problema rinominando simboli. Così il più semplice soluzione rapida per darcs 2.8 è quello di copiare sha2.h e sha2.c da-storage hash, sostituire hashed_storage_ con darcs_ in entrambi i file, e cambiare l'importazione FFI in src/crypt/SHA256.hs in darcs a:

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

Sarei felice di rilasciare darcs 2.8.3 con questo cambiamento se fosse d'aiuto. Per 2.10 passerò ad usare cryptohash come sopra visto che non vedo alcun motivo per continuare ad usare la versione C locale e in generale in Darcs stiamo cercando di sbarazzarci di implementazioni private di codice comune.

EDIT: Inizialmente pensavo che lo storage con hash avrebbe lo stesso problema, ma mi sbagliavo (in retrospettiva è ovvio che si sarebbe scontrato con gli stessi darcs se non per la ridenominazione).

+0

Concordo sul fatto che l'utilizzo di cryptohash sia preferibile a lungo termine, ma può vivere con la soluzione più semplice per il momento, se lo preferisci per 2.8. Un caricamento su Hackage sarebbe fantastico, quindi posso usare una versione rilasciata. Grazie! –

+1

Ora caricato: http://hackage.haskell.org/package/darcs-2.8.3 –