From d2bac19750507c10fcb4c3a92017cdec03184885 Mon Sep 17 00:00:00 2001
From: Juan RP <xtraeme@voidlinux.eu>
Date: Wed, 27 Apr 2016 20:16:59 +0200
Subject: [PATCH] xbps-src: re-introduce etc/virtual.

The `etc/virtual` file declares the default package to be built for
virtual dependencies declared as "virtual?foo" in $depends.

Before this change, the run-time dependency was added as is to the final
binary package but no pkg providing this virtual pkg was built.

With this file we declare the *default* pkg to be built.

NOTE: "virtual?foo" is only applicable to *run* time dependencies, i.e
only those declared in $depends.
---
 README.md                                     |   8 +
 .../hooks/pre-pkg/04-generate-runtime-deps.sh | 317 +++++++++---------
 common/xbps-src/shutils/build_dependencies.sh |  69 ++--
 etc/defaults.virtual                          |  27 ++
 4 files changed, 248 insertions(+), 173 deletions(-)
 create mode 100644 etc/defaults.virtual

diff --git a/README.md b/README.md
index 93505ee7d0a..484d068266a 100644
--- a/README.md
+++ b/README.md
@@ -118,6 +118,14 @@ Native and cross compiler/linker flags are set per architecture in `common/build
 and `common/cross-profiles` respectively. Ideally those settings are good enough by default,
 and there's no need to set your own unless you know what you are doing.
 
+#### Virtual packages
+
+The `etc/defaults.virtual` file contains the default replacements for virtual packages,
+used as dependencies in the source packages tree.
+
+If you want to customize those replacements, copy `etc/defaults.virtual` to `etc/virtual`
+and edit it accordingly to your needs.
+
 ### Directory hierarchy
 
 The following directory hierarchy is used with a default configuration file:
diff --git a/common/hooks/pre-pkg/04-generate-runtime-deps.sh b/common/hooks/pre-pkg/04-generate-runtime-deps.sh
index 9a6cc592e4c..17616de77f8 100644
--- a/common/hooks/pre-pkg/04-generate-runtime-deps.sh
+++ b/common/hooks/pre-pkg/04-generate-runtime-deps.sh
@@ -1,170 +1,181 @@
+# vim: set ts=4 sw=4 et:
+#
 # This hook executes the following tasks:
-#	- Generates rdeps file with run-time dependencies for xbps-create(8)
-#	- Generates shlib-requires file for xbps-create(8)
+#	- Generates rdeps file with run-time dependencies for xbps-create(1)
+#	- Generates shlib-requires file for xbps-create(1)
 
 add_rundep() {
-	local dep="$1" i= rpkgdep= _depname= _rdeps= found=
+    local dep="$1" i= rpkgdep= _depname= _rdeps= found=
 
-	_depname="$($XBPS_UHELPER_CMD getpkgdepname ${dep} 2>/dev/null)"
-	if [ -z "${_depname}" ]; then
-		_depname="$($XBPS_UHELPER_CMD getpkgname ${dep} 2>/dev/null)"
-	fi
+    _depname="$($XBPS_UHELPER_CMD getpkgdepname ${dep} 2>/dev/null)"
+    if [ -z "${_depname}" ]; then
+        _depname="$($XBPS_UHELPER_CMD getpkgname ${dep} 2>/dev/null)"
+    fi
 
-	for i in ${run_depends}; do
-		rpkgdep="$($XBPS_UHELPER_CMD getpkgdepname $i 2>/dev/null)"
-		if [ -z "$rpkgdep" ]; then
-			rpkgdep="$($XBPS_UHELPER_CMD getpkgname $i 2>/dev/null)"
-		fi
-		if [ "${rpkgdep}" != "${_depname}" ]; then
-			continue
-		fi
-		$XBPS_UHELPER_CMD cmpver "$i" "$dep"
-		rval=$?
-		if [ $rval -eq 255 ]; then
-			run_depends="${run_depends/${i}/${dep}}"
-		fi
-		found=1
-	done
-	if [ -z "$found" ]; then
-		run_depends+=" ${dep}"
-	fi
+    for i in ${run_depends}; do
+        rpkgdep="$($XBPS_UHELPER_CMD getpkgdepname $i 2>/dev/null)"
+        if [ -z "$rpkgdep" ]; then
+            rpkgdep="$($XBPS_UHELPER_CMD getpkgname $i 2>/dev/null)"
+        fi
+        if [ "${rpkgdep}" != "${_depname}" ]; then
+            continue
+        fi
+        $XBPS_UHELPER_CMD cmpver "$i" "$dep"
+        rval=$?
+        if [ $rval -eq 255 ]; then
+            run_depends="${run_depends/${i}/${dep}}"
+        fi
+        found=1
+    done
+    if [ -z "$found" ]; then
+        run_depends+=" ${dep}"
+    fi
+}
+
+store_pkgdestdir_rundeps() {
+        if [ -n "$run_depends" ]; then
+            : > ${PKGDESTDIR}/rdeps
+            for f in ${run_depends}; do
+                _curdep="$(echo "$f" | sed -e 's,\(.*\)?.*,\1,')"
+                if [ -z "$($XBPS_UHELPER_CMD getpkgdepname ${_curdep} 2>/dev/null)" -a \
+                     -z "$($XBPS_UHELPER_CMD getpkgname ${_curdep} 2>/dev/null)" ]; then
+                    _curdep="${_curdep}>=0"
+                fi
+                printf "${_curdep} " >> ${PKGDESTDIR}/rdeps
+            done
+        fi
 }
 
 hook() {
-	local depsftmp f j tmplf mapshlibs sorequires
+    local depsftmp f j tmplf mapshlibs sorequires _curdep
 
-	# Disable trap on ERR, xbps-uhelper cmd might return error... but not something
-	# to be worried about because if there are broken shlibs this hook returns
-	# error via msg_error().
-	trap - ERR
+    # Disable trap on ERR, xbps-uhelper cmd might return error... but not something
+    # to be worried about because if there are broken shlibs this hook returns
+    # error via msg_error().
+    trap - ERR
 
-	mapshlibs=$XBPS_COMMONDIR/shlibs
-	tmplf=$XBPS_SRCPKGDIR/$pkgname/template
+    mapshlibs=$XBPS_COMMONDIR/shlibs
+    tmplf=$XBPS_SRCPKGDIR/$pkgname/template
 
-	if [ -n "$noarch" -o -n "$noverifyrdeps" ]; then
-		echo "$run_depends" > ${PKGDESTDIR}/rdeps
-		sed 's,virtual?,,g' -i ${PKGDESTDIR}/rdeps
-		return 0
-	fi
+    if [ -n "$noarch" -o -n "$noverifyrdeps" ]; then
+        store_pkgdestdir_rundeps
+        return 0
+    fi
 
-	depsftmp=$(mktemp -t xbps_src_depstmp.XXXXXXXXXX) || return 1
-	find ${PKGDESTDIR} -type f -perm -u+w > $depsftmp 2>/dev/null
+    depsftmp=$(mktemp -t xbps_src_depstmp.XXXXXXXXXX) || return 1
+    find ${PKGDESTDIR} -type f -perm -u+w > $depsftmp 2>/dev/null
 
-	exec 3<&0 # save stdin
-	exec < $depsftmp
-	while read f; do
-		case "$(file -bi "$f")" in
-			application/x-executable*|application/x-sharedlib*)
-				for nlib in $($OBJDUMP -p "$f"|grep NEEDED|awk '{print $2}'); do
-					if [ -z "$verify_deps" ]; then
-						verify_deps="$nlib"
-						continue
-					fi
-					for j in ${verify_deps}; do
-						[ "$j" != "$nlib" ] && continue
-						found_dup=1
-						break
-					done
-					if [ -z "$found_dup" ]; then
-						verify_deps="$verify_deps $nlib"
-					fi
-					unset found_dup
-				done
-				;;
-		esac
-	done
-	exec 0<&3 # restore stdin
-	rm -f $depsftmp
+    exec 3<&0 # save stdin
+    exec < $depsftmp
+    while read f; do
+        case "$(file -bi "$f")" in
+            application/x-executable*|application/x-sharedlib*)
+                for nlib in $($OBJDUMP -p "$f"|grep NEEDED|awk '{print $2}'); do
+                    if [ -z "$verify_deps" ]; then
+                        verify_deps="$nlib"
+                        continue
+                    fi
+                    for j in ${verify_deps}; do
+                        [ "$j" != "$nlib" ] && continue
+                        found_dup=1
+                        break
+                    done
+                    if [ -z "$found_dup" ]; then
+                        verify_deps="$verify_deps $nlib"
+                    fi
+                    unset found_dup
+                done
+                ;;
+        esac
+    done
+    exec 0<&3 # restore stdin
+    rm -f $depsftmp
 
-	#
-	# Add required run time packages by using required shlibs resolved
-	# above, the mapping is done thru the mapping_shlib_binpkg.txt file.
-	#
-	for f in ${verify_deps}; do
-		unset _f j rdep _rdep rdepcnt soname _pkgname _rdepver found
-		_f=$(echo "$f"|sed -E 's|\+|\\+|g')
-		rdep="$(grep -E "^${_f}[[:blank:]]+.*$" $mapshlibs|awk '{print $2}')"
-		rdepcnt="$(grep -E "^${_f}[[:blank:]]+.*$" $mapshlibs|awk '{print $2}'|wc -l)"
-		if [ -z "$rdep" ]; then
-			# Ignore libs by current pkg
-			soname=$(find ${PKGDESTDIR} -name "$f")
-			if [ -z "$soname" ]; then
-				msg_red_nochroot "   SONAME: $f <-> UNKNOWN PKG PLEASE FIX!\n"
-				broken=1
-			else
-				echo "   SONAME: $f <-> $pkgname (ignored)"
-			fi
-			continue
-		elif [ "$rdepcnt" -gt 1 ]; then
-			unset j found
-			# Check if shlib is provided by multiple pkgs.
-			for j in ${rdep}; do
-				_pkgname=$($XBPS_UHELPER_CMD getpkgname "$j")
-				# if there's a SONAME matching pkgname, use it.
-				for x in ${pkgname} ${subpackages}; do
-					if [ "${_pkgname}" = "${x}" ]; then
-						found=1
-						break
-					fi
-				done
-				if [ -n "$found" ]; then
-					_rdep=$j
-					break
-				fi
-			done
-			if [ -z "${_rdep}" ]; then
-				# otherwise pick up the first one.
-				for j in ${rdep}; do
-					[ -z "${_rdep}" ] && _rdep=$j
-				done
-			fi
-		else
-			_rdep=$rdep
-		fi
-		_pkgname=$($XBPS_UHELPER_CMD getpkgname "${_rdep}" 2>/dev/null)
-		_rdepver=$($XBPS_UHELPER_CMD getpkgversion "${_rdep}" 2>/dev/null)
-		if [ -z "${_pkgname}" -o -z "${_rdepver}" ]; then
-			msg_red_nochroot "   SONAME: $f <-> UNKNOWN PKG PLEASE FIX!\n"
-			broken=1
-			continue
-		fi
-		# Check if pkg is a subpkg of sourcepkg; if true, ignore version
-		# in common/shlibs.
-		_sdep="${_pkgname}>=${_rdepver}"
-		for _subpkg in ${subpackages}; do
-			if [ "${_subpkg}" = "${_pkgname}" ]; then
-				_sdep="${_pkgname}-${version}_${revision}"
-				break
-			fi
-		done
+    #
+    # Add required run time packages by using required shlibs resolved
+    # above, the mapping is done thru the mapping_shlib_binpkg.txt file.
+    #
+    for f in ${verify_deps}; do
+        unset _f j rdep _rdep rdepcnt soname _pkgname _rdepver found
+        _f=$(echo "$f"|sed -E 's|\+|\\+|g')
+        rdep="$(grep -E "^${_f}[[:blank:]]+.*$" $mapshlibs|awk '{print $2}')"
+        rdepcnt="$(grep -E "^${_f}[[:blank:]]+.*$" $mapshlibs|awk '{print $2}'|wc -l)"
+        if [ -z "$rdep" ]; then
+            # Ignore libs by current pkg
+            soname=$(find ${PKGDESTDIR} -name "$f")
+            if [ -z "$soname" ]; then
+                msg_red_nochroot "   SONAME: $f <-> UNKNOWN PKG PLEASE FIX!\n"
+                broken=1
+            else
+                echo "   SONAME: $f <-> $pkgname (ignored)"
+            fi
+            continue
+        elif [ "$rdepcnt" -gt 1 ]; then
+            unset j found
+            # Check if shlib is provided by multiple pkgs.
+            for j in ${rdep}; do
+                _pkgname=$($XBPS_UHELPER_CMD getpkgname "$j")
+                # if there's a SONAME matching pkgname, use it.
+                for x in ${pkgname} ${subpackages}; do
+                    if [ "${_pkgname}" = "${x}" ]; then
+                        found=1
+                        break
+                    fi
+                done
+                if [ -n "$found" ]; then
+                    _rdep=$j
+                    break
+                fi
+            done
+            if [ -z "${_rdep}" ]; then
+                # otherwise pick up the first one.
+                for j in ${rdep}; do
+                    [ -z "${_rdep}" ] && _rdep=$j
+                done
+            fi
+        else
+            _rdep=$rdep
+        fi
+        _pkgname=$($XBPS_UHELPER_CMD getpkgname "${_rdep}" 2>/dev/null)
+        _rdepver=$($XBPS_UHELPER_CMD getpkgversion "${_rdep}" 2>/dev/null)
+        if [ -z "${_pkgname}" -o -z "${_rdepver}" ]; then
+            msg_red_nochroot "   SONAME: $f <-> UNKNOWN PKG PLEASE FIX!\n"
+            broken=1
+            continue
+        fi
+        # Check if pkg is a subpkg of sourcepkg; if true, ignore version
+        # in common/shlibs.
+        _sdep="${_pkgname}>=${_rdepver}"
+        for _subpkg in ${subpackages}; do
+            if [ "${_subpkg}" = "${_pkgname}" ]; then
+                _sdep="${_pkgname}-${version}_${revision}"
+                break
+            fi
+        done
 
-		if [ "${_pkgname}" != "${pkgname}" ]; then
-			echo "   SONAME: $f <-> ${_sdep}"
-			sorequires+="${f} "
-		else
-			# Ignore libs by current pkg
-			echo "   SONAME: $f <-> ${_rdep} (ignored)"
-			continue
-		fi
-		add_rundep "${_sdep}"
-	done
-	#
-	# If pkg uses any unknown SONAME error out.
-	#
-	if [ -n "$broken" -a -z "$allow_unknown_shlibs" ]; then
-		msg_error "$pkgver: cannot guess required shlibs, aborting!\n"
-	fi
+        if [ "${_pkgname}" != "${pkgname}" ]; then
+            echo "   SONAME: $f <-> ${_sdep}"
+            sorequires+="${f} "
+        else
+            # Ignore libs by current pkg
+            echo "   SONAME: $f <-> ${_rdep} (ignored)"
+            continue
+        fi
+        add_rundep "${_sdep}"
+    done
+    #
+    # If pkg uses any unknown SONAME error out.
+    #
+    if [ -n "$broken" -a -z "$allow_unknown_shlibs" ]; then
+        msg_error "$pkgver: cannot guess required shlibs, aborting!\n"
+    fi
 
-	if [ -n "$run_depends" ]; then
-		echo "$run_depends" > ${PKGDESTDIR}/rdeps
-	fi
-	if [ -s ${PKGDESTDIR}/rdeps ]; then
-		sed 's,virtual?,,g' -i ${PKGDESTDIR}/rdeps
-	fi
-	for f in ${shlib_requires}; do
-		sorequires+="${f} "
-	done
-	if [ -n "${sorequires}" ]; then
-		echo "${sorequires}" > ${PKGDESTDIR}/shlib-requires
-	fi
+    store_pkgdestdir_rundeps
+
+    for f in ${shlib_requires}; do
+        sorequires+="${f} "
+    done
+    if [ -n "${sorequires}" ]; then
+        echo "${sorequires}" > ${PKGDESTDIR}/shlib-requires
+    fi
 }
diff --git a/common/xbps-src/shutils/build_dependencies.sh b/common/xbps-src/shutils/build_dependencies.sh
index 8f96265f4b7..958782c21af 100644
--- a/common/xbps-src/shutils/build_dependencies.sh
+++ b/common/xbps-src/shutils/build_dependencies.sh
@@ -17,15 +17,30 @@ setup_pkg_depends() {
         if [ -z "${_pkgdepname}" ]; then
             _pkgdepname="$($XBPS_UHELPER_CMD getpkgname ${_depname} 2>/dev/null)"
         fi
-        if [ -z "${_pkgdepname}" ]; then
-            _pkgdep="${_depname}>=0"
-        else
-            _pkgdep="${_depname}"
+        if [ -s ${XBPS_DISTDIR}/etc/virtual ]; then
+            _replacement=$(egrep "^${_pkgdepname:-${_depname}}[[:blank:]]" ${XBPS_DISTDIR}/etc/virtual|cut -d ' ' -f2)
+        elif [ -s ${XBPS_DISTDIR}/etc/defaults.virtual ]; then
+            _replacement=$(egrep "^${_pkgdepname:-${_depname}}[[:blank:]]" ${XBPS_DISTDIR}/etc/defaults.virtual|cut -d ' ' -f2)
         fi
-
         if [ "${_rpkgname}" = "virtual" ]; then
-            run_depends+=" virtual?${_pkgdep}"
+            if [ -z "${_replacement}" ]; then
+                msg_error "$pkgver: failed to resolve virtual dependency for '$j' (missing from etc/virtual)\n"
+            fi
+            _pkgdepname="$($XBPS_UHELPER_CMD getpkgdepname ${_replacement} 2>/dev/null)"
+            if [ -z "${_pkgdepname}" ]; then
+                _pkgdepname="$($XBPS_UHELPER_CMD getpkgname ${_replacement} 2>/dev/null)"
+            fi
+            if [ -z "${_pkgdepname}" ]; then
+                _pkgdepname="${_replacement}>=0"
+            fi
+            run_depends+=" ${_depname}?${_pkgdepname}"
+            #echo "Adding dependency virtual:  ${_depname}?${_pkgdepname}"
         else
+            if [ -z "${_pkgdepname}" ]; then
+                _pkgdep="${_depname}>=0"
+            else
+                _pkgdep="${_depname}"
+            fi
             run_depends+=" ${_pkgdep}"
         fi
     done
@@ -144,9 +159,9 @@ srcpkg_get_version() {
     local pkg="$1"
     # Run this in a sub-shell to avoid polluting our env.
     (
-        unset XBPS_BINPKG_EXISTS
-        setup_pkg $pkg || exit $?
-        echo "${version}_${revision}"
+    unset XBPS_BINPKG_EXISTS
+    setup_pkg $pkg || exit $?
+    echo "${version}_${revision}"
     ) || msg_error "$pkgver: failed to transform dependency $pkg\n"
 }
 
@@ -154,9 +169,9 @@ srcpkg_get_pkgver() {
     local pkg="$1"
     # Run this in a sub-shell to avoid polluting our env.
     (
-        unset XBPS_BINPKG_EXISTS
-        setup_pkg $pkg || exit $?
-        echo "${sourcepkg}-${version}_${revision}"
+    unset XBPS_BINPKG_EXISTS
+    setup_pkg $pkg || exit $?
+    echo "${sourcepkg}-${version}_${revision}"
     ) || msg_error "$pkgver: failed to transform dependency $pkg\n"
 }
 
@@ -165,7 +180,7 @@ srcpkg_get_pkgver() {
 #
 install_pkg_deps() {
     local pkg="$1" targetpkg="$2" target="$3" cross="$4" cross_prepare="$5"
-    local rval _realpkg curpkgdepname pkgn iver
+    local rval _realpkg _vpkg _curpkg curpkgdepname pkgn iver
     local i j found rundep repo
 
     local -a host_binpkg_deps binpkg_deps host_missing_deps missing_deps missing_rdeps
@@ -259,10 +274,12 @@ install_pkg_deps() {
     #
     for i in ${run_depends}; do
         _realpkg="${i%\?*}"
-        if [ "${_realpkg}" = "virtual" ]; then
-            # ignore virtual dependencies
-            echo "   [runtime] ${i#*\?}: virtual dependency."
-            continue
+        _curpkg="${_realpkg}"
+        _vpkg="${i#*\?}"
+        if [ "${_realpkg}" != "${_vpkg}" ]; then
+            _realpkg="${_vpkg}"
+        else
+            unset _curpkg
         fi
         pkgn=$($XBPS_UHELPER_CMD getpkgdepname "${_realpkg}")
         if [ -z "$pkgn" ]; then
@@ -282,15 +299,27 @@ install_pkg_deps() {
             set -- ${_props}
             $XBPS_UHELPER_CMD pkgmatch ${1} "${_realpkg}"
             if [ $? -eq 1 ]; then
-                echo "   [runtime] ${_realpkg}: found ($2)"
+                if [ -n "${_curpkg}" ]; then
+                    echo "   [runtime] ${_curpkg}:${_realpkg} (virtual dependency): found $1 ($2)"
+                else
+                    echo "   [runtime] ${_realpkg}: found $1 ($2)"
+                fi
                 shift 2
                 continue
             else
-                echo "   [runtime] ${_realpkg}: not found."
+                if [ -n "${_curpkg}" ]; then
+                    echo "   [runtime] ${_curpkg}:${_realpkg} (virtual dependency): not found."
+                else
+                    echo "   [runtime] ${_realpkg}: not found."
+                fi
             fi
             shift 2
         else
-            echo "   [runtime] ${_realpkg}: not found."
+            if [ -n "${_curpkg}" ]; then
+                echo "   [runtime] ${_curpkg}:${_realpkg} (virtual dependency): not found."
+            else
+                echo "   [runtime] ${_realpkg}: not found."
+            fi
         fi
         missing_rdeps+=("${_realpkg}")
     done
diff --git a/etc/defaults.virtual b/etc/defaults.virtual
new file mode 100644
index 00000000000..1a980002b3f
--- /dev/null
+++ b/etc/defaults.virtual
@@ -0,0 +1,27 @@
+# --*-- shell --*--
+#
+# etc/defaults.virtual
+#      default configuration of etc/virtual
+#
+# DO NOT EDIT THIS FILE DIRECTLY; IT MAY BE REPLACED DURING UPDATES,
+# EDIT etc/virtual INSTEAD.
+#
+# This file specifies a mapping between virtual packages and real packages
+# available in the source packages collection (srcpkgs).
+#
+# The format uses 2 arguments delimited by a blank: <vpkgname> <realpkgname>
+#
+# When building a package with "xbps-src", those dependencies declared like
+# "virtual?foo" will use the replacement package defined in `etc/virtual`.
+#
+# NOTE: this mapping is only there to be able to build a default package
+#       to resolve the virtual package dependency later on with xbps-install(1).
+#
+# NOTE: Create your own etc/virtual file to override these defaults.
+
+awk gawk
+java-environment openjdk
+java-runtime openjdk-jre
+ntp-daemon chrony
+xserver-abi-input xorg-server
+xserver-abi-video xorg-server