我用Stack tool创建了一个Haskell CLI。感谢Travis,我已经成功设置了交叉编译功能,但是我不明白为什么linux(6MB),osx(2MB)和Windows(18MB!)之间的可执行文件大小如此不同。怎么会来?
发布:https://github.com/unfog-io/unfog-cli/releases/tag/v0.1.2
Travis conf:https://github.com/unfog-io/unfog-cli/blob/master/.travis.yml
编辑
当我用tar.gz压缩可执行文件时,我减少了差异,但是仍然!我现在有linux(1.35MB),osx(0.61MB),windows(3.93MB)(请参见release)
Linux和MacOS版本之间的差异可能归因于“ split sections”。
在Linux上启用-split-sections
GHC标志会将每个已编译的函数置于其自己的链接器节中(而不是将所有函数置于单个“ .text”节中的传统方法)。这使链接器可以丢弃没有使用的代码,否则将无法实现粒度。
不幸的是,all依赖关系需要使用此标志构建才能受益。您可以通过将以下行添加到项目的stack.yaml
文件中来强制Stack正确地重建所有内容:
ghc-options:
"$everything": -split-sections
这种为依赖项指定GHC选项的方法已在here中记录。
如果您通过此更改来重建unfog
,则实际上会从头开始重建“ base”和“ vector”以及其他所有内容,因此可能需要一段时间。但是,生成的二进制文件值得。不剥皮,它的大小从大约11Meg下降到4Meg,并且如果您剥离它,它只是:
-rwxr-xr-x 1 buhr buhr 1494696 Nov 27 19:40 unfog
甚至比您发布的MacOS版本还要小。
现在,据我所知,原始MacOS版本仅为2Meg的原因是MacOS链接器已经实现了类似于拆分部分的功能。我不确定also为MacOS构建启用-split-sections
是否会带来额外的收益,或者-split-sections
是否为MacOS的自动默认设置。无论如何,尝试它不会有任何伤害。
对于Windows,它如此巨大的主要原因是MinGW GCC工具链用于编译Windows二进制文件,因此存在GNU类库的完整兼容性层(libc,libm,libpthread,libgmp等),以及- -与Linux和MacOS版本不同-它们都被静态链接到Windows二进制文件中。 Windows的唯一动态链接是到标准Windows DLL。
注意-split-sections
在Windows上可能会或可能不会。在错误跟踪器上有一些注释使其不清楚。无论如何,可能值得尝试一下是否有所作为。
一些其他参考:
-split-sections
by default的GHC错误跟踪器>-split-sections
的功能请求