I also intend to add another wrapper script generation function for running executables while changing the root directory.
Signed-off-by: James Le Cuirot <ch...@gentoo.org> --- eclass/sysroot.eclass | 85 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 eclass/sysroot.eclass diff --git a/eclass/sysroot.eclass b/eclass/sysroot.eclass new file mode 100644 index 0000000000000..14f1d251b773d --- /dev/null +++ b/eclass/sysroot.eclass @@ -0,0 +1,85 @@ +# Copyright 2025 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +# @ECLASS: sysroot.eclass +# @MAINTAINER: +# cr...@gentoo.org +# @AUTHOR: +# James Le Cuirot <ch...@gentoo.org> +# @SUPPORTED_EAPIS: 7 8 +# @BLURB: Common functions for using a different sysroot (e.g. cross-compiling) + +case ${EAPI} in + 7|8) ;; + *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;; +esac + +# @FUNCTION: qemu_arch +# @DESCRIPTION: +# Return the QEMU architecture name for the given target or CHOST. This name is +# used in qemu-user binary filenames, e.g. qemu-ppc64le. +qemu_arch() { + local target=${1:-${CHOST}} + case ${target} in + armeb*) echo armeb ;; + arm*) echo arm ;; + hppa*) echo hppa ;; + i?86*) echo i386 ;; + m68*) echo m68k ;; + mips64el*-gnuabi64) echo mips64el ;; + mips64el*-gnuabin32) echo mipsn32el ;; + mips64*-gnuabi64) echo mips64 ;; + mips64*-gnuabin32) echo mipsn32 ;; + powerpc64le*) echo ppc64le ;; + powerpc64*) echo ppc64 ;; + powerpc*) echo ppc ;; + *) echo "${target%%-*}" ;; + esac +} + +# @FUNCTION: sysroot_make_run_prefixed +# @DESCRIPTION: +# Create a wrapper script for directly running executables within a sysroot +# without changing the root directory. The path to that script is returned. If +# no sysroot has been set, then this function returns unsuccessfully. +# +# The script explicitly uses QEMU if this is necessary and it is available in +# this environment. It may otherwise implicitly use a QEMU outside this +# environment if binfmt_misc has been used with the F flag. It is not feasible +# to add a conditional dependency on QEMU. +sysroot_make_run_prefixed() { + [[ -z ${SYSROOT} ]] && return 1 + + local SCRIPT="${T}"/sysroot-run-prefixed + local QEMU_ARCH=$(qemu_arch) + + # Both methods below might need help to find GCC's libraries. GCC might not + # even be installed in the SYSROOT. Note that Clang supports this flag too. + local LIBGCC=$($(tc-getCC) ${CPPFLAGS} ${CFLAGS} ${LDFLAGS} -print-libgcc-file-name) + + if [[ ${QEMU_ARCH} == $(qemu_arch "${CBUILD}") ]]; then + # glibc: ld.so is a symlink, ldd is a binary. + # musl: ld.so doesn't exist, ldd is a symlink. + local DYNLINKER=$(find "${ESYSROOT}"/usr/bin/{ld.so,ldd} -type l -print -quit 2>/dev/null || die "failed to find dynamic linker") + + # musl symlinks ldd to ld-musl.so to libc.so. We want the ld-musl.so + # path, not the libc.so path, so don't resolve the symlinks entirely. + DYNLINKER=$(readlink -ev "${DYNLINKER}" || die "failed to find dynamic linker") + + # Using LD_LIBRARY_PATH to set the prefix is not perfect, as it doesn't + # adjust RUNPATHs, but it is probably good enough. + install -m0755 /dev/stdin "${SCRIPT}" <<-EOF || die + #!/bin/sh + LD_LIBRARY_PATH="\${LD_LIBRARY_PATH}\${LD_LIBRARY_PATH+:}${LIBGCC%/*}:${ESYSROOT}/$(get_libdir):${ESYSROOT}/usr/$(get_libdir)" exec "${DYNLINKER}" "\${@}" + EOF + else + # Use QEMU's environment variables rather than its command line + # arguments to cover both explicit and implicit QEMU usage. + install -m0755 /dev/stdin "${SCRIPT}" <<-EOF || die + #!/bin/sh + QEMU_SET_ENV="\${QEMU_SET_ENV}\${QEMU_SET_ENV+,}LD_LIBRARY_PATH=\${LD_LIBRARY_PATH}\${LD_LIBRARY_PATH+:}${LIBGCC%/*}" QEMU_LD_PREFIX="${SYSROOT}" exec $(type -P "qemu-${QEMU_ARCH}") "\${@}" + EOF + fi + + echo "${SCRIPT}" +} -- 2.49.0