1 # Copyright 1999-2015 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
5 # @ECLASS: ghc-package.eclass
7 # "Gentoo's Haskell Language team" <haskell@gentoo.org>
9 # Original Author: Andres Loeh <kosmikus@gentoo.org>
10 # @BLURB: This eclass helps with the Glasgow Haskell Compiler's package configuration utility.
12 # Helper eclass to handle ghc installation/upgrade/deinstallation process.
16 # @FUNCTION: ghc-getghc
18 # returns the name of the ghc executable
23 # @FUNCTION: ghc-getghcpkg
25 # Internal function determines returns the name of the ghc-pkg executable
30 # @FUNCTION: ghc-getghcpkgbin
32 # returns the name of the ghc-pkg binary (ghc-pkg
33 # itself usually is a shell script, and we have to
34 # bypass the script under certain circumstances);
35 # for Cabal, we add an empty global package config file,
36 # because for some reason the global package file
39 if version_is_at_least "7.9.20141222" "$(ghc-version)"; then
40 # ghc-7.10 stopped supporting single-file database
41 local empty_db="${T}/empty.conf.d" ghc_pkg="$(ghc-libdir)/bin/ghc-pkg"
42 if [[ ! -d ${empty_db} ]]; then
43 "${ghc_pkg}" init "${empty_db}" || die "Failed to initialize empty global db"
45 echo "$(ghc-libdir)/bin/ghc-pkg" "--global-package-db=${empty_db}"
47 elif version_is_at_least "7.7.20121101" "$(ghc-version)"; then
48 # the ghc-pkg executable changed name in ghc 6.10, as it no longer needs
49 # the wrapper script with the static flags
50 # was moved to bin/ subtree by:
51 # http://www.haskell.org/pipermail/cvs-ghc/2012-September/076546.html
52 echo '[]' > "${T}/empty.conf"
53 echo "$(ghc-libdir)/bin/ghc-pkg" "--global-package-db=${T}/empty.conf"
55 elif version_is_at_least "7.5.20120516" "$(ghc-version)"; then
56 echo '[]' > "${T}/empty.conf"
57 echo "$(ghc-libdir)/ghc-pkg" "--global-package-db=${T}/empty.conf"
60 echo '[]' > "${T}/empty.conf"
61 echo "$(ghc-libdir)/ghc-pkg" "--global-conf=${T}/empty.conf"
65 # @FUNCTION: ghc-version
67 # returns upstream version of ghc
68 # as reported by '--numeric-version'
69 # Examples: "7.10.2", "7.9.20141222"
72 if [[ -z "${_GHC_VERSION_CACHE}" ]]; then
73 _GHC_VERSION_CACHE="$($(ghc-getghc) --numeric-version)"
75 echo "${_GHC_VERSION_CACHE}"
78 # @FUNCTION: ghc-pm-version
80 # returns package manager(PM) version of ghc
81 # as reported by '$(best_version)'
82 # Examples: "PM:7.10.2", "PM:7.10.2_rc1", "PM:7.8.4-r4"
83 _GHC_PM_VERSION_CACHE=""
87 if [[ -z "${_GHC_PM_VERSION_CACHE}" ]]; then
88 pm_ghc_p=$(best_version dev-lang/ghc)
89 _GHC_PM_VERSION_CACHE="PM:${pm_ghc_p#dev-lang/ghc-}"
91 echo "${_GHC_PM_VERSION_CACHE}"
94 # @FUNCTION: ghc-cabal-version
96 # return version of the Cabal library bundled with ghc
98 if version_is_at_least "7.9.20141222" "$(ghc-version)"; then
99 # outputs in format: 'version: 1.18.1.5'
100 set -- `$(ghc-getghcpkg) --package-db=$(ghc-libdir)/package.conf.d.initial field Cabal version`
103 local cabal_package=`echo "$(ghc-libdir)"/Cabal-*`
104 # /path/to/ghc/Cabal-${VER} -> ${VER}
105 echo "${cabal_package/*Cabal-/}"
109 # @FUNCTION: ghc-sanecabal
111 # check if a standalone Cabal version is available for the
112 # currently used ghc; takes minimal version of Cabal as
113 # an optional argument
117 if [[ -z "$1" ]]; then version="1.0.1"; else version="$1"; fi
118 for f in $(ghc-confdir)/cabal-*; do
119 [[ -f "${f}" ]] && version_is_at_least "${version}" "${f#*cabal-}" && return
123 # @FUNCTION: ghc-is-dynamic
125 # checks if ghc is built against dynamic libraries
126 # binaries linked against GHC library (and using plugin loading)
127 # have to be linked the same way:
128 # https://ghc.haskell.org/trac/ghc/ticket/10301
130 $(ghc-getghc) --info | grep "GHC Dynamic" | grep -q "YES"
133 # @FUNCTION: ghc-supports-shared-libraries
135 # checks if ghc is built with support for building
136 # shared libraries (aka '-dynamic' option)
137 ghc-supports-shared-libraries() {
138 $(ghc-getghc) --info | grep "RTS ways" | grep -q "dyn"
141 # @FUNCTION: ghc-supports-threaded-runtime
143 # checks if ghc is built with support for threaded
144 # runtime (aka '-threaded' option)
145 ghc-supports-threaded-runtime() {
146 $(ghc-getghc) --info | grep "RTS ways" | grep -q "thr"
149 # @FUNCTION: ghc-supports-smp
151 # checks if ghc is built with support for multiple cores runtime
153 $(ghc-getghc) --info | grep "Support SMP" | grep -q "YES"
156 # @FUNCTION: ghc-supports-interpreter
158 # checks if ghc has interpreter mode (aka GHCi)
159 # It usually means that ghc supports for template haskell.
160 ghc-supports-interpreter() {
161 $(ghc-getghc) --info | grep "Have interpreter" | grep -q "YES"
164 # @FUNCTION: ghc-supports-parallel-make
166 # checks if ghc has support for '--make -j' mode
167 # The option was introduced in ghc-7.8-rc1.
168 ghc-supports-parallel-make() {
169 $(ghc-getghc) --info | grep "Support parallel --make" | grep -q "YES"
172 # @FUNCTION: ghc-extractportageversion
174 # extract the version of a portage-installed package
175 ghc-extractportageversion() {
178 pkg="$(best_version $1)"
180 version="${version%-r*}"
181 version="${version%_pre*}"
185 # @FUNCTION: ghc-libdir
187 # returns the library directory
190 if [[ -z "${_GHC_LIBDIR_CACHE}" ]]; then
191 _GHC_LIBDIR_CACHE="$($(ghc-getghc) --print-libdir)"
193 echo "${_GHC_LIBDIR_CACHE}"
196 # @FUNCTION: ghc-confdir
198 # returns the (Gentoo) library configuration directory, we
199 # store here a hint for 'haskell-updater' about packages
200 # installed for old ghc versions and current ones.
202 echo "$(ghc-libdir)/gentoo"
205 # @FUNCTION: ghc-package-db
207 # returns the global package database directory
209 echo "$(ghc-libdir)/package.conf.d"
212 # @FUNCTION: ghc-localpkgconfd
214 # returns the name of the local (package-specific)
215 # package configuration file
216 ghc-localpkgconfd() {
220 # @FUNCTION: ghc-package-exists
222 # tests if a ghc package exists
223 ghc-package-exists() {
224 $(ghc-getghcpkg) describe "$1" > /dev/null 2>&1
227 # @FUNCTION: check-for-collisions
228 # @DESCRIPTION: makes sure no packages
229 # have the same version as initial package setup
230 check-for-collisions() {
231 local localpkgconf=$1
233 local initial_pkg_db="$(ghc-libdir)/package.conf.d.initial"
235 for checked_pkg in `$(ghc-getghcpkgbin) -f "${localpkgconf}" list --simple-output`
237 # should return empty output
238 local collided=`$(ghc-getghcpkgbin) -f ${initial_pkg_db} list --simple-output "${checked_pkg}"`
240 if [[ -n ${collided} ]]; then
241 eerror "Cabal package '${checked_pkg}' is shipped with '$(ghc-pm-version)' ('$(ghc-version)')."
242 eerror "Ebuild author forgot an entry in CABAL_CORE_LIB_GHC_PV='${CABAL_CORE_LIB_GHC_PV}'."
243 eerror "Found in ${initial_pkg_db}."
249 # @FUNCTION: ghc-install-pkg
251 # moves the local (package-specific) package configuration
252 # file to its final destination
254 local pkg_config_file=$1
255 local localpkgconf="${T}/$(ghc-localpkgconfd)"
256 local pkg_path pkg pkg_db="${D}/$(ghc-package-db)" hint_db="${D}/$(ghc-confdir)"
258 $(ghc-getghcpkgbin) init "${localpkgconf}" || die "Failed to initialize empty local db"
259 $(ghc-getghcpkgbin) -f "${localpkgconf}" update - --force \
260 < "${pkg_config_file}" || die "failed to register ${pkg}"
262 check-for-collisions "${localpkgconf}"
264 mkdir -p "${pkg_db}" || die
265 for pkg_path in "${localpkgconf}"/*.conf; do
266 pkg=$(basename "${pkg_path}")
267 cp "${pkg_path}" "${pkg_db}/${pkg}" || die
270 mkdir -p "${hint_db}" || die
271 cp "${pkg_config_file}" "${hint_db}/${PF}.conf" || die
272 chmod 0644 "${hint_db}/${PF}.conf" || die
275 # @FUNCTION: ghc-recache-db
277 # updates 'package.cache' binary cacne for registered '*.conf'
280 einfo "Recaching GHC package DB"
281 $(ghc-getghcpkg) recache
284 # @FUNCTION: ghc-register-pkg
286 # registers all packages in the local (package-specific)
287 # package configuration file
292 # @FUNCTION: ghc-reregister
294 # re-adds all available .conf files to the global
295 # package conf file, to be used on a ghc reinstallation
300 # @FUNCTION: ghc-unregister-pkg
302 # unregisters a package configuration file
303 ghc-unregister-pkg() {
307 # @FUNCTION: ghc-pkgdeps
309 # exported function: loads a package dependency in a form
310 # cabal_package version
312 echo $($(ghc-getghcpkg) describe "${1}") \
314 -e '/depends/,/^.*:/ !d' \
315 -e 's/\(.*\)-\(.*\)-\(.*\)/\1 \2/' \
319 # @FUNCTION: ghc-package_pkg_postinst
321 # updates package.cache after package install
322 ghc-package_pkg_postinst() {
326 # @FUNCTION: ghc-package_pkg_prerm
328 # updates package.cache after package deinstall
329 ghc-package_pkg_prerm() {
330 ewarn "ghc-package.eclass: 'ghc-package_pkg_prerm()' is a noop"
331 ewarn "ghc-package.eclass: consider 'haskell-cabal_pkg_postrm()' instead"
334 # @FUNCTION: ghc-package_pkg_postrm
336 # updates package.cache after package deinstall
337 ghc-package_pkg_postrm() {