# Copyright 1999-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/sys-libs/glibc/files/eblits/common.eblit,v 1.45 2014/10/18 23:09:51 vapier Exp $

alt_prefix() {
	is_crosscompile && echo /usr/${CTARGET}
}

if [[ ${EAPI:-0} == [012] ]] ; then
	: ${ED:=${D}}
	: ${EROOT:=${ROOT}}
fi
# This indirection is for binpkgs. #523332
_nonfatal() { nonfatal "$@" ; }
if [[ ${EAPI:-0} == [0123] ]] ; then
	nonfatal() { "$@" ; }
	_nonfatal() { "$@" ; }
fi

# We need to be able to set alternative headers for
# compiling for non-native platform
# Will also become useful for testing kernel-headers without screwing up
# the whole system.
# note: intentionally undocumented.
alt_headers() {
	echo ${ALT_HEADERS:=$(alt_prefix)/usr/include}
}
alt_build_headers() {
	if [[ -z ${ALT_BUILD_HEADERS} ]] ; then
		ALT_BUILD_HEADERS=$(alt_headers)
		if tc-is-cross-compiler ; then
			ALT_BUILD_HEADERS=${SYSROOT}$(alt_headers)
			if [[ ! -e ${ALT_BUILD_HEADERS}/linux/version.h ]] ; then
				local header_path=$(echo '#include <linux/version.h>' | $(tc-getCPP ${CTARGET}) ${CFLAGS} 2>&1 | grep -o '[^"]*linux/version.h')
				ALT_BUILD_HEADERS=${header_path%/linux/version.h}
			fi
		fi
	fi
	echo "${ALT_BUILD_HEADERS}"
}

alt_libdir() {
	echo $(alt_prefix)/$(get_libdir)
}
alt_usrlibdir() {
	echo $(alt_prefix)/usr/$(get_libdir)
}

builddir() {
	echo "${WORKDIR}/build-${ABI}-${CTARGET}-$1"
}

setup_target_flags() {
	# This largely mucks with compiler flags.  None of which should matter
	# when building up just the headers.
	just_headers && return 0

	case $(tc-arch) in
		x86)
			# -march needed for #185404 #199334
			if ! glibc_compile_test "" 'void f(int i, void *p) {if (__sync_fetch_and_add(&i, 1)) f(i, p);}\nint main(){return 0;}\n' 2>/dev/null ; then
				local t=${CTARGET_OPT:-${CTARGET}}
				t=${t%%-*}
				filter-flags '-march=*'
				export CFLAGS="-march=${t} ${CFLAGS}"
				einfo "Auto adding -march=${t} to CFLAGS #185404"
			fi
		;;
		amd64)
			# -march needed for #185404 #199334
			if ! glibc_compile_test "${CFLAGS_x86}" 'void f(int i, void *p) {if (__sync_fetch_and_add(&i, 1)) f(i, p);}\nint main(){return 0;}\n' 2>/dev/null ; then
				local t=${CTARGET_OPT:-${CTARGET}}
				t=${t%%-*}
				filter-flags '-march=*'
				# ugly, ugly, ugly.  ugly.
				CFLAGS_x86=$(CFLAGS=${CFLAGS_x86} filter-flags '-march=*'; echo "${CFLAGS}")
				export CFLAGS_x86="${CFLAGS_x86} -march=${t}"
				einfo "Auto adding -march=${t} to CFLAGS_x86 #185404"
			fi
		;;
		ppc)
			append-flags "-freorder-blocks"
		;;
		sparc)
			# Both sparc and sparc64 can use -fcall-used-g6.  -g7 is bad, though.
			filter-flags "-fcall-used-g7"
			append-flags "-fcall-used-g6"
			filter-flags "-mvis"

			GLIBCMAJOR=$(get_version_component_range 1 ${PV})
			GLIBCMINOR=$(get_version_component_range 2 ${PV})

			# set CTARGET_OPT so glibc can use cpu-specific .S files for better performance
			# - UltraSPARC T1 (niagara) support requires >= glibc 2.8
			# - UltraSPARC T2 (niagara2) support requires >= glibc 2.7

			if is_crosscompile || [[ ${PROFILE_ARCH} == "sparc64" ]] || { has_multilib_profile && ! tc-is-cross-compiler; } ; then
				case ${ABI}:${CTARGET} in
					sparc64:*|\
					default:sparc64*)
						filter-flags -Wa,-xarch -Wa,-A

						if is-flagq "-mcpu=niagara2" && [[ ${GLIBCMAJOR}.${GLIBCMINOR} > 2.7 ]] ; then
							CTARGET_OPT="sparc64v2-unknown-linux-gnu"
							append-flags "-Wa,-xarch=v9b"
							export ASFLAGS="${ASFLAGS} -Wa,-xarch=v9b"
						elif { is-flagq "-mcpu=niagara" || is-flagq "-mcpu=niagara2" ; } && [[ ${GLIBCMAJOR}.${GLIBCMINOR} > 2.6 ]] ; then
							CTARGET_OPT="sparc64v-unknown-linux-gnu"
							append-flags "-Wa,-xarch=v9b"
							export ASFLAGS="${ASFLAGS} -Wa,-xarch=v9b"
						elif is-flagq "-mcpu=ultrasparc3" || is-flagq "-mcpu=niagara" || is-flagq "-mcpu=niagara2"; then
							CTARGET_OPT="sparc64b-unknown-linux-gnu"
							append-flags "-Wa,-xarch=v9b"
							export ASFLAGS="${ASFLAGS} -Wa,-xarch=v9b"
						else
							CTARGET_OPT="sparc64-unknown-linux-gnu"
							append-flags "-Wa,-xarch=v9a"
							export ASFLAGS="${ASFLAGS} -Wa,-xarch=v9a"
						fi
					;;
					*)
						if is-flagq "-mcpu=niagara2" && [[ ${GLIBCMAJOR}.${GLIBCMINOR} > 2.7 ]] ; then
							CTARGET_OPT="sparcv9v2-unknown-linux-gnu"
						elif { is-flagq "-mcpu=niagara" || is-flagq "-mcpu=niagara2" ; } && [[ ${GLIBCMAJOR}.${GLIBCMINOR} > 2.6 ]] ; then
							CTARGET_OPT="sparcv9v-unknown-linux-gnu"
						elif is-flagq "-mcpu=ultrasparc3" || is-flagq "-mcpu=niagara" || is-flagq "-mcpu=niagara2"; then
							CTARGET_OPT="sparcv9b-unknown-linux-gnu"
						else
							CTARGET_OPT="sparcv9-unknown-linux-gnu"
						fi
					;;
				esac
			else
				if is-flagq "-mcpu=niagara2" && [[ ${GLIBCMAJOR}.${GLIBCMINOR} > 2.7 ]] ; then
					CTARGET_OPT="sparcv9v2-unknown-linux-gnu"
				elif { is-flagq "-mcpu=niagara" || is-flagq "-mcpu=niagara2" ; } && [[ ${GLIBCMAJOR}.${GLIBCMINOR} > 2.6 ]] ; then
					CTARGET_OPT="sparcv9v-unknown-linux-gnu"
				elif is-flagq "-mcpu=ultrasparc3" || is-flagq "-mcpu=niagara" || is-flagq "-mcpu=niagara2"; then
					CTARGET_OPT="sparcv9b-unknown-linux-gnu"
				elif { is_crosscompile && want_nptl; } || is-flagq "-mcpu=ultrasparc2" || is-flagq "-mcpu=ultrasparc"; then
					CTARGET_OPT="sparcv9-unknown-linux-gnu"
				fi
			fi
		;;
	esac
}

