Haskell Packaging Guidelines

This page documents the guidelines and conventions for packaging Haskell projects in Fedora.

GHC (Glasgow Haskell Compiler) is the current mainstream Haskell compiler. Most Haskell packages are released on Hackage and use the Cabal package system. So the current guidelines largely focus on packaging for GHC using Cabal.

Spec file templates

Spec files in line with these templates are generated automatically by the cabal-rpm packaging tool which also adds dependencies listed in the package’s .cabal configuration file. Most packages should then build, though for some packages it may be necessary to specify some additional BuildRequires and/or Requires, and to check non-Haskell devel dependencies.

Standardizing the packaging helps to lower the maintenance burden across Fedora’s Haskell packages.

There are three types of Haskell Cabal packages: library (Lib), binary only (Bin), and binary with library (BinLib):

Library Only

%global pkg_name @PACKAGE@

Name:           ghc-%{pkg_name}
Version:        @VERSION@
Release:        1%{?dist}
Summary:        @SUMMARY@

License:        @LICENSE@
URL:            https://hackage.haskell.org/package/%{pkg_name}
Source:         https://hackage.haskell.org/package/%{pkg_name}-%{version}/%{pkg_name}-%{version}.tar.gz

BuildRequires:  ghc-Cabal-devel
BuildRequires:  ghc-rpm-macros
BuildRequires:  ghc-base-prof

%description
@DESCRIPTION@

%package devel
Summary:        Haskell %{pkg_name} library development files
Provides:       %{name}-static = %{version}-%{release}
Provides:       %{name}-static%{?_isa} = %{version}-%{release}
Requires:       ghc-compiler = %{ghc_version}
Requires:       %{name}%{?_isa} = %{version}-%{release}

%description devel
This package provides the Haskell %{pkg_name} library development files.


%package doc
Summary:        Haskell %{pkg_name} library documentation
BuildArch:      noarch

%description doc
This package provides the Haskell %{pkg_name} library documentation.


%package prof
Summary:        Haskell %{pkg_name} profiling library
Requires:       %{name}-devel%{?_isa} = %{version}-%{release}
Supplements:    (%{name}-devel and ghc-prof)

%description prof
This package provides the Haskell %{pkg_name} profiling library.


%prep
%setup -q -n %{pkg_name}-%{version}


%build
%ghc_lib_build


%install
%ghc_lib_install


%files -f %{name}.files
%license LICENSE


%files devel -f %{name}-devel.files


%files doc -f %{name}-doc.files
%license LICENSE


%files prof -f %{name}-prof.files

Binary Only

Name:           @PACKAGE@
Version:        @VERSION@
Release:        1%{?dist}
Summary:        @SUMMARY@

License:        @LICENSE@
URL:            https://hackage.haskell.org/package/%{name}
Source:         https://hackage.haskell.org/package/%{name}-%{version}/%{name}-%{version}.tar.gz

BuildRequires:  ghc-Cabal-devel
BuildRequires:  ghc-rpm-macros
BuildRequires:  ghc-base-static

%description
@DESCRIPTION@


%prep
%setup -q


%build
%ghc_bin_build


%install
%ghc_bin_install


%files
%license LICENSE
%{_bindir}/%{name}

BinLib

%global pkg_name @PACKAGE@

Name:           %{pkg_name}
Version:        @VERSION@
Release:        1%{?dist}
Summary:        @SUMMARY@

License:        @LICENSE@
URL:            https://hackage.haskell.org/package/%{name}
Source:         https://hackage.haskell.org/package/%{name}-%{version}/%{name}-%{version}.tar.gz

BuildRequires:  ghc-Cabal-devel
BuildRequires:  ghc-rpm-macros
BuildRequires:  ghc-base-prof

%description
@DESCRIPTION@


%package -n ghc-%{name}
Summary:        Haskell %{name} library

%description -n ghc-%{name}
This package contains the Haskell %{name} library.


