mirror of
https://git.FreeBSD.org/doc.git
synced 2026-06-02 19:35:07 +00:00
Porter Handbook: Update documentation on porting Haskell programs.
Reviewed by: fernape, pauamma Differential Revision: https://reviews.freebsd.org/D36090
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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`
|
||||
|
||||
Reference in New Issue
Block a user