mkdir repro
cd repro
cabal get snappy
cd snappy-0.2.0.2
brew install snappy
cabal sandbox init
cabal install
Then create a simple hello world file:
module Main where
import qualified Data.ByteString as B
import Codec.Compression.Snappy
main :: IO ()
main = do
f <- B.readFile "foo.jpg"
B.writeFile "foo.snp" (compress f)
And finally try to compile it:
ghc HelloSnappy.hs
[1 of 3] Compiling Codec.Compression.Snappy.Internal ( Codec/Compression/Snappy/Internal.hs, Codec/Compression/Snappy/Internal.o )
[2 of 3] Compiling Codec.Compression.Snappy ( Codec/Compression/Snappy.hs, Codec/Compression/Snappy.o )
[3 of 3] Compiling Main ( HelloSnappy.hs, HelloSnappy.o )
Linking HelloSnappy ...
Undefined symbols for architecture x86_64:
"__hsnappy_GetUncompressedLength", referenced from:
_c3Jf_info in Snappy.o
"__hsnappy_MaxCompressedLength", referenced from:
_c2Fq_info in Internal.o
"__hsnappy_RawCompress", referenced from:
_c3Co_info in Snappy.o
"__hsnappy_RawUncompress", referenced from:
_c3Ha_info in Snappy.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
The "solution" is to compile referencing the position of the compiled .dylib directory, living inside dist/build:
ghc HelloSnappy.hs -L./dist/dist-sandbox-2e5d78d/build -lHSSnappy-0.2.0.2-ghc7.8.3
Linking HelloSnappy ...
This compiles fine, but still crashed at runtime:
./HelloSnappy
dyld: Library not loaded: @rpath/libHSsnappy-0.2.0.2-ghc7.8.3.dylib
Referenced from: /Users/adinapoli/programming/haskell/snappy/snappy-0.2.0.2/./HelloSnappy
Reason: image not found
[1] 1828 trace trap ./HelloSnappy
Solution is once again to make dlopen aware of the .dylib:
☁ snappy-0.2.0.2 export LD_LIBRARY_PATH=$PWD/dist/dist-sandbox-2e5d78d/build
☁ snappy-0.2.0.2 ./HelloSnappy
HelloSnappy: foo.jpg: openBinaryFile: does not exist (No such file or directory)
Sean Leather on the Haskell Cafè gave me this solution (thanks!):
You're installing into a cabal sandbox and compiling directly with ghc (not cabal), but ghc doesn't know anything about the sandbox. You need to point it to the package database with -package-db and tell it the package for linking with -package [2].
$ ghc -package-db .cabal-sandbox/x86_64-osx-ghc-7.8.3-packages.conf.d -package snappy HelloSnappy.hs
Linking HelloSnappy ...
$ ./HelloSnappy
HelloSnappy: foo.jpg: openBinaryFile: does not exist (No such file or directory)
[1] http://www.haskell.org/ghc/docs/latest/html/users_guide/packages.html#package-databases
[2] http://www.haskell.org/ghc/docs/latest/html/users_guide/options-phases.html#options-linker
Alternatively, if you've got a recent version of cabal you can use
cabal exec -- ghc HelloSnappy.hs
instead.
You can also load up GHCi in the sandbox using cabal exec ghci
or
cabal repl
.
I wonder if there is a problem with linking
snappy
Haskell to C++ symbols. This makes me think so:What happens if you add a C header file to
snappy
withextern "C"
wrapped around thehs_snappy.cpp
function signatures?