#952 update Haskell to latest current practices and packaging
Merged 2 months ago by churchyard. Opened 2 months ago by petersen.
petersen/packaging-committee master  into  master

@@ -3,7 +3,7 @@ 

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

  

  http://haskell.org/ghc[GHC] (Glasgow Haskell Compiler) is the current mainstream Haskell compiler.

- Most Haskell packages are released on http://hackage.haskell.org[Hackage] and use the http://www.haskell.org/cabal/[Cabal] package system. So the current guidelines mostly focus on packaging for GHC using Cabal.

+ Most Haskell packages are released on http://hackage.haskell.org[Hackage] and use the http://www.haskell.org/cabal/[Cabal] package system. So the current guidelines largely focus on packaging for GHC using Cabal.

  

  == Spec file templates

  

@@ -13,7 +13,7 @@ 

  

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

  

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

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

  

  === Library Only

  

@@ -26,26 +26,44 @@ 

  Summary:        @SUMMARY@

  

  License:        @LICENSE@

- URL:            http://hackage.haskell.org/package/%{pkg_name}

- Source0:        http://hackage.haskell.org/packages/archive/%{pkg_name}/%{version}/%{pkg_name}-%{version}.tar.gz

+ URL:            https://hackage.haskell.org/package/%{pkg_name}

+ Source0:        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(post): ghc-compiler = %{ghc_version}

- Requires(postun): ghc-compiler = %{ghc_version}

- Requires:       %{name} = %{version}-%{release}

+ 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}

  

@@ -58,14 +76,6 @@ 

  %ghc_lib_install

  

  

- %post devel

- %ghc_pkg_recache

- 

- 

- %postun devel

- %ghc_pkg_recache

- 

- 

  %files -f %{name}.files

  %license LICENSE

  

@@ -73,9 +83,11 @@ 

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

  

  

- %changelog

- * @DATE@ Fedora Haskell SIG <haskell@lists.fedoraproject.org>

- - spec file generated by cabal-rpm

+ %files doc -f %{name}-doc.files

+ %license LICENSE

+ 

+ 

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

  ....

  

  === Binary Only

@@ -87,11 +99,12 @@ 

  Summary:        @SUMMARY@

  

  License:        @LICENSE@

- URL:            http://hackage.haskell.org/package/%{name}

- Source0:        http://hackage.haskell.org/packages/archive/%{name}/%{version}/%{name}-%{version}.tar.gz

+ URL:            https://hackage.haskell.org/package/%{name}

+ Source0:        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@

@@ -112,14 +125,10 @@ 

  %files

  %license LICENSE

  %{_bindir}/%{name}

- 

- 

- %changelog

- * @DATE@ Fedora Haskell SIG <haskell@lists.fedoraproject.org>

- - spec file generated by cabal-rpm

  ....

  

- === Library and Binary

+ 

+ === BinLib

  

  ....

  %global pkg_name @PACKAGE@

@@ -131,10 +140,11 @@ 

  

  License:        @LICENSE@

  URL:            http://hackage.haskell.org/package/%{name}

- Source0:        http://hackage.haskell.org/packages/archive/%{name}/%{version}/%{name}-%{version}.tar.gz

+ Source0:        http://hackage.haskell.org/package/%{name}-%{version}/%{name}-%{version}.tar.gz

  

  BuildRequires:  ghc-Cabal-devel

  BuildRequires:  ghc-rpm-macros

+ BuildRequires:  ghc-base-prof

  

  %description

  @DESCRIPTION@

@@ -150,14 +160,29 @@ 

  %package -n ghc-%{name}-devel

  Summary:        Haskell %{name} library development files

  Requires:       ghc-compiler = %{ghc_version}

- Requires(post): ghc-compiler = %{ghc_version}

- Requires(postun): 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:       %{name}-devel%{?_isa} = %{version}-%{release}

+ Supplements:    (%{name}-devel and ghc-prof)

+ 

+ %description -n ghc-%{name}-prof

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

+ 

+ 

  %prep

  %setup -q

  

@@ -170,14 +195,6 @@ 

  %ghc_lib_install

  

  

- %post -n ghc-%{name}-devel

- %ghc_pkg_recache

- 

- 

- %postun -n ghc-%{name}-devel

- %ghc_pkg_recache

- 

- 

  %files

  %license LICENSE

  %{_bindir}/%{name}

@@ -190,29 +207,35 @@ 

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

  

  

- %changelog

- * @DATE@ Fedora Haskell SIG <haskell@lists.fedoraproject.org>

- - spec file generated by cabal-rpm

+ %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 and BinLib packages should follow the usual Fedora Package Naming Guidelines for base package naming: i.e., follow the upstream name. Examples include projects like `+darcs+` and `+xmonad+`.

- However there may be cases where a Haskell BinLib package is really a Lib package with a minor or unimportant executable: in this case it is better to treat the package a Lib package, optionally with a executable subpackage if appropriate.

+ 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.

  

- The names of Haskell Lib packages, packaged for `+ghc+`, are prefixed by "ghc-". For example the Haskell X11 library package is named `+ghc-X11+`, and the Haskell mmap library package is named `+ghc-mmap+`, 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 `+xmonad+` BinLib package has library subpackages

+ For example the `+pandoc+` BinLib package has library subpackages

  

- * `+ghc-xmonad+` for the shared library, and

- * `+ghc-xmonad-devel+` for devel files and the static library.

