Skip to content

package.yaml

Now let's have a look at the package.yaml of our hello-world project:

package.yaml
name:                hello-world
version:             0.1.0.0
github:              "githubuser/hello-world"
license:             BSD3
author:              "Author name here"
maintainer:          "example@example.com"
copyright:           "2023 Author name here"

extra-source-files:
- README.md
- CHANGELOG.md

# Metadata used when publishing your package
# synopsis:            Short description of your package
# category:            Web

# To avoid duplicated efforts in documentation and dealing with the
# complications of embedding Haddock markup inside cabal files, it is
# common to point users to the README.md file.
description:         Please see the README on GitHub at <https://github.com/githubuser/hello-world#readme>

dependencies:
- base >= 4.7 && < 5

ghc-options:
- -Wall
- -Wcompat
- -Widentities
- -Wincomplete-record-updates
- -Wincomplete-uni-patterns
- -Wmissing-export-lists
- -Wmissing-home-modules
- -Wpartial-fields
- -Wredundant-constraints

library:
  source-dirs: src

executables:
  hello-world-exe:
    main:                Main.hs
    source-dirs:         app
    ghc-options:
    - -threaded
    - -rtsopts
    - -with-rtsopts=-N
    dependencies:
    - hello-world

tests:
  hello-world-test:
    main:                Spec.hs
    source-dirs:         test
    ghc-options:
    - -threaded
    - -rtsopts
    - -with-rtsopts=-N
    dependencies:
    - hello-world

The file starts with package information used when publishing the package on Hackage. This includes the package name, its version, the URL where the package is published on Github, the name of the license used, the author, the maintainer, and copyright information.

extra-source-files is a list of files that are not part of the Haskell source code but should be included in the package when creating an archive for example for upload to Hackage.

synopsis and description are short and long descriptions of the package. category is the category under which this package should be found when searching the packages on Hackage. We'll ignore these settings because we won't publish our package to Hackage.

Now let's look at the sections we do care about.

dependencies is a list of package names that our project depends on. base is already included as an entry in this list because most projects depend on the standard library. This line also says that our project needs the standard library version 4.7 or higher but less than version 5. If we need arrays, maps, and monad transformers in your project, we'd add the lines

- array
- containers
- mtl

to the dependencies list.

ghc-options specifies compiler options to be used for our project. We'll ignore them here. Leave them alone.

library tells Stack where in our project the modules are to be found that constitute the library component of our project. Remember, these are the modules that other packages can import if we upload our package to Hackage and those other packages specify our package as a dependency. source-dirs specifies the directory or directories where the library files are found. It is common to have just a single directory here, and to leave it at the default, src.

executables configures a list of executable programs to be built from our package. Given that our package is called hello-world, the default executable to be created is hello-world-exe. You can change this executable name to anything you want. It is also possible to specify multiple executables to be built. Each needs to be represented by its separate section under executables, similar to the one for hello-world-exe.

Each executable section has an entry main that states the name of the main module. By default, this is Main.hs.

Next we have source-dirs, which states where the source code for this executable, including Main.hs, can be found. By default, this is app. Once again, the code can be spread over multiple source directories, but it is common to use only one.

Then we have a ghc-options section again. The top-level ghc-options section sets the compiler options for the whole project, including the library. The ghc-options for an executable affect only this executable.

Finally, we have a list of dependencies. Once again, the dependencies on the top level of the file are dependencies needed by all the code in our project, including the library. The dependencies of an executable are dependencies needed only for building this executable. Each executable is a self-contained project within our package. It doesn't even know anything about the library component of our package. If it needs the code in the library component of our package, which is quite common, it needs to specify our package itself as a dependency. stack new does this for us by default, by including hello-world in the dependencies list of hello-world-exe.

The final section is a tests section. The structure of this section is identical to the executables section. The difference is in how Stack treats these two sections. The executables under executables are built when running stack build, run when running stack run, and installed on our system when running stack install. The executables under tests are run when running stack test. Since we won't be writing any tests in this course, you can delete the tests section from package.yaml and delete the test directory from the project.