media-fonts/noto-emoji: add ~ppc64 keyword
[gentoo.git] / eclass / usr-ldscript.eclass
1 # Copyright 2019 Gentoo Authors
2 # Distributed under the terms of the GNU General Public License v2
3
4 # @ECLASS: usr-ldscript.eclass
5 # @MAINTAINER:
6 # Toolchain Ninjas <toolchain@gentoo.org>
7 # @SUPPORTED_EAPIS: 4 5 6 7
8 # @BLURB: Defines the gen_usr_ldscript function.
9
10 if [[ -z ${_USR_LDSCRIPT_ECLASS} ]]; then
11 _USR_LDSCRIPT_ECLASS=1
12
13 case ${EAPI:-0} in
14         4|5|6|7) ;;
15         *) die "EAPI=${EAPI} is not supported" ;;
16 esac
17
18 inherit multilib toolchain-funcs
19
20 IUSE="split-usr"
21
22 # @FUNCTION: gen_usr_ldscript
23 # @USAGE: [-a] <list of libs to create linker scripts for>
24 # @DESCRIPTION:
25 # This function generate linker scripts in /usr/lib for dynamic
26 # libs in /lib.  This is to fix linking problems when you have
27 # the .so in /lib, and the .a in /usr/lib.  What happens is that
28 # in some cases when linking dynamic, the .a in /usr/lib is used
29 # instead of the .so in /lib due to gcc/libtool tweaking ld's
30 # library search path.  This causes many builds to fail.
31 # See bug #4411 for more info.
32 #
33 # Note that you should in general use the unversioned name of
34 # the library (libfoo.so), as ldconfig should usually update it
35 # correctly to point to the latest version of the library present.
36 gen_usr_ldscript() {
37         local lib libdir=$(get_libdir) output_format="" auto=false suffix=$(get_libname)
38
39         tc-is-static-only && return
40
41         # We only care about stuffing / for the native ABI. #479448
42         if [[ $(type -t multilib_is_native_abi) == "function" ]] ; then
43                 multilib_is_native_abi || return 0
44         fi
45
46         # Eventually we'd like to get rid of this func completely #417451
47         case ${CTARGET:-${CHOST}} in
48         *-darwin*) ;;
49         *-android*) return 0 ;;
50         *linux*|*-freebsd*|*-openbsd*|*-netbsd*)
51                 use prefix && return 0
52                 use split-usr || return 0
53                 ;;
54         *) return 0 ;;
55         esac
56
57         # Just make sure it exists
58         dodir /usr/${libdir}
59
60         if [[ $1 == "-a" ]] ; then
61                 auto=true
62                 shift
63                 dodir /${libdir}
64         fi
65
66         # OUTPUT_FORMAT gives hints to the linker as to what binary format
67         # is referenced ... makes multilib saner
68         local flags=( ${CFLAGS} ${LDFLAGS} -Wl,--verbose )
69         if $(tc-getLD) --version | grep -q 'GNU gold' ; then
70                 # If they're using gold, manually invoke the old bfd. #487696
71                 local d="${T}/bfd-linker"
72                 mkdir -p "${d}"
73                 ln -sf $(which ${CHOST}-ld.bfd) "${d}"/ld
74                 flags+=( -B"${d}" )
75         fi
76         output_format=$($(tc-getCC) "${flags[@]}" 2>&1 | sed -n 's/^OUTPUT_FORMAT("\([^"]*\)",.*/\1/p')
77         [[ -n ${output_format} ]] && output_format="OUTPUT_FORMAT ( ${output_format} )"
78
79         for lib in "$@" ; do
80                 local tlib
81                 if ${auto} ; then
82                         lib="lib${lib}${suffix}"
83                 else
84                         # Ensure /lib/${lib} exists to avoid dangling scripts/symlinks.
85                         # This especially is for AIX where $(get_libname) can return ".a",
86                         # so /lib/${lib} might be moved to /usr/lib/${lib} (by accident).
87                         [[ -r ${ED%/}/${libdir}/${lib} ]] || continue
88                         #TODO: better die here?
89                 fi
90
91                 case ${CTARGET:-${CHOST}} in
92                 *-darwin*)
93                         if ${auto} ; then
94                                 tlib=$(scanmacho -qF'%S#F' "${ED%/}"/usr/${libdir}/${lib})
95                         else
96                                 tlib=$(scanmacho -qF'%S#F' "${ED%/}"/${libdir}/${lib})
97                         fi
98                         [[ -z ${tlib} ]] && die "unable to read install_name from ${lib}"
99                         tlib=${tlib##*/}
100
101                         if ${auto} ; then
102                                 mv "${ED%/}"/usr/${libdir}/${lib%${suffix}}.*${suffix#.} "${ED%/}"/${libdir}/ || die
103                                 # some install_names are funky: they encode a version
104                                 if [[ ${tlib} != ${lib%${suffix}}.*${suffix#.} ]] ; then
105                                         mv "${ED%/}"/usr/${libdir}/${tlib%${suffix}}.*${suffix#.} "${ED%/}"/${libdir}/ || die
106                                 fi
107                                 rm -f "${ED%/}"/${libdir}/${lib}
108                         fi
109
110                         # Mach-O files have an id, which is like a soname, it tells how
111                         # another object linking against this lib should reference it.
112                         # Since we moved the lib from usr/lib into lib this reference is
113                         # wrong.  Hence, we update it here.  We don't configure with
114                         # libdir=/lib because that messes up libtool files.
115                         # Make sure we don't lose the specific version, so just modify the
116                         # existing install_name
117                         if [[ ! -w "${ED%/}/${libdir}/${tlib}" ]] ; then
118                                 chmod u+w "${ED%/}/${libdir}/${tlib}" # needed to write to it
119                                 local nowrite=yes
120                         fi
121                         install_name_tool \
122                                 -id "${EPREFIX}"/${libdir}/${tlib} \
123                                 "${ED%/}"/${libdir}/${tlib} || die "install_name_tool failed"
124                         [[ -n ${nowrite} ]] && chmod u-w "${ED%/}/${libdir}/${tlib}"
125                         # Now as we don't use GNU binutils and our linker doesn't
126                         # understand linker scripts, just create a symlink.
127                         pushd "${ED%/}/usr/${libdir}" > /dev/null
128                         ln -snf "../../${libdir}/${tlib}" "${lib}"
129                         popd > /dev/null
130                         ;;
131                 *)
132                         if ${auto} ; then
133                                 tlib=$(scanelf -qF'%S#F' "${ED%/}"/usr/${libdir}/${lib})
134                                 [[ -z ${tlib} ]] && die "unable to read SONAME from ${lib}"
135                                 mv "${ED%/}"/usr/${libdir}/${lib}* "${ED%/}"/${libdir}/ || die
136                                 # some SONAMEs are funky: they encode a version before the .so
137                                 if [[ ${tlib} != ${lib}* ]] ; then
138                                         mv "${ED%/}"/usr/${libdir}/${tlib}* "${ED%/}"/${libdir}/ || die
139                                 fi
140                                 rm -f "${ED%/}"/${libdir}/${lib}
141                         else
142                                 tlib=${lib}
143                         fi
144                         cat > "${ED%/}/usr/${libdir}/${lib}" <<-END_LDSCRIPT
145                         /* GNU ld script
146                            Since Gentoo has critical dynamic libraries in /lib, and the static versions
147                            in /usr/lib, we need to have a "fake" dynamic lib in /usr/lib, otherwise we
148                            run into linking problems.  This "fake" dynamic lib is a linker script that
149                            redirects the linker to the real lib.  And yes, this works in the cross-
150                            compiling scenario as the sysroot-ed linker will prepend the real path.
151
152                            See bug https://bugs.gentoo.org/4411 for more info.
153                          */
154                         ${output_format}
155                         GROUP ( ${EPREFIX}/${libdir}/${tlib} )
156                         END_LDSCRIPT
157                         ;;
158                 esac
159                 fperms a+x "/usr/${libdir}/${lib}" || die "could not change perms on ${lib}"
160         done
161 }
162
163 fi # _USR_LDSCRIPT_ECLASS