+ * `+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.

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

  

  == Headers

  

@@ -223,33 +246,30 @@ 

  

  == Cabal Flags

  

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

+ 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.

+ 

  `+%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.

  

- == Dependency Generation

+ == Dependencies

+ The `+cabal-tweak-dep-ver+` script can used to change version bounds of dependencies in the package's .cabal file, and similarly `+cabal-tweak-drop-dep+` for dropping a redundant dependency (eg a compatibility dummy package).

  

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

  

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

- 

- The `+cabal-tweak-dep-ver+` script can be used to bump versions of dependencies in the package .cabal file.

+ 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 by default, but supports shared libraries on some architectures: currently i686 and x86_64. Lib and BinLib packages should provide static, shared, and profiling libraries:

- 

- * the shared library lives in the base library package, and

- * the static and profiling library and header files in the -devel subpackage.

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

  

- Because GHC still assumes static versions of libraries are installed they need to be in the devel subpackage and it doesn't make sense to subpackage them yet.

+ * 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.

  

- Executables in Bin and BinLib packages should be dynamically linked to shared libraries.

+ 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.

  

- Note that executables in most BinLib packages are currently statically linked against the library in their own package (unless the .cabal file explicitly lists it as a dependency), but dynamically linked against other dependent libraries. BinLib executables that do link dynamically against their own library should use `+%ghc_fix_dynamic_rpath+` to fix its RPATH.

- 

- Some particular packages may do user compilation during runtime in which case they will need Requires as well as BuildRequires for their dependencies: examples include xmonad and yi which require their devel package to be present to allow users to relink their configuration or customization.

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

  

  == RPM Macros

  

@@ -270,7 +290,7 @@ 

  

  == Bin packages

  

- Bin package executables should be dynamically linked to shared Haskell libraries when available, but this can be overridden if necessary by defining the `+ghc_without_dynamic+` macro.

+ Executables are statically linked to Haskell libraries by default.

  

  ....

  %build

@@ -283,27 +303,21 @@ 

  

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

  

- * `+%global debug_package %{nil}+`: debuginfo is disabled since ghc's output is not in GDB format.

  * `+%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+`: installs the package.

- * `+%ghc_strip_dynlinked+`: strips the dynamically linked binary.

+ * `+%cabal_install+`: to install the package.

  

  == Lib and BinLib packages

  

- BinLib package executables should be dynamically linked to other shared Haskell libraries when available, but this can be overridden if necessary by defining the `+ghc_without_dynamic+` macro.

- 

  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(post): ghc-compiler = %{ghc_version}

- Requires(postun): ghc-compiler = %{ghc_version}

  Requires:       ghc-%{pkg_name} = %{version}-%{release}

  ....

  

@@ -323,37 +337,30 @@ 

  

  %install

  %ghc_lib_install

- 

- 

- %post devel

- %ghc_pkg_recache

- 

- 

- %postun devel

- %ghc_pkg_recache

  ....

  

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

  

- * `+%global debug_package %{nil}+`: debuginfo is disabled since ghc's output is not in DWARF format.

  * `+%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 documentation from the source code.

- ** If necessary (if e.g. documentation is failing to build for some reason) this can be skipped by defining `+without_haddock+`.

- ** Additionally links to colored html sourcecode are also generated with `+hscolour+`, which can be disabled by defining `+without_hscolour+`.

+ ** 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 file for package installation time

  * `+%ghc_gen_filelists+`: generates rpm filelists.

- * `+%ghc_strip_dynlinked+`: strips dynamically linked objects.

  

- `+%ghc_pkg_recache+`: used in %post and %postun for devel subpackage - refreshes the ghc package cache database with .conf file data.

+ == 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 `+%ghcpkgdir/%{pkg_name}-%{version}+`:

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

  

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

  

@@ -361,7 +368,7 @@ 

  

  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+` and `+ghc-%{pkg_name}-devel.files+`.

+ 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

  

@@ -372,5 +379,4 @@ 

  * https://hackage.haskell.org/package/cabal-rpm

  * https://src.fedoraproject.org/rpms/ghc-rpm-macros

  * https://wiki.debian.org/Haskell[Debian Haskell Group]

- * xref:OCaml.adoc[Fedora OCaml Packaging Guidelines]

  * https://fedoraproject.org/wiki/Haskell_SIG[Fedora Haskell SIG]

Main changes:

  • addition of prof and doc subpackages for libraries
  • change from dynamic linking of executables to static linking
  • static provides and BRs

I can provide a more detailed changelog and comments if needed, but most of the remaining changes are just minor tweaks and small updates.

I have one question about the use of BuildRequires: ghc-*-static, when it is provided by ghc-*-devel: is it mandatory? I ask because eg we have a source package ghc-yesod-static for example which creates resolver ambiguity with the ghc-yesod-static provided by ghc-yesod-devel.

Naively the solution could be to provide and require ghc-*-static%{_isa} instead.
But of course this is not allowed for BuildRequires, therefore I prefer to use BuildRequires: ghc-*-devel at least where there is ambiguity.

rebased onto 5e9d0bb

2 months ago

I suggest you help the resolver via:

 BuildRequires: (ghc-yesod-static with ghc-yesod-devel)

Meaning a single package needs to provide both.

However, would it make snese to avoid the name clash in the first place?

Update of the Haskell Packaging Guidelines (+1:5, 0:0, -1:0)

Pull-Request has been merged by churchyard

2 months ago

Thank you, appreciate the review and
the helpful comments about the corner case static provides conflict.

Metadata