昨天我了解了一个名为Stack的新Haskell工具。乍一看,看起来它与Cabal完全相同。那么,它们之间有什么区别?堆叠是Cabal的替代品吗?在哪些情况下我应该使用Stack而不是Cabal?什么可以堆栈做Cabal不能?
答案 0 :(得分:55)
堆叠是Cabal的替代品吗?
是和否。
在哪种情况下,我应该使用Stack而不是Cabal? Stack可以做什么?Cabal可以做什么?
由于Stack
使用 default 的策划堆栈包,因此已知这些包可以一起构建。在Cabal,你可能会受到阴谋的打击。 Stack也在本地缓存你的包,这样你下次使用那个包(或它的传递依赖)时就不会从头开始编译所有东西。请注意,还有使用非堆栈包的规定,因此即使堆栈快照中没有包也可以使用。
就个人而言,我喜欢Stack,并建议每个Haskell开发人员使用它。他们的发展是快。他们不担心(那么多)有关向后兼容性的问题。它有一个很多更好的用户体验。 stack
Cabal
提供的内容stack build --fast --file-watch
尚未提供:{/ p>
--pedantic
。如果更改存在的本地文件,这将自动重建。将它与{{1}}选项一起使用对我来说是一个交易障碍。有一篇很好的博客文章解释了这些差异:Why is Stack not Cabal?
答案 1 :(得分:23)
在下文中,我将把两个被比较的工具称为 cabal-install 和 stack 。特别是,我将使用 cabal-install 来避免与 Cabal 库混淆,后者是两种工具使用的通用基础结构。从广义上讲,我们可以说 cabal-install 和堆栈是 Cabal 的前端,它们之间的主要区别归结为默认的工作流程是:
默认情况下, cabal-install 在被要求构建项目时,会查看其.cabal
文件中指定的依赖项,并使用依赖项求解器来计算(如果可能的话)一组满足它的包和包版本。这个集合来自Hackage整体 - 所有包和所有版本,过去和现在。一旦找到可行的构建计划,默认情况下,所选择的依赖项版本将安装在~/.cabal
某处已安装软件包的单个数据库中并注册。
堆栈将首先查看stack.yaml
的resolver
字段。该字段通常指定Stackage 快照,它是Hackage包的一个子集,其中已修复的版本已知是相互兼容的。默认情况下, stack 将尝试使用快照提供的内容来满足依赖关系。从一个快照安装的软件包在不同且隔离的数据库中注册,并且维护单独的GHC安装以考虑快照所需的内容。这种方法具有一点灵活性,保证安装的软件包之间不存在版本不兼容(使用单个软件包数据库与 cabal-install 时的常见问题,原因在this article中讨论),以及总是可以找出用于构建项目的确切版本的依赖项(这对于确保完全充实项目的可重复构建以及轻松指定非常有用)没有伴随.hs
文件的自包含.cabal
脚本的依赖关系。
请注意,上述说明涵盖了每种工具的默认工作流程。 stack 所做的大部分工作都可以通过逐步退出默认值以 cabal-install 以某种(可能不那么方便)的方式实现,反之亦然。特别是:
cabal-install 通过cabal sandbox
命令支持每个项目的隔离包数据库,但与 stack 和Stackage快照不同,不可能跨项目共享已安装的包。通过.cabal
,也可以独立于cabal freeze
修复要用于构建的依赖项版本。 (一个相关的堆栈功能,没有 cabal-install 模拟,是对单独的GHC安装的管理,即stack setup
。)
堆栈项目可以使用正在使用的Stackage快照中不可用的软件包,方法是在stack.yaml
(extra-deps
中为Hackage提供的软件包设置相应的字段,但不能来自Stackage,packages
使用自定义location
来获取不在Hackage中的软件包。这些非Stackage软件包基于每个项目安装,与快照隔离。还有一个stack solver
命令,它为Hackage(即非Stackage)依赖项执行自动依赖项解析。
最后,值得一提的是,{em> cabal-install 正在添加对Nix-style local builds的支持,作为缓解版本冲突的替代方法,这可能比{{更方便“ 1}}。此功能作为预览版本可从 cabal-install 1.24。
中获得答案 2 :(得分:8)
从我从常见问题解答中可以看出,似乎Stack使用Cabal库,而不是cabal.exe
二进制文件(更正确地称为cabal-install)。看起来该项目的目标是自动沙箱并避免依赖地狱。
换句话说,它使用相同的Cabal包结构,它只是提供了一个不同的前端来管理这些东西。 (我想!)