Skip to content

Commit

Permalink
Merge pull request #2373 from flatcar/krnowak/add-usr-ldscript-eclass…
Browse files Browse the repository at this point in the history
…-to-pkg-auto

Add eclass/usr-ldscript.eclass to package automation
  • Loading branch information
krnowak authored Oct 16, 2024
2 parents 920cbde + 66f10fe commit ecd0d40
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 4 deletions.
4 changes: 1 addition & 3 deletions .github/workflows/portage-stable-packages-list
Original file line number Diff line number Diff line change
Expand Up @@ -461,9 +461,7 @@ eclass/tree-sitter-grammar.eclass
eclass/udev.eclass
eclass/unpacker.eclass
eclass/user-info.eclass
# This file is modified by us to be an empty file, so can't be synced for now.
#
# eclass/usr-ldscript.eclass
eclass/usr-ldscript.eclass
eclass/vcs-clean.eclass
eclass/vcs-snapshot.eclass
eclass/verify-sig.eclass
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,172 @@
# Empty file
# Copyright 2019-2023 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

# @ECLASS: usr-ldscript.eclass
# @MAINTAINER:
# Toolchain Ninjas <toolchain@gentoo.org>
# @SUPPORTED_EAPIS: 7 8
# @BLURB: Defines the gen_usr_ldscript function.

case ${EAPI} in
7|8) ;;
*) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;;
esac

if [[ -z ${_USR_LDSCRIPT_ECLASS} ]]; then
_USR_LDSCRIPT_ECLASS=1

inherit multilib toolchain-funcs

IUSE="split-usr"

# @FUNCTION: gen_usr_ldscript
# @USAGE: [-a] <list of libs to create linker scripts for>
# @DESCRIPTION:
# This function generate linker scripts in /usr/lib for dynamic
# libs in /lib. This is to fix linking problems when you have
# the .so in /lib, and the .a in /usr/lib. What happens is that
# in some cases when linking dynamic, the .a in /usr/lib is used
# instead of the .so in /lib due to gcc/libtool tweaking ld's
# library search path. This causes many builds to fail.
# See bug #4411 for more info.
#
# Note that you should in general use the unversioned name of
# the library (libfoo.so), as ldconfig should usually update it
# correctly to point to the latest version of the library present.
gen_usr_ldscript() {
local lib libdir=$(get_libdir) output_format="" auto=false suffix=$(get_libname)

tc-is-static-only && return
use prefix && return

# The toolchain's sysroot is automatically prepended to paths in this
# script. We therefore need to omit EPREFIX on standalone prefix (RAP)
# systems. prefix-guest (non-RAP) systems don't apply a sysroot so EPREFIX
# is still needed in that case. This is moot because the above line makes
# the function a noop on prefix, but we keep this in case that changes.
local prefix=$(usex prefix-guest "${EPREFIX}" "")

# We only care about stuffing / for the native ABI. #479448
if [[ $(type -t multilib_is_native_abi) == "function" ]] ; then
multilib_is_native_abi || return 0
fi

# Eventually we'd like to get rid of this func completely #417451
case ${CTARGET:-${CHOST}} in
*-darwin*) ;;
*-android*) return 0 ;;
*linux*)
use split-usr || return 0
;;
*) return 0 ;;
esac

# Just make sure it exists
dodir /usr/${libdir}

if [[ $1 == "-a" ]] ; then
auto=true
shift
dodir /${libdir}
fi

# OUTPUT_FORMAT gives hints to the linker as to what binary format
# is referenced ... makes multilib saner
local flags=( ${CFLAGS} ${LDFLAGS} -Wl,--verbose )
if $(tc-getLD) --version | grep -q 'GNU gold' ; then
# If they're using gold, manually invoke the old bfd. #487696
local d="${T}/bfd-linker"
mkdir -p "${d}"
ln -sf $(type -P ${CHOST}-ld.bfd) "${d}"/ld
flags+=( -B"${d}" )
fi
output_format=$($(tc-getCC) "${flags[@]}" 2>&1 | sed -n 's/^OUTPUT_FORMAT("\([^"]*\)",.*/\1/p')
[[ -n ${output_format} ]] && output_format="OUTPUT_FORMAT ( ${output_format} )"

