Vediamo cosa sta succedendo, prova
$ 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)
...
Dall'output si vede ldd
che GHC ha prodotto un eseguibile collegato dinamicamente, ma solo le librerie C sono collegate dinamicamente ! Tutte le librerie di Haskell sono copiate alla lettera.
A parte: dal momento che si tratta di un'app ad alta intensità grafica, mi piacerebbe sicuramente compilare ghc -O2
Ci sono due cose che puoi fare.
Simboli di stripping
Una soluzione semplice: togli il binario:
$ strip A
$ du -hs A
5.8M A
Strip elimina i simboli dal file oggetto. Sono generalmente necessari solo per il debug.
Librerie Haskell collegate dinamicamente
Più recentemente, GHC ha ottenuto il supporto per il collegamento dinamico di entrambe le librerie C e Haskell . La maggior parte delle distribuzioni ora distribuisce una versione di GHC creata per supportare il collegamento dinamico delle librerie Haskell. Le librerie condivise Haskell possono essere condivise tra molti programmi Haskell, senza copiarle ogni volta nell'eseguibile.
Al momento della scrittura di Linux e Windows sono supportati.
Per consentire alle librerie Haskell di essere collegate dinamicamente, è necessario compilarle -dynamic
, in questo modo:
$ ghc -O2 --make -dynamic A.hs
Inoltre, tutte le librerie che si desidera condividere devono essere create con --enabled-shared
:
$ cabal install opengl --enable-shared --reinstall
$ cabal install glfw --enable-shared --reinstall
E finirai con un eseguibile molto più piccolo, che ha risolto dinamicamente sia le dipendenze C che Haskell.
$ 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...
E, voilà!
$ du -hs A
124K A
che puoi rimuovere per renderlo ancora più piccolo:
$ strip A
$ du -hs A
84K A
Un eseguibile weensy eensy, costruito da molti pezzi C e Haskell collegati dinamicamente:
$ 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 ultimo punto: anche su sistemi con solo collegamento statico, è possibile utilizzare -split-objs , per ottenere un file .o per funzione di livello superiore, che può ridurre ulteriormente la dimensione delle librerie collegate staticamente. Ha bisogno che GHC sia costruito con -split-objs, cosa che alcuni sistemi dimenticano di fare.