usr-ldscript.eclass: return early if USE=split-usr is disabled
[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 # @BLURB: Defines the gen_usr_ldscript function.
8
9 if [[ -z ${_USR_LDSCRIPT_ECLASS} ]]; then
10 _USR_LDSCRIPT_ECLASS=1
11
12 inherit multilib toolchain-funcs
13
14 IUSE="split-usr"
15
16 # @FUNCTION: gen_usr_ldscript
17 # @USAGE: [-a] <list of libs to create linker scripts for>
18 # @DESCRIPTION:
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.
26 #
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.
30 gen_usr_ldscript() {
31         local lib libdir=$(get_libdir) output_format="" auto=false suffix=$(get_libname)
32         [[ -z ${ED+set} ]] && local ED=${D%/}${EPREFIX}/
33
34         tc-is-static-only && return
35
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
39         fi
40
41         # Eventually we'd like to get rid of this func completely #417451
42         case ${CTARGET:-${CHOST}} in
43         *-darwin*) ;;
44         *-android*) return 0 ;;
45         *linux*|*-freebsd*|*-openbsd*|*-netbsd*)
46                 use prefix && return 0
47                 use split-usr || return 0
48                 ;;
49         *) return 0 ;;
50         esac
51
52         # Just make sure it exists
53         dodir /usr/${libdir}
54
55         if [[ $1 == "-a" ]] ; then
56                 auto=true
57                 shift
58                 dodir /${libdir}
59         fi
60
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"
67                 mkdir -p "${d}"
68                 ln -sf $(which ${CHOST}-ld.bfd) "${d}"/ld
69                 flags+=( -B"${d}" )
70         fi
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} )"
73
74         for lib in "$@" ; do
75                 local tlib
76                 if ${auto} ; then
77                         lib="lib${lib}${suffix}"
78                 else
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?
84                 fi
85
86                 case ${CTARGET:-${CHOST}} in
87                 *-darwin*)
88                         if ${auto} ; then
89                                 tlib=$(scanmacho -qF'%S#F' "${ED}"/usr/${libdir}/${lib})
90                         else
91                                 tlib=$(scanmacho -qF'%S#F' "${ED}"/${libdir}/${lib})
92                         fi
93                         [[ -z ${tlib} ]] && die "unable to read install_name from ${lib}"
94                         tlib=${tlib##*/}
95
96                         if ${auto} ; then
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
101                                 fi
102                                 rm -f "${ED}"/${libdir}/${lib}
103                         fi
104
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
114                                 local nowrite=yes
115                         fi
116                         install_name_tool \
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}"
124                         popd > /dev/null
125                         ;;
126                 *)
127                         if ${auto} ; then
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
134                                 fi
135                                 rm -f "${ED}"/${libdir}/${lib}
136                         else
137                                 tlib=${lib}
138                         fi
139                         cat > "${ED}/usr/${libdir}/${lib}" <<-END_LDSCRIPT
140                         /* GNU ld script
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.
146
147                            See bug https://bugs.gentoo.org/4411 for more info.
148                          */
149                         ${output_format}
150                         GROUP ( ${EPREFIX}/${libdir}/${tlib} )
151                         END_LDSCRIPT
152                         ;;
153                 esac
154                 fperms a+x "/usr/${libdir}/${lib}" || die "could not change perms on ${lib}"
155         done
156 }
157
158 fi # _USR_LDSCRIPT_ECLASS