peta - instalar haskell en ubuntu
Cómo compilar Haskell a una biblioteca estática? (2)
Esto hace que ghc compile estáticamente (tenga en cuenta que pthread es anterior a optl-static): ghc --make -static -optl-pthread -optl-static test.hs
Editar: Pero la compilación estática parece ser un poco arriesgada. La mayoría de las veces hay algunos errores. Y en mi x64 fedora no funciona en absoluto. El binario resultante también es bastante grande, 1.5M para main = putStrLn "hello world"
Hola, estoy aprendiendo Haskell y estoy interesado en usarlo para hacer bibliotecas estáticas para usar en Python y probablemente C. Después de buscar en Google descubrí cómo hacer que GHC produzca un objeto compartido, pero depende dinámicamente de GHC` s bibliotecas. El ELF resultante de la compilación en GHC depende dinámicamente y solo de C libs, y está un poco por debajo de un MB en tamaño; se ha vinculado estáticamente con las librerías de GHC. ¿Cómo y si se puede lograr esto para los objetos compartidos?
Ejemplo de estado actual:
$ 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)
Si intento compilarlo con (sin ''-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
Cuando busqué en Google, encontré algo sobre todo este asunto: ¿que puede provenir del hecho de que GHC está compilado de una manera específica (dinámica / estática?) Y, por lo tanto, no es posible establecer enlaces estáticos. Si esto es cierto, ¿cómo es posible que el binario ELF esté vinculado estáticamente?
De todos modos, espero que alguien pueda arrojar algo de luz sobre esto, ya que una gran cantidad de Google me dejó con más preguntas de las que comencé.
Muchas gracias.
La forma canónica de esto es:
- Exporte las funciones (a través de FFI) para inicializar RTS (sistema de tiempo de ejecución) mediante el programa externo
- Exporta funciones reales que te gustaría implementar en Haskell
Las siguientes secciones del manual describen esto: [1] [2]
Por otro lado, puedes probar la técnica descrita en esta publicación de blog (que, por cierto, la mía):
http://mostlycode.wordpress.com/2010/01/03/shared-haskell-so-library-with-ghc-6-10-4-and-cabal/
Todo se reduce a la creación de un pequeño archivo C que se llama automáticamente justo después de que se carga una biblioteca. Debería estar vinculado a la biblioteca.
#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 ();
}
Editar: La publicación original del blog que describe esta técnica es la siguiente: http://weblog.haskell.cz/pivnik/building-a-shared-library-in-haskell/