Hãy xem những gì đang xảy ra, hãy thử
$ 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)
...
Bạn thấy từ ldd
đầu ra mà GHC đã tạo ra một tệp thực thi được liên kết động, nhưng chỉ các thư viện C được liên kết động ! Tất cả các thư viện Haskell được sao chép nguyên văn.
Ngoài ra: vì đây là một ứng dụng chuyên sâu về đồ họa, tôi chắc chắn sẽ biên dịch với ghc -O2
Có hai điều bạn có thể làm.
Tước biểu tượng
Một giải pháp dễ dàng: tước nhị phân:
$ strip A
$ du -hs A
5.8M A
Dải loại bỏ các ký hiệu từ tệp đối tượng. Chúng thường chỉ cần để gỡ lỗi.
Các thư viện Haskell được liên kết động
Gần đây, GHC đã đạt được sự hỗ trợ cho liên kết động của cả thư viện C và Haskell . Hầu hết các bản phân phối hiện phân phối một phiên bản GHC được xây dựng để hỗ trợ liên kết động của các thư viện Haskell. Các thư viện Haskell được chia sẻ có thể được chia sẻ giữa nhiều chương trình Haskell mà không cần sao chép chúng vào tệp thực thi mỗi lần.
Tại thời điểm viết Linux và Windows được hỗ trợ.
Để cho phép các thư viện Haskell được liên kết động, bạn cần biên dịch chúng với -dynamic
, như vậy:
$ ghc -O2 --make -dynamic A.hs
Ngoài ra, bất kỳ thư viện nào bạn muốn được chia sẻ nên được xây dựng với --enabled-shared
:
$ cabal install opengl --enable-shared --reinstall
$ cabal install glfw --enable-shared --reinstall
Và bạn sẽ kết thúc với một thực thi nhỏ hơn nhiều, có cả hai phụ thuộc C và Haskell được giải quyết một cách linh hoạt.
$ 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...
Và Voila!
$ du -hs A
124K A
mà bạn có thể tước để làm cho nhỏ hơn nữa:
$ strip A
$ du -hs A
84K A
Một tập tin eensy thực thi, được xây dựng từ nhiều phần C và Haskell được liên kết động:
$ 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 => ...
Điểm cuối cùng: ngay cả trên các hệ thống chỉ có liên kết tĩnh, bạn có thể sử dụng -split-objs , để lấy một tệp .o cho mỗi hàm cấp cao nhất, có thể giảm thêm kích thước của các thư viện được liên kết tĩnh. Nó cần GHC để được xây dựng với -split-objs, điều mà một số hệ thống quên làm.