#!/bin/bash # Copyright 2008-2023 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 if [[ $1 == "--help" || $1 == "-h" ]] ; then cat <<-EOF Usage: emerge-wrapper [--target ] <--init|commands for cross-emerge> emerge-wrapper is used in one of two ways: - Use --init to setup cross-toolchain environment(s) - Pass the command line through to cross-emerge EOF exit 0 fi PREFIX="@PREFIX@" # Enable this script to be manually installed while debugging [[ ${PREFIX} == "@"PREFIX"@" ]] && PREFIX="/usr" err() { echo "emerge-wrapper: ERROR: $*" 1>&2; exit 1; } emit_setup_warning() { if ! ${setup_warning} ; then setup_warning=true echo "!!! WARNING - Cannot auto-configure CHOST ${CHOST};" echo "!!! You should edit ${confs[*]}" echo "!!! by hand to complete your configuration." fi echo "!!! $*" } cross_wrap_etc() { [[ $1 == "-q" ]] || echo "${CHOST}: setting up cross basics in ${SYSROOT}/etc" setup_warning=false cp -a "${PREFIX}"/share/crossdev/etc ${SYSROOT}/ || return 1 ln -snf "${MAIN_REPO_PATH}/profiles/embedded" "${SYSROOT}/etc/portage/make.profile" || return 1 local confs=( ${SYSROOT}/etc/portage/make.conf ${SYSROOT}/etc/portage/profile/make.defaults ${SYSROOT}/etc/portage/profile/use.force ) # Re-use existing CHOST->portage ARCH mapping code ARCH=$( inherit() { :; } die() { err "toolchain-funcs.eclass$*"; } EAPI=7 . "${MAIN_REPO_PATH}"/eclass/toolchain-funcs.eclass tc-arch ) [[ $? -ne 0 ]] && err "Failed calling 'tc-arch' from toolchain-funcs.eclass." [[ ${ARCH} == "unknown" ]] && emit_setup_warning "No ARCH is known for this target." LIBC="__LIBC__" case ${CHOST} in *gnu*) LIBC=glibc ;; *uclibc*) LIBC=uclibc-ng ;; *musl*) LIBC=musl ;; *cygwin*) LIBC=Cygwin ;; *mingw*) LIBC=mingw ;; *-newlib|*-elf|*-eabi) LIBC=newlib ;; *) emit_setup_warning "No LIBC is known for this target." ;; esac KERNEL="__KERNEL__" case ${CHOST} in *linux*) KERNEL=linux ;; *mingw*) KERNEL=Winnt ;; *) emit_setup_warning "No KERNEL is known for this target." ;; esac if [[ -n ${KERNEL} ]]; then USE_FORCE_KERNEL="kernel_${KERNEL}" else USE_FORCE_KERNEL="" fi sed -i \ -e "s:__LIBC__:${LIBC}:g" \ -e "s:__ARCH__:${ARCH}:g" \ -e "s:__KERNEL__:${KERNEL}:g" \ -e "s:__USE_FORCE_KERNEL__:${USE_FORCE_KERNEL}:g" \ -e "s:__CHOST__:${CHOST}:g" \ -e "s:__CBUILD__:${CBUILD}:g" \ "${confs[@]}" if [[ "${LLVM}" == "yes" ]] ; then cat <<-EOF >>${SYSROOT}/etc/portage/profile/make.defaults AR=llvm-ar AS=llvm-as CC="${CHOST}-clang" CROSS_COMPILE="${CHOST}-" CXX="${CHOST}-clang++" DLLTOOL=llvm-dlltool HOSTCC="${CC:=clang}" HOSTCXX="${CXX:=clang++}" LD=ld.lld LLVM=1 NM=llvm-nm OBJCOPY=llvm-objcopy RANLIB=llvm-ranlib READELF=llvm-readelf STRIP=llvm-strip EOF fi return 0 } cross_wrap_bin() { [[ $1 == "-q" ]] || echo "${CHOST}: Setting up symlinks" pushd "${0%/*}" >/dev/null local wrapper for wrapper in ebuild emerge fix-root pkg-config ; do ln -sf cross-${wrapper} ${CHOST}-${wrapper} done # some people like their tab completion ln -sf cross-emerge emerge-${CHOST} popd >/dev/null } cross_wrap() { SYSROOT=@GENTOO_PORTAGE_EPREFIX@/usr/${CHOST} cross_wrap_bin "$@" || return $? if [[ -d ${SYSROOT} ]] && [[ ! -d ${SYSROOT}/etc ]] ; then cross_wrap_etc "$@" fi return $? } cross_init() { if [[ ${CHOST} == "wrapper" ]] ; then err "missing --target option" fi # Initialize env for just one target. This is the automated behavior # when crossdev is setting things up for people. cross_wrap -q } # CBUILD must be the first thing we export, but might as well avoid # running portageq multiple times ... import_vars="DISTDIR MAKEOPTS GENTOO_MIRRORS" eval $(portageq envvar -v CBUILD ${import_vars}) export CBUILD MAIN_REPO_PATH=$(crossdev --show-repo-cfg MAIN_REPO_PATH) # Get default CHOST value from program name CHOST=${0##*/} CHOST=${CHOST%-emerge} CHOST=${CHOST#emerge-} export CHOST if [[ $1 == "--target" ]] ; then CHOST=$2 shift 2 fi if [[ $1 == "--init" ]] ; then cross_init exit $? fi if [[ $CHOST == "wrapper" ]] ; then echo "After running this program with the --init option as root" echo "you can call it directly like emerge-wrapper --target CHOST " echo "or using the emerge-CHOST wrappers" exit 1 fi type -P -- ${CHOST}-gcc >/dev/null || err "you need to 'crossdev $CHOST' first" exec cross-emerge "$@"