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