Stack的package.yaml和stack.yaml有什么区别?

21
Stack自至少此次提交以来就支持hpackpackage.yaml配置文件,但据我所知,关于它与stack.yaml文件之间的差异并没有太多文档资料。
我找到的为数不多的一些链接之一是此文档,其中提到:

package.yaml是由hpack支持的一种文件格式。它在cabal的基础上添加了一些好处。例如,hpack支持YAML语法,并且会自动生成exposed-modules列表。但是,它只是cabal包文件的前端。

因此,从这个描述来看,package.yaml似乎提供了*.cabal文件配置能力的超集,就像stack.yaml文件也是如此。

这里的文档暗示stack.yaml是配置文件:

接下来,让我们看看我们的stack.yaml文件,它提供了我们项目级别的设置。

...稍后又说package.yaml用于存储依赖项:

要告诉 stack 使用text,需要将其添加到package.yaml文件中 - 具体来说是在您的依赖项部分中...

这个相关问题,但遗憾的是它没有澄清两个文件之间的区别。

我一直在使用package.yaml来进行我所有项目的配置,并且从未使用stack.yaml


那么,堆栈的package.yamlstack.yaml文件之间的关系是什么?如果/当它们的职责重叠时,使用哪个更好?

你使用 stack 吗?stack build 没有 stack.yaml 真的能成功吗? - Li-yao Xia
1
@Li-yaoXia 刚刚检查了一下,如果没有 stack.yaml 文件是无法构建的,但是文件中唯一的内容(由 stack 1.6.5 生成)是一个 resolver 和一个 packages 标签 - 其他所有内容都在 package.yaml 中。我甚至可以注释掉 packages 标签,构建也能正常运行。 - hnefatl
你了解 package-name.cabalstack.yaml 之间的区别吗?package.yaml 可以作为 cabal 文件的替代方案。 - Potato44
1个回答

20
因此,从这个角度来看,package.yaml 提供了一个比 *.cabal 文件更强大的配置功能,就像 stack.yaml 文件一样。 stack.yaml 并没有提供比 *.cabal 更强大的配置能力。
*.cabal 文件是包级别的配置文件。它可以由 hpackpackage.yaml 生成。该配置文件提供有关包的基本信息:依赖项、导出组件(库、可执行程序、测试套件)和构建过程的设置(预处理器、自定义 Setup.hs)。许多项目也不使用 hpack,只有一个 *.cabal 文件。 stack.yaml 文件是项目级别的配置文件,指定特定的环境以使构建可复现,固定编译器和依赖项的版本。这通常由解析器(例如 lts-11.4)指定。 stack.yaml 不会与 package.yaml 重复。 package.yaml 指定需要哪些依赖项。 stack.yaml 表示一种一致地解决依赖项的方式(特定包版本,或从何处获取它,例如:在 Hackage、远程仓库或本地目录)。 stack.yaml 对开发人员最有用:我们不希望在处理另一个项目时依赖项升级而导致构建突然中断,因此我们使用 stack.yaml 固定所有内容。对用户来说,该文件不太有用,他们可能有外部约束(通常是某些分发版已经固定了版本)。
  • 在许多情况下,只需在 stack.yaml 中指定解析器即可。因此,新的 stack 用户通常不需要担心配置 stack.yaml

  • 解析器指定了一组精选的带有特定版本的软件包(标准软件包在stackage.org上列出)。如果所选解析器缺少软件包的依赖项,则必须将其列在stack.yamlextra-deps字段中。

  • 一个项目可以跨越多个软件包,因此将它们添加到stack.yamlpackages字段中,这样它们可以在单个公共环境中构建并相互依赖。

  • 另一个常见用例是创建许多不同名称的stack.yaml以轻松测试各种配置(例如GHC版本或软件包标志)。


  • 谢谢,这是一个很好的回答 - 只是为了澄清:如果您需要固定其版本,那么只需要在stack.yaml中放置依赖项?而将其放在package.yaml中则让解析器选择一个版本? - hnefatl
    2
    stack.yaml 实际上为所有包指定了版本。其中大多数通常在解析器的选择中是隐含的。有一些没有包的解析器(ghc-*),需要将每个依赖项(包括传递依赖项)都列为额外依赖项。 - Li-yao Xia
    @hnefatl 如果一个依赖项包含在解析器中,或者您想要一个特定的版本,则只需要在extra-deps中添加一个条目。请注意,预期不会更改解析器中包含的软件包和版本,并且据我所知,stack将缓存解析器的数据。另一方面,*.cabalpackage.yaml中的依赖关系应该是软性的,以免失去使版本与多个解析器兼容的能力。 - MauganRa
    3
    或许现在评论有点晚,但是:我认为需要指出的是 package.yaml 并非强制要求——它只是对 *.cabal 文件的一层薄包装,很多人(包括我)选择直接编辑 *.cabal 文件。请注意不要改变原意,使翻译内容通俗易懂。 - bradrn
    另一个常见的用例是创建许多不同名称的 stack.yaml,以轻松测试各种配置(例如 GHC 版本或包标志)。@Li-yaoXia,您知道有没有一些你所说内容的示例的地方? - Nicolas Henin
    一个地方可以在Github上查找类似于stack-lts*.yaml的文件:https://github.com/search?p=1&q=filename%3Astack-lts*.yaml&type=Code 我知道aeson在其根目录中有一堆stack文件,我不确定它们是否仍在使用,但那是我第一次接触到它的地方。 - Li-yao Xia

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