class: center, middle
Emanuel Borsboom
FP Complete
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.
-
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 thestack
umbrella -
Emphasized user-friendliness in further development for open source version
- 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
-
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
, orcpphs
, 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
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.
-
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]
-
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
-
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/
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]
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
-
Does not build packages if no source files changed
- No waiting for unnecessary runs of
ghc --make
and linking executables in multi-package projects
- No waiting for unnecessary runs of
-
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]
-
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
-
Uses the Cabal library to build packages
- Each package still has a
.cabal
file - Custom
Setup.hs
supported
- Each package still has a
-
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]
-
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
- "Global" state in
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-installstack
does not attempt to replicate everything cabal-install can do- But: helps make most thing you actually want to do go smoothly
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
-
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?