stack build Lecture 1

Compiling Haskell code

  • GHC - Glasgow Haskell Compiler

  • GHCi - Interpreter of Haskell code

$ ghc -o fac fac.hs
$ ./fac
1405006117752879898543142606244511569936384000000000
$ ghci main.hs
GHCi, version 8.2.2: http://www.haskell.org/ghc/  :? for help
[1 of 1] Compiling Main             ( /Users/pva701/main.hs, interpreted )
Ok, one module loaded.
*Main> 
$ ghci
GHCi, version 8.2.2: http://www.haskell.org/ghc/  :? for help
Loading package base ... linking ... done.
Prelude>

Haskell project structure

  • Code is in .hs files

  • Each source file is called module

  • Module name corresponds to relative path to file

module Snowdrop.Core.ChangeSet.Type where

...
Snowdrop/Core/ChangeSet/Type.hs
  • Modules form package

Building Haskell project

stack is a cross-platform build tool for Haskell projects

​Features

  • Create an isolate location

  • Install packages needed for your project

  • Build, run tests and benchmarks

  • Reproducible builds

Cabal ecosystem

  • Hackage is a huge repository of open-source Haskell libraries
  • .cabal is an extension of package specification.              Describes which packages and versions must be used for building package
  • cabal is a tool for building and packaging Haskell libraries and programs. It takes packages for building from Hackage

Cabal tool caused dependency hell

stack ecosystem

  • stack uses curated package sets called snapshots
  • Stackage is a stable repository of Haskell packages
  • resolver is a reference to a snapshot using for build 

Snapshots example

Encapsulation of ecosystem

How to start with stack

$ stack new new-project
Downloading template "new-template" to create project "new-project" in new-project/ ...
...
$ cd new-project
$ tree .
.
├── app
│   └── Main.hs
├── new-project.cabal
├── src
│   └── Lib.hs
├── stack.yaml
└── test
    └── Spec.hs
$ cat stack.yaml
# Resolver to choose a 'specific' stackage snapshot or a compiler version.
resolver: lts-13.2

# User packages to be built.
packages:
- .

# Dependency packages to be pulled from upstream that are not in the resolver
# extra-deps: []

# Override default flag values for local packages and extra-deps
# flags: {}

stack.yaml

$ cat new-project.cabal
...
library                      -- library keyword which starts description of library
  exposed-modules:           -- Modules which are visible outside of library
      Lib
  other-modules:             -- Rest modules. All modules in library must be listed
      Paths_new_project
  hs-source-dirs:
      src                    -- Directory with sources
  build-depends:
      base >=4.7 && <5       -- Packages which library depends on with range of versions
  default-language: Haskell2010

executable new-project-exe   -- executable keyword which starts description of executable
  main-is: Main.hs           -- Modules which is an entry point
  other-modules:
      Paths_new_project      -- Rest modules
  hs-source-dirs:
      app                    -- Directory where executable's modules are
  ghc-options: -threaded -rtsopts -with-rtsopts=-N -- Options which will be passed to GHC
  build-depends:
      base >=4.7 && <5
    , new-project            -- Executable depends on new-project library
  default-language: Haskell2010

test-suite new-project-test -- test-suite keyword which starts description of executable
  type: exitcode-stdio-1.0
  main-is: Spec.hs
  other-modules:
      Paths_new_project
  hs-source-dirs:
      test
  ghc-options: -threaded -rtsopts -with-rtsopts=-N
  build-depends:
      base >=4.7 && <5
    , new-project .        -- tests depend on new-project library
  default-language: Haskell2010

new-project.cabal

How to build with stack

$ stack setup
Preparing to install GHC to an isolated location.
This will not interfere with any system-level installation.
Downloaded ghc-8.6.3.
Installed GHC.

Installs GHC to ~/.stack

$ stack build
Building all executables for `new-project' once. After a successful build of all of them, only specified executables will be rebuilt.
...
Preprocessing library for new-project-0.1.0.0..
Building library for new-project-0.1.0.0..
[1 of 2] Compiling Lib              ( src/Lib.hs, .stack-work/dist/x86_64-osx/Cabal-2.4.0.1/build/Lib.o )
...

Preprocessing executable 'new-project-exe' for new-project-0.1.0.0..
Building executable 'new-project-exe' for new-project-0.1.0.0..
[1 of 2] Compiling Main             ( app/Main.hs, .stack-work/dist/x86_64-osx/Cabal-2.4.0.1/build/new-project-exe/new-project-exe-tmp/Main.o )
...

new-project-0.1.0.0: copy/register
Installing library in /Users/pva701/github/new-project/.stack-work/install/x86_64-osx/lts-13.2/8.6.3/lib/x86_64-osx-ghc-8.6.3/new-project-0.1.0.0-DWmU5UqJZ7qKBPe1ysCDyB
Installing executable new-project-exe in /Users/pva701/github/new-project/.stack-work/install/x86_64-osx/lts-13.2/8.6.3/bin
Registering library for new-project-0.1.0.0..

More commands

$ stack test

Builds and runs tests in new-project/test

$ stack build --test

Builds project and test and runs tests

$ stack exec new-project-exe

Flag --fast disables optimizations like --O2. Builds a project faster

$ stack build --fast

Execute built executable new-project-exe

$ stack clean

Remove all built data of local packages

$ stack build hw1

Build hw1 package

Useful links

Lecture 01: stack build

By ITMO CTD Haskell

Lecture 01: stack build

Introduction lecture. First steps to start playing with Haskell.

  • 4,185