Build Tools, Packaging and Deployment
52.1 cabal vs Stack
Hackage (with solver) Stackage snapshots (curated sets of compatible versions) cabal freeze, index-state Snapshot resolver in stack.yaml .cabal, cabal.project
stack.yaml + .cabal or package.yaml (hpack) Libraries, modern default Applications wanting curated sets
Nix (haskell.nix, nixpkgs) gives fully reproducible builds and is popular in industry. Bazel (rules_haskell) suits large monorepos.
52.2 Publishing and Documentation
Follow the Package Versioning Policy (PVP): A.B.C.D, where A.B is the major version (breaking changes).
cabal check # validate the package metadata
cabal sdist # create a source tarball
cabal upload --publish dist-newstyle/sdist/my-lib-0.1.0.0.tar.gz # to Hackage
cabal haddock --haddock-for-hackage && cabal upload -d --publish ...52.3 Deployment
Static binaries: build with --enable-executable-static on musl (Alpine) or via Nix (pkgsStatic).
CI: GitHub Actions with haskell-actions/setup, cache ~/.cabal/store and dist-newstyle, run cabal build all, cabal test all, HLint, and the formatter check. haskell-ci generates CI configs for multiple GHC versions.
# Multi-stage Docker build
FROM haskell:9.6 AS build
WORKDIR /app
COPY *.cabal cabal.project* ./
RUN cabal update && cabal build --only-dependencies
COPY . .
RUN cabal install --installdir=/app/bin --install-method=copy exe:my-app
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y libgmp10 ca-certificates && rm -rf /var/lib/apt/lists/*
COPY --from=build /app/bin/my-app /usr/local/bin/my-app
EXPOSE 8080
CMD ["my-app", "+RTS", "-N", "-A64m", "-RTS"]