git: 08dd1185b4 - main - Porter Handbook: Update documentation on porting Haskell programs.

Gleb Popov <[email protected]>
Newsgroups gmane.os.freebsd.devel.cvs.doc
Message-ID <[email protected]>
The branch main has been updated by arrowd (ports committer):

URL: https://cgit.FreeBSD.org/doc/commit/?id=08dd1185b44003d698b267851f704820c9d492c6

commit 08dd1185b44003d698b267851f704820c9d492c6
Author:     Gleb Popov <[email protected]>
AuthorDate: 2022-08-09 13:09:26 +0000
Commit:     Gleb Popov <[email protected]>
CommitDate: 2022-08-15 07:16:10 +0000

    Porter Handbook: Update documentation on porting Haskell programs.
    
    Reviewed by: fernape, pauamma
    
    Differential Revision: https://reviews.freebsd.org/D36090
---
 .../en/books/porters-handbook/special/_index.adoc  | 162 +++++++++++++++++----
 .../en/books/porters-handbook/uses/_index.adoc     |  45 ++++--
 2 files changed, 168 insertions(+), 39 deletions(-)

diff --git a/documentation/content/en/books/porters-handbook/special/_index.adoc b/documentation/content/en/books/porters-handbook/special/_index.adoc
index 7bef554080..88a72595db 100644
--- a/documentation/content/en/books/porters-handbook/special/_index.adoc
+++ b/documentation/content/en/books/porters-handbook/special/_index.adoc
@@ -965,8 +965,8 @@ Refer to crossref:uses[uses-cabal,`cabal`] for a list of variables that can be s
 .Creating a Port for a Hackage-hosted Haskell Application
 [example]
 ====
-When preparing a Haskell Cabal port, the package:devel/hs-cabal-install[] program is required, so make sure it is installed beforehand.
-First we need to define common ports variables that allows cabal-install to fetch the package distribution file:
+When preparing a Haskell Cabal port, package:devel/hs-cabal-install[] and package:ports-mgmt/hs-cabal2tuple[] programs are required, so make sure they are installed beforehand.
+First we need to define common ports variables that allow cabal-install to fetch the package distribution file:
 
 [.programlisting]
 ....
@@ -982,7 +982,7 @@ USES=		cabal
 .include <bsd.port.mk>
 ....
 
-This minimal Makefile allows us to fetch the distribution file:
+This minimal Makefile fetches the distribution file with the `cabal-extract` helper target:
 
 [source,shell]
 ....
@@ -995,49 +995,34 @@ Downloaded   ShellCheck-0.6.0
 Unpacking to ShellCheck-0.6.0/
 ....
 
-Now we have ShellCheck.cabal package description file, which allows us to fetch all package's dependencies, including transitive ones:
+Now that we have ShellCheck.cabal package description file under `${WRKSRC}`, we can use `cabal-configure` to generate the build plan:
 
 [source,shell]
 ....
-% make cabal-extract-deps
+% make cabal-configure
 [...]
 Resolving dependencies...
-Downloading  base-orphans-0.8.2
-Downloaded   base-orphans-0.8.2
-Downloading  primitive-0.7.0.0
-Starting     base-orphans-0.8.2 (lib)
-Building     base-orphans-0.8.2 (lib)
-Downloaded   primitive-0.7.0.0
-Downloading  dlist-0.8.0.7
+Build profile: -w ghc-8.10.7 -O1
+In order, the following would be built (use -v for more details):
+ - Diff-0.4.1 (lib) (requires download & build)
+ - OneTuple-0.3.1 (lib) (requires download & build)
 [...]
 ....
 
-As a side effect, the package's dependencies are also compiled, so the command may take some time.
 Once done, a list of required dependencies can generated:
 
 [source,shell]
 ....
 % make make-use-cabal
-USE_CABAL=QuickCheck-2.12.6.1 \
-hashable-1.3.0.0 \
-integer-logarithms-1.0.3 \
+USE_CABAL=	QuickCheck-2.12.6.1 \
+		hashable-1.3.0.0 \
+		integer-logarithms-1.0.3 \
 [...]
 ....
 
 Haskell packages may contain revisions, just like FreeBSD ports.
-Revisions can affect only [.filename]#.cabal# files, but it is still important to pull them in.
-To check `USE_CABAL` items for available revision updates, run following command:
-
-[source,shell]
-....
-% make make-use-cabal-revs
-USE_CABAL=QuickCheck-2.12.6.1_1 \
-hashable-1.3.0.0 \
-integer-logarithms-1.0.3_2 \
-[...]
-....
-
-Note additional version numbers after `_` symbol.
+Revisions can affect [.filename]#.cabal# files only.
+Note additional version numbers after the `_` symbol.
 Put newly generated `USE_CABAL` list instead of an old one.
 
 Finally, [.filename]#distinfo# needs to be regenerated to contain all the distribution files:
