perl-functions.eclass: should 'just work' in EAPI=6
[gentoo.git] / eclass / libtool.eclass
1 # Copyright 1999-2014 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3 # $Id$
4
5 # @ECLASS: libtool.eclass
6 # @MAINTAINER:
7 # base-system@gentoo.org
8 # @BLURB: quickly update bundled libtool code
9 # @DESCRIPTION:
10 # This eclass patches ltmain.sh distributed with libtoolized packages with the
11 # relink and portage patch among others
12 #
13 # Note, this eclass does not require libtool as it only applies patches to
14 # generated libtool files.  We do not run the libtoolize program because that
15 # requires a regeneration of the main autotool files in order to work properly.
16
17 if [[ -z ${_LIBTOOL_ECLASS} ]]; then
18 _LIBTOOL_ECLASS=1
19
20 # If an overlay has eclass overrides, but doesn't actually override the
21 # libtool.eclass, we'll have ECLASSDIR pointing to the active overlay's
22 # eclass/ dir, but libtool.eclass is still in the main Gentoo tree.  So
23 # add a check to locate the ELT-patches/ regardless of what's going on.
24 # Note: Duplicated in eutils.eclass.
25 _LIBTOOL_ECLASSDIR_LOCAL=${BASH_SOURCE[0]%/*}
26 libtool_elt_patch_dir() {
27         local d="${ECLASSDIR}/ELT-patches"
28         if [[ ! -d ${d} ]] ; then
29                 d="${_LIBTOOL_ECLASSDIR_LOCAL}/ELT-patches"
30         fi
31         echo "${d}"
32 }
33
34 inherit multilib toolchain-funcs
35
36 #
37 # See if we can apply $2 on $1, and if so, do it
38 #
39 ELT_try_and_apply_patch() {
40         local ret=0
41         local file=$1
42         local patch=$2
43         local src=$3
44         local disp="${src} patch"
45         local log="${T}/elibtool.log"
46
47         if [[ -z ${_ELT_NOTED_TMP} ]] ; then
48                 _ELT_NOTED_TMP=true
49                 printf 'temp patch: %s\n' "${patch}" > "${log}"
50         fi
51         printf '\nTrying %s\n' "${disp}" >> "${log}"
52
53         if [[ ! -e ${file} ]] ; then
54                 echo "File not found: ${file}" >> "${log}"
55                 return 1
56         fi
57
58         # Save file for permission restoration.  `patch` sometimes resets things.
59         # Ideally we'd want 'stat -c %a', but stat is highly non portable and we are
60         # guaranted to have GNU find, so use that instead.
61         local perms="$(find ${file} -maxdepth 0 -printf '%m')"
62         # We only support patchlevel of 0 - why worry if its static patches?
63         if patch -p0 --dry-run "${file}" "${patch}" >> "${log}" 2>&1 ; then
64                 einfo "  Applying ${disp} ..."
65                 patch -p0 -g0 --no-backup-if-mismatch "${file}" "${patch}" >> "${log}" 2>&1
66                 ret=$?
67                 export ELT_APPLIED_PATCHES="${ELT_APPLIED_PATCHES} ${src}"
68         else
69                 ret=1
70         fi
71         chmod "${perms}" "${file}"
72
73         return "${ret}"
74 }
75
76 #
77 # Get string version of ltmain.sh or ltconfig (passed as $1)
78 #
79 ELT_libtool_version() {
80         (
81         unset VERSION
82         eval $(grep -e '^[[:space:]]*VERSION=' "$1")
83         echo "${VERSION:-0}"
84         )
85 }
86
87 #
88 # Run through the patches in $2 and see if any
89 # apply to $1 ...
90 #
91 ELT_walk_patches() {
92         local patch tmp
93         local ret=1
94         local file=$1
95         local patch_set=$2
96         local patch_dir="$(libtool_elt_patch_dir)/${patch_set}"
97         local rem_int_dep=$3
98
99         [[ -z ${patch_set} ]] && return 1
100         [[ ! -d ${patch_dir} ]] && return 1
101
102         # Allow patches to use @GENTOO_LIBDIR@ replacements
103         local sed_args=( -e "s:@GENTOO_LIBDIR@:$(get_libdir):g" )
104         if [[ -n ${rem_int_dep} ]] ; then
105                 # replace @REM_INT_DEP@ with what was passed
106                 # to --remove-internal-dep
107                 sed_args+=( -e "s|@REM_INT_DEP@|${rem_int_dep}|g" )
108         fi
109
110         pushd "$(libtool_elt_patch_dir)" >/dev/null || die
111
112         # Go through the patches in reverse order (newer version to older)
113         for patch in $(find "${patch_set}" -maxdepth 1 -type f | LC_ALL=C sort -r) ; do
114                 tmp="${T}/libtool-elt.patch"
115                 sed "${sed_args[@]}" "${patch}" > "${tmp}" || die
116                 if ELT_try_and_apply_patch "${file}" "${tmp}" "${patch}" ; then
117                         # Break to unwind w/popd rather than return directly
118                         ret=0
119                         break
120                 fi
121         done
122
123         popd >/dev/null
124         return ${ret}
125 }
126
127 # @FUNCTION: elibtoolize
128 # @USAGE: [dirs] [--portage] [--reverse-deps] [--patch-only] [--remove-internal-dep=xxx] [--shallow] [--no-uclibc]
129 # @DESCRIPTION:
130 # Apply a smorgasbord of patches to bundled libtool files.  This function
131 # should always be safe to run.  If no directories are specified, then
132 # ${S} will be searched for appropriate files.
133 #
134 # If the --shallow option is used, then only ${S}/ltmain.sh will be patched.
135 #
136 # The other options should be avoided in general unless you know what's going on.
137 elibtoolize() {
138         local x
139         local dirs=()
140         local do_portage="no"
141         local do_reversedeps="no"
142         local do_only_patches="no"
143         local do_uclibc="yes"
144         local deptoremove=
145         local do_shallow="no"
146         local force="false"
147         local elt_patches="install-sh ltmain portage relink max_cmd_len sed test tmp cross as-needed target-nm"
148
149         for x in "$@" ; do
150                 case ${x} in
151                         --portage)
152                                 # Only apply portage patch, and don't
153                                 # 'libtoolize --copy --force' if all patches fail.
154                                 do_portage="yes"
155                                 ;;
156                         --reverse-deps)
157                                 # Apply the reverse-deps patch
158                                 # http://bugzilla.gnome.org/show_bug.cgi?id=75635
159                                 do_reversedeps="yes"
160                                 elt_patches+=" fix-relink"
161                                 ;;
162                         --patch-only)
163                                 # Do not run libtoolize if none of the patches apply ..
164                                 do_only_patches="yes"
165                                 ;;
166                         --remove-internal-dep=*)
167                                 # We will replace @REM_INT_DEP@ with what is needed
168                                 # in ELT_walk_patches() ...
169                                 deptoremove=${x#--remove-internal-dep=}
170
171                                 # Add the patch for this ...
172                                 [[ -n ${deptoremove} ]] && elt_patches+=" rem-int-dep"
173                                 ;;
174                         --shallow)
175                                 # Only patch the ltmain.sh in ${S}
176                                 do_shallow="yes"
177                                 ;;
178                         --no-uclibc)
179                                 do_uclibc="no"
180                                 ;;
181                         --force)
182                                 force="true"
183                                 ;;
184                         -*)
185                                 eerror "Invalid elibtoolize option: ${x}"
186                                 die "elibtoolize called with ${x} ??"
187                                 ;;
188                         *)      dirs+=( "${x}" )
189                 esac
190         done
191
192         [[ ${do_uclibc} == "yes" ]] && elt_patches+=" uclibc-conf uclibc-ltconf"
193
194         case ${CHOST} in
195                 *-aix*)     elt_patches+=" hardcode aixrtl" ;; #213277
196                 *-darwin*)  elt_patches+=" darwin-ltconf darwin-ltmain darwin-conf" ;;
197                 *-solaris*) elt_patches+=" sol2-conf sol2-ltmain" ;;
198                 *-freebsd*) elt_patches+=" fbsd-conf fbsd-ltconf" ;;
199                 *-hpux*)    elt_patches+=" hpux-conf deplibs hc-flag-ld hardcode hardcode-relink relink-prog no-lc" ;;
200                 *-irix*)    elt_patches+=" irix-ltmain" ;;
201                 *-mint*)    elt_patches+=" mint-conf" ;;
202         esac
203
204         if $(tc-getLD) --version 2>&1 | grep -qs 'GNU gold'; then
205                 elt_patches+=" gold-conf"
206         fi
207
208         # Find out what dirs to scan.
209         if [[ ${do_shallow} == "yes" ]] ; then
210                 [[ ${#dirs[@]} -ne 0 ]] && die "Using --shallow with explicit dirs doesn't make sense"
211                 [[ -f ${S}/ltmain.sh || -f ${S}/configure ]] && dirs+=( "${S}" )
212         else
213                 [[ ${#dirs[@]} -eq 0 ]] && dirs+=( "${S}" )
214                 dirs=( $(find "${dirs[@]}" '(' -name ltmain.sh -o -name configure ')' -printf '%h\n' | sort -u) )
215         fi
216
217         local d p ret
218         for d in "${dirs[@]}" ; do
219                 export ELT_APPLIED_PATCHES=
220
221                 if [[ -f ${d}/.elibtoolized ]] ; then
222                         ${force} || continue
223                 fi
224
225                 local outfunc="einfo"
226                 [[ -f ${d}/.elibtoolized ]] && outfunc="ewarn"
227                 ${outfunc} "Running elibtoolize in: ${d#${WORKDIR}/}/"
228                 if [[ ${outfunc} == "ewarn" ]] ; then
229                         ewarn "  We've already been run in this tree; you should"
230                         ewarn "  avoid this if possible (perhaps by filing a bug)"
231                 fi
232
233                 # patching ltmain.sh
234                 [[ -f ${d}/ltmain.sh ]] &&
235                 for p in ${elt_patches} ; do
236                         ret=0
237
238                         case ${p} in
239                                 portage)
240                                         # Stupid test to see if its already applied ...
241                                         if ! grep -qs 'We do not want portage' "${d}/ltmain.sh" ; then
242                                                 ELT_walk_patches "${d}/ltmain.sh" "${p}"
243                                                 ret=$?
244                                         fi
245                                         ;;
246                                 rem-int-dep)
247                                         ELT_walk_patches "${d}/ltmain.sh" "${p}" "${deptoremove}"
248                                         ret=$?
249                                         ;;
250                                 fix-relink)
251                                         # Do not apply if we do not have the relink patch applied ...
252                                         if grep -qs 'inst_prefix_dir' "${d}/ltmain.sh" ; then
253                                                 ELT_walk_patches "${d}/ltmain.sh" "${p}"
254                                                 ret=$?
255                                         fi
256                                         ;;
257                                 max_cmd_len)
258                                         # Do not apply if $max_cmd_len is not used ...
259                                         if grep -qs 'max_cmd_len' "${d}/ltmain.sh" ; then
260                                                 ELT_walk_patches "${d}/ltmain.sh" "${p}"
261                                                 ret=$?
262                                         fi
263                                         ;;
264                                 as-needed)
265                                         ELT_walk_patches "${d}/ltmain.sh" "${p}"
266                                         ret=$?
267                                         ;;
268                                 uclibc-ltconf)
269                                         # Newer libtoolize clears ltconfig, as not used anymore
270                                         if [[ -s ${d}/ltconfig ]] ; then
271                                                 ELT_walk_patches "${d}/ltconfig" "${p}"
272                                                 ret=$?
273                                         fi
274                                         ;;
275                                 fbsd-ltconf)
276                                         if [[ -s ${d}/ltconfig ]] ; then
277                                                 ELT_walk_patches "${d}/ltconfig" "${p}"
278                                                 ret=$?
279                                         fi
280                                         ;;
281                                 darwin-ltconf)
282                                         # Newer libtoolize clears ltconfig, as not used anymore
283                                         if [[ -s ${d}/ltconfig ]] ; then
284                                                 ELT_walk_patches "${d}/ltconfig" "${p}"
285                                                 ret=$?
286                                         fi
287                                         ;;
288                                 darwin-ltmain)
289                                         # special case to avoid false positives (failing to apply
290                                         # ltmain.sh path message), newer libtools have this patch
291                                         # built in, so not much to patch around then
292                                         if [[ -e ${d}/ltmain.sh ]] && \
293                                            ! grep -qs 'verstring="-compatibility_version' "${d}/ltmain.sh" ; then
294                                                 ELT_walk_patches "${d}/ltmain.sh" "${p}"
295                                                 ret=$?
296                                         fi
297                                         ;;
298                                 install-sh)
299                                         ELT_walk_patches "${d}/install-sh" "${p}"
300                                         ret=$?
301                                         ;;
302                                 cross)
303                                         if tc-is-cross-compiler ; then
304                                                 ELT_walk_patches "${d}/ltmain.sh" "${p}"
305                                                 ret=$?
306                                         fi
307                                         ;;
308                                 *)
309                                         ELT_walk_patches "${d}/ltmain.sh" "${p}"
310                                         ret=$?
311                                         ;;
312                         esac
313
314                         if [[ ${ret} -ne 0 ]] ; then
315                                 case ${p} in
316                                         relink)
317                                                 local version=$(ELT_libtool_version "${d}/ltmain.sh")
318                                                 # Critical patch, but could be applied ...
319                                                 # FIXME:  Still need a patch for ltmain.sh > 1.4.0
320                                                 if ! grep -qs 'inst_prefix_dir' "${d}/ltmain.sh" && \
321                                                    [[ $(VER_to_int "${version}") -ge $(VER_to_int "1.4.0") ]] ; then
322                                                         ewarn "  Could not apply relink.patch!"
323                                                 fi
324                                                 ;;
325                                         portage)
326                                                 # Critical patch - for this one we abort, as it can really
327                                                 # cause breakage without it applied!
328                                                 if [[ ${do_portage} == "yes" ]] ; then
329                                                         # Stupid test to see if its already applied ...
330                                                         if ! grep -qs 'We do not want portage' "${d}/ltmain.sh" ; then
331                                                                 echo
332                                                                 eerror "Portage patch requested, but failed to apply!"
333                                                                 eerror "Please file a bug report to add a proper patch."
334                                                                 die "Portage patch requested, but failed to apply!"
335                                                         fi
336                                                 else
337                                                         if grep -qs 'We do not want portage' "${d}/ltmain.sh" ; then
338                                                         #       ewarn "  Portage patch seems to be already applied."
339                                                         #       ewarn "  Please verify that it is not needed."
340                                                                 :
341                                                         else
342                                                                 local version=$(ELT_libtool_version "${d}"/ltmain.sh)
343                                                                 echo
344                                                                 eerror "Portage patch failed to apply (ltmain.sh version ${version})!"
345                                                                 eerror "Please file a bug report to add a proper patch."
346                                                                 die "Portage patch failed to apply!"
347                                                         fi
348                                                         # We do not want to run libtoolize ...
349                                                         ELT_APPLIED_PATCHES="portage"
350                                                 fi
351                                                 ;;
352                                         darwin-*)
353                                                 [[ ${CHOST} == *"-darwin"* ]] && ewarn "  Darwin patch set '${p}' failed to apply!"
354                                                 ;;
355                                 esac
356                         fi
357                 done
358
359                 # makes sense for ltmain.sh patches only
360                 [[ -f ${d}/ltmain.sh ]] &&
361                 if [[ -z ${ELT_APPLIED_PATCHES} ]] ; then
362                         if [[ ${do_portage} == "no" && \
363                                   ${do_reversedeps} == "no" && \
364                                   ${do_only_patches} == "no" && \
365                                   ${deptoremove} == "" ]]
366                         then
367                                 ewarn "Cannot apply any patches, please file a bug about this"
368                                 die
369                         fi
370                 fi
371
372                 # patching configure
373                 [[ -f ${d}/configure ]] &&
374                 for p in ${elt_patches} ; do
375                         ret=0
376
377                         case ${p} in
378                                 uclibc-conf)
379                                         if grep -qs 'Transform linux' "${d}/configure" ; then
380                                                 ELT_walk_patches "${d}/configure" "${p}"
381                                                 ret=$?
382                                         fi
383                                         ;;
384                                 fbsd-conf)
385                                         if grep -qs 'version_type=freebsd-' "${d}/configure" ; then
386                                                 ELT_walk_patches "${d}/configure" "${p}"
387                                                 ret=$?
388                                         fi
389                                         ;;
390                                 darwin-conf)
391                                         if grep -qs '&& echo \.so ||' "${d}/configure" ; then
392                                                 ELT_walk_patches "${d}/configure" "${p}"
393                                                 ret=$?
394                                         fi
395                                         ;;
396                                 aixrtl|hpux-conf)
397                                         ret=1
398                                         local subret=0
399                                         # apply multiple patches as often as they match
400                                         while [[ $subret -eq 0 ]]; do
401                                                 subret=1
402                                                 if [[ -e ${d}/configure ]]; then
403                                                         ELT_walk_patches "${d}/configure" "${p}"
404                                                         subret=$?
405                                                 fi
406                                                 if [[ $subret -eq 0 ]]; then
407                                                         # have at least one patch succeeded.
408                                                         ret=0
409                                                 fi
410                                         done
411                                         ;;
412                                 mint-conf|gold-conf|sol2-conf)
413                                         ELT_walk_patches "${d}/configure" "${p}"
414                                         ret=$?
415                                         ;;
416                                 target-nm)
417                                         ELT_walk_patches "${d}/configure" "${p}"
418                                         ret=$?
419                                         ;;
420                                 *)
421                                         # ltmain.sh patches are applied above
422                                         ;;
423                         esac
424
425                         if [[ ${ret} -ne 0 ]] ; then
426                                 case ${p} in
427                                         uclibc-*)
428                                                 [[ ${CHOST} == *-uclibc ]] && ewarn "  uClibc patch set '${p}' failed to apply!"
429                                                 ;;
430                                         fbsd-*)
431                                                 if [[ ${CHOST} == *-freebsd* ]] ; then
432                                                         if [[ -z $(grep 'Handle Gentoo/FreeBSD as it was Linux' \
433                                                                 "${d}/configure" 2>/dev/null) ]]; then
434                                                                 eerror "  FreeBSD patch set '${p}' failed to apply!"
435                                                                 die "FreeBSD patch set '${p}' failed to apply!"
436                                                         fi
437                                                 fi
438                                                 ;;
439                                         darwin-*)
440                                                 [[ ${CHOST} == *"-darwin"* ]] && ewarn "  Darwin patch set '${p}' failed to apply!"
441                                                 ;;
442                                 esac
443                         fi
444                 done
445
446                 rm -f "${d}/libtool"
447
448                 > "${d}/.elibtoolized"
449         done
450 }
451
452 uclibctoolize() { die "Use elibtoolize"; }
453 darwintoolize() { die "Use elibtoolize"; }
454
455 # char *VER_major(string)
456 #
457 #    Return the Major (X of X.Y.Z) version
458 #
459 VER_major() {
460         [[ -z $1 ]] && return 1
461
462         local VER=$@
463         echo "${VER%%[^[:digit:]]*}"
464 }
465
466 # char *VER_minor(string)
467 #
468 #    Return the Minor (Y of X.Y.Z) version
469 #
470 VER_minor() {
471         [[ -z $1 ]] && return 1
472
473         local VER=$@
474         VER=${VER#*.}
475         echo "${VER%%[^[:digit:]]*}"
476 }
477
478 # char *VER_micro(string)
479 #
480 #    Return the Micro (Z of X.Y.Z) version.
481 #
482 VER_micro() {
483         [[ -z $1 ]] && return 1
484
485         local VER=$@
486         VER=${VER#*.*.}
487         echo "${VER%%[^[:digit:]]*}"
488 }
489
490 # int VER_to_int(string)
491 #
492 #    Convert a string type version (2.4.0) to an int (132096)
493 #    for easy compairing or versions ...
494 #
495 VER_to_int() {
496         [[ -z $1 ]] && return 1
497
498         local VER_MAJOR=$(VER_major "$1")
499         local VER_MINOR=$(VER_minor "$1")
500         local VER_MICRO=$(VER_micro "$1")
501         local VER_int=$(( VER_MAJOR * 65536 + VER_MINOR * 256 + VER_MICRO ))
502
503         # We make version 1.0.0 the minimum version we will handle as
504         # a sanity check ... if its less, we fail ...
505         if [[ ${VER_int} -ge 65536 ]] ; then
506                 echo "${VER_int}"
507                 return 0
508         fi
509
510         echo 1
511         return 1
512 }
513
514 fi