Hey, I'm learning Haskell and I'm interested in using it to make static libraries for using in Python and probably C. After some googling I found out how to get GHC to output a shared object, but it dynamically depends on GHC`s libraries. The resulting ELF from compiling in GHC is dynamically dependand only on C libs and it's a bit under a MB in size - it has been statically linked with GHC`s libs. How and if can this be achieved for shared objects?
Example of current state:
$ ghc --make -dynamic -shared -fPIC foo.hs -o libfoo.so $ ldd libfoo.so linux-vdso.so.1 => (0x00007fff125ff000) libHSbase-4.2.0.2-ghc6.12.3.so => /usr/lib/ghc-6.12.3/base-4.2.0.2/libHSbase-4.2.0.2-ghc6.12.3.so (0x00007f7d5fcbe000) libHSinteger-gmp-0.2.0.1-ghc6.12.3.so => /usr/lib/ghc-6.12.3/integer-gmp-0.2.0.1/libHSinteger-gmp-0.2.0.1-ghc6.12.3.so (0x00007f7d5faac000) libgmp.so.10 => /usr/lib/libgmp.so.10 (0x00007f7d5f816000) libHSghc-prim-0.2.0.0-ghc6.12.3.so => /usr/lib/ghc-6.12.3/ghc-prim-0.2.0.0/libHSghc-prim-0.2.0.0-ghc6.12.3.so (0x00007f7d5f591000) libHSffi-ghc6.12.3.so => /usr/lib/ghc-6.12.3/libHSffi-ghc6.12.3.so (0x00007f7d5f383000) libc.so.6 => /lib/libc.so.6 (0x00007f7d5f022000) /lib/ld-linux-x86-64.so.2 (0x00007f7d60661000) $ ghc foo.hs $ ldd foo linux-vdso.so.1 => (0x00007fff2d3ff000) libgmp.so.10 => /usr/lib/libgmp.so.10 (0x00007f50014ec000) libm.so.6 => /lib/libm.so.6 (0x00007f5001269000) librt.so.1 => /lib/librt.so.1 (0x00007f5001061000) libdl.so.2 => /lib/libdl.so.2 (0x00007f5000e5d000) libc.so.6 => /lib/libc.so.6 (0x00007f5000afc000) libpthread.so.0 => /lib/libpthread.so.0 (0x00007f50008df000) /lib/ld-linux-x86-64.so.2 (0x00007f5001759000)
If I try to compile it with(without '-dynamic'):
$ ghc --make -shared -fPIC foo.hs -o libfoo.so Linking libfoo.so ... /usr/bin/ld: foo.o: relocation R_X86_64_32S against `stg_CAF_BLACKHOLE_info' can not be used when making a shared object; recompile with -fPIC foo.o: could not read symbols: Bad value collect2: ld returned 1 exit status
When googling I found something about this whole issue - that it may come from the fact that GHC is compiled in a specific way(dynamic/static?) and so static linking is not possible. If this is true how is it possible that the ELF binary is statically linked?
Anyway, I am hoping someone can shed some light on this since a huge amount of googling left me with more questions than I started with.
Huge thanks.
The canonical way of is this:
The following sections of manual describe this: [1] [2]
On the other way, you can try technique described in this blog post (which mine, by the way):
http://mostlycode.wordpress.com/2010/01/03/shared-haskell-so-library-with-ghc-6-10-4-and-cabal/
It boils down to creating a small C file which is called automatically right after a library is loaded. It should be linked together into the library.
#define CAT(a,b) XCAT(a,b) #define XCAT(a,b) a ## b #define STR(a) XSTR(a) #define XSTR(a) #a #include extern void CAT (__stginit_, MODULE) (void); static void library_init (void) __attribute__ ((constructor)); static void library_init (void) { /* This seems to be a no-op, but it makes the GHCRTS envvar work. */ static char *argv[] = { STR (MODULE) ".so", 0 }, **argv_ = argv; static int argc = 1; hs_init (&argc, &argv_); hs_add_root (CAT (__stginit_, MODULE)); } static void library_exit (void) __attribute__ ((destructor)); static void library_exit (void) { hs_exit (); }
Edit: Original blog post describing this technique is this: http://weblog.haskell.cz/pivnik/building-a-shared-library-in-haskell/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With