Cabal和Stack有什么区别?


104

昨天,我了解了一个名为Stack的新Haskell工具。乍一看,它看起来和Cabal差不多。那么,它们之间有什么区别?堆栈可以代替Cabal吗?在哪些情况下应该使用Stack而不是Cabal?Cabal不能做什么Stack?


fpcomplete.com/blog/2015/06/announcing-first-public-beta-stack(总而言之,它cabal-install尽可能多地替换和使用堆叠-在某些时候可能会向后集成到cabal-install中,我认为社区不确定这是否是一件好事,因为这可能会分裂社区)
Carsten

AFAIU堆栈便于快速处理现有项目。如果您从头开始,一定会使用cabal。
mb14 2015年

@ mb14事实并非如此。您可以使用堆栈从头开始项目。实际上,堆栈模板提供了一种简便的方法。
西比

请参阅以下简短文章,以获取良好的概述:scs.stanford.edu/16wi-cs240h/labs/stack.html
michid

Answers:


74

堆栈可以代替Cabal吗?

是和否

在哪些情况下应该使用Stack而不是Cabal?Cabal不能做什么Stack?

Stack通过以下方式使用策划的堆叠包装 默认情况下,。这样一来,就可以将任何依赖项组合在一起,避免了版本冲突问题(在Haskell经验中它们很常见,以前称为“ cabal hell”)。Cabal的最新版本还具有防止冲突的措施。但是,使用Stack可以更直接地设置可重现的构建配置,在该配置中您确切知道将从存储库中提取的内容。请注意,还提供了使用非堆栈式软件包的规定,因此即使堆栈快照中不存在软件包,也可以使用。

就个人而言,我喜欢Stack,并建议每个Haskell开发人员都使用它。他们的发展很快。它有一个很大更好的UX。而Stack却没有提供Stack所提供的某些功能:

  • Stack甚至可以为您下载GHC,并将其保存在一个隔离的位置。
  • Docker支持(这对于部署Haskell应用程序非常方便)
  • 可复制的Haskell脚本:您可以查明软件包的版本,并可以保证该软件包将始终执行而不会出现任何问题。(Cabal还具有脚本功能,但是要完全确保其可重复性并不是那么简单。)
  • 做事能力强stack build --fast --file-watch。如果您更改存在的本地文件,它将自动重建。--pedantic对我来说,将它与option 一起使用是一个大难题。
  • Stack支持使用模板创建项目。它还支持您自己的自定义模板。
  • Stack内置了hpack支持。它提供了一种使用yaml文件写入集团文件的替代方法(IMO,更好),该方法在行业中使用更为广泛。
  • Intero 在使用Stack时具有流畅的体验。

有一篇不错的博客文章解释了不同之处:为什么Stack不是Cabal?尽管Cabal在担任该职位后的几年中一直在发展,以克服此处讨论的一些问题,但有关Stack背后的设计目标和理念的讨论仍然有意义。


自从阴谋3发行以来,有什么变化吗?
William Rusnack

1
@WilliamRusnack是的,有。首先,默认的Cabal工作流程现在包含了避免依赖冲突的方法,尽管它使用的策略与Stack的策略明显不同。(@Sibi:我已经自由地更新了您的答案,以便更好地反映这些天的状况。)
duplode

35

在下面的内容中,我将比较的两个工具称为cabal-installstack。特别是,我将使用cabal-install来避免与Cabal库混淆,Cabal库是两种工具都使用的通用基础结构。

概括地说,可以说cabal-installstackCabal的前端。两种工具都可以构建Haskell项目,这些项目的依赖关系集可能在单个系统的范围内相互冲突。它们之间的主要区别在于它们如何实现此目标:

  • 默认情况下,cabal-install将在被要求构建项目时,查看其.cabal文件中指定的依赖项,并使用依赖项求解器找出一组满足该要求的软件包和软件包版本。该集合是从Hackage整体上提取的-过去和现在的所有软件包和所有版本。一旦找到可行的构建计划,所选的依赖项版本将被安装并在的某个位置的数据库中建立索引~/.cabal。通过根据已安装的程序包的版本(以及其他相关的配置选项)对索引进行索引,可以避免依赖项之间的版本冲突,以便不同的项目可以检索所需的依赖项版本,而无需踩到对方的脚。这种安排是cabal-install文档通过“ Nix风格的本地版本”来表示

  • 当被要求构建项目时,堆栈将而不是进入Hackage,而是查看的resolver字段stack.yaml。在默认工作流程中,该字段指定Stackage 快照,它是具有固定版本的已知相互兼容的Hackage软件包的子集。然后,堆栈将仅使用快照提供的内容来尝试满足.cabal文件(或可能project.yaml文件 -不同格式,相同角色)中指定的依赖性。从每个快照安装的软件包都注册在单独的数据库中,这两个数据库不会互相干扰。

我们可能会说,在指定构建配置时,堆栈方法将一些设置灵活性换成了简单性。特别是,如果您知道您的项目使用了LTS 15.3快照,则可以转到其Stackage页面,一目了然地知道任何依赖项堆栈的版本都可能从Stackage中提取。也就是说,这两种工具都提供了超出基本工作流程的功能,因此,大体上,每个工具都可以完成彼此的所有工作(尽管可能不太方便)。例如,有一些方法可以冻结已知良好构建配置的确切版本,并通过cabal-install 解决具有旧状态的Hackage的依赖关系。,并且在使用stack时可能需要非Stackage依赖性或覆盖快照程序包版本

最后,cabal-installstack之间的另一个区别要大到值得在本概述中提及的地方是stack旨在提供具有自动GHC安装管理Docker集成等功能的完整构建环境。相比之下,cabal-install旨在与生态系统的其他部分正交,因此,它不会尝试提供此类功能(特别是,必须通过Linux发行版单独安装和管理GHC版本)软件包,Windows中的Haskell Platform Coreghcup工具)。


11

从常见问题解答中可以看出,Stack似乎使用Cabal库,而不使用cabal.exe二进制库(更正确地称为cabal-install)。看起来该项目的目标是自动沙箱和避免依赖地狱。

换句话说,它使用相同的Cabal软件包结构,只是提供了一个用于管理这些东西的前端。(我认为!)


除此之外cabal,它们的源代码似乎也正在使用docker。虽然我不知道他们是否使用过。
Sibi

@Sibi是的,您似乎可以选择将东西扔到Docker中,并且可以正常工作。我没有进一步研究……
MathematicalOrchid
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.