dev-python/cryptography: Bump to 2.8
[gentoo.git] / eclass / ghc-package.eclass
1 # Copyright 1999-2018 Gentoo Authors
2 # Distributed under the terms of the GNU General Public License v2
3
4 # @ECLASS: ghc-package.eclass
5 # @MAINTAINER:
6 # "Gentoo's Haskell Language team" <haskell@gentoo.org>
7 # @AUTHOR:
8 # Original Author: Andres Loeh <kosmikus@gentoo.org>
9 # @BLURB: This eclass helps with the Glasgow Haskell Compiler's package configuration utility.
10 # @DESCRIPTION:
11 # Helper eclass to handle ghc installation/upgrade/deinstallation process.
12
13 inherit multiprocessing
14
15 # Maintain version-testing compatibility with ebuilds not using EAPI 7.
16 case "${EAPI:-0}" in
17         4|5|6) inherit eapi7-ver ;;
18         *) ;;
19 esac
20
21 # @FUNCTION: ghc-getghc
22 # @DESCRIPTION:
23 # returns the name of the ghc executable
24 ghc-getghc() {
25         type -P ${HC:-ghc}
26 }
27
28 # @FUNCTION: ghc-getghcpkg
29 # @DESCRIPTION:
30 # Internal function determines returns the name of the ghc-pkg executable
31 ghc-getghcpkg() {
32         type -P ${HC_PKG:-ghc-pkg}
33 }
34
35 # @FUNCTION: ghc-getghcpkgbin
36 # @DESCRIPTION:
37 # returns the name of the ghc-pkg binary (ghc-pkg
38 # itself usually is a shell script, and we have to
39 # bypass the script under certain circumstances);
40 # for Cabal, we add an empty global package config file,
41 # because for some reason the global package file
42 # must be specified
43 ghc-getghcpkgbin() {
44         if ver_test "$(ghc-version)" -ge "7.9.20141222"; then
45                 # ghc-7.10 stopped supporting single-file database
46                 local empty_db="${T}/empty.conf.d" ghc_pkg="$(ghc-libdir)/bin/ghc-pkg"
47                 if [[ ! -d ${empty_db} ]]; then
48                         "${ghc_pkg}" init "${empty_db}" || die "Failed to initialize empty global db"
49                 fi
50                 echo "$(ghc-libdir)/bin/ghc-pkg" "--global-package-db=${empty_db}"
51
52         elif ver_test "$(ghc-version)" -ge "7.7.20121101"; then
53                 # the ghc-pkg executable changed name in ghc 6.10, as it no longer needs
54                 # the wrapper script with the static flags
55                 # was moved to bin/ subtree by:
56                 # http://www.haskell.org/pipermail/cvs-ghc/2012-September/076546.html
57                 echo '[]' > "${T}/empty.conf"
58                 echo "$(ghc-libdir)/bin/ghc-pkg" "--global-package-db=${T}/empty.conf"
59
60         elif ver_test "$(ghc-version)" -ge "7.5.20120516"; then
61                 echo '[]' > "${T}/empty.conf"
62                 echo "$(ghc-libdir)/ghc-pkg" "--global-package-db=${T}/empty.conf"
63
64         else
65                 echo '[]' > "${T}/empty.conf"
66                 echo "$(ghc-libdir)/ghc-pkg" "--global-conf=${T}/empty.conf"
67         fi
68 }
69
70 # @FUNCTION: ghc-version
71 # @DESCRIPTION:
72 # returns upstream version of ghc
73 # as reported by '--numeric-version'
74 # Examples: "7.10.2", "7.9.20141222"
75 _GHC_VERSION_CACHE=""
76 ghc-version() {
77         if [[ -z "${_GHC_VERSION_CACHE}" ]]; then
78                 _GHC_VERSION_CACHE="$($(ghc-getghc) --numeric-version)"
79         fi
80         echo "${_GHC_VERSION_CACHE}"
81 }
82
83 # @FUNCTION: ghc-pm-version
84 # @DESCRIPTION:
85 # returns package manager(PM) version of ghc
86 # as reported by '$(best_version)'
87 # Examples: "PM:7.10.2", "PM:7.10.2_rc1", "PM:7.8.4-r4"
88 _GHC_PM_VERSION_CACHE=""
89 ghc-pm-version() {
90         local pm_ghc_p
91
92         if [[ -z "${_GHC_PM_VERSION_CACHE}" ]]; then
93                 pm_ghc_p=$(best_version dev-lang/ghc)
94                 _GHC_PM_VERSION_CACHE="PM:${pm_ghc_p#dev-lang/ghc-}"
95         fi
96         echo "${_GHC_PM_VERSION_CACHE}"
97 }
98
99 # @FUNCTION: ghc-cabal-version
100 # @DESCRIPTION:
101 # return version of the Cabal library bundled with ghc
102 ghc-cabal-version() {
103         if ver_test "$(ghc-version)" -ge "7.9.20141222"; then
104                 # outputs in format: 'version: 1.18.1.5'
105                 set -- `$(ghc-getghcpkg) --package-db=$(ghc-libdir)/package.conf.d.initial field Cabal version`
106                 echo "$2"
107         else
108                 local cabal_package=`echo "$(ghc-libdir)"/Cabal-*`
109                 # /path/to/ghc/Cabal-${VER} -> ${VER}
110                 echo "${cabal_package/*Cabal-/}"
111         fi
112 }
113
114 # @FUNCTION: ghc-is-dynamic
115 # @DESCRIPTION:
116 # checks if ghc is built against dynamic libraries
117 # binaries linked against GHC library (and using plugin loading)
118 # have to be linked the same way:
119 #    https://ghc.haskell.org/trac/ghc/ticket/10301
120 ghc-is-dynamic() {
121         $(ghc-getghc) --info | grep "GHC Dynamic" | grep -q "YES"
122 }
123
124 # @FUNCTION: ghc-supports-shared-libraries
125 # @DESCRIPTION:
126 # checks if ghc is built with support for building
127 # shared libraries (aka '-dynamic' option)
128 ghc-supports-shared-libraries() {
129         $(ghc-getghc) --info | grep "RTS ways" | grep -q "dyn"
130 }
131
132 # @FUNCTION: ghc-supports-threaded-runtime
133 # @DESCRIPTION:
134 # checks if ghc is built with support for threaded
135 # runtime (aka '-threaded' option)
136 ghc-supports-threaded-runtime() {
137         $(ghc-getghc) --info | grep "RTS ways" | grep -q "thr"
138 }
139
140 # @FUNCTION: ghc-supports-smp
141 # @DESCRIPTION:
142 # checks if ghc is built with support for multiple cores runtime
143 ghc-supports-smp() {
144         $(ghc-getghc) --info | grep "Support SMP" | grep -q "YES"
145 }
146
147 # @FUNCTION: ghc-supports-interpreter
148 # @DESCRIPTION:
149 # checks if ghc has interpreter mode (aka GHCi)
150 # It usually means that ghc supports for template haskell.
151 ghc-supports-interpreter() {
152         $(ghc-getghc) --info | grep "Have interpreter" | grep -q "YES"
153 }
154
155 # @FUNCTION: ghc-supports-parallel-make
156 # @DESCRIPTION:
157 # checks if ghc has support for '--make -j' mode
158 # The option was introduced in ghc-7.8-rc1.
159 ghc-supports-parallel-make() {
160         $(ghc-getghc) --info | grep "Support parallel --make" | grep -q "YES"
161 }
162
163 # @FUNCTION: ghc-extractportageversion
164 # @DESCRIPTION:
165 # extract the version of a portage-installed package
166 ghc-extractportageversion() {
167         local pkg
168         local version
169         pkg="$(best_version $1)"
170         version="${pkg#$1-}"
171         version="${version%-r*}"
172         version="${version%_pre*}"
173         echo "${version}"
174 }
175
176 # @FUNCTION: ghc-libdir
177 # @DESCRIPTION:
178 # returns the library directory
179 _GHC_LIBDIR_CACHE=""
180 ghc-libdir() {
181         if [[ -z "${_GHC_LIBDIR_CACHE}" ]]; then
182                 _GHC_LIBDIR_CACHE="$($(ghc-getghc) --print-libdir)"
183         fi
184         echo "${_GHC_LIBDIR_CACHE}"
185 }
186
187 # @FUNCTION: ghc-make-args
188 # @DESCRIPTION:
189 # Returns default arguments passed along 'ghc --make'
190 # build mode. Used mainly to enable parallel build mode.
191 ghc-make-args() {
192         local ghc_make_args=()
193         # parallel on all available cores
194         if ghc-supports-smp && ghc-supports-parallel-make; then
195                 # It should have been just -j$(makeopts_jobs)
196                 # but GHC does not yet have nice defaults:
197                 #    https://ghc.haskell.org/trac/ghc/ticket/9221#comment:57
198                 # SMP is a requirement for parallel GC's gen0
199                 # 'qb' balancing.
200                 echo "-j$(makeopts_jobs) +RTS -A256M -qb0 -RTS"
201                 ghc_make_args=()
202         fi
203         echo "${ghc_make_args[@]}"
204 }
205
206 # @FUNCTION: ghc-confdir
207 # @DESCRIPTION:
208 # returns the (Gentoo) library configuration directory, we
209 # store here a hint for 'haskell-updater' about packages
210 # installed for old ghc versions and current ones.
211 ghc-confdir() {
212         echo "$(ghc-libdir)/gentoo"
213 }
214
215 # @FUNCTION: ghc-package-db
216 # @DESCRIPTION:
217 # returns the global package database directory
218 ghc-package-db() {
219         echo "$(ghc-libdir)/package.conf.d"
220 }
221
222 # @FUNCTION: ghc-localpkgconfd
223 # @DESCRIPTION:
224 # returns the name of the local (package-specific)
225 # package configuration file
226 ghc-localpkgconfd() {
227         echo "${PF}.conf.d"
228 }
229
230 # @FUNCTION: ghc-package-exists
231 # @DESCRIPTION:
232 # tests if a ghc package exists
233 ghc-package-exists() {
234         $(ghc-getghcpkg) describe "$1" > /dev/null 2>&1
235 }
236
237 # @FUNCTION: check-for-collisions
238 # @DESCRIPTION:
239 # makes sure no packages
240 # have the same version as initial package setup
241 check-for-collisions() {
242         local localpkgconf=$1
243         local checked_pkg
244         local initial_pkg_db="$(ghc-libdir)/package.conf.d.initial"
245
246         for checked_pkg in `$(ghc-getghcpkgbin) -f "${localpkgconf}" list --simple-output`
247         do
248                 # should return empty output
249                 local collided=`$(ghc-getghcpkgbin) -f ${initial_pkg_db} list --simple-output "${checked_pkg}"`
250
251                 if [[ -n ${collided} ]]; then
252                         eerror "Cabal package '${checked_pkg}' is shipped with '$(ghc-pm-version)' ('$(ghc-version)')."
253                         eerror "Ebuild author forgot an entry in CABAL_CORE_LIB_GHC_PV='${CABAL_CORE_LIB_GHC_PV}'."
254                         eerror "Found in ${initial_pkg_db}."
255                         die
256                 fi
257         done
258 }
259
260 # @FUNCTION: ghc-install-pkg
261 # @DESCRIPTION:
262 # moves the local (package-specific) package configuration
263 # file to its final destination
264 ghc-install-pkg() {
265         local localpkgconf="${T}/$(ghc-localpkgconfd)"
266         local pkg_path pkg pkg_db="${D}/$(ghc-package-db)" hint_db="${D}/$(ghc-confdir)"
267
268         $(ghc-getghcpkgbin) init "${localpkgconf}" || die "Failed to initialize empty local db"
269         for pkg_config_file in "$@"; do
270                 $(ghc-getghcpkgbin) -f "${localpkgconf}" update - --force \
271                                 < "${pkg_config_file}" || die "failed to register ${pkg}"
272         done
273
274         check-for-collisions "${localpkgconf}"
275
276         mkdir -p "${pkg_db}" || die
277         for pkg_path in "${localpkgconf}"/*.conf; do
278                 pkg=$(basename "${pkg_path}")
279                 cp "${pkg_path}" "${pkg_db}/${pkg}" || die
280         done
281
282         mkdir -p "${hint_db}" || die
283         for pkg_config_file in "$@"; do
284                 local pkg_name="gentoo-${CATEGORY}-${PF}-"$(basename "${pkg_config_file}")
285                 cp "${pkg_config_file}" "${hint_db}/${pkg_name}" || die
286                 chmod 0644 "${hint_db}/${pkg_name}" || die
287         done
288 }
289
290 # @FUNCTION: ghc-recache-db
291 # @DESCRIPTION:
292 # updates 'package.cache' binary cacne for registered '*.conf'
293 # packages
294 ghc-recache-db() {
295         einfo "Recaching GHC package DB"
296         $(ghc-getghcpkg) recache
297 }
298
299 # @FUNCTION: ghc-register-pkg
300 # @DESCRIPTION:
301 # registers all packages in the local (package-specific)
302 # package configuration file
303 ghc-register-pkg() {
304         ghc-recache-db
305 }
306
307 # @FUNCTION: ghc-reregister
308 # @DESCRIPTION:
309 # re-adds all available .conf files to the global
310 # package conf file, to be used on a ghc reinstallation
311 ghc-reregister() {
312         ghc-recache-db
313 }
314
315 # @FUNCTION: ghc-unregister-pkg
316 # @DESCRIPTION:
317 # unregisters a package configuration file
318 ghc-unregister-pkg() {
319         ghc-recache-db
320 }
321
322 # @FUNCTION: ghc-pkgdeps
323 # @DESCRIPTION:
324 # exported function: loads a package dependency in a form
325 # cabal_package version
326 ghc-pkgdeps() {
327         echo $($(ghc-getghcpkg) describe "${1}") \
328         | sed \
329                         -e '/depends/,/^.*:/ !d' \
330                         -e 's/\(.*\)-\(.*\)-\(.*\)/\1 \2/' \
331                         -e 's/^.*://g'
332 }
333
334 # @FUNCTION: ghc-package_pkg_postinst
335 # @DESCRIPTION:
336 # updates package.cache after package install
337 ghc-package_pkg_postinst() {
338         ghc-recache-db
339 }
340
341 # @FUNCTION: ghc-package_pkg_prerm
342 # @DESCRIPTION:
343 # updates package.cache after package deinstall
344 ghc-package_pkg_prerm() {
345         ewarn "ghc-package.eclass: 'ghc-package_pkg_prerm()' is a noop"
346         ewarn "ghc-package.eclass: consider 'haskell-cabal_pkg_postrm()' instead"
347 }
348
349 # @FUNCTION: ghc-package_pkg_postrm
350 # @DESCRIPTION:
351 # updates package.cache after package deinstall
352 ghc-package_pkg_postrm() {
353         ghc-recache-db
354 }