Даже тривиально маленькие программы на Haskell превращаются в гигантские исполняемые файлы.
Я написал небольшую программу, которая была скомпилирована (с помощью GHC) в двоичный файл размером более 7 МБ!
Что может заставить даже небольшую программу на Haskell компилироваться в огромный двоичный файл?
Что я могу сделать, чтобы уменьшить это?
strip
на двоичном файле, чтобы удалить таблицу символов.strip test
. Эта команда удаляет часть отладочной информации из программы и уменьшает ее размер.data M3 = M3 !V3 !V3 !V3
иdata V3 = V3 !Float !Float !Float
. Скомпилируйте с помощьюghc -O2 -funbox-strict-fields
.Ответы:
Посмотрим, что происходит, попробуем
Из
ldd
вывода видно, что GHC создал динамически скомпонованный исполняемый файл, но только библиотеки C связаны динамически ! Все библиотеки Haskell скопированы дословно.В сторону: поскольку это приложение с интенсивной графикой, я бы определенно компилировал с
ghc -O2
Вы можете сделать две вещи.
Удаление символов
Простое решение: удалите двоичный файл:
Стрип удаляет символы из объектного файла. Обычно они нужны только для отладки.
Динамически подключаемые библиотеки Haskell
Совсем недавно GHC получил поддержку динамической компоновки библиотек C и Haskell . Большинство дистрибутивов теперь распространяют версию GHC, созданную для поддержки динамического связывания библиотек Haskell. Общие библиотеки Haskell могут использоваться многими программами Haskell, не копируя их каждый раз в исполняемый файл.
На момент написания поддерживаются Linux и Windows.
Чтобы позволить библиотекам Haskell быть динамически связанными, вам нужно скомпилировать их
-dynamic
, например:Кроме того, любые библиотеки, которыми вы хотите поделиться, должны быть созданы с помощью
--enabled-shared
:В итоге вы получите исполняемый файл гораздо меньшего размера, в котором зависимости C и Haskell будут динамически разрешены.
И вуаля!
которые можно разделить, чтобы сделать еще меньше:
Очень приятный исполняемый файл, созданный из множества динамически связанных частей C и Haskell:
И последнее: даже в системах со статической компоновкой вы можете использовать -split-objs , чтобы получить один файл .o для каждой функции верхнего уровня, что может еще больше уменьшить размер статически связанных библиотек. Ему нужно, чтобы GHC был построен с -split-objs, что некоторые системы забывают делать.
источник
cabal install
удаляет установленный двоичный файл по умолчанию?enable-shared
рассмотрено. launchpad.net/ubuntu/+source/pandoc/+bugsПо умолчанию Haskell использует статическое связывание. То есть все привязки к OpenGL копируются в вашу программу. Поскольку они довольно большие, ваша программа излишне раздувается. Вы можете обойти это, используя динамическое связывание, хотя по умолчанию оно не включено.
источник
--enabled-shared
», поэтому, если ваша платформа Haskell поставляется с библиотеками, созданными без--enabled shared
вас, вам придется перекомпилировать базовые библиотеки, что может быть довольно болезненным.