2011-05-24 10 views
115

Incluso los programas de Haskell trivialmente pequeños se convierten en gigantescos ejecutables.Pequeño programa de Haskell compilado con GHC en un enorme binario

He escrito un programa pequeño, que se compiló (con GHC) con el binario y el tamaño se extendió a 7 MB.

¿Qué puede causar que incluso un pequeño programa Haskell se compile en el enorme binario?

¿Qué puedo hacer para reducir esto?

+1

¿Has intentado simplemente despojarlo? –

+4

No sé lo que eso significa –

+17

Ejecute el programa 'strip' en el binario para eliminar la tabla de símbolos. –

Respuesta

206

Vamos a ver lo que está pasando, tratar

$ du -hs A 
    13M A 

    $ file A 
    A: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), 
    dynamically linked (uses shared libs), for GNU/Linux 2.6.27, not stripped 

    $ ldd A 
    linux-vdso.so.1 => (0x00007fff1b9ff000) 
    libXrandr.so.2 => /usr/lib/libXrandr.so.2 (0x00007fb21f418000) 
    libX11.so.6 => /usr/lib/libX11.so.6 (0x00007fb21f0d9000) 
    libGLU.so.1 => /usr/lib/libGLU.so.1 (0x00007fb21ee6d000) 
    libGL.so.1 => /usr/lib/libGL.so.1 (0x00007fb21ebf4000) 
    libgmp.so.10 => /usr/lib/libgmp.so.10 (0x00007fb21e988000) 
    libm.so.6 => /lib/libm.so.6 (0x00007fb21e706000) 
    ...  

que se ve desde la salida ldd que GHC ha producido un ejecutable enlazado dinámicamente, pero sólo las bibliotecas de C están vinculados dinámicamente! Todas las bibliotecas de Haskell están copiadas textualmente.

Aparte: ya que esta es una aplicación de uso intensivo de gráficos, sin duda compilar con ghc -O2

Hay dos cosas que puede hacer.

símbolos desprendimiento

una solución fácil: Tira el binario:

$ strip A 
$ du -hs A 
5.8M A 

Strip descarta símbolos desde el archivo de objeto. Por lo general, solo son necesarios para la depuración.

vinculada de forma dinámica las bibliotecas de Haskell

Más recientemente, GHC ha ganado el apoyo de dynamic linking of both C and Haskell libraries. La mayoría de las distribuciones ahora distribuyen una versión de GHC construida para admitir el enlace dinámico de las bibliotecas de Haskell. Las bibliotecas compartidas de Haskell se pueden compartir entre muchos programas Haskell, sin copiarlos en el ejecutable cada vez.

En el momento de escribir Linux y Windows son compatibles.

para permitir que las bibliotecas de Haskell para vincularse dinámicamente, debe compilar con -dynamic, así:

$ ghc -O2 --make -dynamic A.hs 

Además, ninguna biblioteca que desea ser compartida debe ser construido con --enabled-shared:

$ cabal install opengl --enable-shared --reinstall  
$ cabal install glfw --enable-shared --reinstall 

Y terminará con un ejecutable mucho más pequeño, que tiene las dependencias C y Haskell resueltas dinámicamente.

$ ghc -O2 -dynamic A.hs       
[1 of 4] Compiling S3DM.V3   (S3DM/V3.hs, S3DM/V3.o) 
[2 of 4] Compiling S3DM.M3   (S3DM/M3.hs, S3DM/M3.o) 
[3 of 4] Compiling S3DM.X4   (S3DM/X4.hs, S3DM/X4.o) 
[4 of 4] Compiling Main    (A.hs, A.o) 
Linking A... 

Y, voilà!

$ du -hs A 
124K A 

que se puede quitar para hacer aún más pequeño:

$ strip A 
$ du -hs A 
84K A 

un ejecutable eensy weensy, construido a partir de muchas piezas C y Haskell de enlace dinámico:

$ ldd A 
    libHSOpenGL-2.4.0.1-ghc7.0.3.so => ... 
    libHSTensor-1.0.0.1-ghc7.0.3.so => ... 
    libHSStateVar-1.0.0.0-ghc7.0.3.so =>... 
    libHSObjectName-1.0.0.0-ghc7.0.3.so => ... 
    libHSGLURaw-1.1.0.0-ghc7.0.3.so => ... 
    libHSOpenGLRaw-1.1.0.1-ghc7.0.3.so => ... 
    libHSbase-4.3.1.0-ghc7.0.3.so => ... 
    libHSinteger-gmp-0.2.0.3-ghc7.0.3.so => ... 
    libHSghc-prim-0.2.0.0-ghc7.0.3.so => ... 
    libHSrts-ghc7.0.3.so => ... 
    libm.so.6 => /lib/libm.so.6 (0x00007ffa4ffd6000) 
    librt.so.1 => /lib/librt.so.1 (0x00007ffa4fdce000) 
    libdl.so.2 => /lib/libdl.so.2 (0x00007ffa4fbca000) 
    libHSffi-ghc7.0.3.so => ... 

Uno punto final: incluso en sistemas con enlace estático solamente, puede use -split-objs, para obtener un archivo .o por nivel superior la función el, que puede reducir aún más el tamaño de las bibliotecas vinculadas estáticamente. Necesita que GHC se genere con -split-objs on, algo que algunos sistemas olvidan hacer.

+7

¿cuándo está viniendo la vinculación dinámica para llegar a ghc en el mac? –

+104

Los usuarios de Mac deben aportar código o efectivo. –

+1

... no 'cabal instale' tira el binario instalado por defecto? – hvr

11

Haskell utiliza la vinculación estática por defecto. Es decir, todas las vinculaciones de OpenGL se copian en su programa. Como son bastante grandes, su programa se inflará innecesariamente. Puede solucionar esto utilizando enlaces dinámicos, aunque no está habilitado de manera predeterminada.

+5

Puede vincular dinámicamente bibliotecas para evitar esto. No estoy seguro de por qué es importante lo que es predeterminado, la bandera es lo suficientemente simple. –

+2

El problema es que "cualquier biblioteca que desee compartir se debe compilar con' - habilitada-compartida' ", de modo que si su plataforma Haskell viene con bibliotecas compiladas sin' --habilitado compartido', debe recompilar las bibliotecas base que pueden ser bastante doloroso – nponeccop

Cuestiones relacionadas