Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add eclass/usr-ldscript.eclass to package automation #2373

Merged
merged 2 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading