GHCで巨大なバイナリにコンパイルされた小さなHaskellプログラム


127

些細な小さなHaskellプログラムでさえ、巨大な実行可能ファイルになります。

私は(GHCで)コンパイルされてサイズが7 MBのバイナリにコンパイルされた小さなプログラムを書きました!

小さなHaskellプログラムでも巨大なバイナリにコンパイルされる原因は何ですか?

これを減らすにはどうしたらいいですか?


2
剥がしてみましたか?
Fred Foo、

21
stripバイナリ上でプログラムを実行して、シンボルテーブルを削除します。
Fred Foo、

1
@ tm1rbt:を実行しますstrip test。このコマンドは、プログラムから一部のデバッグ情報を削除し、それを小さくします。
fuz

8
余談ですが、3D数学ライブラリのデータ型は、パフォーマンス上の理由から厳しくする必要がdata M3 = M3 !V3 !V3 !V3ありdata V3 = V3 !Float !Float !Floatます。でコンパイルしghc -O2 -funbox-strict-fieldsます。
Don Stewart、

8
この投稿はmetaで議論されています。
Patrick Hofman、2014

回答:


215

何が起こっているのか見てみましょう

  $ 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)
    ...      

ldd出力から、GHCが動的にリンクされた実行可能ファイルを生成したことがわかりますが、動的にリンクされているのはCライブラリだけです。すべてのHaskellライブラリはそのままコピーされます。

余談ですが、これはグラフィックを多用するアプリなので、必ずコンパイルします ghc -O2

できることは2つあります。

シンボルの除去

簡単な解決策:バイナリを削除します。

$ strip A
$ du -hs A
5.8M    A

Stripは、オブジェクトファイルからシンボルを破棄します。通常、これらはデバッグにのみ必要です。

動的にリンクされたHaskellライブラリ

最近では、GHCはCとHaskellライブラリの両方の動的リンクのサポートを獲得しています。現在、ほとんどのディストリビューションは、Haskellライブラリの動的リンクをサポートするためにビルドされたバージョンのGHCを配布しています。共有Haskellライブラリは、実行可能ファイルに毎回コピーすることなく、多くのHaskellプログラム間で共有できます。

執筆時点では、LinuxとWindowsがサポートされています。

Haskellライブラリを動的にリンクできるようにするには-dynamic、次のようにそれらをでコンパイルする必要があります。

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

また、共有したいライブラリは、以下を使用してビルドする必要があります--enabled-shared

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

そして、Cと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...

そして、ほら!

$ du -hs A
124K    A

あなたはストリップしてさらに小さくすることができます:

$ strip A
$ du -hs A
84K A

動的にリンクされた多くのCとHaskellのピースから構築された、意地悪で不快な実行可能ファイル:

$ 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 => ...

最後に、静的リンクのみのシステムでも、-split-objsを使用して、トップレベル関数ごとに1つの.oファイルを取得できます。これにより、静的リンクライブラリのサイズをさらに削減できます。-split-objsをオンにしてGHCを構築する必要がありますが、一部のシステムではこれを忘れています。


7
Macのghcの到着によるダイナミックリンクはいつですか?
Carter Tazio Schonwald

1
... cabal installデフォルトでインストール済みのバイナリを削除しませんか?
hvr '25年

1
Windowsでこれを実行すると、結果のファイルが実行不能になり、libHSrts-ghc7.0.3.dllが見つからないというメッセージが表示されます
is7s

3
このバイナリは、これらの手順の後に他のLinuxマシンで動作しますか?
アレックス

1
2011年からOPをこんにちは!私は将来の出身ですが、Ubuntu 16.04で実行可能なpandocは50MBのファットであり、packages.ubuntu.com/zesty/pandocに基づいて変更される予定はないことがわかります。近い将来の自分や他の人へのメッセージ:パッケージのメンテナに連絡して、enable-shared検討されたかどうか尋ねてください。launchpad.net/ubuntu/+source/pandoc/+bugs
ステフェイン・グーリッホン

11

Haskellはデフォルトで静的リンクを使用します。つまり、OpenGLへのバインディング全体がプログラムにコピーされます。それらは非常に大きいので、プログラムは不必要に膨張します。これは、デフォルトでは有効になっていませんが、動的リンクを使用して回避できます。


5
ライブラリを動的にリンクして、これを回避できます。なぜデフォルトが重要であるのかわからないので、フラグは十分に単純です。
Thomas M. DuBuisson、

4
問題は、「共有したいすべてのライブラリはで構築する必要がある--enabled-shared」ということです。そのため、Haskellプラットフォームに--enabled shared、基本ライブラリを再コンパイルせずに構築されたライブラリが付属している場合は、非常に面倒です。
nponeccop
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.