Gentoo Archives: gentoo-dev

From: "Michał Górny" <mgorny@g.o>
To: gentoo-dev@l.g.o
Cc: "Michał Górny" <mgorny@g.o>
Subject: [gentoo-dev] [PATCH 3/3] ltprune.eclass: Split prune_libtool_files out of eutils
Date: Sun, 12 Mar 2017 11:03:01
Message-Id: 20170312110009.3109-4-mgorny@gentoo.org
In Reply to: [gentoo-dev] [PATCH v2] ltprune.eclass by "Michał Górny"
1 Move the prune_libtool_files into a dedicated ltprune.eclass.
2 The function is quite complex and depends on toolchain-funcs. It has
3 a separate maintainer, is not useful to non-autotools ebuilds, and even
4 there it is frequently replaced by the simpler 'find ... -delete' call.
5
6 The new eclass is implicitly inherited by eutils in EAPI 6 and older
7 in order to preserve compatibility with existing ebuilds. However, all
8 ebuilds should switch to inheriting it directly.
9
10 The split has been suggested by Ulrich Müller.
11 ---
12 eclass/eutils.eclass | 150 +--------------------------------------------
13 eclass/ltprune.eclass | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++
14 2 files changed, 168 insertions(+), 149 deletions(-)
15 create mode 100644 eclass/ltprune.eclass
16
17 diff --git a/eclass/eutils.eclass b/eclass/eutils.eclass
18 index cb472caee1d4..c932d685c0e9 100644
19 --- a/eclass/eutils.eclass
20 +++ b/eclass/eutils.eclass
21 @@ -17,12 +17,10 @@
22 if [[ -z ${_EUTILS_ECLASS} ]]; then
23 _EUTILS_ECLASS=1
24
25 -inherit toolchain-funcs
26 -
27 # implicitly inherited (now split) eclasses
28 case ${EAPI:-0} in
29 0|1|2|3|4|5|6)
30 - inherit epatch estack multilib
31 + inherit epatch estack ltprune multilib toolchain-funcs
32 ;;
33 esac
34
35 @@ -869,152 +867,6 @@ use_if_iuse() {
36 use $1
37 }
38
39 -# @FUNCTION: prune_libtool_files
40 -# @USAGE: [--all|--modules]
41 -# @DESCRIPTION:
42 -# Locate unnecessary libtool files (.la) and libtool static archives
43 -# (.a) and remove them from installation image.
44 -#
45 -# By default, .la files are removed whenever the static linkage can
46 -# either be performed using pkg-config or doesn't introduce additional
47 -# flags.
48 -#
49 -# If '--modules' argument is passed, .la files for modules (plugins) are
50 -# removed as well. This is usually useful when the package installs
51 -# plugins and the plugin loader does not use .la files.
52 -#
53 -# If '--all' argument is passed, all .la files are removed without
54 -# performing any heuristic on them. You shouldn't ever use that,
55 -# and instead report a bug in the algorithm instead.
56 -#
57 -# The .a files are only removed whenever corresponding .la files state
58 -# that they should not be linked to, i.e. whenever these files
59 -# correspond to plugins.
60 -#
61 -# Note: if your package installs both static libraries and .pc files
62 -# which use variable substitution for -l flags, you need to add
63 -# pkg-config to your DEPEND.
64 -prune_libtool_files() {
65 - debug-print-function ${FUNCNAME} "$@"
66 -
67 - local removing_all removing_modules opt
68 - for opt; do
69 - case "${opt}" in
70 - --all)
71 - removing_all=1
72 - removing_modules=1
73 - ;;
74 - --modules)
75 - removing_modules=1
76 - ;;
77 - *)
78 - die "Invalid argument to ${FUNCNAME}(): ${opt}"
79 - esac
80 - done
81 -
82 - local f
83 - local queue=()
84 - while IFS= read -r -d '' f; do # for all .la files
85 - local archivefile=${f/%.la/.a}
86 -
87 - # The following check is done by libtool itself.
88 - # It helps us avoid removing random files which match '*.la',
89 - # see bug #468380.
90 - if ! sed -n -e '/^# Generated by .*libtool/q0;4q1' "${f}"; then
91 - continue
92 - fi
93 -
94 - [[ ${f} != ${archivefile} ]] || die 'regex sanity check failed'
95 - local reason= pkgconfig_scanned=
96 - local snotlink=$(sed -n -e 's:^shouldnotlink=::p' "${f}")
97 -
98 - if [[ ${snotlink} == yes ]]; then
99 -
100 - # Remove static libs we're not supposed to link against.
101 - if [[ -f ${archivefile} ]]; then
102 - einfo "Removing unnecessary ${archivefile#${D%/}} (static plugin)"
103 - queue+=( "${archivefile}" )
104 - fi
105 -
106 - # The .la file may be used by a module loader, so avoid removing it
107 - # unless explicitly requested.
108 - if [[ ${removing_modules} ]]; then
109 - reason='module'
110 - fi
111 -
112 - else
113 -
114 - # Remove .la files when:
115 - # - user explicitly wants us to remove all .la files,
116 - # - respective static archive doesn't exist,
117 - # - they are covered by a .pc file already,
118 - # - they don't provide any new information (no libs & no flags).
119 -
120 - if [[ ${removing_all} ]]; then
121 - reason='requested'
122 - elif [[ ! -f ${archivefile} ]]; then
123 - reason='no static archive'
124 - elif [[ ! $(sed -nre \
125 - "s/^(dependency_libs|inherited_linker_flags)='(.*)'$/\2/p" \
126 - "${f}") ]]; then
127 - reason='no libs & flags'
128 - else
129 - if [[ ! ${pkgconfig_scanned} ]]; then
130 - # Create a list of all .pc-covered libs.
131 - local pc_libs=()
132 - if [[ ! ${removing_all} ]]; then
133 - local pc
134 - local tf=${T}/prune-lt-files.pc
135 - local pkgconf=$(tc-getPKG_CONFIG)
136 -
137 - while IFS= read -r -d '' pc; do # for all .pc files
138 - local arg libs
139 -
140 - # Use pkg-config if available (and works),
141 - # fallback to sed.
142 - if ${pkgconf} --exists "${pc}" &>/dev/null; then
143 - sed -e '/^Requires:/d' "${pc}" > "${tf}"
144 - libs=$(${pkgconf} --libs "${tf}")
145 - else
146 - libs=$(sed -ne 's/^Libs://p' "${pc}")
147 - fi
148 -
149 - for arg in ${libs}; do
150 - if [[ ${arg} == -l* ]]; then
151 - if [[ ${arg} == '*$*' ]]; then
152 - eerror "${FUNCNAME}: variable substitution likely failed in ${pc}"
153 - eerror "(arg: ${arg})"
154 - eerror "Most likely, you need to add virtual/pkgconfig to DEPEND."
155 - die "${FUNCNAME}: unsubstituted variable found in .pc"
156 - fi
157 -
158 - pc_libs+=( lib${arg#-l}.la )
159 - fi
160 - done
161 - done < <(find "${D}" -type f -name '*.pc' -print0)
162 -
163 - rm -f "${tf}"
164 - fi
165 -
166 - pkgconfig_scanned=1
167 - fi # pkgconfig_scanned
168 -
169 - has "${f##*/}" "${pc_libs[@]}" && reason='covered by .pc'
170 - fi # removal due to .pc
171 -
172 - fi # shouldnotlink==no
173 -
174 - if [[ ${reason} ]]; then
175 - einfo "Removing unnecessary ${f#${D%/}} (${reason})"
176 - queue+=( "${f}" )
177 - fi
178 - done < <(find "${D}" -xtype f -name '*.la' -print0)
179 -
180 - if [[ ${queue[@]} ]]; then
181 - rm -f "${queue[@]}"
182 - fi
183 -}
184 -
185 # @FUNCTION: optfeature
186 # @USAGE: <short description> <package atom to match> [other atoms]
187 # @DESCRIPTION:
188 diff --git a/eclass/ltprune.eclass b/eclass/ltprune.eclass
189 new file mode 100644
190 index 000000000000..6b3e93921d96
191 --- /dev/null
192 +++ b/eclass/ltprune.eclass
193 @@ -0,0 +1,167 @@
194 +# Copyright 1999-2017 Gentoo Foundation
195 +# Distributed under the terms of the GNU General Public License v2
196 +
197 +# @ECLASS: ltprune.eclass
198 +# @MAINTAINER:
199 +# Michał Górny <mgorny@g.o>
200 +# @BLURB: Smart .la file pruning
201 +# @DESCRIPTION:
202 +# A function to locate and remove unnecessary .la files.
203 +#
204 +# Discouraged. Whenever possible, please use much simpler:
205 +# @CODE
206 +# find "${D}" -name '*.la' -delete || die
207 +# @CODE
208 +
209 +if [[ -z ${_LTPRUNE_ECLASS} ]]; then
210 +
211 +inherit toolchain-funcs
212 +
213 +# @FUNCTION: prune_libtool_files
214 +# @USAGE: [--all|--modules]
215 +# @DESCRIPTION:
216 +# Locate unnecessary libtool files (.la) and libtool static archives
217 +# (.a) and remove them from installation image.
218 +#
219 +# By default, .la files are removed whenever the static linkage can
220 +# either be performed using pkg-config or doesn't introduce additional
221 +# flags.
222 +#
223 +# If '--modules' argument is passed, .la files for modules (plugins) are
224 +# removed as well. This is usually useful when the package installs
225 +# plugins and the plugin loader does not use .la files.
226 +#
227 +# If '--all' argument is passed, all .la files are removed without
228 +# performing any heuristic on them. You shouldn't ever use that,
229 +# and instead report a bug in the algorithm instead.
230 +#
231 +# The .a files are only removed whenever corresponding .la files state
232 +# that they should not be linked to, i.e. whenever these files
233 +# correspond to plugins.
234 +#
235 +# Note: if your package installs both static libraries and .pc files
236 +# which use variable substitution for -l flags, you need to add
237 +# pkg-config to your DEPEND.
238 +prune_libtool_files() {
239 + debug-print-function ${FUNCNAME} "$@"
240 +
241 + local removing_all removing_modules opt
242 + for opt; do
243 + case "${opt}" in
244 + --all)
245 + removing_all=1
246 + removing_modules=1
247 + ;;
248 + --modules)
249 + removing_modules=1
250 + ;;
251 + *)
252 + die "Invalid argument to ${FUNCNAME}(): ${opt}"
253 + esac
254 + done
255 +
256 + local f
257 + local queue=()
258 + while IFS= read -r -d '' f; do # for all .la files
259 + local archivefile=${f/%.la/.a}
260 +
261 + # The following check is done by libtool itself.
262 + # It helps us avoid removing random files which match '*.la',
263 + # see bug #468380.
264 + if ! sed -n -e '/^# Generated by .*libtool/q0;4q1' "${f}"; then
265 + continue
266 + fi
267 +
268 + [[ ${f} != ${archivefile} ]] || die 'regex sanity check failed'
269 + local reason= pkgconfig_scanned=
270 + local snotlink=$(sed -n -e 's:^shouldnotlink=::p' "${f}")
271 +
272 + if [[ ${snotlink} == yes ]]; then
273 +
274 + # Remove static libs we're not supposed to link against.
275 + if [[ -f ${archivefile} ]]; then
276 + einfo "Removing unnecessary ${archivefile#${D%/}} (static plugin)"
277 + queue+=( "${archivefile}" )
278 + fi
279 +
280 + # The .la file may be used by a module loader, so avoid removing it
281 + # unless explicitly requested.
282 + if [[ ${removing_modules} ]]; then
283 + reason='module'
284 + fi
285 +
286 + else
287 +
288 + # Remove .la files when:
289 + # - user explicitly wants us to remove all .la files,
290 + # - respective static archive doesn't exist,
291 + # - they are covered by a .pc file already,
292 + # - they don't provide any new information (no libs & no flags).
293 +
294 + if [[ ${removing_all} ]]; then
295 + reason='requested'
296 + elif [[ ! -f ${archivefile} ]]; then
297 + reason='no static archive'
298 + elif [[ ! $(sed -nre \
299 + "s/^(dependency_libs|inherited_linker_flags)='(.*)'$/\2/p" \
300 + "${f}") ]]; then
301 + reason='no libs & flags'
302 + else
303 + if [[ ! ${pkgconfig_scanned} ]]; then
304 + # Create a list of all .pc-covered libs.
305 + local pc_libs=()
306 + if [[ ! ${removing_all} ]]; then
307 + local pc
308 + local tf=${T}/prune-lt-files.pc
309 + local pkgconf=$(tc-getPKG_CONFIG)
310 +
311 + while IFS= read -r -d '' pc; do # for all .pc files
312 + local arg libs
313 +
314 + # Use pkg-config if available (and works),
315 + # fallback to sed.
316 + if ${pkgconf} --exists "${pc}" &>/dev/null; then
317 + sed -e '/^Requires:/d' "${pc}" > "${tf}"
318 + libs=$(${pkgconf} --libs "${tf}")
319 + else
320 + libs=$(sed -ne 's/^Libs://p' "${pc}")
321 + fi
322 +
323 + for arg in ${libs}; do
324 + if [[ ${arg} == -l* ]]; then
325 + if [[ ${arg} == '*$*' ]]; then
326 + eerror "${FUNCNAME}: variable substitution likely failed in ${pc}"
327 + eerror "(arg: ${arg})"
328 + eerror "Most likely, you need to add virtual/pkgconfig to DEPEND."
329 + die "${FUNCNAME}: unsubstituted variable found in .pc"
330 + fi
331 +
332 + pc_libs+=( lib${arg#-l}.la )
333 + fi
334 + done
335 + done < <(find "${D}" -type f -name '*.pc' -print0)
336 +
337 + rm -f "${tf}"
338 + fi
339 +
340 + pkgconfig_scanned=1
341 + fi # pkgconfig_scanned
342 +
343 + has "${f##*/}" "${pc_libs[@]}" && reason='covered by .pc'
344 + fi # removal due to .pc
345 +
346 + fi # shouldnotlink==no
347 +
348 + if [[ ${reason} ]]; then
349 + einfo "Removing unnecessary ${f#${D%/}} (${reason})"
350 + queue+=( "${f}" )
351 + fi
352 + done < <(find "${D}" -xtype f -name '*.la' -print0)
353 +
354 + if [[ ${queue[@]} ]]; then
355 + rm -f "${queue[@]}"
356 + fi
357 +}
358 +
359 +_LTPRUNE_ECLASS=1
360 +fi #_LTPRUNE_ECLASS
361 --
362 2.12.0