21

Stack has supported hpack's package.yaml configuration files since at least around this commit, as far as I can tell, but there's not much documentation about the differences between it and the stack.yaml file.

One of the few links I've found talking about it is this documentation, where it says:

package.yaml is a file format supported by hpack. It adds some niceties on top of cabal. For example, hpack has YAML syntax support and will automatically generate of exposed-modules lists. However, it's just a frontend to cabal package files.

So from this, it seems like package.yaml provides a superset of the *.cabal file's configuration ability, like the stack.yaml file also does.


The documentation here implies stack.yaml is the configuration file:

Next, let's look at our stack.yaml file, which gives our project-level settings.

...and later says that package.yaml is for storing dependencies:

To tell stack to use text, you need to add it to your package.yaml file — specifically in your dependencies section...

There's this related question, but it sadly doesn't clarify the difference between the two files.

I've been using package.yaml for all my project's configurations, and never using stack.yaml.


So, what is the relationship between stack's package.yaml and stack.yaml files? If/when their responsibilities overlap, which is it better practice to use?

hnefatl
  • 5,860
  • 2
  • 27
  • 49
  • Do you use `stack`? Can `stack build` really succeed without a `stack.yaml`? – Li-yao Xia Apr 11 '18 at 12:24
  • 1
    @Li-yaoXia Just checked and it can't build without a `stack.yaml`, but the only things in the file (that was generated by stack 1.6.5) are a `resolver` and a `packages` tag - everything else is in the `package.yaml`. I can even comment out the `packages` tag and the build runs fine. – hnefatl Apr 11 '18 at 12:35
  • Do you understand what the difference between the `package-name.cabal` and `stack.yaml` is? `package.yaml` serves as an alternative for the cabal file. – Potato44 Apr 11 '18 at 12:52

1 Answers1

19

So from this, it seems like package.yaml provides a superset of the *.cabal file's configuration ability, like the stack.yaml file also does.

stack.yaml does not provide a superset of *.cabal configurations.


The *.cabal file is the package-level configuration. It can be generated by hpack from a package.yaml. This configuration provides essential information about the package: dependencies, exported components (libraries, executables, test suites), and settings for the build process (preprocessors, custom Setup.hs). Many projects also don't use hpack and don't have a package.yaml, only a *.cabal file.

The stack.yaml file is the project-level configuration, which specifies a particular environment to make a build reproducible, pinning versions of compiler and dependencies. This is usually specified by a resolver (such as lts-11.4).

stack.yaml is not redundant with package.yaml. package.yaml specifies what dependencies are needed. stack.yaml indicates one way to consistently resolve dependencies (specific package version, and/or where to get it from, for example: on Hackage, a remote repository, or a local directory).

stack.yaml is most useful to developers: we don't want our build to suddenly break because a dependency upgraded while working on another project, hence we pin everything with stack.yaml. This file is less useful to users, who may have external constraints (typically, versions are already fixed by some distribution).

  • In many cases, just specifying the resolver in stack.yaml is enough. Hence new stack users usually don't need to worry about configuring stack.yaml.

  • A resolver specifies a curated set of packages with specific versions (the standard ones are listed on stackage.org). If a dependency of the package is missing from the chosen resolver, then it must be listed in the extra-deps field of stack.yaml.

  • A project can span multiple packages, that thus get added to the packages field of stack.yaml, so they can be built in a single common environment and depend on each other.

  • Another common use case is to create many stack.yaml (with different names) to easily test various configurations (e.g., GHC versions or package flags).

Li-yao Xia
  • 31,896
  • 2
  • 33
  • 56
  • Thanks, this is a nice answer - just to clarify: would you only need to put a dependency in `stack.yaml` if you require its version to be pinned? Whereas putting it in `package.yaml` lets the resolver pick a version? – hnefatl Apr 11 '18 at 13:31
  • 2
    The stack.yaml actually specifies versions for all packages. Most of them are usually implicit in the choice of resolver. There are resolvers with no packages (`ghc-*`), with which every single dependency, including transitive ones, need to be listed as extra-deps. – Li-yao Xia Apr 11 '18 at 13:38
  • @hnefatl An entry in `extra-deps` is only required if a dependency is not contained in a resolver, or if you want to have a specific version. Note that packages and versions contained in a resolver are expected to not change, and as far as I know `stack` will cache the resolver's data. On the other hand, dependencies in `*.cabal` and `package.yaml` should be soft, lest one loses the ability to make a version compatible to multiple resolvers. – MauganRa May 27 '18 at 16:19
  • 3
    Maybe it's a bit late to comment, but: I think it should also be noted that `package.yaml` is not mandatory in any way - it's just a thin layer over the `*.cabal` file, and many people (including me) choose to edit the `*.cabal` file directly. – bradrn May 26 '19 at 02:47
  • "Another common use case is to create many stack.yaml (with different names) to easily test various configurations (e.g., GHC versions or package flags)." @Li-yaoXia do you know a place where there are some examples of what you say ? – Nicolas Henin Jul 25 '20 at 13:12
  • One place is to look for files like `stack-lts*.yaml` on Github: https://github.com/search?p=1&q=filename%3Astack-lts*.yaml&type=Code I know aeson has a bunch of stack files in its root, I'm not sure whether they are still used, but that's where I first picked it up. – Li-yao Xia Jul 25 '20 at 16:25