diff --git a/documentation/content/en/books/porters-handbook/special/_index.adoc b/documentation/content/en/books/porters-handbook/special/_index.adoc --- a/documentation/content/en/books/porters-handbook/special/_index.adoc +++ b/documentation/content/en/books/porters-handbook/special/_index.adoc @@ -965,8 +965,8 @@ .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 @@ .include .... -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 @@ 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 @@ 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 +.... + +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 +.... + +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 +.... + +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 --- a/documentation/content/en/books/porters-handbook/uses/_index.adoc +++ b/documentation/content/en/books/porters-handbook/uses/_index.adoc @@ -187,12 +187,15 @@ 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 @@ 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`