Skip to content

Instantly share code, notes, and snippets.

@borsboom
Last active September 2, 2015 16:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save borsboom/ab5a1b859ca5619c2f8b to your computer and use it in GitHub Desktop.
Save borsboom/ab5a1b859ca5619c2f8b to your computer and use it in GitHub Desktop.
`stack` slides for HIW'15
#!/usr/bin/env stack
-- stack --install-ghc runghc --package=extra
import System.Info.Extra (isWindows)
main = putStrLn $ "Hello, " ++ if isWindows then "Windows" else "Un*x"
<!DOCTYPE html>
<html>
<head>
<title>Introduction to 'stack' build tool</title>
<meta charset="utf-8">
<style>
@import url(https://fonts.googleapis.com/css?family=Yanone+Kaffeesatz);
@import url(https://fonts.googleapis.com/css?family=Droid+Serif:400,700,400italic);
@import url(https://fonts.googleapis.com/css?family=Ubuntu+Mono:400,700,400italic);
body { font-family: 'Droid Serif'; }
h1, h2, h3 {
font-family: 'Yanone Kaffeesatz';
font-weight: normal;
}
.remark-code, .remark-inline-code { font-family: 'Ubuntu Mono'; }
.red { color: #fa0000; }
.purple { color: #fa00fa; }
.footnote {
position: absolute;
bottom: 3em;
}
</style>
</head>
<body>
<script src="https://gnab.github.io/remark/downloads/remark-latest.min.js">
</script>
<script>
var slideshow = remark.create({
sourceUrl: 'slides.md'
});
</script>
</body>
</html>

class: center, middle

Introduction to stack

"The Haskell Tool Stack"

Emanuel Borsboom
FP Complete


What is stack?

A build tool to make new and experienced Haskellers' lives easier.

  • User-friendly
  • Easy setup
  • Isolated
  • Predictable
  • Project based
  • Efficient

Comparable to Clojure's Leiningen, Scala's sbt, Ruby's Bundler.


History

  • Conducted a survey of current and potential commercial Haskell users in early 2015

  • Learned: current build tooling was among the major factors holding up Haskell adoption

    • 2/3 of respondents rated "crucial" or "important"
  • Decided to open-source an internal-to-FP Complete build tool that's been developed over the last year.

  • Also integrated various stackage-* tools under the stack umbrella

  • Emphasized user-friendliness in further development for open source version


stack is user-friendly

  • Most common tasks are simple commands
  • Does the "right thing" by default
  • Intuitive, discoverable command-line interface
$ git clone git@github.com:/me/myproject.git
$ cd myproject
$ stack test

More advanced:

$ stack build --pedantic \
              --haddock \
              --test \
              --exec "echo Yay, it succeeded" \
              --file-watch

GHCi with packages loaded:

$ stack ghci

stack makes setup easy

  • Provide binaries of stack for common platforms

  • Works around various issues in Windows

  • stack setup will fetch and install the correct GHC version to build your project .red[*]

  • Automatically installs tools like like alex, happy, or cpphs, when they are needed to build a package

  • Updates package database whenever a package cannot be found

.footnote[.red[*] Will use GHC on $PATH if it is already the right version]


stack is isolated

  • stack installs tools, including GHC, under ~/.stack

  • Packages are implicitly "sandboxed".

  • Does not interfere with existing tools or global/user package DBs.

  • Projects do not interfere with each other.


stack is predictable

  • Philosophy: build should be reproducible

  • Uses Stackage snapshots for dependency resolution by default .red[*]

  • Isolation means your project will build the same way every time, no matter what you do for other projects

  • Great for teams: for a given git commit of the project, everyone will get same result when they build .purple[^]

.footnote[.red[*] Can also use cabal-install's solver, but doing so is an explicit step and results are "frozen".

.purple[^] barring differences in your OS setup, but stack also supports implicitly using a Docker image to get 100% reproducible results]


Aside: what is Stackage/LTS?

  • A "Stackage snapshot" is a semi-curated set of packages guaranteed to be compatible with each other

  • Anyone can add a package. Requirements:

    • Compatible with all other packages in stackage (everything builds)
    • Tests pass
  • Automated as much as possible, with manual intervention when needed

  • Currently ~1400 packages

  • Snapshots tied to specific GHC version

  • Can also be used with cabal-install by downloading a cabal.config


Aside: what is Stackage/LTS? (continued)

  • Two flavours of snapshots:

    • Nightly (e.g. nightly-2015-08-30)

      • New snapshot every night, with latest versions of packages (as much as possible)
    • LTS ("Long Term Support", e.g. lts-3.2):

      • Periodic "snapshot" of nightly, then:
      • New snapshot every week, with only minor version updates of packages
      • For now: cutting a new LTS major version every 3-5 months, with no overlap
  • Learn more: https://www.stackage.org/


stack is project based

A project configuration consists of:

  • A list of packages that are part of a project

    • these can be local or pulled directly from a Git repository
  • Resolver for dependencies .red[*]

    • Stackage snapshot (LTS or nightly)
    • GHC (only packages included with GHC)
    • Custom snapshot
  • Overrides if you need packages or versions not in the snapshot

  • Extra Cabal flags, and ghc-options

.footnote[.red[*] Implies GHC version]


Project configuration example

WAI's stack.yaml:

resolver: lts-2.17
packages:
- ./wai
- ./wai-extra
- ./warp
- ./warp-tls
- ./wai-app-static
- ./wai-handler-fastcgi
- ./wai-handler-launch
- ./wai-websockets
- ./wai-conduit
- ./mime-types
- ./auto-update
extra-deps:
- doctest-0.10.1
- http2-1.0.2
- hex-0.1.2

stack is efficient

  • Does not build packages if no source files changed

    • No waiting for unnecessary runs of ghc --make and linking executables in multi-package projects
  • When projects can safely share packages (e.g., using same Stackage snapshot), they are stored in shared package database .red[*]

  • Caches time-consuming steps

.footnote[.red[*] With GHC's new support for multiple instances of the same package version in a DB, support for sharing packages between snapshots as well is planned]


Some more features

  • Create stack.yaml for an existing package: stack init

  • Create a new project from a template: stack new

  • GHCJS support

  • Use stack as a shell interpreter:

    #!/usr/bin/env stack
    -- stack --install-ghc runghc --package=extra
    import System.Info.Extra (isWindows)
    main = putStrLn $ "Hello, " ++ if isWindows then "Windows" else "Un*x"
  • stack-ide: JSON interface to ide-backend, for editor integration .red[*]

    • Emacs integration (stack-mode)
    • Sublime Text 3 integration (stack-ide-sublime)
  • Visualize dependency tree (w/ GraphViz): stack dot

.footnote[.red[*] Still a work in progress]


class: center, middle

.hundred[WAI DOT]


Implementation

  • Uses the Cabal library to build packages

    • Each package still has a .cabal file
    • Custom Setup.hs supported
  • Dependencies are pulled from Hackage .red[*]

  • Package index is a Git repository (fast updates!)

  • Snapshots are defined in a YAML file, pulled from Git repository

.footnote[.red[*] Actually an Amazon S3-hosted Hackage mirror, by default]


Implementation (continued)

  • 3-Tiered package DB strategy:

    • Global: stack will read but not write GHC's global package DB
    • Snapshot: stack reads and only writes packages from the Stackage snapshot
    • Local: the project's packages and extra dependencies
  • File paths:

    • "Global" state in ~/.stack: GHC, tools, snapshot packages
    • Project state in <project-dir>/.stack-work: local package database
    • Package state in <package-dir>/.stack-work/dist

stack is not

stack does many things, but there are some things it does not aim to be:

  • stack is not a package manager

    • Will not install to OS-global locations
    • No "uninstall" functionality
    • But: for convenience, it can copy built executables to a location on your PATH
  • stack is not a full replacement for cabal-install

    • stack does not attempt to replicate everything cabal-install can do
    • But: helps make most thing you actually want to do go smoothly

To come...

Stack is moving fast. Some things being worked on now:

  • Easy GHCJS setup

  • Sharing packages between snapshots

  • Install packages/executables in a specific prefix

  • Improvement to editor integration

  • Extensible custom snapshots

  • Support for custom GHC binary distributions

  • Continuing improvements: bug fixes, optimization, documentation


stack, a build tool

  • Project of the Commercial Haskell SIG

    • Anyone interested in commercial use of Haskell welcome to join (no fees or commitments)
    • Currently ~40 companies, ~100 individuals
  • Spearheaded by FP Complete

  • Very open to open to pull requests

    • 48 contributors since released in June
    • Liberally granting push access
  • Beta software

    • Regular releases
    • Please file issues

class: center, middle

Get stack here:

https://github.com/commercialhaskell/stack


class: center, middle

Questions?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment