• Stars
    star
    611
  • Rank 73,401 (Top 2 %)
  • Language
    Haskell
  • License
    MIT License
  • Created about 10 years ago
  • Updated 4 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

hpack: A modern format for Haskell packages

Hackage version Stackage LTS version hpack on Stackage Nightly

hpack: A modern format for Haskell packages

Hpack is a format for Haskell packages. It is a modern alternative to the Cabal package format and follows different design principles.

Design principles

The guiding design principles for Hpack are:

  • Don't require the user to state the obvious, make sensible assumptions by default
  • Give the user 100% control when needed
  • Don't require the user to repeat things, facilitate DRYness

Tool integration

Hpack packages are described in a file named package.yaml. Both cabal2nix and stack support package.yaml natively. For other build tools the hpack executable can be used to generate a .cabal file from package.yaml.

There is no user guide

There is reference documentation below, but introductory documentation is still lacking. For the time being, take a look at the slides from my talk about Hpack at the Singapore Haskell meetup: http://typeful.net/talks/hpack

Examples

Documentation

Handling of Paths_ modules

Cabal generates a Paths_ module for every package. By default Hpack adds that module to other-modules when generating a .cabal file. This is sometimes useful and most of the time not harmful.

However, there are situations when this can lead to compilation errors (e.g when using a custom Prelude).

To prevent Hpack from adding the Paths_ module to other-modules add the following to package.yaml:

library:
  when:
  - condition: false
    other-modules: Paths_name # substitute name with the package name

Quick-reference

Top-level fields

Hpack Cabal Default Notes Example Since
spec-version The minimum version of hpack that is required to parse this package description. spec-version: 0.30.0 0.30.0
name Β·
version Β· 0.0.0
synopsis Β·
description Β·
category Β·
stability Β·
homepage Β· If github given, <repo>#readme
bug-reports Β· If github given, <repo>/issues
author Β· May be a list
maintainer Β· author May be a list
copyright Β· May be a list
license Β· Inferred from license-file Both SPDX license expressions and traditional Cabal license identifiers are accepted. license: MIT SPDX: 0.29.0
license-file license-file or license-files LICENSE if file exists May be a list
tested-with Β· May be a list (since 0.34.3)
build-type Β· Simple, or Custom if custom-setup exists Must be Simple, Configure, Make, or Custom
extra-source-files Β· Accepts glob patterns
extra-doc-files Β· Accepts glob patterns 0.21.2
data-files Β· Accepts glob patterns
data-dir Β·
github source-repository head Accepts owner/repo or owner/repo/subdir github: foo/bar
git source-repository head No effect if github given git: https://my.repo.com/foo
custom-setup Β· See Custom setup
flags flag <name> Map from flag name to flag (see Flags)
library Β· See Library fields
internal-libraries library <name> Map from internal library name to a dict of library fields and global top-level fields. 0.21.0
executables executable <name> Map from executable name to executable (see Executable fields)
executable executable <package-name> Shortcut for executables: { package-name: ... } 0.18.0
tests test-suite <name> Map from test name to test (see Test fields)
benchmarks benchmark <name> Map from benchmark name to benchmark (see Benchmark fields)
defaults See Defaults, may be a list

cabal-version

Hpack does not require you to specify a cabal-version manually. When generating a .cabal file, Hpack sets the cabal-version automatically based on the features that are used.

If you want to override this behavior you can use verbatim to set cabal-version manually, e.g.:

verbatim:
  cabal-version: 2.2

Defaults

Hpack allows the inclusion of common fields from a file on GitHub or a local file.

To use this feature a user must specify a GitHub repository, Git reference and a path to a file within that repository; alternatively, a path to the local file must be given.

Example:

defaults:
  github: sol/hpack-template
  ref: 2017
  path: defaults.yaml

This will include all common fields from https://github.com/sol/hpack-template/blob/2017/defaults.yaml into the package specification.

Field Default Notes Example
github For github defaults. Accepts <owner>/<repo> github: sol/hpack-template
ref For github defaults. ref: 2017
path .hpack/defaults.yaml For github defaults. A relative path to a file within the repository, path segments are separated by / and must not contain : and \. path: defaults.yaml
local For local defaults. New in 0.26.0.

Exactly one of github and local must be given in a defaults section.

Hpack supports shorthand syntax for specifying github and ref as a string:

defaults: sol/hpack-template@2017

This is equivalent to:

defaults:
  github: sol/hpack-template
  ref: 2017

Note: Hpack caches downloaded files under ~/.hpack/defaults/<owner>/<repo>/<path>. Once downloaded, a file is reused from the cache. If the content on GitHub changes the file is not updated. For this reason it is recommended to only use tags as Git references.

  • If a defaults file has changed on GitHub and you want to use the latest version, then you have to delete that file from the cache manually.

  • If you want to prevent Hpack from accessing the network to download a defaults file, then you can achieve this by adding that file to the cache manually.

Custom setup

Hpack Cabal Default Notes Example
dependencies setup-depends Implies build-type: Custom

Common fields

These fields can be specified top-level or on a per section basis; top-level values are merged with per section values.

Hpack Cabal Default Notes
buildable Β· Per section takes precedence over top-level
source-dirs hs-source-dirs
default-extensions Β·
language default-language Haskell2010 Also accepts Haskell98 or GHC2021. Per section takes precedence over top-level
other-extensions Β·
ghc-options Β·
ghc-prof-options Β·
ghc-shared-options Β·
ghcjs-options Β·
cpp-options Β·
cc-options Β·
c-sources Β· Accepts glob patterns
cxx-options Β·
cxx-sources Β· Accepts glob patterns
js-sources Β· Accepts glob patterns
extra-lib-dirs Β·
extra-libraries Β·
include-dirs Β·
install-includes Β·
frameworks Β·
extra-frameworks-dirs Β·
ld-options Β·
dependencies build-depends See Dependencies
pkg-config-dependencies pkgconfig-depends
build-tools build-tools and/or build-tool-depends
system-build-tools build-tools A set of system executables that have to be on the PATH to build this component
when Accepts a list of conditionals (see Conditionals)

build-tools: A set of Haskell executables that are needed to build this component

Each element consists of a name and an optional version constraint.

The name can be specified in two ways:

  1. Qualified: <package>:<executable>
  2. Unqualified: <executable>

A qualified name refers to an executable named <executable> from a package named <package>.

An unqualified name either refers to an executables in the same package, or if no such executable exists it is desugared to <executable>:<executable>.

build-tools can be specified as a list or a mapping.

Examples:

build-tools:
  - alex
  - happy:happy
  - hspec-discover == 2.*
build-tools:
  alex: 3.2.*
  happy:happy: 1.19.*
  hspec-discover: 2.*

When generating a .cabal file each element of build-tools is either added to build-tools or build-tool-depends.

If the name refers to one of alex, c2hs, cpphs, greencard, haddock, happy, hsc2hs or hscolour then the element is added to build-tools, otherwise it is added to build-tool-depends.

This is done to allow compatibility with a wider range of Cabal versions.

Note: Unlike Cabal, Hpack does not accept system executables as build-tools. Use system-build-tools if you need this.

Library fields

Hpack Cabal Default Notes
exposed Β·
visibility Β·
exposed-modules Β· All modules in source-dirs less other-modules less any modules mentioned in when
generated-exposed-modules Added to exposed-modules and autogen-modules. Since 0.23.0.
other-modules Β· Outside conditionals: All modules in source-dirs less exposed-modules less any modules mentioned in when. Inside conditionals, and only if exposed-modules is not specified inside the conditional: All modules in source-dirs of the conditional less any modules mentioned in when of the conditional
generated-other-modules Added to other-modules and autogen-modules. Since 0.23.0.
reexported-modules Β·
signatures Β·

Executable fields

Hpack Cabal Default Notes
main main-is
other-modules Β· All modules in source-dirs less main less any modules mentioned in when
generated-other-modules Added to other-modules and autogen-modules. Since 0.23.0.

Test fields

Hpack Cabal Default Notes
type exitcode-stdio-1.0
main main-is
other-modules Β· All modules in source-dirs less main less any modules mentioned in when
generated-other-modules Added to other-modules and autogen-modules. Since 0.23.0.

Benchmark fields

Hpack Cabal Default Notes
type exitcode-stdio-1.0
main main-is
other-modules Β· All modules in source-dirs less main less any modules mentioned in when
generated-other-modules Added to other-modules and autogen-modules. Since 0.23.0.

Flags

Hpack Cabal Default Notes
description Β· Optional
manual Β· Required (unlike Cabal)
default Β· Required (unlike Cabal)

Dependencies

Dependencies can be specified as either a list or an object. These are equivalent:

  dependencies:
    - base >= 4.10.1.0
    - containers >= 5.10
  dependencies:
    base: ">= 4.10.1.0"
    containers: ">= 5.10"

The individual dependencies can also be specified as an object:

  dependencies:
    - name: base
      version: ">= 4.10.1.0"
    - name: containers

You can use objects at both levels, or have a mix of valid ways to specify the individual dependencies:

  dependencies:
    base:
      version: ">= 4.10.1.0"
    # If you don't give a version, it defaults to 'any version'.
    containers: {}
    transformers: ">= 0.5.5.0 && < 5.6"

Individual dependencies as objects are only supported from version 0.31.0.

When a dependency is specified as an object, you can use the mixin field to control what modules from the dependency your program will see and how its signatures are filled in:

  dependencies:
    # This gives you a shorter name to import from, and hides the other modules.
    - name: containers
      mixin:
        - (Data.Map.Lazy as Map)
    # This hides the System.IO.Unsafe module, and leaves the other modules unchanged.
    - name: base
      mixin:
        - hiding (System.IO.Unsafe)
    # This exposes only the listed modules - you won't be able to import the others!
    - name: lens
      mixin:
        - (Control.Lens, Data.Set.Lens, Data.Map.Lens as MapL)
    # This will rename the module, and expose the others.
    - name: transformers
      mixin:
        - hiding (Control.Monad.Trans.State.Lazy)
        - (Control.Monad.Trans.State.Lazy as State)

For more information, see the Cabal documentation.

Hint: you can hide the Prelude module from base, and then rename an alternative prelude to Prelude so that it doesn't need to be imported!

mixin was added in version 0.31.0.

Conditionals

Conditionals with no else branch:

  • Must have a condition field
  • May have any number of other fields

For example,

when:
  - condition: os(darwin)
    extra-lib-dirs: lib/darwin

becomes

if os(darwin)
  extra-lib-dirs:
    lib/darwin

Conditionals with an else branch:

  • Must have a condition field
  • Must have a then field, itself an object containing any number of other fields
  • Must have a else field, itself an object containing any number of other fields

For example,

when:
  - condition: flag(fast)
    then:
      ghc-options: -O2
    else:
      ghc-options: -O0

becomes

if flag(fast)
  ghc-options: -O2
else
  ghc-options: -O0

Note: Conditionals with condition: false are omitted from the generated .cabal file.

File globbing

At place where you can specify a list of files you can also use glob patterns. Glob patterns and ordinary file names can be freely mixed, e.g.:

extra-source-files:
  - static/*.js
  - static/site.css

Glob patterns are expanded according to the following rules:

  • ? and * are expanded according to POSIX (they match arbitrary characters, except for directory separators)
  • ** is expanded in a zsh-like fashion (matching across directory separators)
  • ?, * and ** do not match a . at the beginning of a file/directory

Passing things to Cabal verbatim

(since hpack-0.24.0)

In cases where Hpack does not (yet!) support what you want to do, you can use the verbatim field to pass things to Cabal verbatim. It is recognized top-level, in sections, and in conditionals.

verbatim accepts an object or a string (or a list of objects and strings).

Disclaimer: The content of verbatim fields are merged into the generated .cabal file as a final step, after Hpack is done with most of its work. Before that final step Hpack does not look at any verbatim fields. Consequently, the content of a verbatim field does not affect any other fields that are populated by Hpack. As an example, if you use verbatim to override hs-source-dirs, the overridden information will not be used when Hpack infers exposed-modules or other-modules.

Objects

When an object is used:

  • field values can be strings, numbers, booleans, or null
  • existing .cabal fields can be overridden
  • existing .cabal fields can be removed by overriding with null
  • additional .cabal fields can be added

Example:

tests:
  spec:
    main: Spec.hs
    source-dirs: test
    verbatim:
      type: detailed-0.9     # change type from exitcode-stdio-1.0
      default-language: null # remove default-language

Strings

When a string is used:

  • it will be added verbatim, indented to match the indentation of the surrounding context.
  • all existing .cabal fields are left untouched

Example:

verbatim: |
  build-tool-depends:
      hspec-discover:hspec-discover == 2.*

Lists of objects and strings

You can combine the use of objects and strings to gain more fine-grained control, e.g. you can remove an existing field with an object and then include it with a string so that you have 100% control over the layout.

verbatim:
  - build-depends: null
  - |
    -- let's use Cabal 5.0 dependency syntax
    build-depends:
      hspec: [2-3[

Not repeating yourself

It is possible to use YAML anchors (&), aliases (*) and merge keys (<<) to define fields and reference them later.

executables:
  my-exe-1: &my-exe
    main: my-exe-1.hs
    dependencies: [base, my-lib]
    ghc-options: [-threaded]
  my-exe-2:
    <<: *my-exe
    main: my-exe-2.hs

Fields that start with an underscore are ignored by hpack, so they can be used to declare aliases:

_exe-ghc-options: &exe-ghc-options
  - -threaded
  - -rtsopts

executables:
  my-exe-1:
    ghc-options: *exe-ghc-options

It is also possible to use the !include directive:

# ...

tests:
  hlint: !include "../common/hlint.yaml"

hlint.yaml:

source-dirs: test
main: hlint.hs
dependencies: [base, hlint]

This can also be used to provide entire libraries of snippets:

_common/lib: !include "../common/lib.yaml"

name: example1
version: '0.1.0.0'
synopsis: Example
<<: *legal

<<: *defaults

library:
  source-dirs: src

tests:
  hlint: *test_hlint

lib.yaml:

- &legal
  maintainer: Some One <[email protected]>
  copyright: (c) 2017 Some One
  license: BSD3

- &defaults
  dependencies:
    - base
    - containers
  ghc-options:
    - -Wall
    - -Werror

- &test_hlint
  source-dirs: test
  main: hlint.hs
  dependencies: [hlint]

Vim integration

To run hpack automatically on modifications to package.yaml add the following to your ~/.vimrc:

autocmd BufWritePost package.yaml call Hpack()

function Hpack()
  let err = system('hpack ' . expand('%'))
  if v:shell_error
    echo err
  endif
endfunction

Stack support

Stack has built-in support for Hpack. If you are using Stack you can use package.yaml instead of a .cabal file. No additional steps are required.

Binaries for use on Travis CI

You can get binaries for use on Travis CI with:

curl -sSL https://github.com/sol/hpack/raw/master/get-hpack.sh | bash

(both Linux and OS X are supported)

More Repositories

1

doctest

An implementation of Python's doctest for Haskell
Haskell
375
star
2

markdown-unlit

Literate Haskell support for Markdown
Haskell
125
star
3

tinc

A dependency manager for Haskell
Haskell
97
star
4

aeson-qq

JSON quasiquoter for Haskell
Haskell
78
star
5

reserve

Universal and robust reloading for Haskell web applications
Haskell
70
star
6

pwsafe

A command-line password manager
Haskell
31
star
7

interpolate

String interpolation for Haskell done right!
Haskell
31
star
8

v8

Haskell bindings to Google's V8 JavaScript Engine
Haskell
14
star
9

logging-facade

An experimental logging API for Haskell, inspired by slf4j
Haskell
11
star
10

mpd

Mirror of git://git.musicpd.org/master/mpd.git
C
11
star
11

cucumber-haskell

Cucumber for Haskell
9
star
12

hspec-tutorial

Developing a tiny time-service with WAI and Hspec
Haskell
7
star
13

with-location

DEPRECATED, use https://github.com/sol/call-stack instead
Haskell
6
star
14

haskell-platform-versions-comparison-chart

NOTE: This project is superseded by http://www.haskell.org/platform/changelog.html
Haskell
6
star
15

rewrite-with-location

Proposal: A simple and extensible mechanism for source locations in library code
Haskell
6
star
16

haskell-autotag

A GitHub Action that creates a Git tag on .cabal version bumps
Haskell
5
star
17

http-kit

A low-level HTTP library
Haskell
5
star
18

pandoc-unlit

Literate Haskell support for GitHub's Markdown flavor
Haskell
5
star
19

aenea-box

Linux speech recognition setup based on Vagrant, Aenea, Dragonfly, NatLink and Dragon
Makefile
5
star
20

hspec-test-framework

Run test-framework tests with Hspec
Haskell
4
star
21

strafunski

Mirror of http://code.google.com/p/strafunski/
Haskell
4
star
22

HackageOneFive

Reverse dependency lookup for all packages on Hackage
Haskell
4
star
23

inject

Inject the output of shell commands into arbitrary text templates
Haskell
3
star
24

call-stack

Use GHC call-stacks in a backward compatible way
Haskell
3
star
25

attoparsec-parsec

An Attoparsec compatibility layer for Parsec
Haskell
3
star
26

solid

A functional scripting environment
Haskell
3
star
27

hspec-shouldbe

Convenience wrapper and utilities for hspec
Vim Script
3
star
28

stringbuilder

A writer monad for multi-line string literals
Haskell
3
star
29

hackage-jsonp

Latest package versions on Hackage as JSONP
Haskell
2
star
30

mpdinfo

A libmpd-haskell toy project, prints the currently played song and elapsed time
Haskell
2
star
31

string

An effort to provide all functions from Data.Text for strings
Haskell
2
star
32

darcs-mirrors

Haskell
2
star
33

json-fu

JSON serialization / deserialization
Haskell
2
star
34

GHC2021

Use GHC2021 with existing versions of GHC
2
star
35

logsink

A logging framework for Haskell
Haskell
2
star
36

test-framework-spec

A DSL for building Hspec/RSpec style test suites for test-framework
Haskell
2
star
37

stats

Haskell
2
star
38

haskell-code-edit

Haskell
2
star
39

infer-license

Infer software license from a given license file
Haskell
2
star
40

format

String interpolation for Haskell
Haskell
2
star
41

get-bootstrapped

Stable links for bootstrap releases
JavaScript
2
star
42

config-ng

Format preserving parser and renderer for INI-style config files
Haskell
2
star
43

depends

A simple configuration management tool for Haskell
Haskell
2
star
44

display

Convert Haskell values to a textual representation
Haskell
2
star
45

run-haskell-tests

2
star
46

ghc-env

Automatically download and manage multiple versions of GHC
Haskell
2
star
47

uu-parsinglib

A mirror of uu-parsinglib's svn repository
Haskell
2
star
48

hexpat

A mirror of http://code.haskell.org/hexpat/
C
1
star
49

qreadline

A drop-in replacement for QLineEdit with emacs-like key bindings
C++
1
star
50

ci

Haskell
1
star
51

cg1

A simple OpenGL application
C++
1
star
52

setenv

A cross-platform Haskell library for setting environment variables
Haskell
1
star
53

rest-client

Haskell
1
star
54

aeson-toolkit

A generalization of Aeson over Failure
Haskell
1
star
55

fancontrol

Minimalistic fan control for my x200
Haskell
1
star
56

json-stream

Haskell
1
star
57

KBDevBoard

A development board for rapid prototyping of keyboard circuitry ⚑
1
star
58

conduit-issue

Haskell
1
star
59

better-process

A *better* incarnation of Haskell's `process` library
Haskell
1
star
60

simdjson

Haskell
1
star
61

hspec-experimental

An experimental DSL for testing on top of Hspec
Haskell
1
star