From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 9A424139694 for ; Sun, 12 Mar 2017 11:03:01 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id E4F27E0DED; Sun, 12 Mar 2017 11:00:29 +0000 (UTC) Received: from smtp.gentoo.org (mail.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 9533AE0DD4 for ; Sun, 12 Mar 2017 11:00:19 +0000 (UTC) Received: from localhost.localdomain (d202-252.icpnet.pl [109.173.202.252]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: mgorny) by smtp.gentoo.org (Postfix) with ESMTPSA id 244BC340BEA; Sun, 12 Mar 2017 11:00:17 +0000 (UTC) From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= To: gentoo-dev@lists.gentoo.org Cc: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= Subject: [gentoo-dev] [PATCH 3/3] ltprune.eclass: Split prune_libtool_files out of eutils Date: Sun, 12 Mar 2017 12:00:09 +0100 Message-Id: <20170312110009.3109-4-mgorny@gentoo.org> X-Mailer: git-send-email 2.12.0 In-Reply-To: <20170312110009.3109-1-mgorny@gentoo.org> References: <20170312103943.23092-1-mgorny@gentoo.org> <20170312110009.3109-1-mgorny@gentoo.org> Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-dev@lists.gentoo.org Reply-to: gentoo-dev@lists.gentoo.org MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Archives-Salt: d3b3f3d2-c6ba-4c62-bb71-28c0b5dd555a X-Archives-Hash: 9de0101d230394dde1ef07130c92ab28 Move the prune_libtool_files into a dedicated ltprune.eclass. The function is quite complex and depends on toolchain-funcs. It has a separate maintainer, is not useful to non-autotools ebuilds, and even there it is frequently replaced by the simpler 'find ... -delete' call. The new eclass is implicitly inherited by eutils in EAPI 6 and older in order to preserve compatibility with existing ebuilds. However, all ebuilds should switch to inheriting it directly. The split has been suggested by Ulrich Müller. --- eclass/eutils.eclass | 150 +-------------------------------------------- eclass/ltprune.eclass | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+), 149 deletions(-) create mode 100644 eclass/ltprune.eclass diff --git a/eclass/eutils.eclass b/eclass/eutils.eclass index cb472caee1d4..c932d685c0e9 100644 --- a/eclass/eutils.eclass +++ b/eclass/eutils.eclass @@ -17,12 +17,10 @@ if [[ -z ${_EUTILS_ECLASS} ]]; then _EUTILS_ECLASS=1 -inherit toolchain-funcs - # implicitly inherited (now split) eclasses case ${EAPI:-0} in 0|1|2|3|4|5|6) - inherit epatch estack multilib + inherit epatch estack ltprune multilib toolchain-funcs ;; esac @@ -869,152 +867,6 @@ use_if_iuse() { use $1 } -# @FUNCTION: prune_libtool_files -# @USAGE: [--all|--modules] -# @DESCRIPTION: -# Locate unnecessary libtool files (.la) and libtool static archives -# (.a) and remove them from installation image. -# -# By default, .la files are removed whenever the static linkage can -# either be performed using pkg-config or doesn't introduce additional -# flags. -# -# If '--modules' argument is passed, .la files for modules (plugins) are -# removed as well. This is usually useful when the package installs -# plugins and the plugin loader does not use .la files. -# -# If '--all' argument is passed, all .la files are removed without -# performing any heuristic on them. You shouldn't ever use that, -# and instead report a bug in the algorithm instead. -# -# The .a files are only removed whenever corresponding .la files state -# that they should not be linked to, i.e. whenever these files -# correspond to plugins. -# -# Note: if your package installs both static libraries and .pc files -# which use variable substitution for -l flags, you need to add -# pkg-config to your DEPEND. -prune_libtool_files() { - debug-print-function ${FUNCNAME} "$@" - - local removing_all removing_modules opt - for opt; do - case "${opt}" in - --all) - removing_all=1 - removing_modules=1 - ;; - --modules) - removing_modules=1 - ;; - *) - die "Invalid argument to ${FUNCNAME}(): ${opt}" - esac - done - - local f - local queue=() - while IFS= read -r -d '' f; do # for all .la files - local archivefile=${f/%.la/.a} - - # The following check is done by libtool itself. - # It helps us avoid removing random files which match '*.la', - # see bug #468380. - if ! sed -n -e '/^# Generated by .*libtool/q0;4q1' "${f}"; then - continue - fi - - [[ ${f} != ${archivefile} ]] || die 'regex sanity check failed' - local reason= pkgconfig_scanned= - local snotlink=$(sed -n -e 's:^shouldnotlink=::p' "${f}") - - if [[ ${snotlink} == yes ]]; then - - # Remove static libs we're not supposed to link against. - if [[ -f ${archivefile} ]]; then - einfo "Removing unnecessary ${archivefile#${D%/}} (static plugin)" - queue+=( "${archivefile}" ) - fi - - # The .la file may be used by a module loader, so avoid removing it - # unless explicitly requested. - if [[ ${removing_modules} ]]; then - reason='module' - fi - - else - - # Remove .la files when: - # - user explicitly wants us to remove all .la files, - # - respective static archive doesn't exist, - # - they are covered by a .pc file already, - # - they don't provide any new information (no libs & no flags). - - if [[ ${removing_all} ]]; then - reason='requested' - elif [[ ! -f ${archivefile} ]]; then - reason='no static archive' - elif [[ ! $(sed -nre \ - "s/^(dependency_libs|inherited_linker_flags)='(.*)'$/\2/p" \ - "${f}") ]]; then - reason='no libs & flags' - else - if [[ ! ${pkgconfig_scanned} ]]; then - # Create a list of all .pc-covered libs. - local pc_libs=() - if [[ ! ${removing_all} ]]; then - local pc - local tf=${T}/prune-lt-files.pc - local pkgconf=$(tc-getPKG_CONFIG) - - while IFS= read -r -d '' pc; do # for all .pc files - local arg libs - - # Use pkg-config if available (and works), - # fallback to sed. - if ${pkgconf} --exists "${pc}" &>/dev/null; then - sed -e '/^Requires:/d' "${pc}" > "${tf}" - libs=$(${pkgconf} --libs "${tf}") - else - libs=$(sed -ne 's/^Libs://p' "${pc}") - fi - - for arg in ${libs}; do - if [[ ${arg} == -l* ]]; then - if [[ ${arg} == '*$*' ]]; then - eerror "${FUNCNAME}: variable substitution likely failed in ${pc}" - eerror "(arg: ${arg})" - eerror "Most likely, you need to add virtual/pkgconfig to DEPEND." - die "${FUNCNAME}: unsubstituted variable found in .pc" - fi - - pc_libs+=( lib${arg#-l}.la ) - fi - done - done < <(find "${D}" -type f -name '*.pc' -print0) - - rm -f "${tf}" - fi - - pkgconfig_scanned=1 - fi # pkgconfig_scanned - - has "${f##*/}" "${pc_libs[@]}" && reason='covered by .pc' - fi # removal due to .pc - - fi # shouldnotlink==no - - if [[ ${reason} ]]; then - einfo "Removing unnecessary ${f#${D%/}} (${reason})" - queue+=( "${f}" ) - fi - done < <(find "${D}" -xtype f -name '*.la' -print0) - - if [[ ${queue[@]} ]]; then - rm -f "${queue[@]}" - fi -} - # @FUNCTION: optfeature # @USAGE: [other atoms] # @DESCRIPTION: diff --git a/eclass/ltprune.eclass b/eclass/ltprune.eclass new file mode 100644 index 000000000000..6b3e93921d96 --- /dev/null +++ b/eclass/ltprune.eclass @@ -0,0 +1,167 @@ +# Copyright 1999-2017 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +# @ECLASS: ltprune.eclass +# @MAINTAINER: +# Michał Górny +# @BLURB: Smart .la file pruning +# @DESCRIPTION: +# A function to locate and remove unnecessary .la files. +# +# Discouraged. Whenever possible, please use much simpler: +# @CODE +# find "${D}" -name '*.la' -delete || die +# @CODE + +if [[ -z ${_LTPRUNE_ECLASS} ]]; then + +inherit toolchain-funcs + +# @FUNCTION: prune_libtool_files +# @USAGE: [--all|--modules] +# @DESCRIPTION: +# Locate unnecessary libtool files (.la) and libtool static archives +# (.a) and remove them from installation image. +# +# By default, .la files are removed whenever the static linkage can +# either be performed using pkg-config or doesn't introduce additional +# flags. +# +# If '--modules' argument is passed, .la files for modules (plugins) are +# removed as well. This is usually useful when the package installs +# plugins and the plugin loader does not use .la files. +# +# If '--all' argument is passed, all .la files are removed without +# performing any heuristic on them. You shouldn't ever use that, +# and instead report a bug in the algorithm instead. +# +# The .a files are only removed whenever corresponding .la files state +# that they should not be linked to, i.e. whenever these files +# correspond to plugins. +# +# Note: if your package installs both static libraries and .pc files +# which use variable substitution for -l flags, you need to add +# pkg-config to your DEPEND. +prune_libtool_files() { + debug-print-function ${FUNCNAME} "$@" + + local removing_all removing_modules opt + for opt; do + case "${opt}" in + --all) + removing_all=1 + removing_modules=1 + ;; + --modules) + removing_modules=1 + ;; + *) + die "Invalid argument to ${FUNCNAME}(): ${opt}" + esac + done + + local f + local queue=() + while IFS= read -r -d '' f; do # for all .la files + local archivefile=${f/%.la/.a} + + # The following check is done by libtool itself. + # It helps us avoid removing random files which match '*.la', + # see bug #468380. + if ! sed -n -e '/^# Generated by .*libtool/q0;4q1' "${f}"; then + continue + fi + + [[ ${f} != ${archivefile} ]] || die 'regex sanity check failed' + local reason= pkgconfig_scanned= + local snotlink=$(sed -n -e 's:^shouldnotlink=::p' "${f}") + + if [[ ${snotlink} == yes ]]; then + + # Remove static libs we're not supposed to link against. + if [[ -f ${archivefile} ]]; then + einfo "Removing unnecessary ${archivefile#${D%/}} (static plugin)" + queue+=( "${archivefile}" ) + fi + + # The .la file may be used by a module loader, so avoid removing it + # unless explicitly requested. + if [[ ${removing_modules} ]]; then + reason='module' + fi + + else + + # Remove .la files when: + # - user explicitly wants us to remove all .la files, + # - respective static archive doesn't exist, + # - they are covered by a .pc file already, + # - they don't provide any new information (no libs & no flags). + + if [[ ${removing_all} ]]; then + reason='requested' + elif [[ ! -f ${archivefile} ]]; then + reason='no static archive' + elif [[ ! $(sed -nre \ + "s/^(dependency_libs|inherited_linker_flags)='(.*)'$/\2/p" \ + "${f}") ]]; then + reason='no libs & flags' + else + if [[ ! ${pkgconfig_scanned} ]]; then + # Create a list of all .pc-covered libs. + local pc_libs=() + if [[ ! ${removing_all} ]]; then + local pc + local tf=${T}/prune-lt-files.pc + local pkgconf=$(tc-getPKG_CONFIG) + + while IFS= read -r -d '' pc; do # for all .pc files + local arg libs + + # Use pkg-config if available (and works), + # fallback to sed. + if ${pkgconf} --exists "${pc}" &>/dev/null; then + sed -e '/^Requires:/d' "${pc}" > "${tf}" + libs=$(${pkgconf} --libs "${tf}") + else + libs=$(sed -ne 's/^Libs://p' "${pc}") + fi + + for arg in ${libs}; do + if [[ ${arg} == -l* ]]; then + if [[ ${arg} == '*$*' ]]; then + eerror "${FUNCNAME}: variable substitution likely failed in ${pc}" + eerror "(arg: ${arg})" + eerror "Most likely, you need to add virtual/pkgconfig to DEPEND." + die "${FUNCNAME}: unsubstituted variable found in .pc" + fi + + pc_libs+=( lib${arg#-l}.la ) + fi + done + done < <(find "${D}" -type f -name '*.pc' -print0) + + rm -f "${tf}" + fi + + pkgconfig_scanned=1 + fi # pkgconfig_scanned + + has "${f##*/}" "${pc_libs[@]}" && reason='covered by .pc' + fi # removal due to .pc + + fi # shouldnotlink==no + + if [[ ${reason} ]]; then + einfo "Removing unnecessary ${f#${D%/}} (${reason})" + queue+=( "${f}" ) + fi + done < <(find "${D}" -xtype f -name '*.la' -print0) + + if [[ ${queue[@]} ]]; then + rm -f "${queue[@]}" + fi +} + +_LTPRUNE_ECLASS=1 +fi #_LTPRUNE_ECLASS -- 2.12.0