# Copyright 1999-2006 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header$ # Filter which environment variables to save/restore. _select_saved_vars() { egrep -v "^(LD_PRELOAD|SANDBOX_|PORTAGE_|DISTCC_|CCACHE_|current_vars|target_vars|var|file|abi)" } # We need to save/restore the environment for each ABI we are installing for separately save_abi_env() { local file if [ "$#" = "1" ]; then file="${T}/environment.${1}" else file="${T}/environment" fi local oldumask=$(umask) umask 002 set | _select_saved_vars > ${file} || die "Unable to save environment settings." export -p | sed 's:declare -r\{0,1\}x ::' | _select_saved_vars | sed 's:^:declare -x :' >> ${file} || die "Unable to save environment settings." chown portage:portage ${file} &>/dev/null chmod g+w ${file} &>/dev/null umask ${oldumask} } restore_abi_env() { local file if [ "$#" = "1" -a -f "${T}/environment.${1}" ]; then file="${T}/environment.${1}" elif [ -f "${T}/environment" ]; then file="${T}/environment" else return fi local current_vars=$(set | egrep '^[_A-Za-z0-9]+=' | cut -f1 -d= | _select_saved_vars) local target_vars=$(cat ${file} | egrep '^[_A-Za-z0-9]+=' | cut -f1 -d= | _select_saved_vars) for var in ${current_vars}; do if ! hasq ${var} ${target_vars}; then # Redirect to /dev/null so we don't get spam'd about # any read-only variables. if hasq auto-multilib-debug ${FEATURES}; then echo ">>> Unsetting: ${var}=${!var}" fi unset ${var} &>/dev/null fi done source ${file} &>/dev/null || die "IO Failure in restore_abi_env" } get_abi_order() { local order= dodefault= for y in ${USE}; do [[ ${y} =~ "multilib_abis_" ]] || continue x=${y/multilib_abis_/} if [ "${x}" != "${DEFAULT_ABI}" ]; then order="${order} ${x}" else dodefault=1 fi done [ "$dodefault" ] && order="${order} ${DEFAULT_ABI}" order=${order:-${DEFAULT_ABI}} if [ -z "${order}" ]; then die "Could not determine your profile ABI(s). Perhaps your USE flags or ABIS, or MULTILIB_ABIS are too restrictive for this package or your profile does not set DEFAULT_ABI." fi echo ${order} } get_mabi_order() { #echo $(for XX in $(get_abi_order); do echo multilib_abis_${XX}; done) echo $(for XX in $(get_abi_order); do echo abis_${XX}; done) } set_abi() { if [ "$#" != "1" ]; then die "set_abi needs to be given the ABI to use." fi local abi=${1} # Save ABI if it is already set if [ -n "${ABI}" -a -z "${ABI_SAVE}" ]; then ABI_SAVE=${ABI} fi if [ -d "${WORKDIR}" ]; then _unset_abi_dir else save_abi_env fi restore_abi_env ${abi} if [ -d "${WORKDIR}.${abi}" ]; then # If it doesn't exist, then we're making it soon in dyn_unpack mv ${WORKDIR}.${abi} ${WORKDIR} || die "IO Failure -- Failed to 'mv work.${abi} work'" fi echo "${abi}" > ${PORTAGE_BUILDDIR}/.abi || die "IO Failure -- Failed to create .abi." # Export variables we need for toolchain export ABI="${abi}" echo ">>> ABI=${ABI}" local VAR VAR="CFLAGS_${ABI}" [ -n "${!VAR}" ] && eval export ${VAR} VAR="ASFLAGS_${ABI}" [ -n "${!VAR}" ] && eval export ${VAR} } _unset_abi_dir() { if [ -f "${PORTAGE_BUILDDIR}/.abi" ]; then local abi=$(cat ${PORTAGE_BUILDDIR}/.abi) [ ! -d "${WORKDIR}" ] && die "unset_abi: .abi present (${abi}) but workdir not present." save_abi_env ${abi} restore_abi_env mv ${WORKDIR} ${WORKDIR}.${abi} || die "IO Failure -- Failed to 'mv work work.${abi}'." rm -rf ${PORTAGE_BUILDDIR}/.abi || die "IO Failure -- Failed to 'rm -rf .abi'." fi } unset_abi() { _unset_abi_dir if [ -n "${ABI_SAVE}" ]; then export ABI=${ABI_SAVE} else unset ABI fi } # Remove symlinks for alternate ABIs so that packages that use # symlink without using the force option to ln ("-f"). # # Also, create multilib header redirects if any of the headers # differ between ABIs. # # ABI_HEADER_DIRS defaults to /usr/include but the ebuild can override # _finalize_abi_install() { local ALL_ABIS=$(get_abi_order) local ALTERNATE_ABIS=${ALL_ABIS% *} local dirs=${ABI_HEADER_DIRS-/usr/include} local base= # Sanity check ABI variables [ "${ALL_ABIS}" != "${ALL_ABIS/ /}" ] || return 0; [ -n "${ABI}" ] && [ -n "${DEFAULT_ABI}" ] || return 0; # Save header files for each ABI for dir in ${dirs}; do [ -d "${D}/${dir}" ] || continue vecho ">>> Saving headers (for ABI=${ABI})" base=${T}/gentoo-multilib/${dir}/gentoo-multilib mkdir -p ${base} [ -d ${base}/${ABI} ] && rm -rf ${base}/${ABI} mv ${D}/${dir} ${base}/${ABI} || die "ABI header save failed" done # Symlinks are not overwritten without the "-f" option, so # remove them in non-default ABI if [ "${ABI}" != "${DEFAULT_ABI}" ]; then vecho ">>> Removing installed symlinks (for ABI=${ABI})" find ${D} -type l ! -regex '.*/lib[0-9]*/.*' -exec rm -f {} \; fi # After final ABI is installed, if headers differ # then create multilib header redirects if [ "${ABI}" = "${DEFAULT_ABI}" ]; then local diffabi= abis_differ= for dir in ${dirs}; do base=${T}/gentoo-multilib/${dir}/gentoo-multilib [ -d "${base}" ] || continue for diffabi in ${ALTERNATE_ABIS}; do diff -rNq ${base}/${ABI} ${base}/${diffabi} || abis_differ=1 done done if [ -z "${abis_differ}" ]; then # No differences, restore original header files for default ABI for dir in ${dirs}; do base=${T}/gentoo-multilib/${dir}/gentoo-multilib [ -d "${base}" ] || continue mv ${base}/${ABI} ${D}/${dir} \ || die "ABI header restore failed" done else # ABIS differ vecho ">>> Creating multilib headers" base=${T}/gentoo-multilib pushd "${base}" find . | tar -c -T - -f - | tar -x --no-same-owner -f - -C ${D} popd # This 'set' stuff is required by mips profiles to properly pass # CDEFINE's (which have spaces) to sub-functions set -- for dir in ${dirs} ; do set -- "$@" "${dir}" for diffabi in ${ALL_ABIS}; do local define_var=CDEFINE_${diffabi} set -- "$@" "${!define_var}:${dir}/gentoo-multilib/${diffabi}" done _create_abi_includes "$@" done fi fi # Create config file redirects based on # ${ABI_REDIRECT_PROGS} if [ -n "${ABI_REDIRECT_PROGS}" ]; then create_config_redirect fi } # Redirect *-config routines to honor ABI # This can be called from src_install() with the path to the already # installed *-config program. Or the ABI_REDIRECT_PROGS variable can # be used to specify the file(s) to redirect. create_config_redirect() { local cfile for cfile in ${1} ${ABI_REDIRECT_PROGS}; do local mypath= # Allow the caller to use prog-name, install or final path if [ -f ${D}/usr/bin/${cfile} ]; then mypath=${D}/usr/bin/${cfile} elif [ -f ${D}/${cfile} ]; then mypath=${D}/${cfile} elif [ -f ${cfile} ]; then mypath=${cfile} fi [ -f "${mypath}" ] || continue grep -qs "Redirect based on ABI" "${mypath}" && continue mkdir -p "${D}"/usr/$(get_libdir)/config-progs mv ${mypath} "${D}"/usr/$(get_libdir)/config-progs/ cat > ${mypath} <: where is what is put in the #ifdef for # choosing that dir. # # Ideas for this code came from debian's sparc-linux headers package. # # Example: # _create_abi_includes /usr/include/asm __sparc__:/usr/include/asm-sparc __sparc64__:/usr/include/asm-sparc64 # _create_abi_includes /usr/include/asm __i386__:/usr/include/asm-i386 __x86_64__:/usr/include/asm-x86_64 # # Warning: Be careful with the ordering here. The default ABI has to be the # last, because it is always defined (by GCC) _create_abi_includes() { local dest=$1 shift local basedirs=$(_create_abi_includes-listdirs "$@") _create_abi_includes-makedestdirs ${dest} ${basedirs} local file for file in $(_create_abi_includes-allfiles ${basedirs}) ; do #local name=$(echo ${file} | tr '[:lower:]' '[:upper:]' | sed 's:[^[:upper:]]:_:g') ( echo "/* Autogenerated by by portage FEATURE auto-multilib */" local dir for dir in ${basedirs}; do if [[ -f ${D}/${dir}/${file} ]] ; then echo "" local sym=$(_create_abi_includes-sym_for_dir ${dir} "$@") if [[ ${sym/=} != "${sym}" ]] ; then echo "#if ${sym}" elif [[ ${sym::1} == "!" ]] ; then echo "#ifndef ${sym:1}" else echo "#ifdef ${sym}" fi echo "# include <$(_create_abi_includes-absolute ${dir}/${file})>" echo "#endif /* ${sym} */" fi done #echo "#endif /* __CREATE_ABI_INCLUDES_STUB_${name}__ */" ) > "${D}/${dest}/${file}" done } # Helper function for _create_abi_includes _create_abi_includes-absolute() { local dst="$(_create_abi_includes-tidy_path $1)" dst=(${dst//\// }) local i for ((i=0; i<${#dst[*]}; i++)); do [ "${dst[i]}" == "include" ] && break done local strip_upto=$i for ((i=strip_upto+1; i<${#dst[*]}-1; i++)); do echo -n ${dst[i]}/ done echo -n ${dst[i]} } # Helper function for _create_abi_includes _create_abi_includes-tidy_path() { local removed=$1 if [ -n "${removed}" ]; then # Remove multiple slashes while [ "${removed}" != "${removed/\/\//\/}" ]; do removed=${removed/\/\//\/} done # Remove . directories while [ "${removed}" != "${removed//\/.\//\/}" ]; do removed=${removed//\/.\//\/} done [ "${removed##*/}" = "." ] && removed=${removed%/*} # Removed .. directories while [ "${removed}" != "${removed//\/..\/}" ]; do local p1="${removed%%\/..\/*}" local p2="${removed#*\/..\/}" removed="${p1%\/*}/${p2}" done # Remove trailing .. [ "${removed##*/}" = ".." ] && removed=${removed%/*/*} # Remove trailing / [ "${removed##*/}" = "" ] && removed=${removed%/*} echo ${removed} fi } # Helper function for create_abi_includes _create_abi_includes-listdirs() { local dirs local data for data in "$@"; do dirs="${dirs} ${data/*:/}" done echo ${dirs:1} } # Helper function for _create_abi_includes _create_abi_includes-makedestdirs() { local dest=$1 shift local basedirs=$@ dodir ${dest} local basedir for basedir in ${basedirs}; do local dir for dir in $(find ${D}/${basedir} -type d); do dodir ${dest}/${dir/${D}\/${basedir}/} done done } # Helper function for _create_abi_includes _create_abi_includes-allfiles() { local basedir file for basedir in "$@" ; do for file in $(find "${D}"/${basedir} -type f); do echo ${file/${D}\/${basedir}\//} done done | sort | uniq } # Helper function for _create_abi_includes _create_abi_includes-sym_for_dir() { local dir=$1 shift local data for data in "$@"; do if [[ ${data} == *:${dir} ]] ; then echo ${data/:*/} return 0 fi done echo "Shouldn't be here -- _create_abi_includes-sym_for_dir $1 $@" # exit because we'll likely be called from a subshell exit 1 }