Home > other >  On a stack's package file, what is the difference between library and executables dependencies?
On a stack's package file, what is the difference between library and executables dependencies?

Time:12-09

In Haskell, while using stack, there are three places where we can define dependencies on the package.yaml file; under library and executables. What is the difference between defining a dependency in these places and when should I use them?

CodePudding user response:

Let's say you want to build and application with two front ends: CLI and a GUI, both using the same underliying logic. Obviously, your CLI doesn't use any graphical libraries, so It shouldn't depend on them and viceversa. Your package.yaml will look something like.

name:                my-app
version:             0.1.0.0

# This are the dependencies all the components depends on. 
dependencies:
- base >= 4.7 && < 5

# This is the description of your "common logic" i.e. the library 
library:
  source-dirs: src
# depends on whatever libraries of your choice
  dependencies:
    - bytestring
    - megaparsec
    - parser-combinators
    - transformers

executables:
# The executable name for the cli
  my-app-cli:
# The main function is in cli.hs
    main:                cli.hs
    source-dirs:         app
    ghc-options:
      - -Wall
      - -Wextra
      - -threaded
      - -rtsopts
      - -with-rtsopts=-qg
# It depends on you library, the base library (which remember is at the top of the file), and on whatever other libraries you use to build the cli, for example optparse-applicative
    dependencies:
      - my-app
      - optparse-applicative


# The executable name for the GUI
  my-app-gui:
# The main function is on gui.hs
    main:                gui.hs
    source-dirs:         app
    ghc-options:
      - -Wall
      - -Wextra
      - -threaded
      - -rtsopts
      - -with-rtsopts=-qg
# Again, It depends on your library, the base, and a GUI library of your choice. Example monomer.
    dependencies:
      - my-app
      - monomer

Now when you run stack build it will create two executables, one named my-app-cli and other my-app-gui, each with its own dependencies, but sharing the common ones. Ideally one could run stack build my-app:my-app-cli to build just one of the executables, but for some reason stack builds everything (which apparently is due to some cabal behaviour... don't know, don't care)

That been said, I don't think this is different from other programming languages. For example, I tend to structure my Python code the same way. A common library with its own requirements.txt and then different applications each with its own requirement.txt depending if the application is gonna be a web server, a machine learning model or what ever... this simplifies creating cached layer in docker for example. If I need to add some dependencies to the web server, they are added to the web server requirements.txt instead of the library one. This is, of course opinionated but my point is that this isn't haskell specific.

  • Related