%package -n ghc-%{name}-devel
Summary:        Haskell %{name} library development files
Requires:       ghc-compiler = %{ghc_version}
Requires:       ghc-%{name} = %{version}-%{release}

%description -n ghc-%{name}-devel
This package provides the Haskell %{pkg_name} library development files.


%package -n ghc-%{name}-doc
Summary:        Haskell %{pkg_name} library documentation
BuildArch:      noarch

%description -n ghc-%{name}-doc
This package provides the Haskell %{pkg_name} library documentation.


%package -n ghc-%{name}-prof
Summary:        Haskell %{pkg_name} profiling library
Requires:       ghc-%{name}-devel%{?_isa} = %{version}-%{release}
Supplements:    (ghc-%{name}-devel and ghc-prof)

%description -n ghc-%{name}-prof
This package provides the Haskell %{pkg_name} profiling library.


%prep
%setup -q


%build
%ghc_lib_build


%install
%ghc_lib_install


%files
%license LICENSE
%{_bindir}/%{name}


%files -n ghc-%{name} -f ghc-%{name}.files
%license LICENSE


%files -n ghc-%{name}-devel -f ghc-%{name}-devel.files


%files -n ghc-%{name}-doc -f ghc-%{name}-doc.files
%license LICENSE


%files -n ghc-%{name}-prof -f ghc-%{name}-prof.files

Package Naming

Haskell Bin packages should follow the usual Fedora Package Naming Guidelines for base package naming: i.e., follow the upstream name. Examples include projects like alex and cabal-install.

The names of Haskell Lib packages, packaged for ghc, are prefixed by "ghc-". For example the Haskell aeson library package is named ghc-aeson, and the Haskell X11 library package is named ghc-X11, etc.

Haskell BinLib packages should be named like a Bin package if the most important part they provide is an executable (eg hlint, ShellCheck, and pandoc), otherwise they should be named and packaged as a Lib package (eg ghc-hakyll (has a setup executable), ghc-vty (has demo executables)) if they are actually a library that includes an helper executable or demo or minor utility. In this case typically the executable should live in the devel subpackage (or maybe the library base package if it is used at runtime).

Note that having different Haskell source packages named "ghc-xyz" and "xyz" is not allowed since they would both correspond to the same upstream package named "xyz" on Hackage.

BinLib packages should subpackage their libraries with naming following Lib packages. For example the pandoc BinLib package has library subpackages

  • ghc-pandoc for the shared library,

  • ghc-pandoc-devel for devel files and the static library,

  • ghc-pandoc-prof for the profiling static library,

  • ghc-pandoc-doc for the library’s extracted development documentation.

