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