当我创建一个新项目时。比如说,一个使用Snap的网络应用程序。
我使用snap init barebones
生成框架,创建一个新的沙箱,然后安装依赖项。
这需要永远。认真。如果您曾经使用过几乎任何其他Web框架(例如,带有express的node.js),则该过程几乎完全相同,但只需要一小部分时间。我知道大多数节点依赖都不需要任何编译,但我发现这并不奇怪,这不是一个更大的问题。例如,我永远无法在我的廉价VPS上运行Yesod应用程序,因为VPS不够强大,无法编译它,我无法真正上传500mb的预编译库。
问题是,为什么不是存储库主机二进制文件而不仅仅是代码? .NET也被编译(到字节码),但我可以使用它的DLL,而无需重新编译。
托管二进制文件当然存在缺陷,例如需要更多的存储空间,每个库的多个二进制文件用于多个操作系统......但是所有问题对于您获得的巨大好处似乎无关紧要
我很难理解为什么首先存在阴谋。如果所有库都可用于动态链接,那么根本不存在重新编译的需要吗?
目前,在这些方面,我们必须努力坚持使用Haskell。看起来这个系统会因为尝试一些东西而惩罚我。如果我想在我的项目中添加一个新库,我必须确保我愿意等待15-45(!!!)分钟才能编译。更不用说图书馆的编译方式不会比我更熟悉。在这个过程中幸存下来之后,我才能真正弄清楚该库是否是我想要使用的,或者它是否与我项目的其余部分兼容。
答案 0 :(得分:3)
简而言之:因为本机代码很难。
如果要为任意系统托管二进制文件,则必须将二进制文件与要运行的每个系统进行匹配。这可能意味着要编译几十套二进制文件来支持代码编译的所有系统。
另一方面,您可能会发现某人已编译了您需要的代码:您的分发提供商可能会为您需要的Haskell库提供软件包。
答案 1 :(得分:2)
因为这是在保持最新状态的同时分发所有内容的最简单方法。通过向用户卸载构建成本,库作者只需要提供源代码。
这可以通过各种方式减轻。例如,my CI setup使用CircleCI和Heroku。两个节点都装有预制的cabal沙箱(它实际上非常容易设置)。我在Heroku上构建我的项目,但是没有理由不能从CI中获取预构建的工件并直接部署它们。
对于动态链接,可以动态链接Haskell模块,但共享库通常是问题的根源。看看Windows DLL地狱应该足以看到这一点,大多数商业应用程序只是提供他们使用的DLL。如果库发生了变化,那么无论如何都必须更换DLL,而Cabal的方式使得最简单的方法可以获得所有内容的最新版本。
答案 2 :(得分:1)
首先,请注意在某些平台上, 实际上可以安装二进制库。例如,在我的OpenSUSE Linux系统上,YaST非常乐意下载并安装某些Haskell库,而无需从源代码构建任何东西。
当然,这只涵盖了相当少的一组库,并且所有的RPM都将过时许多个月。 (对X11来说并不是什么大不了的事,对像Yesod这样一个正处于重大发展之类的事情来说是一种交易破坏......)
我认为问题的另一个重要部分是,如果使用GHC 7.6.4编译Haskell库,那么不能使用GHC 7.8.3的二进制编译库。所以我们不只是讨论每个操作系统的一个编译二进制文件;我们正在讨论每个OS + GHC次要点释放组合的一个编译二进制文件。
哦,我提到了吗?如果您针对ByteString 0.9.2.0编译Yesod 1.4.0,那么如果您的系统安装了ByteString 0.9.2.1,那么编译后的二进制文件将无用。因此,对于每个操作系统,每个GHC版本以及它可传递依赖的每个库的每个版本,您可能需要一个已编译的二进制文件。
......这就是Haskell平台发明的部分原因。这是一个单独的二进制下载,它为您提供了一大堆代码,您无需从源代码编译,并且其中所有库的版本都是相互兼容的。 (没有依赖性地狱 - Haskell平台维护者为你排序!)
我同意二进制包非常好。但上述问题使其不太可能,恕我直言。