Veamos qué está pasando, intenta
$ 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)
...
Como puede ver en el ldd
resultado, GHC ha producido un ejecutable vinculado dinámicamente, ¡pero solo las bibliotecas C están vinculadas dinámicamente ! Todas las bibliotecas de Haskell se copian al pie de la letra.
Aparte: dado que esta es una aplicación intensiva en gráficos, definitivamente compilaría con ghc -O2
Hay dos cosas que puedes hacer.
Símbolos de pelado
Una solución fácil: tira el binario:
$ strip A
$ du -hs A
5.8M A
Strip descarta los símbolos del archivo objeto. Por lo general, solo son necesarios para la depuración.
Bibliotecas Haskell vinculadas dinámicamente
Más recientemente, GHC ha obtenido soporte para la vinculación dinámica de las bibliotecas C y Haskell . La mayoría de las distribuciones ahora distribuyen una versión de GHC creada para admitir el enlace dinámico de las bibliotecas Haskell. Las bibliotecas Haskell compartidas se pueden compartir entre muchos programas Haskell, sin copiarlas en el ejecutable cada vez.
Al momento de escribir, Linux y Windows son compatibles.
Para permitir que las bibliotecas de Haskell se vinculen dinámicamente, debe compilarlas de esta -dynamic
manera:
$ ghc -O2 --make -dynamic A.hs
Además, todas las bibliotecas que desee compartir deben compilarse 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 puedes quitar para hacer aún más pequeño:
$ strip A
$ du -hs A
84K A
Un ejecutable eensy weensy, creado a partir de muchas piezas de C y Haskell vinculadas dinámicamente:
$ 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 => ...
Un último punto: incluso en sistemas con enlace estático solamente, puede usar -split-objs , para obtener un archivo .o por función de nivel superior, lo que puede reducir aún más el tamaño de las bibliotecas enlazadas estáticamente. Necesita que GHC se construya con -split-objs, algo que algunos sistemas olvidan hacer.