aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eclass/dmd-r1.eclass414
1 files changed, 414 insertions, 0 deletions
diff --git a/eclass/dmd-r1.eclass b/eclass/dmd-r1.eclass
new file mode 100644
index 0000000..802e820
--- /dev/null
+++ b/eclass/dmd-r1.eclass
@@ -0,0 +1,414 @@
+# Copyright 2024 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+# @ECLASS: dmd-r1.eclass
+# @MAINTAINER:
+# Andrei Horodniceanu <a.horodniceanu@proton.me>
+# @AUTHOR:
+# Andrei Horodniceanu <a.horodniceanu@proton.me>
+# Based on dmd.eclass by Marco Leise <marco.leise@gmx.de>.
+# @BUGREPORTS:
+# Please report bugs via https://github.com/gentoo/dlang/issues
+# @VCSURL: https://github.com/gentoo/dlang
+# @SUPPORTED_EAPIS: 8
+# @BLURB: Captures most of the logic for building and installing DMD
+# @DESCRIPTION:
+# Helps with the maintenance of the various DMD versions by capturing common
+# logic.
+
+if [[ ! ${_ECLASS_ONCE_DMD_R1} ]] ; then
+_ECLASS_ONCE_DMD_R1=1
+
+case ${EAPI:-0} in
+ 8) ;;
+ *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;;
+esac
+
+DESCRIPTION="Reference compiler for the D programming language"
+HOMEPAGE="https://dlang.org/"
+
+# DMD supports amd64/x86 exclusively
+# @ECLASS_VARIABLE: MULTILIB_COMPAT
+# @DESCRIPTION:
+# A list of multilib ABIs supported by $PN. It only supports
+# abi_x86_{32,64}. See the multilib-build.eclass documentation for this
+# variable for more information.
+MULTILIB_COMPAT=( abi_x86_{32,64} )
+
+inherit desktop edos2unix dlang-single multilib-build multiprocessing optfeature
+
+LICENSE=Boost-1.0
+SLOT=$(ver_cut 1-2)
+readonly MAJOR=$(ver_cut 1)
+readonly MINOR=$(ver_cut 2)
+readonly PATCH=$(ver_cut 3)
+readonly VERSION=$(ver_cut 1-3)
+readonly BETA=$(ver_cut 4-)
+
+# For prereleases, 2.097.0_rc1 -> 2.097.0-rc.1
+MY_VER=$(ver_rs 3 - 4 .)
+
+DLANG_ORG=https://downloads.dlang.org/${BETA:+pre-}releases/2.x/${VERSION}
+SRC_URI="
+ https://github.com/dlang/${PN}/archive/refs/tags/v${MY_VER}.tar.gz -> ${PN}-${MY_VER}.tar.gz
+ https://github.com/dlang/phobos/archive/refs/tags/v${MY_VER}.tar.gz -> phobos-${MY_VER}.tar.gz
+ selfhost? ( ${DLANG_ORG}/dmd.${MY_VER}.linux.tar.xz )
+ doc? ( ${DLANG_ORG}/dmd.${MY_VER}.linux.tar.xz )
+"
+
+IUSE="doc examples +selfhost static-libs"
+REQUIRED_USE="^^ ( selfhost ${DLANG_REQUIRED_USE} )"
+IDEPEND=">=app-eselect/eselect-dlang-20140709"
+BDEPEND="!selfhost? ( ${DLANG_DEPS} )"
+# We don't need anything in DEPEND, curl is dl-opened
+# so it belongs in RDEPEND.
+#DEPEND=
+# Since 2.107.0, dmd links the standard library of the host
+# compiler. Since this eclass is only used by >=dmd-2.107.0-r1 the
+# dependency is added unconditionally.
+RDEPEND="
+ ${IDEPEND}
+ net-misc/curl[${MULTILIB_USEDEP}]
+ !selfhost? ( ${DLANG_DEPS} )
+"
+
+dmd-r1_pkg_setup() {
+ if use !selfhost; then
+ dlang-single_pkg_setup
+ # set by dlang-single.eclass:
+ # $EDC, $DC, $DLANG_LDFLAGS, $DCFLAGS
+
+ # Now let's build our environment
+ export DMDW=$(dlang_get_dmdw)
+ export DMDW_DCFLAGS=$(dlang_get_dmdw_dcflags)
+ export DMDW_LDFLAGS=$(dlang_get_dmdw_ldflags)
+ else
+ # Setup up similar variables to the above
+ export EDC=dmd-${SLOT}
+ #export DC= # is set inside src_unpack
+ #export DMDW= # is set inside src_unpack
+ export DLANG_LDFLAGS=$(dlang_get_ldflags)
+ # Should we put user DMDFLAGS here?
+ export DMDW_DCFLAGS= DCFLAGS=
+ export DMDW_LDFLAGS=$(dlang_get_dmdw_ldflags)
+ fi
+}
+
+dmd-r1_src_unpack() {
+ # Here because pkgdev complains about it being in pkg_setup
+ if use selfhost; then
+ export DC=${WORKDIR}/dmd2/linux/bin$(_get_abi_bits)/dmd
+ export DMDW=${DC}
+ fi
+
+ default
+
+ # $S may collide with $PN-$MY_VER
+ mv "${PN}-${MY_VER}" tmp || die
+ mkdir "${S}" || die
+ mv -T tmp "${S}/${PN}" || die
+ mv -T "phobos-${MY_VER}" "${S}/phobos" || die
+}
+
+dmd-r1_src_prepare() {
+ einfo "Removing dos-style line endings."
+ local file
+ while read -rd '' file; do
+ edos2unix "${file}"
+ done < <( find "${WORKDIR}" \( -name '*.txt' -o -name '*.html' -o -name '*.d' \
+ -o -name '*.di' -o -name '*.ddoc' -type f \) \
+ -print0 )
+
+ default
+}
+
+dmd-r1_src_compile() {
+ einfo "Building dmd build script"
+ dlang_compile_bin dmd/compiler/src/build{,.d}
+ local BUILD_D=${S}/dmd/compiler/src/build
+
+ local cmd=(
+ env
+ VERBOSE=1
+ HOST_DMD="${DMDW}"
+ # Just like old dmd.eclass.
+ #
+ # TODO, this has to be fixed but right now we either do
+ # ENABLE_RELEASE (we add -O -inline -release) or build.d will
+ # add -g.
+ ENABLE_RELEASE=1
+ "${BUILD_D}"
+ -j$(makeopts_jobs)
+ # A bit overkill to specify the flags here but it does get the
+ # jobs done.
+ DFLAGS="${DMDW_DCFLAGS} ${DMDW_LDFLAGS}"
+ )
+
+ einfo "Building dmd"
+ echo "${cmd[@]}"
+ "${cmd[@]}" || die "Failed to build dmd"
+
+ # The release here is from ENABLE_RELEASE, keep them in sync.
+ export GENERATED_DMD=${S}/dmd/generated/linux/release/$(_get_abi_bits)/dmd
+
+ compile_libraries() {
+ local commonMakeArgs=(
+ DMD="${GENERATED_DMD}"
+ MODEL=${MODEL}
+
+ # Just like how multilib_toolchain_setup does it:
+ CC="$(tc-getCC) $(get_abi_CFLAGS)"
+ # The flags are, a little, project dependent
+ #CFLAGS=
+
+ # With DFLAGS we have 2 problems:
+ #
+ # 1. it's pretty hard to specify them for druntime so
+ # it would need a makefile patch
+ #
+ # 2. we have the same question as in pkg_setup, do we
+ # respect DMDFLAGS when building with the generated dmd?
+ #
+ #DFLAGS=
+ )
+ local druntimeMakeArgs=(
+ # Calls git in global scope, only used for whitespace checks.
+ MANIFEST=
+
+ # Specifying user flags here discards the, hopefully
+ # relevant, values from the makefile so add them back.
+ CFLAGS="${CFLAGS} -fPIC -DHAVE_UNISTD_H" # -m32/64 is added in $CC.
+
+ # druntime's notion of a shared library is a static archive
+ # that is embedded into the phobos shared library.
+ #
+ # Technically there is the dll_so target which is the proper
+ # so file but who's gonna use it? Perhaps if phobos would
+ # not incorporate druntime we could install them as separate
+ # libraries (like ldc2 and gdc).
+ $(usex static-libs 'lib dll' dll)
+
+ # We also need to copy the headers to the proper location
+ import
+ )
+ local phobosMakeArgs=(
+ # If unspecified, would rebuild druntime.
+ CUSTOM_DRUNTIME=1
+
+ # Like druntime, specifying flags removes the makefile added ones.
+ CFLAGS="${CFLAGS} -fPIC -std=c11 -DHAVE_UNISTD_H" # -m32/64 is added in $CC.
+
+ # Overkill but it does work. Remember that we have to
+ # convert $LDFLAGS to something dmd understands.
+ DFLAGS="$(dlang_get_ldflags ${PN}-${SLOT})"
+
+ # By default builds both static+dynamic libraries.
+ $(usex static-libs 'lib dll' dll)
+ )
+
+ emake -C dmd/druntime "${commonMakeArgs[@]}" "${druntimeMakeArgs[@]}"
+ emake -C phobos "${commonMakeArgs[@]}" "${phobosMakeArgs[@]}"
+ }
+
+ _dmd_foreach_abi compile_libraries
+
+ # Build the man pages
+ local cmd=(
+ env
+ VERBOSE=1
+ HOST_DMD="${GENERATED_DMD}"
+ "${BUILD_D}"
+ -j$(makeopts_jobs)
+ man
+ # ${GENERATED_DMD} is not yet fully functional as we didn't
+ # create a good dmd.conf. But instead of doing that we're going
+ # to specify our flags here.
+ DFLAGS="-defaultlib=phobos2 -L-rpath=${S}/phobos/generated/linux/release/$(_get_abi_bits)"
+ )
+ echo "${cmd[@]}"
+ "${cmd[@]}" || die "Could not generate man pages"
+
+ # Now clean up some artifacts that would make the install phase
+ # harder (we rely on globbing and recursive calls a lot).
+
+ # The object file is useless
+ rm -f phobos/generated/linux/release/*/libphobos2.so.0.${MINOR}.o || die
+ # the zlib folder contains source code which is no longer
+ # needed. Don't touch etc/c/zlib.d however, that's important.
+ rm -rf phobos/etc/c/zlib || die
+}
+
+dmd-r1_src_test() {
+ # As opposed to old dmd.eclass we have access to actual tests. For
+ # porting reasons we're going to keep only the old test,
+ # hello_world.
+
+ test_hello_world() {
+ local phobosDir=${S}/phobos/generated/linux/release/${MODEL}
+ local commandArgs=(
+ # Copied from _gen_dmd.conf
+ -L--export-dynamic
+ -defaultlib=phobos2 # If unspecified, defaults to libphobos2.a
+ -fPIC
+ -L-L"${phobosDir}"
+ -L-rpath="${phobosDir}"
+
+ -conf= # Don't use dmd.conf
+ -m${MODEL}
+ -Iphobos
+ -Idmd/druntime/import
+ )
+
+ "${GENERATED_DMD}" "${commandArgs[@]}" dmd/compiler/samples/hello.d \
+ || die "Failed to build hello.d (${MODEL}-bit)"
+ ./hello ${MODEL}-bit || die "Failed to run test sample (${MODEL}-bit)"
+ }
+
+ _dmd_foreach_abi test_hello_world
+
+}
+
+dmd-r1_src_install() {
+ local EDC=${PN}-${SLOT} # overwrite the one from pkg_setup
+ local dmd_prefix=/usr/lib/${PN}/$(dlang_get_be_version)
+
+ dodir /etc/dmd
+ _gen_dmd.conf > "${ED}"/etc/dmd/${SLOT}.conf || die "Could not generate dmd.conf"
+ # Put a symlink to dmd.conf into the same folder as the dmd
+ # executable so it gets picked up automatically (and instead of
+ # /etc/dmd.conf).
+ dosym -r "/etc/dmd/${SLOT}.conf" "${dmd_prefix}/bin/dmd.conf"
+
+ into "${dmd_prefix}"
+ dobin "${GENERATED_DMD}"
+ dosym -r "${dmd_prefix}/bin/dmd" "/usr/bin/dmd-${SLOT}"
+
+ insinto "${dmd_prefix}"
+ doins -r dmd/druntime/import
+
+ # Old dmd.eclass installed the so to $(get_libdir) and symlinked it
+ # into ${dmd_prefix}. We do it the other way around.
+ install_phobos_2() {
+ local G=phobos/generated/linux/release/${MODEL}
+ into /usr
+
+ dlang_dolib.so "${G}"/libphobos2.so*
+ use static-libs && dlang_dolib.a "${G}"/libphobos2.a
+
+ # The symlinks under $(get_libdir) are only for backwards
+ # compatibility purposes.
+ local filename=libphobos2.so.0.${MINOR}
+ dosym -r "/usr/$(dlang_get_libdir)/${filename}" "/usr/$(get_libdir)/${filename}"
+ dosym -r "/usr/$(dlang_get_libdir)/${filename}.${PATCH}" "/usr/$(get_libdir)/${filename}.${PATCH}"
+ }
+ _dmd_foreach_abi install_phobos_2
+ insinto "${dmd_prefix}"/import
+ doins -r phobos/{etc,std}
+
+ insinto "${dmd_prefix}"/man/man1
+ doins dmd/generated/docs/man/man1/dmd.1
+ insinto "${dmd_prefix}"/man/man5
+ doins dmd/generated/docs/man/man5/dmd.conf.5
+
+ if use examples; then
+ insinto "${dmd_prefix}"/samples
+ doins -r dmd/compiler/samples/*
+ docompress -x "${dmd_prefix}"/samples
+ fi
+
+ if use doc; then
+ HTML_DOCS=( "${WORKDIR}"/dmd2/html/* )
+ einstalldocs
+ insinto "/usr/share/doc/${PF}/html"
+ doins "${FILESDIR}/dmd-doc.png"
+ make_desktop_entry "xdg-open ${EPREFIX}/usr/share/doc/${PF}/html/d/index.html" \
+ "DMD ${PV}" \
+ "${EPREFIX}/usr/share/doc/${PF}/html/dmd-doc.png" \
+ "Development"
+ fi
+}
+
+dmd-r1_pkg_postinst() {
+ "${EROOT}"/usr/bin/eselect dlang update dmd
+
+ use examples && elog "Examples can be found in: ${dmd_prefix}/samples"
+ use doc && elog "HTML documentation is in: /usr/share/doc/${PF}/html"
+
+ optfeature "additional D development tools" "dev-util/dlang-tools"
+}
+
+dmd-r1_pkg_postrm() {
+ "${ERROT}"/usr/bin/eselect dlang update dmd
+}
+
+# @FUNCTION: _gen_dmd.conf
+# @INTERNAL
+# @DESCRIPTION:
+# Print a dmd.conf to be installed on the user system. Needs $EDC to be
+# set up up beforehand.
+_gen_dmd.conf() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ # Note, the logic for which libdir is used is all kept in
+ # dlang-utils.eclass in order not to duplicate code.
+
+ local import_dir=${EPREFIX}/usr/lib/${PN}/$(dlang_get_be_version)/import
+ # Should this, instead, check which ABIs have been enabled?
+ if has_multilib_profile; then
+ local libdir_amd64=${EPREFIX}/usr/$(ABI=amd64 dlang_get_libdir)
+ local libdir_x86=${EPREFIX}/usr/$(ABI=x86 dlang_get_libdir)
+ cat <<EOF
+[Environment]
+DFLAGS=-I${import_dir} -L--export-dynamic -defaultlib=phobos2 -fPIC
+[Environment32]
+DFLAGS=%DFLAGS% -L-L${libdir_x86} -L-rpath=${libdir_x86}
+[Environment64]
+DFLAGS=%DFLAGS% -L-L${libdir_amd64} -L-rpath=${libdir_amd64}
+EOF
+
+ else
+ local libdir=${EPREFIX}/usr/$(dlang_get_libdir)
+ cat <<EOF
+[Environment]
+DFLAGS=-I${import_dir} -L--export-dynamic -defaultlib=phobos2 -fPIC -L-L${libdir} -L-rpath=${libdir}
+EOF
+
+ fi
+}
+
+# @FUNCTION: _get_abi_bits
+# @USAGE: [<abi>]
+# @INTERNAL
+# @DESCRIPTION:
+# Echo the bits of abi, 64 for amd64 and 32 for x86. If unspecified, the
+# value is taken from $ABI.
+_get_abi_bits() {
+ case "${1:-${ABI}}" in
+ amd64*) echo 64 ;;
+ x86*) echo 32 ;;
+ *) die "Unknown ABI: ${ABI}." ;;
+ esac
+}
+
+# @FUNCTION: _dmd_foreach_abi
+# @USAGE: <cmd> [<args>...]
+# @INTERNAL
+# @DESCRIPTION:
+# Run a command for each enabled ABI, similar to multilib_foreach_abi but
+# without setting $BUILD_DIR. Sets up $ABI and $MODEL (bits)
+# appropriately.
+_dmd_foreach_abi() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ local ABI
+ for ABI in $(multilib_get_enabled_abis); do
+ local MODEL=$(_get_abi_bits)
+ einfo "Executing ${1} in ${MODEL}-bit"
+ "${@}"
+ done
+}
+
+fi
+
+EXPORT_FUNCTIONS pkg_setup src_unpack src_prepare src_compile src_test src_install \
+ pkg_postinst pkg_postrm