commit: 8468c732604cf2a0827c0025534173f4276b05f6 Author: Horodniceanu Andrei <a.horodniceanu <AT> proton <DOT> me> AuthorDate: Tue Oct 17 06:47:24 2023 +0000 Commit: Horodniceanu Andrei <a.horodniceanu <AT> proton <DOT> me> CommitDate: Sun Oct 29 10:59:45 2023 +0000 URL: https://gitweb.gentoo.org/repo/user/dlang.git/commit/?id=8468c732
scripts: update-gdc-versions.sh support gdc-SLOT USE flags Other changes: - added an usage header - option -a can be used to test all relevant gcc ebuilds - fixed typoes Closes: https://github.com/gentoo/dlang/pull/126 Signed-off-by: Horodniceanu Andrei <a.horodniceanu <AT> proton.me> scripts/update-gdc-versions.sh | 205 ++++++++++++++++++++++++++--------------- 1 file changed, 131 insertions(+), 74 deletions(-) diff --git a/scripts/update-gdc-versions.sh b/scripts/update-gdc-versions.sh index 4b0050f..e3a33b4 100755 --- a/scripts/update-gdc-versions.sh +++ b/scripts/update-gdc-versions.sh @@ -2,6 +2,26 @@ # Copyright 2023 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 +###### Usage ###### +# ./update-gdc-versions.sh [-a] +# +# Update all gdc related variables in this overlay: +# 1. gdmd keywords +# 2. dlang-compilers.eclass +# 3. use.desc +# based on the gcc versions currently available in ::gentoo. +# +# You will be prompted for you sudo/doas password at the end to +# extract the dmd version from the gcc sources because the ebuild +# command requires elevated privileges. Alternatively you may run this +# script as root. +# +# By default, only 1 gcc version for each gdmd slot needs to be +# extracted. Otherwise, when the -a option is passed, force check of +# (almost) all gcc ebuilds. This will prompt for your sudo/doas password +# more so it may be worth to run the script as root in this case. +###### End Usage ###### + # This script uses various utilities from app-portage/portage-utils # No -u because /lib/gentoo/functions.sh doesn't work with it @@ -14,11 +34,12 @@ REPO="$(dirname "${0}")" cd "${REPO}/.." readonly EROOT=$(portageq envvar EROOT) readonly PORTDIR=$(portageq get_repo_path "${EROOT}" gentoo) +[[ ${1} == "-a" ]] && readonly CHECK_ALL=1 || readonly CHECK_ALL=0 # Associative array betwen gcc $PVRs and their keywords declare -A GCC_TO_KEYWORDS # Associative array between gcc slots (gdmd versions) and a combination -# of the keywords of each gcc version is said slot. +# of the keywords of each gcc version in said slot. declare -A SLOT_TO_KEYWORDS # Program to use for running privileged commands. # The user may specify this manually, or it will be autodetected. @@ -40,7 +61,7 @@ keyword_to_arch () { } keyword_to_stability () { - [[ $# -ne 1 ]] && die "Internal error: Passed $# arguments to ${FUNCNAME}" + [[ $# -ne 1 ]] && die "Internal error: Passed $# arguments to ${FUNCNAME}, expected 1" if [[ ${1:0:1} = '-' ]]; then echo 0 @@ -56,7 +77,7 @@ keyword_to_stability () { # ~amd64 - unstable # -amd64 - disabled combine_arch_keywords () { - [[ $# -ne 2 ]] && die "Internal error: Passed $# arguments to ${FUNCNAME}" + [[ $# -ne 2 ]] && die "Internal error: Passed $# arguments to ${FUNCNAME}, expected 2" local k1="${1}" k2="${2}" [[ $(keyword_to_arch $k1) != $(keyword_to_arch $k2) ]] && \ die "Internal error: ${FUNCNAME} got keywords for difference arches" @@ -75,7 +96,7 @@ combine_arch_keywords () { # Given 2 list of keywords returns a new list with the most stable keywords taken # from both lists combine_keywords () { - [[ $# -ne 2 ]] && die "Internal error: Passed $# arguments to ${FUNCNAME}" + [[ $# -ne 2 ]] && die "Internal error: Passed $# arguments to ${FUNCNAME}, exptected 2" local v1=($1) v2=($2) # We want the expansion # We take advantage that the keyword arrays are sorted @@ -85,23 +106,23 @@ combine_keywords () { local result=() while (( i < n && j < m )); do - local a1=$(keyword_to_arch "${v1[$i]}") - local a2=$(keyword_to_arch "${v2[$j]}") + local a1=$(keyword_to_arch "${v1[i]}") + local a2=$(keyword_to_arch "${v2[j]}") if [[ $a1 = $a2 ]]; then - result+=("$(combine_arch_keywords "${v1[$i]}" "${v2[$j]}")") + result+=("$(combine_arch_keywords "${v1[i]}" "${v2[j]}")") ((++i, ++j)) || true elif [[ $a1 < $a2 ]]; then - result+=("${v1[$i]}") + result+=("${v1[i]}") ((++i)) || true else - result+=("${v2[$j]}") + result+=("${v2[j]}") ((++j)) || true fi done - result+=("${v1[@]:$i}") - result+=("${v2[@]:$j}") + result+=("${v1[@]:i}") + result+=("${v2[@]:j}") echo "${result[@]}" } @@ -110,7 +131,7 @@ combine_keywords () { # $1 can either be a gcc slot of a gcc version, they are both calculated # in the same way. can_handle () { - [[ $# -ne 1 ]] && die "Internal error: Passed $# arguments to ${FUNCNAME}" + [[ $# -ne 1 ]] && die "Internal error: Passed $# arguments to ${FUNCNAME}, exptected 1" local slot="${1%%\.*}" @@ -136,6 +157,48 @@ asroot () { ${SUDO} "${@}" } +# Get the dmd version from a gcc PVR +get_gcc_dmd_version () { + [[ $# -ne 1 ]] && die "Internal error: Passed $# arguments to ${FUNCNAME}, expected 1" + version="${1}" + + ebuild="${PORTDIR}/sys-devel/gcc/gcc-${version}.ebuild" + # Pass the ebuild output on stderr + asroot ebuild "${ebuild}" unpack >&2 + + prefix="$(portageq envvar PORTAGE_TMPDIR)/portage/sys-devel/gcc-${version}" + + # Make /var/tmp/portage/sys-devel/gcc* traversable for the normal user + # to prevent asking for the root password for each file we want to check. + asroot chmod +rx "${prefix}" "${prefix}/work" >&2 + + # I don't know another way to explicitly expand the * + path=$(echo "${prefix}/work/gcc-"*/gcc/d/dmd/VERSION) + + if [[ -f ${path} ]]; then + dmdVersion=$(cat "${path}") + # The version in $path looks like: v2.100.1 or v2.103.0-rc.1 + dmdVersion=${dmdVersion#v} + dmdVersion=${dmdVersion%-*} # In case there's a -rc.x component + dmdVersion=${dmdVersion%.*} + else + # This one is always present + merge_file=$(echo "${prefix}/work/gcc-"*/gcc/d/dmd/MERGE) + [[ ! -f ${merge_file} ]] && die "Can not access '${merge_file}'" + if [[ $(head -n1 ${merge_file}) = "0450061c8de71328815da9323bd35c92b37d51d2" ]]; then + # A common commit id with dmd version 2.076 + dmdVersion="2.076" + else + dmdVersion="<CHANGEME>" + fi + fi + + asroot ebuild "${ebuild}" clean >&2 + + echo "${dmdVersion}" +} + +# Find the keywords for each gcc ebuild (that support d) while read -r keywords; do filename="${keywords%:*}" keywords="${keywords#*KEYWORDS=\"}" @@ -160,6 +223,7 @@ while read -r keywords; do done < <(egrep "^\s*KEYWORDS" "${PORTDIR}/sys-devel/gcc/gcc"*) +# Merge all the KEYWORDS in a slot into a single list for version in "${!GCC_TO_KEYWORDS[@]}"; do slot="${version%%\.*}" @@ -172,62 +236,65 @@ for version in "${!GCC_TO_KEYWORDS[@]}"; do fi done -###### Modify keywords for each gdmd ebuild ####### +###### Modify keywords for each gdmd ebuild and gdc USE flags ####### +declare -a GDC_TARGETS for slot in "${!SLOT_TO_KEYWORDS[@]}"; do if ! can_handle "${slot}"; then continue; fi file="dev-util/gdmd/gdmd-${slot}.ebuild" sed -i -e 's/^KEYWORDS=.*$/KEYWORDS="'"${SLOT_TO_KEYWORDS[$slot]}"'"/' "${file}" -done -##### Calculate gdc frontends ##### -declare -a GDC_TARGETS -for version in "${!GCC_TO_KEYWORDS[@]}"; do - if ! can_handle "${version}"; then continue; fi - # For a gdc USE flag, we need only the package version (i.e. no -r* sufix) - pv="${version%-r*}" - - ebuild="${PORTDIR}/sys-devel/gcc/gcc-${version}.ebuild" - asroot ebuild "${ebuild}" unpack - - prefix="$(portageq envvar PORTAGE_TMPDIR)/portage/sys-devel/gcc-${version}" - - # Make /var/tmp/portage/sys-devel/gcc* traversable for the normal user - # to prevent asking for the root password for each file we want to check. - asroot chmod +rx "${prefix}" "${prefix}/work" + if [[ ${CHECK_ALL} == 0 ]]; then + atom="$(portageq best_visible "${EROOT}" "sys-devel/gcc:${slot}")" + version="${atom##*-}" - # I don't know how to expand the string properly, without bash quiting due to the error of not finding the path - path=$(echo "${prefix}/work/gcc-"*/gcc/d/dmd/VERSION) + dmdVersion="$(get_gcc_dmd_version "${version}")" + [[ -z ${dmdVersion} ]] && dmdVersion="<CHANGEME>" - if [[ -f ${path} ]]; then - dmdVersion=$(cat "${path}") - # The version in $path looks like: v2.100.1 or v2.103.0-rc.1 - dmdVersion=${dmdVersion#v} - dmdVersion=${dmdVersion%-*} # In case there's a -rc.x component - dmdVersion=${dmdVersion%.*} + # We skip adding the [" that should be at the begining so we + # can properly sort the array later. + GDC_TARGETS+=("${slot}\"]=\"${dmdVersion} ${SLOT_TO_KEYWORDS[${slot}]}\"") else - # This one is always present - merge_file=$(echo "${prefix}/work/gcc-"*/gcc/d/dmd/MERGE) - [[ ! -f ${merge_file} ]] && die "Can not access '${merge_file}'" - if [[ $(head -n1 ${merge_file}) = "0450061c8de71328815da9323bd35c92b37d51d2" ]]; then - # A common commit id with dmd version 2.076 - dmdVersion="2.076" - else - dmdVersion="<CHANGEME>" - fi + # Avoid multiple extractions for the same ebuild. + # Let the code below generate the targets + : fi - - # For the format of an element look in eclass/dlang-compilers.eclass. - - # Don't add the [" that should be at the beggining of an element - # because we will need to sort the array and `sort -n` doesn't like - # the leading non-numerical characters. - # We will add [" later. - GDC_TARGETS+=("${pv}\"]=\"${dmdVersion} ${GCC_TO_KEYWORDS[$version]}\"") - - asroot ebuild "${ebuild}" clean done +###### Verify all gcc ebuilds ###### +if [[ ${CHECK_ALL} == 1 ]]; then + # Theoretically, we only need to check 1 version for each slot but, + # for safety, check them all and see if all versions in 1 slot + # have the same dmd version. + declare -A SLOT_TO_DMD_VERSIONS + for version in "${!GCC_TO_KEYWORDS[@]}"; do + if ! can_handle "${version}"; then continue; fi + slot="${version%%\.*}" + dmdVersion="$(get_gcc_dmd_version "${version}")" + + if [[ ! -v SLOT_TO_DMD_VERSIONS[${slot}] ]]; then + # First time seeing a version for $slot, not much to check. + SLOT_TO_DMD_VERSIONS[${slot}]="${dmdVersion}" + + # Don't forget that we also have to generate GDC_TARGETS. + if can_handle "${slot}"; then + # Same notes as above. + GDC_TARGETS+=("${slot}\"]=\"${dmdVersion} ${SLOT_TO_KEYWORDS[${slot}]}\"") + fi + else + # We know what dmdVersion should be for a slot. + if [[ ${SLOT_TO_DMD_VERSIONS[${slot}]} != ${dmdVersion} ]]; then + eerror "Found multiple dmd versions in the same slot ${slot}." + eerror "Did gcc's policies change?" + die "Assumptions by this script about gcc slots were not met" + else + # All good :) + : + fi + fi + done +fi + # Sort the GDC_TARGETS array IFS=$'\n' GDC_TARGETS=($(sort -n <<<"${GDC_TARGETS[*]}")) unset IFS @@ -249,21 +316,12 @@ perl -0777 -i -wpe \ ##### Add the USE flag descriptions ##### declare -a GDC_DESCRIPTIONS -for version in "${!GCC_TO_KEYWORDS[@]}"; do - if ! can_handle "${version}"; then continue; fi - # $version may look like: 11.3.1_p20221209, 11.4.0, 10.3.1_p20230426-r1 - # we need use.desc to contain: - # gdc-11_3_1_p20231209 - Build for GCC 11.3.1_p20221209 - # gdc-11_4_0 - Build for GCC 11.4.0 - # gdc-10_3_1_p20230426 - Build for GCC 10.3.1_p20230426 - - pv="${version%-r*}" - - # For each line add the text starting from the version (remove 'gdc-') - # to be able to sort the entries properly after. - gdc="${pv//./_}" - gcc="${pv}" - GDC_DESCRIPTIONS+=("${gdc} - Build for GCC ${gcc}") +for slot in "${!SLOT_TO_KEYWORDS[@]}"; do + if ! can_handle "${slot}"; then continue; fi + # slot is a simple number: 11, 12, 13 etc. + + # Same as for the other array, we wil add the prefix 'gdc-' later. + GDC_DESCRIPTIONS+=("${slot} - Build for GCC ${slot}") done # Sort the descriptions @@ -272,8 +330,7 @@ unset IFS perl -0777 -i -wpe \ 's{ - (?:^gdc.*\n)+ # we change all the lines that starts with gdc - # We need the multiline mode (m) below to make ^ match and embeded new lines + (?:^gdc.*\n)+ # we change all the lines that start with gdc + # We need the multiline mode (m) below to make ^ match at embeded new lines }{'"$(printf 'gdc-%s\n' "${GDC_DESCRIPTIONS[@]}")"'\n}xm' profiles/use.desc -exit 0