If a library is packaged for more than one Haskell compiler or interpreter, the base name should instead be prefixed with haskell, e.g. haskell-X11. Such a package would then have subpackages for each compiler and/or interpreter it is built for (e.g. ghc-X11, hugs98-X11`, etc).

Package naming preserves case to follow the upstream naming conventions as closely as possible, including package dependencies.

Headers

The macro pkg_name is used to carry the name of the upstream library package (i.e. without the Fedora "ghc-" prefix). It should be defined at the top of Lib and BinLib packages:

+%global pkg_name +

Cabal Flags

If needed Cabal flags for build options should be set by changing the package’s .cabal file: this can usually be done with the cabal-tweak-flag script to avoid having to carry and maintain patches for this.

For example cabal-tweak-flag systemlib True might enable a flag to use a system library dependency.

%cabal_configure_options can be set to pass other options to Cabal.

Modifying the .cabal file flags defaults allows packagers and tools like cabal-rpm to track actual package dependencies correctly.

Dependencies

The cabal-tweak-dep-ver script can used to change version bounds of dependencies in the package’s .cabal file: cabal-tweak-dep-ver deppkg oldbound newbound

eg: cabal-tweak-dep-ver base '< 4.16' '< 4.17'

Similarly cabal-tweak-drop-dep for dropping a redundant dependency (eg a compatibility dummy package).

eg: cabal-tweak-drop-dep mtl-compat

Spec file build dependencies are generated by the cabal-rpm packaging tool.

Binary RPM dependencies for Haskell libraries are automatically generated at build-time by the ghc-deps.sh script.

Shared and static library linking

GHC uses static libraries for linking by default. Lib and BinLib packages should provide static, shared, and profiling libraries:

  • the shared library lives in the base library package,

  • the static library and interface development files in the -devel subpackage,

  • and the profiling library and profiling interface files in the -prof subpackage.

Since GHC assumes static versions of libraries are installed they need to be in the devel subpackage and it doesn’t make sense to subpackage them.

Executables in Bin and BinLib packages should be statically linked for portability.

Due to how GHC links shared libraries using --no-as-needed they generate a lot of rpmlint E: undefined-non-weak-symbol errors, this is unfortunately currently expected (see these upstream issues).

RPM Macros

The templates all have buildrequires for ghc-rpm-macros, which provides macros.ghc to assist with packaging Haskell Cabal packages.

BuildRequires:  ghc-rpm-macros

The main commonly used macros are:

  • %ghc_bin_build

  • %ghc_lib_build

  • %ghc_bin_install

  • %ghc_lib_install

They are used in the templates and explained in more detail below.

Bin packages

Executables are statically linked to Haskell libraries by default.

%build
%ghc_bin_build


%install
%ghc_bin_install

%ghc_bin_build is used to configure and build bin packages. It runs:

  • %cabal_configure: configure the package for building and dynamic linking.

  • %cabal build: builds the package.

%ghc_bin_install is used to install bin packages. It runs:

  • %cabal_install: to install the package.

Lib and BinLib packages

Devel subpackages need to setup some Requires:

%package -n ghc-%{pkg_name}-devel
Summary:        Haskell %{pkg_name} library development files
Requires:       ghc-compiler = %{ghc_version}
Requires:       ghc-%{pkg_name} = %{version}-%{release}

Lib packages need to use %setup -n:

%prep
%setup -q -n %{pkg_name}-%{version}

Both Lib and BinLib have:

%build
%ghc_lib_build


%install
%ghc_lib_install

%ghc_lib_build is used to configure, build and generate documentation for Lib and BinLib packages. It runs:

  • %cabal_configure --ghc -p: configures the package for building with ghc and profiling. Libraries should build profiling versions of their static libraries.

  • %cabal build: builds the package.

  • %cabal haddock: generates HTML library documentationr from the source code.

    • If documentation is failing to build for some reason, %ghc_lib_build_without_haddock can be used instead of %ghc_lib_build to disable haddock generation.

%ghc_lib_install is used to install Lib and BinLib packages. It runs:

  • %cabal_install: installs the package without registering it in ghc-pkg.

  • %cabal_pkg_conf: creates ghc-pkg .conf metadata filer for package installation time

  • %ghc_gen_filelists: generates rpm filelists.

Debuginfo

Debuginfo is currently disabled for Haskell packages, because ghc’s Dwarf output is not very useful. Stack backtraces can also be generated using profiling libraries.

Directories

GHC libraries are installed under %ghclibdir/%{pkg_name}-%{version}:

Library documentation lives under %ghclibdocdir/%{pkg_name}-%{version}.

File lists

Filelists for shared and devel library subpackages are generated through %ghc_lib_install using the macro %ghc_gen_filelists.

It generates the filelists ghc-%{pkg_name}.files, ghc-%{pkg_name}-devel.files, ghc-%{pkg_name}-prof.files, and ghc-%{pkg_name}-doc.files.

Compiling non-Cabal packages

Packages compiling Haskell code without Cabal, i.e., directly with ghc or ghc --make, should use -O1 optimization, like Cabal does by default.