setup_flags() {
	# Make sure host make.conf doesn't pollute us
	if is_crosscompile || tc-is-cross-compiler ; then
		CHOST=${CTARGET} strip-unsupported-flags
	fi

	# Store our CFLAGS because it's changed depending on which CTARGET
	# we are building when pulling glibc on a multilib profile
	CFLAGS_BASE=${CFLAGS_BASE-${CFLAGS}}
	CFLAGS=${CFLAGS_BASE}
	CXXFLAGS_BASE=${CXXFLAGS_BASE-${CXXFLAGS}}
	CXXFLAGS=${CXXFLAGS_BASE}
	ASFLAGS_BASE=${ASFLAGS_BASE-${ASFLAGS}}
	ASFLAGS=${ASFLAGS_BASE}

	# Over-zealous CFLAGS can often cause problems.  What may work for one
	# person may not work for another.  To avoid a large influx of bugs
	# relating to failed builds, we strip most CFLAGS out to ensure as few
	# problems as possible.
	strip-flags
	strip-unsupported-flags
	filter-flags -m32 -m64 -mabi=*

	# Bug 492892.
	filter-flags -frecord-gcc-switches

	unset CBUILD_OPT CTARGET_OPT
	if use multilib ; then
		CTARGET_OPT=$(get_abi_CTARGET)
		[[ -z ${CTARGET_OPT} ]] && CTARGET_OPT=$(get_abi_CHOST)
	fi

	setup_target_flags

	if [[ -n ${CTARGET_OPT} && ${CBUILD} == ${CHOST} ]] && ! is_crosscompile; then
		CBUILD_OPT=${CTARGET_OPT}
	fi

	# Lock glibc at -O2 -- linuxthreads needs it and we want to be
	# conservative here.  -fno-strict-aliasing is to work around #155906
	filter-flags -O?
	append-flags -O2 -fno-strict-aliasing

	# Can't build glibc itself with fortify code.  Newer versions add
	# this flag for us, so no need to do it manually.
	version_is_at_least 2.16 ${PV} || append-cppflags -U_FORTIFY_SOURCE

	# building glibc with SSP is fraught with difficulty, especially
	# due to __stack_chk_fail_local which would mean significant changes
	# to the glibc build process. See bug #94325 #293721
	# Note we have to handle both user-given CFLAGS and gcc defaults via
	# spec rules here.  We can't simply add -fno-stack-protector as it gets
	# added before user flags, and we can't just filter-flags because
	# _filter_hardened doesn't support globs.
	filter-flags -fstack-protector*
	gcc-specs-ssp && append-flags $(test-flags -fno-stack-protector)

	if use hardened && gcc-specs-pie ; then
		# Force PIC macro definition for all compilations since they're all
		# either -fPIC or -fPIE with the default-PIE compiler.
		append-cppflags -DPIC
	else
		# Don't build -fPIE without the default-PIE compiler and the
		# hardened-pie patch
		filter-flags -fPIE
	fi
}

