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