123 votes

Petit programme de Haskell, compilé avec GHC énorme binaire

Même trivialement petits programmes Haskell se transformer en gigantesques exécutables.

J’ai écrit un petit programme, qui a été compilé (avec GHC) vers le fichier binaire avec la taille qui s’étend de 7 MB !

Quelles sont les causes même un petit programme de Haskell Compiler le binaire énorme ?

Que, si quelque chose, puis-je faire pour réduire cela ?

210voto

Don Stewart Points 94361

Voyons voir ce qu'il se passe, essayez de

  $ 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 de l' ldd sortie GHC a produit un exécutable dynamiquement lié, mais seulement les bibliothèques C sont liés de façon dynamique! Tous les Haskell bibliothèques sont copiés dans le verbatim.

De côté: puisque c'est une des images graphiques app, je serais certainement compiler avec ghc -O2

Il y a deux choses que vous pouvez faire.

Décapage des symboles

Une solution simple: la bande de la binaire:

$ strip A
$ du -hs A
5.8M    A

Bande de rejets des symboles à partir du fichier de l'objet. Ils sont généralement nécessaires pour le débogage.

Liée de façon dynamique Haskell bibliothèques

Plus récemment, GHC a obtenu le soutien de la liaison dynamique de C et de Haskell bibliothèques. La plupart des distributions maintenant de distribuer une version de GHC construit à l'appui de la liaison dynamique de Haskell bibliothèques. Partagé Haskell bibliothèques peut être partagé entre plusieurs programmes Haskell, sans les copier sur le fichier exécutable à chaque fois.

Au moment de l'écriture de Linux et Windows sont pris en charge.

Pour permettre le Haskell bibliothèques à être liée de manière dynamique, vous avez besoin de compiler avec -dynamic, comme suit:

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

Aussi, toutes les bibliothèques que vous voulez être partagée devrait être construit avec --enabled-shared:

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

Et vous vous retrouverez avec un beaucoup plus petit exécutable, qui a à la fois C et Haskell dépendances 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

qui vous pouvez tracé pour le rendre encore plus petit:

$ strip A
$ du -hs A
84K A

Un eensy weensy exécutable, construit à partir de nombreux liées dynamiquement C et Haskell pièces:

$ 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 des systèmes avec la liaison statique uniquement, vous pouvez utiliser -split-objs, pour en obtenir un .o fichier par le haut niveau de la fonction, ce qui peut réduire la taille de statiquement les bibliothèques. Il a besoin de GHC à être construit avec -split-objs sur, que certains systèmes oubliez pas de le faire.

11voto

FUZxxl Points 21462

Haskell utilise une liaison statique par défaut. Il s’agit, les liaisons ensemble à OpenGL sont copiés dans votre programme. Comme ils sont assez grands, votre programme obtient inutilement gonflé. Vous pouvez contourner cela en utilisant une liaison dynamique, même si elle n’est pas activée par défaut.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X