want_nptl() {
	[[ -z ${LT_VER} ]] && return 0
	want_tls || return 1
	use nptl || return 1

	# Older versions of glibc had incomplete arch support for nptl.
	# But if you're building those now, you can handle USE=nptl yourself.
	return 0
}

want_linuxthreads() {
	[[ -z ${LT_VER} ]] && return 1
	use linuxthreads
}

want_tls() {
	# Archs that can use TLS (Thread Local Storage)
	case $(tc-arch) in
		x86)
			# requires i486 or better #106556
			[[ ${CTARGET} == i[4567]86* ]] && return 0
			return 1
		;;
	esac

	return 0
}

want__thread() {
	want_tls || return 1

	# For some reason --with-tls --with__thread is causing segfaults on sparc32.
	[[ ${PROFILE_ARCH} == "sparc" ]] && return 1

	[[ -n ${WANT__THREAD} ]] && return ${WANT__THREAD}

	# only test gcc -- cant test linking yet
	tc-has-tls -c ${CTARGET}
	WANT__THREAD=$?

	return ${WANT__THREAD}
}

use_multiarch() {
	# Make sure binutils is new enough to support indirect functions #336792
	# This funky sed supports gold and bfd linkers.
	local bver nver
	bver=$($(tc-getLD ${CTARGET}) -v | sed -n -r '1{s:[^0-9]*::;s:^([0-9.]*).*:\1:;p}')
	case $(tc-arch ${CTARGET}) in
	amd64|x86) nver="2.20" ;;
	arm)       nver="2.22" ;;
	hppa)      nver="2.23" ;;
	ppc|ppc64) nver="2.20" ;;
	# ifunc was added in 2.23, but glibc also needs machinemode which is in 2.24.
	s390)      nver="2.24" ;;
	sparc)     nver="2.21" ;;
	*)         return 1 ;;
	esac
	version_is_at_least ${nver} ${bver}
}

# Setup toolchain variables that had historically
# been defined in the profiles for these archs.
setup_env() {
	# silly users
	unset LD_RUN_PATH
	unset LD_ASSUME_KERNEL

	multilib_env ${CTARGET_OPT:-${CTARGET}}
	if is_crosscompile || tc-is-cross-compiler ; then
		if ! use multilib ; then
			MULTILIB_ABIS=${DEFAULT_ABI}
		else
			MULTILIB_ABIS=${MULTILIB_ABIS:-${DEFAULT_ABI}}
		fi

		# If the user has CFLAGS_<CTARGET> in their make.conf, use that,
		# and fall back on CFLAGS.
		local VAR=CFLAGS_${CTARGET//[-.]/_}
		CFLAGS=${!VAR-${CFLAGS}}
	fi

	setup_flags

	export ABI=${ABI:-${DEFAULT_ABI:-default}}

	local VAR=CFLAGS_${ABI}
	# We need to export CFLAGS with abi information in them because glibc's
	# configure script checks CFLAGS for some targets (like mips).  Keep
	# around the original clean value to avoid appending multiple ABIs on
	# top of each other.
	: ${__GLIBC_CC:=$(tc-getCC ${CTARGET_OPT:-${CTARGET}})}
	export __GLIBC_CC CC="${__GLIBC_CC} ${!VAR}"
}

foreach_abi() {
	setup_env

	local ret=0
	local abilist=""
	if use multilib ; then
		abilist=$(get_install_abis)
	else
		abilist=${DEFAULT_ABI}
	fi
	evar_push ABI
	export ABI
	for ABI in ${abilist:-default} ; do
		setup_env
		einfo "Running $1 for ABI ${ABI}"
		$1
		: $(( ret |= $? ))
	done
	evar_pop
	return ${ret}
}

just_headers() {
	is_crosscompile && use crosscompile_opts_headers-only
}

glibc_banner() {
	local b="Gentoo ${PVR}"
	[[ -n ${SNAP_VER} ]] && b+=" snapshot ${SNAP_VER}"
	[[ -n ${BRANCH_UPDATE} ]] && b+=" branch ${BRANCH_UPDATE}"
	[[ -n ${PATCH_VER} ]] && ! use vanilla && b+=" p${PATCH_VER}"
	echo "${b}"
}