for lib in "$@" ; do
local tlib
if ${auto} ; then
lib="lib${lib}${suffix}"
else
# Ensure /lib/${lib} exists to avoid dangling scripts/symlinks.
# This especially is for AIX where $(get_libname) can return ".a",
# so /lib/${lib} might be moved to /usr/lib/${lib} (by accident).
[[ -r ${ED}/${libdir}/${lib} ]] || continue
#TODO: better die here?
fi

case ${CTARGET:-${CHOST}} in
*-darwin*)
if ${auto} ; then
tlib=$(scanmacho -qF'%S#F' "${ED}"/usr/${libdir}/${lib})
else
tlib=$(scanmacho -qF'%S#F' "${ED}"/${libdir}/${lib})
fi
[[ -z ${tlib} ]] && die "unable to read install_name from ${lib}"
tlib=${tlib##*/}

if ${auto} ; then
mv "${ED}"/usr/${libdir}/${lib%${suffix}}.*${suffix#.} "${ED}"/${libdir}/ || die
# some install_names are funky: they encode a version
if [[ ${tlib} != ${lib%${suffix}}.*${suffix#.} ]] ; then
mv "${ED}"/usr/${libdir}/${tlib%${suffix}}.*${suffix#.} "${ED}"/${libdir}/ || die
fi
rm -f "${ED}"/${libdir}/${lib}
fi

# Mach-O files have an id, which is like a soname, it tells how
# another object linking against this lib should reference it.
# Since we moved the lib from usr/lib into lib this reference is
# wrong. Hence, we update it here. We don't configure with
# libdir=/lib because that messes up libtool files.
# Make sure we don't lose the specific version, so just modify the
# existing install_name
if [[ ! -w "${ED}/${libdir}/${tlib}" ]] ; then
chmod u+w "${ED}/${libdir}/${tlib}" || die # needed to write to it
local nowrite=yes
fi
install_name_tool \
-id "${EPREFIX}"/${libdir}/${tlib} \
"${ED}"/${libdir}/${tlib} || die "install_name_tool failed"
if [[ -n ${nowrite} ]] ; then
chmod u-w "${ED}/${libdir}/${tlib}" || die
fi
# Now as we don't use GNU binutils and our linker doesn't
# understand linker scripts, just create a symlink.
pushd "${ED}/usr/${libdir}" > /dev/null
ln -snf "../../${libdir}/${tlib}" "${lib}"
popd > /dev/null
;;
*)
if ${auto} ; then
tlib=$(scanelf -qF'%S#F' "${ED}"/usr/${libdir}/${lib})
[[ -z ${tlib} ]] && die "unable to read SONAME from ${lib}"
mv "${ED}"/usr/${libdir}/${lib}* "${ED}"/${libdir}/ || die
# some SONAMEs are funky: they encode a version before the .so
if [[ ${tlib} != ${lib}* ]] ; then
mv "${ED}"/usr/${libdir}/${tlib}* "${ED}"/${libdir}/ || die
fi
rm -f "${ED}"/${libdir}/${lib}
else
tlib=${lib}
fi
cat > "${ED}/usr/${libdir}/${lib}" <<-END_LDSCRIPT
/* GNU ld script
Since Gentoo has critical dynamic libraries in /lib, and the static versions
in /usr/lib, we need to have a "fake" dynamic lib in /usr/lib, otherwise we
run into linking problems. This "fake" dynamic lib is a linker script that
redirects the linker to the real lib. And yes, this works in the cross-
compiling scenario as the sysroot-ed linker will prepend the real path.
See bug https://bugs.gentoo.org/4411 for more info.
*/
${output_format}
GROUP ( ${prefix}/${libdir}/${tlib} )
END_LDSCRIPT
;;
esac
fperms a+x "/usr/${libdir}/${lib}" || die "could not change perms on ${lib}"
done
}

fi # _USR_LDSCRIPT_ECLASS

0 comments on commit ecd0d40

Please sign in to comment.