Haskell工具栈和可执行文件大小

4
我用 Stack 工具 创建了一个 Haskell 命令行接口。我刚刚通过 Travis 成功地设置了交叉编译,但我不明白为什么在 Linux(6MB)、OS X(2MB)和 Windows(18MB!)之间可执行文件的大小差别如此之大。这是怎么回事?释放版本:https://github.com/unfog-io/unfog-cli/releases/tag/v0.1.2;Travis 配置:https://github.com/unfog-io/unfog-cli/blob/master/.travis.yml编辑: 当我使用 tar.gz 压缩可执行文件时,我减少了其中的差异,但仍然很大!现在我有 Linux(1.35MB)、OS X(0.61MB)、Windows(3.93MB)(请参见发行说明) 。

我对此并不是很了解,但是有一些问题需要考虑。看一下这个链接,可能会有所帮助:https://dev59.com/Qmcs5IYBdhLWcg3wmlIK - lsmor
谢谢提供链接,我会去查看,但它似乎更多地解决了“为什么这么大”的问题。我的观点更多是关于“为什么不同操作系统的大小如此不同”。 - soywod
1个回答

3
Linux和MacOS版本之间的区别可能是由于称为“split sections”的东西。在Linux上启用-split-sections GHC标志会将每个编译函数放入自己的链接器部分(而不是将所有函数放入单个“.text”部分的历史方法)。这使得链接器能够以实际上无法实现的粒度丢弃未使用的代码。不幸的是,所有依赖项都需要使用此标志构建才能受益。您可以通过将以下行添加到项目的stack.yaml文件中来强制Stack正确重新构建所有内容:
ghc-options:
    "$everything": -split-sections

这种指定 GHC 依赖项选项的方法在 这里 中有记录。

如果你使用这种变化重新构建你的 unfog,它实际上会从头开始重建 "base" 和 "vector" 以及其他所有内容,因此可能需要一些时间。但是,得到的二进制文件非常值得。未剥离的大小从约 11 兆字节减小到了 4 兆字节,如果进行剥离,则只有:

-rwxr-xr-x 1 buhr buhr 1494696 Nov 27 19:40 unfog

现在,据我了解,原始的MacOS版本只有2兆的原因是MacOS链接器已经实现了类似于分割节的东西。我不确定为MacOS构建是否-split-sections也可以提供额外的收益,或者-split-sections是否在MacOS下是自动默认的。无论如何,尝试一下也无妨。

对于Windows来说,它之所以如此庞大,主要原因是使用MinGW GCC工具链来编译Windows二进制文件,因此存在一个GNU-ish库的完整兼容性层(libc、libm、libpthread、libgmp等),并且与Linux和MacOS构建不同,它们都被静态链接到Windows二进制文件中。Windows的唯一动态链接是标准的Windows DLL。

请注意,-split-sections可能在Windows上工作或不工作。在bug跟踪器上有一些评论使其不清楚。无论如何,值得尝试一下,看看它是否有所不同。

一些其他参考资料:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接