Voyons ce qui se passe, essayez
$ 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)
...
Vous voyez dans la ldd
sortie que GHC a produit un exécutable lié dynamiquement, mais seules les bibliothèques C sont liées dynamiquement ! Toutes les bibliothèques Haskell sont copiées in extenso.
A part: puisqu'il s'agit d'une application gourmande en graphiques, je compilerais certainement avec ghc -O2
Vous pouvez faire deux choses.
Symboles de dépouillement
Une solution simple: dépouiller le binaire:
$ strip A
$ du -hs A
5.8M A
Supprimer supprime les symboles du fichier objet. Ils ne sont généralement nécessaires que pour le débogage.
Bibliothèques Haskell liées dynamiquement
Plus récemment, GHC a pris en charge la liaison dynamique des bibliothèques C et Haskell . La plupart des distributions distribuent désormais une version de GHC conçue pour prendre en charge la liaison dynamique des bibliothèques Haskell. Les bibliothèques Haskell partagées peuvent être partagées entre de nombreux programmes Haskell, sans les copier dans l'exécutable à chaque fois.
Au moment de l'écriture, Linux et Windows sont pris en charge.
Pour permettre aux bibliothèques Haskell d'être liées dynamiquement, vous devez les compiler avec -dynamic
, comme ceci:
$ ghc -O2 --make -dynamic A.hs
De plus, toutes les bibliothèques que vous souhaitez partager doivent être créées avec --enabled-shared
:
$ cabal install opengl --enable-shared --reinstall
$ cabal install glfw --enable-shared --reinstall
Et vous vous retrouverez avec un exécutable beaucoup plus petit, qui a à la fois les dépendances C et Haskell résolues dynamiquement.
$ 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...
Et voilà!
$ du -hs A
124K A
que vous pouvez décaper pour rendre encore plus petit:
$ strip A
$ du -hs A
84K A
Un exécutable très simple, construit à partir de nombreux éléments C et Haskell liés dynamiquement:
$ 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 dernier point: même sur les systèmes avec des liaisons statiques uniquement, vous pouvez utiliser -split-objs , pour obtenir un fichier .o par fonction de niveau supérieur, ce qui peut encore réduire la taille des bibliothèques liées statiquement. Il faut que GHC soit construit avec -split-objs, ce que certains systèmes oublient de faire.