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 millionsimport 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.
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.
Non puoi semplicemente rinominare la versione Darcs di questa funzione in qualcosa come "darcs_sha256_init'? –
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? –
Tuttavia, la rinomina della funzione C è d'aiuto. Vedi la mia risposta rivista. –