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 ofexposed-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 yourpackage.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?
So from this, it seems like
package.yaml
provides a superset of the*.cabal
file's configuration ability, like thestack.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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With