@@ -1059,6 +1044,125 @@ The port is now ready for a test build and further adjustments like creating a p
 If you are not testing your port in a clean environment like with Poudriere, remember to run `make clean` before any testing.
 ====
 
+Some Haskell ports install various data files under `share/${PORTNAME}`. For such cases special handling is required on the port side.
+The port should define the `CABAL_WRAPPER_SCRIPTS` knob listing each executable that is going to use data files. Moreover, in rare cases the program
+being ported uses data files of other Haskell packages, in which case the `FOO_DATADIR_VARS` comes to the rescue.
+
+[[cabal-ex2]]
+.Handling Data Files in a Haskell Port
+[example]
+====
+`devel/hs-profiteur` is a Haskell application that generates a single-page HTML with some content.
+
+[.programlisting]
+....
+PORTNAME=	profiteur
+
+[...]
+
+USES=		cabal
+
+USE_CABAL=	OneTuple-0.3.1_2 \
+		QuickCheck-2.14.2 \
+		[...]
+
+.include <bsd.port.mk>
+....
+
+It installs HTML templates under `share/profiteur`, so we need to add `CABAL_WRAPPER_SCRIPTS` knob:
+
+[.programlisting]
+....
+[...]
+
+USE_CABAL=	OneTuple-0.3.1_2 \
+		QuickCheck-2.14.2 \
+		[...]
+		
+
+CABAL_WRAPPER_SCRIPTS=		${CABAL_EXECUTABLES}
+
+.include <bsd.port.mk>
+....
+
+The program also tries to access the `jquery.js` file, which is a part of `js-jquery-3.3.1` Haskell package.
+For that file to be found, we need to make the wrapper script to look for `js-jquery` data files in `share/profiteur` too.
+We use `profiteur_DATADIR_VARS` for this:
+
+[.programlisting]
+....
+[...]
+
+CABAL_WRAPPER_SCRIPTS=		${CABAL_EXECUTABLES}
+profiteur_DATADIR_VARS=		js-jquery
+
+.include <bsd.port.mk>
+....
+
+Now the port will install the actual binary into `libexec/cabal/profiteur` and the script into `bin/profiteur`.
+
+====
+
+There is no easy way to find out a proper value for the `FOO_DATADIR_VARS` knob apart from running the program and checking that everything works.
+Luckily, the need to use `FOO_DATADIR_VARS` is very rare.
+
+Another corner case when porting complex Haskell programs is the presence of VCS dependencies in the `cabal.project` file.
+
+[[cabal-ex3]]
+.Porting Haskell Applications with VCS Dependencies
+[example]
+====
+
+`net-p2p/cardano-node` is an extremely complex piece of software. In its `cabal.project` there are a lot of blocks like this:
+
+[.programlisting]
+....
+[...]
+source-repository-package
+  type: git
+  location: https://github.com/input-output-hk/cardano-crypto
+  tag: f73079303f663e028288f9f4a9e08bcca39a923e
+[...]
+....
+
+Dependencies of type `source-repository-package` are automatically pulled in by `cabal` during the build process.
+Unfortunately, this makes use of the network after the `fetch` stage. This is disallowed by the ports framework.
+These sources need to be listed in the port's Makefile. The `make-use-cabal` helper target can make it easy for packages hosted on GitHub.
+Running this target after the usual `cabal-extract` and `cabal-configure` will produce not only the `USE_CABAL` knob, but also `GH_TUPLE`:
+
+[source,shell]
+....
+% make make-use-cabal
+USE_CABAL=	Diff-0.4.1 \
+		Glob-0.10.2_3 \
+		HUnit-1.6.2.0 \
+		[...]
+
+GH_TUPLE=		input-output-hk:cardano-base:0f3a867493059e650cda69e20a5cbf1ace289a57:cardano_base/dist-newstyle/src/cardano-b_-c8db9876882556ed \
+		input-output-hk:cardano-crypto:f73079303f663e028288f9f4a9e08bcca39a923e:cardano_crypto/dist-newstyle/src/cardano-c_-253fd88117badd8f \
+		[...]
+....
+
+It might be useful to separate the `GH_TUPLE` items coming from `make-use-cabal` from the other ones to make it easy to update the port:
+
+[.programlisting]
+....
+GH_TUPLE=	input-output-hk:cardano-base:0f3a867493059e650cda69e20a5cbf1ace289a57:cardano_base/dist-newstyle/src/cardano-b_-c8db9876882556ed \
+		input-output-hk:cardano-crypto:f73079303f663e028288f9f4a9e08bcca39a923e:cardano_crypto/dist-newstyle/src/cardano-c_-253fd88117badd8f \
+		[...]
+		
+GH_TUPLE+=	bitcoin-core:secp256k1:ac83be33d0956faf6b7f61a60ab524ef7d6a473a:secp
+....
+
+Haskell ports with VCS dependencies also require the following hack for the time being:
+
+[.programlisting]
+....
+BINARY_ALIAS=	git=true
+....
+
+====
+
 [[using-autotools]]
 == Using GNU Autotools
 
