commit: acecfa43882156c2e00e6babae105289e4d29675 Author: Jack Todaro <solpeth <AT> posteo <DOT> org> AuthorDate: Fri Jul 22 22:29:26 2022 +0000 Commit: Sam James <sam <AT> gentoo <DOT> org> CommitDate: Sat Jul 23 01:51:45 2022 +0000 URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=acecfa43
haskell-cabal.eclass: sync from ::haskell The eclass has a number of additions and some changes which allow for automated revision handling from hackage.haskell.org packages. For those that are unaware, Hackage trustees as well as package authors are able to make limited changes to a package's build file (the .cabal file) on the Hackage package index. These changes are mostly to do with either loosening upper bounds on dependency version ranges, or adding them in when a new package version causes other packages to silently break. See the PVP for more information on Haskell versioning, if need be. A hackage revision does _not_ affect the tarball. Instead, the revised .cabal file sits atop the tarball and is used by tools like cabal-install to reset the dependency version bounds at build time. hackport, the tool we use to automate writing new ebuilds and bumping package versions, always brought in the revised .cabal file if it existed, as under the hood it is using the exact same Cabal and cabal-install libraries to navigate the Hackage package index. However, it did not patch the .cabal file in the tarball, which Portage uses for building. As such, it could be the case that RDEPENDs and the underlying dependencies in the .cabal file would not match up, and src_configure could fail due to 'missing dependencies'. hackport HEAD, in conjunction with this eclass change, automatically handles replacing the underlying .cabal file with the latest revised one from the Hackage index - and this is now all visible to the developer. As such, this eclass change in conjunction with the newer hackport reduces silent breakages. Signed-off-by: Jack Todaro <solpeth <AT> posteo.org> Signed-off-by: Sam James <sam <AT> gentoo.org> eclass/haskell-cabal.eclass | 168 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 136 insertions(+), 32 deletions(-) diff --git a/eclass/haskell-cabal.eclass b/eclass/haskell-cabal.eclass index 541bb4a90ee5..d437fc824f53 100644 --- a/eclass/haskell-cabal.eclass +++ b/eclass/haskell-cabal.eclass @@ -8,7 +8,6 @@ # Original author: Andres Loeh <kosmi...@gentoo.org> # Original author: Duncan Coutts <dcou...@gentoo.org> # @SUPPORTED_EAPIS: 6 7 8 -# @PROVIDES: ghc-package # @BLURB: for packages that make use of the Haskell Common Architecture for Building Applications and Libraries (cabal) # @DESCRIPTION: # Basic instructions: @@ -50,7 +49,7 @@ esac inherit ghc-package multilib toolchain-funcs -EXPORT_FUNCTIONS pkg_setup src_configure src_compile src_test src_install pkg_postinst pkg_postrm +EXPORT_FUNCTIONS pkg_setup src_prepare src_configure src_compile src_test src_install pkg_postinst pkg_postrm # @ECLASS_VARIABLE: CABAL_EXTRA_CONFIGURE_FLAGS # @USER_VARIABLE @@ -123,6 +122,72 @@ EXPORT_FUNCTIONS pkg_setup src_configure src_compile src_test src_install pkg_po # Set to anything else to disable. : ${CABAL_REPORT_OTHER_BROKEN_PACKAGES:=yes} +# @ECLASS_VARIABLE: CABAL_HACKAGE_REVISION +# @PRE_INHERIT +# @DESCRIPTION: +# Set the upstream revision number from Hackage. This will automatically +# add the upstream cabal revision to SRC_URI and apply it in src_prepare. +: ${CABAL_HACKAGE_REVISION:=0} + +# @ECLASS_VARIABLE: CABAL_PN +# @PRE_INHERIT +# @DESCRIPTION: +# Set the name of the package as it is recorded in the Hackage database. This +# is mostly used when packages use CamelCase names upstream, but we want them +# to be lowercase in portage. +: ${CABAL_PN:=${PN}} + +# @ECLASS_VARIABLE: CABAL_PV +# @PRE_INHERIT +# @DESCRIPTION: +# Set the version of the package as it is recorded in the Hackage database. +# This can be useful if we use a different versioning scheme in Portage than +# the one from upstream +: ${CABAL_PV:=${PV}} + +# @ECLASS_VARIABLE: CABAL_P +# @OUTPUT_VARIABLE +# @DESCRIPTION: +# The combined $CABAL_PN and $CABAL_PV variables, analogous to $P +CABAL_P="${CABAL_PN}-${CABAL_PV}" + +S="${WORKDIR}/${CABAL_P}" + +# @ECLASS_VARIABLE: CABAL_FILE +# @DESCRIPTION: +# The location of the .cabal file for the Haskell package. This defaults to +# "${S}/${CABAL_PN}.cabal". +: ${CABAL_FILE:="${S}/${CABAL_PN}.cabal"} + +# @ECLASS_VARIABLE: CABAL_DISTFILE +# @OUTPUT_VARIABLE +# @DESCRIPTION: +# The name of the .cabal file downloaded from Hackage. This filename does not +# include $DISTDIR +if [[ ${CABAL_HACKAGE_REVISION} -ge 1 ]]; then + CABAL_DISTFILE="${P}-rev${CABAL_HACKAGE_REVISION}.cabal" +fi + +# @ECLASS_VARIABLE: CABAL_CHDEPS +# @DEFAULT_UNSET +# @DESCRIPTION: +# Specifies changes to be made to the .cabal file. Uses the cabal_chdeps +# function internally and shares the same syntax. +# @EXAMPLE: +# CABAL_CHDEPS=( +# 'base >= 4.2 && < 4.6' 'base >= 4.2 && < 4.7' +# 'containers ==0.4.*' 'containers >= 0.4 && < 0.6' +# ) +: ${CABAL_CHDEPS:=} + + +# @ECLASS_VARIABLE: CABAL_LIVE_VERSION +# @PRE_INHERIT +# @DEFAULT_UNSET +# @DESCRIPTION: +# Set this to any value to prevent SRC_URI from being set automatically. +: ${CABAL_LIVE_VERSION:=} + # 'dev-haskell/cabal' passes those options with ./configure-based # configuration, but most packages don't need/don't accept it: # #515362, #515362 @@ -156,7 +221,7 @@ fi if [[ -n "${CABAL_USE_HOOGLE}" ]]; then # enabled only in ::haskell - #IUSE="${IUSE} hoogle" + # IUSE="${IUSE} hoogle" CABAL_USE_HOOGLE= fi @@ -169,6 +234,26 @@ if [[ -n "${CABAL_TEST_SUITE}" ]]; then RESTRICT+=" !test? ( test )" fi +# If SRC_URI is defined in the ebuild without appending, it will overwrite +# the value set here. This will not be set on packages whose versions end in "9999" +# or if CABAL_LIVE_VERSION is set. +case $PV in + *9999) ;; + *) + if [[ -z "${CABAL_LIVE_VERSION}" ]]; then + if [[ "${CABAL_P}" == "${P}" ]]; then + SRC_URI="https://hackage.haskell.org/package/${P}/${P}.tar.gz" + else + SRC_URI="https://hackage.haskell.org/package/${CABAL_P}/${CABAL_P}.tar.gz -> ${P}.tar.gz" + fi + if [[ -n ${CABAL_DISTFILE} ]]; then + SRC_URI+=" https://hackage.haskell.org/package/${CABAL_P}/revision/${CABAL_HACKAGE_REVISION}.cabal -> ${CABAL_DISTFILE}" + fi + fi ;; +esac + +BDEPEND="${BDEPEND} app-text/dos2unix" + # returns the version of cabal currently in use. # Rarely it's handy to pin cabal version from outside. : ${_CABAL_VERSION_CACHE:=""} @@ -228,20 +313,6 @@ cabal-bootstrap() { $(ghc-getghc) "$@" } if $(ghc-supports-shared-libraries); then - # # some custom build systems might use external libraries, - # # for which we don't have shared libs, so keep static fallback - # bug #411789, http://hackage.haskell.org/trac/ghc/ticket/5743#comment:3 - # http://hackage.haskell.org/trac/ghc/ticket/7062 - # http://hackage.haskell.org/trac/ghc/ticket/3072 - # ghc does not set RPATH for extralibs, thus we do it ourselves by hands - einfo "Prepending $(ghc-libdir) to LD_LIBRARY_PATH" - if [[ ${CHOST} != *-darwin* ]]; then - LD_LIBRARY_PATH="$(ghc-libdir)${LD_LIBRARY_PATH:+:}${LD_LIBRARY_PATH}" - export LD_LIBRARY_PATH - else - DYLD_LIBRARY_PATH="$(ghc-libdir)${DYLD_LIBRARY_PATH:+:}${DYLD_LIBRARY_PATH}" - export DYLD_LIBRARY_PATH - fi { make_setup -dynamic "$@" && ./setup --help >/dev/null; } || make_setup "$@" || die "compiling ${setupmodule} failed" else @@ -288,8 +359,8 @@ cabal-show-brokens() { elog "ghc-pkg check: 'checking for other broken packages:'" # pretty-printer $(ghc-getghcpkg) check 2>&1 \ - | grep -E -v '^Warning: haddock-(html|interfaces): ' \ - | grep -E -v '^Warning: include-dirs: ' \ + | egrep -v '^Warning: haddock-(html|interfaces): ' \ + | egrep -v '^Warning: include-dirs: ' \ | head -n 20 cabal-die-if-nonempty 'broken' \ @@ -448,7 +519,7 @@ cabal-build() { } cabal-copy() { - set -- copy --destdir="${D}" "$@" + set -- copy "$@" --destdir="${D}" echo ./setup "$@" ./setup "$@" || die "setup copy failed" @@ -510,6 +581,29 @@ haskell-cabal_pkg_setup() { fi } +haskell-cabal_src_prepare() { + # Needed for packages that are still using MY_PN + if [[ -n ${MY_PN} ]]; then + local cabal_file="${S}/${MY_PN}.cabal" + else + local cabal_file="${CABAL_FILE}" + fi + + if [[ -n ${CABAL_DISTFILE} ]]; then + # pull revised cabal from upstream + einfo "Using revised .cabal file from Hackage: revision ${CABAL_HACKAGE_REVISION}" + cp "${DISTDIR}/${CABAL_DISTFILE}" "${cabal_file}" || die + fi + + # Convert to unix line endings + dos2unix "${cabal_file}" || die + + # Apply patches *after* pulling the revised cabal + default + + [[ -n "${CABAL_CHDEPS}" ]] && cabal_chdeps "${CABAL_CHDEPS[@]}" +} + haskell-cabal_src_configure() { cabal-is-dummy-lib && return @@ -599,7 +693,8 @@ haskell-cabal_src_test() { # exported function: cabal-style copy and register cabal_src_install() { if ! cabal-is-dummy-lib; then - cabal-copy + # Pass arguments to cabal-copy + cabal-copy "$@" cabal-pkg fi @@ -614,10 +709,14 @@ cabal_src_install() { touch "${hint_file}" || die } +# Arguments passed to this function will make their way to `cabal-copy` +# and eventually `./setup copy`. This allows you to specify which +# components will be installed. +# e.g. `haskell-cabal_src_install "lib:${PN}"` will only install the library haskell-cabal_src_install() { pushd "${S}" > /dev/null || die - cabal_src_install + cabal_src_install "$@" popd > /dev/null || die } @@ -678,23 +777,28 @@ cabal_flag() { #} # or # src_prepare() { -# CABAL_FILE=${S}/${MY_PN}.cabal cabal_chdeps \ +# CABAL_FILE=${S}/${CABAL_PN}.cabal cabal_chdeps \ # 'base >= 4.2 && < 4.6' 'base >= 4.2 && < 4.7' -# CABAL_FILE=${S}/${MY_PN}-tools.cabal cabal_chdeps \ +# CABAL_FILE=${S}/${CABAL_PN}-tools.cabal cabal_chdeps \ # 'base == 3.*' 'base >= 4.2 && < 4.7' #} # cabal_chdeps() { - local cabal_fn=${MY_PN:-${PN}}.cabal - local cf=${CABAL_FILE:-${S}/${cabal_fn}} + # Needed for compatibility with ebuilds still using MY_PN + if [[ -n ${MY_PN} ]]; then + local cabal_file="${S}/${MY_PN}.cabal" + else + local cabal_file="${CABAL_FILE}" + fi + local from_ss # ss - substring local to_ss local orig_c # c - contents local new_c - [[ -f $cf ]] || die "cabal file '$cf' does not exist" + [[ -f "${cabal_file}" ]] || die "cabal file '${cabal_file}' does not exist" - orig_c=$(< "$cf") + orig_c=$(< "${cabal_file}") while :; do from_pat=$1 @@ -712,9 +816,9 @@ cabal_chdeps() { new_c=${orig_c//${from_pat}/${to_str}} if [[ -n $CABAL_DEBUG_LOOSENING ]]; then - echo "${orig_c}" >"${T}/${cf}".pre - echo "${new_c}" >"${T}/${cf}".post - diff -u "${T}/${cf}".{pre,post} + echo "${orig_c}" >"${T}/${cabal_file}".pre + echo "${new_c}" >"${T}/${cabal_file}".post + diff -u "${T}/${cabal_file}".{pre,post} fi [[ "${orig_c}" == "${new_c}" ]] && die "no trigger for '${from_pat}'" @@ -723,7 +827,7 @@ cabal_chdeps() { shift done - echo "${new_c}" > "$cf" || + echo "${new_c}" > "$cabal_file" || die "failed to update" }