diff --git a/documentation/content/en/books/porters-handbook/uses/_index.adoc b/documentation/content/en/books/porters-handbook/uses/_index.adoc
index 959bbb2c7f..202df85c52 100644
--- a/documentation/content/en/books/porters-handbook/uses/_index.adoc
+++ b/documentation/content/en/books/porters-handbook/uses/_index.adoc
@@ -187,12 +187,15 @@ Uses package:devel/bison[] By default, with no arguments or with the `build` arg
 Ports should not be created for Haskell libraries, see crossref:special[haskell-libs,Haskell Libraries] for more information.
 ====
 
-Possible arguments: (none), `hpack`
+Possible arguments: (none), `hpack`, `nodefault`
 
 Sets default values and targets used to build Haskell software using Cabal.
-A build dependency on the Haskell compiler port (GHC) is added.
-If `hpack` argument is given, a build dependency on package:devel/hs-hpack[] is added and `hpack` is invoked at configuration step to generate.
-cabal file.
+A build dependency on the Haskell compiler port (package:lang/ghc[]) is added.
+If there is some other version of GHC already listed in the `BUILD_DEPENDS` variable (for example, package:lang/ghc810[]), it would be used instead.
+If the `hpack` argument is given, a build dependency on package:devel/hs-hpack[] is added and `hpack` is invoked at configuration step to
+generate .cabal file.
+If the `nodefault` argument is given, the framework will not try to pull the main distribution file from the Hackage.
+This argument is implicitly added if `USE_GITHUB` or `USE_GITLAB` is present.
 
 The framework provides the following variables:
 
@@ -200,32 +203,54 @@ The framework provides the following variables:
 If the software uses Haskell dependencies, list them in this variable.
 Each item should be present on Hackage and be listed in form `packagename-_0.1.2_`.
 Dependencies can have revisions, which are specified after the `_` symbol.
-Automatic generation of dependency list is supported, see crossref:special[using-cabal,Building Haskell Applications with `cabal`].
+Automatic generation of the dependency list is supported, see crossref:special[using-cabal,Building Haskell Applications with `cabal`].
 
 `CABAL_FLAGS`::
 List of flags to be passed to `cabal-install` during the configuring and building stage.
 The flags are passed verbatim.
+This variable is usually used to enable or disable flags that are declared in the .cabal file.
+Pass `foo` to enable the `foo` flag and `-foo` to disable it.
 
-`EXECUTABLES`::
+`CABAL_EXECUTABLES`::
 List of executable files installed by the port.
 Default value: `${PORTNAME}`.
+Consult the .cabal file of the project being ported to get a list of possible
+values for this variable. Each value corresponds to an `executable` stanza in the .cabal file.
 Items from this list are automatically added to pkg-plist.
 
 `SKIP_CABAL_PLIST`::
-If defined, do not add items from `${EXECUTABLES}` to pkg-plist.
+If defined, do not add items from `${CABAL_EXECUTABLES}` to pkg-plist.
 
 `opt_USE_CABAL`::
 Adds items to `${USE_CABAL}` depending on `opt` option.
 
-`opt_EXECUTABLES`::
-Adds items to `${EXECUTABLES}` depending on `opt` option.
+`opt_CABAL_EXECUTABLES`::
+Adds items to `${CABAL_EXECUTABLES}` depending on `opt` option.
 
 `opt_CABAL_FLAGS`::
 If `opt` is enabled, append the value to `${CABAL_FLAGS}`.
 Otherwise, append `-value` to disable the flag.
+Note that this behavior is slightly different from the plain `CABAL_FLAGS` as it does not accept values starting with `-`.
+
+`CABAL_WRAPPER_SCRIPTS`::
+A subset of `${CABAL_EXECUTABLES}` containing Haskell programs to be wrapped into a shell script
+that sets `*_datadir` environment variables before running the program.
+This also causes the actual Haskell binary to be installed under `libexec/cabal/` directory.
+This knob is needed for Haskell programs that install their data files under `share/` directory.
 
 `FOO_DATADIR_VARS`::
-For an executable named `FOO` list Haskell packages, whose data files should be accessible by the executable.
+List of extra Haskell packages, whose data files should be accessible by the executable named `FOO`.
+The executable should be a part of `${CABAL_WRAPPER_SCRIPTS}`.
+Haskell packages listed there should not have a version suffix.
+
+`CABAL_PROJECT`::
+Some Haskell projects may already have a `cabal.project` file, which is also generated by the ports framework.
+If that is the case, use this variable to specify what to do with the original `cabal.project`.
+Setting this variable to `remove` will cause the original file to be removed.
+Setting this variable to `append` will:
+. Move the original file to `cabal.project.${PORTNAME}` during the `extract` stage.
+. Concatenate the original `cabal.project.${PORTNAME}` and the generated `cabal.project` into a single file after the `patch` stage.
+Using `append` makes it possible to perform patching on the original file before it gets merged.
 
 [[uses-cargo]]
 == `cargo`
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.