#!/bin/bash # Copyright 1999-2004 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: /var/cvsroot/gentoo-x86/sys-devel/gcc-config/files/gcc-config-1.3.7,v 1.5 2004/11/28 16:39:49 lv Exp $ # Author: Martin Schlemmer trap ":" INT QUIT TSTP source /etc/init.d/functions.sh || { echo "$0: Could not source /etc/init.d/functions.sh!" exit 1 } umask 022 usage() { cat << "USAGE_END" Usage: gcc-config [options] [CC Profile] Change the current cc/gcc profile, or give info about profiles. Options: -O, --use-old Use the old profile if one was selected. -P, --use-portage-chost Only set to given profile if its CHOST is the same as that set for portage in /etc/make.conf (or one of other portage config files...). -c, --get-current-profile Print current used gcc profile. -l, --list-profiles Print a list of available profiles. -E, --print-environ Print environment that can be used to setup the current gcc profile, or a specified one. -B, --get-bin-path Print path where binaries of the given/current profile are located. -L, --get-lib-path Print path where libraries of the given/current profile are located. -X, --get-stdcxx-incdir Print path where g++ include files of the given/current profile are located. Profile names are of the form: - For example: i686-pc-linux-gnu-3.2.1 USAGE_END exit 1 } if [ "$#" -lt 1 ] then usage fi find_path() { [ -z "$1" ] && return 0 local fullpath="$(type -P $1)" if [ -x "${fullpath}" ] then echo "${fullpath}" return 0 fi for x in /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin do if [ -x "${x}/$1" -a -r "${x}/$1" ] then echo "${x}/$1" return 0 fi done return 0 } cmd_setup() { # Sourcing /etc/env.d/gcc/${CC_COMP} is going to mess up # PATH among things... CP="$(find_path cp)" RM="$(find_path rm)" MV="$(find_path mv)" LN="$(find_path ln)" CAT="$(find_path cat)" AWK="$(find_path gawk)" GREP="$(find_path grep)" FIND="$(find_path find)" CHMOD="$(find_path chmod)" TOUCH="$(find_path touch)" ENV_UPDATE="$(find_path env-update)" } get_real_chost() { [ -n "${REAL_CHOST}" ] && return 0 # Use absolute path until all protage versions have portageq in /usr/bin export REAL_CHOST="$(/usr/lib/portage/bin/portageq envvar CHOST)" if [ -z "${REAL_CHOST}" ] then eerror "$0: Could not get portage CHOST!" return 1 fi } switch_profile() { local MY_LDPATH= local GCC_PROFILES= local OLD_CC_COMP= local GCC_BIN_PATH= if [ "$(id -u)" -ne 0 ] then eerror "$0: Must be root." exit 1 fi if [ -r "${GCC_ENV_D}/config" ] then source "${GCC_ENV_D}/config" if [ -n "${CURRENT}" ] then OLD_CC_COMP="${CURRENT}" fi fi ebegin "Switching to ${CC_COMP} compiler" # Sourcing /etc/env.d/gcc/${CC_COMP} is going to mess up # PATH among things... cmd_setup # Order our profiles to have the default first ... # We do this so that we can have them ordered with default # first in /etc/ld.so.conf, as the logical is that all # compilers for default CHOST will be used to compile stuff, # and thus we want all their lib paths in /etc/ld.so.conf ... get_real_chost GCC_PROFILES="$(${FIND} "${GCC_ENV_D}" -name "${REAL_CHOST}-*" -a ! -name "${CC_COMP}")" GCC_PROFILES="${GCC_ENV_D}/${CC_COMP} ${GCC_PROFILES}" # Extract all LDPATH's for our CHOST for x in ${GCC_PROFILES} do if [ -f "${x}" ] then source "${x}" # Handle LDPATH's that have multiple directories local old_IFS="${IFS}" export IFS=":" local sub_ldpath= for sub_ldpath in ${LDPATH} do if [ -z "${MY_LDPATH}" ] then if [ -d "${sub_ldpath}" ] then MY_LDPATH="${sub_ldpath}" fi else if [ -d "${sub_ldpath}" ] then MY_LDPATH="${MY_LDPATH}:${sub_ldpath}" fi fi done export IFS="${old_IFS}" fi done # Setup things properly again for this profile source "${GCC_ENV_D}/${CC_COMP}" # Setup /etc/env.d/05gcc ${AWK} '!/^(STDCXX_INCDIR|LDPATH|CC|CXX|GCCBITS)=/ {print $0}' \ "${GCC_ENV_D}/${CC_COMP}" > "${ENV_D}/05gcc" # Add our custom LDPATH echo "LDPATH=\"${MY_LDPATH}\"" >> "${ENV_D}/05gcc" # Make sure we do not recreate /lib/cpp and /usr/bin/cc ... # echo "DISABLE_GEN_GCC_WRAPPERS=\"yes\"" >> "${ENV_D}/05gcc" echo "CURRENT=${CC_COMP}" > ${GCC_ENV_D}/config # Save PATH GCC_BIN_PATH="${PATH}" # Fix environment source /etc/profile umask 022 # These might not be installed, and we want to update the mtime # for ccache and distcc anyhow ... ${RM} -f "${ROOT}/lib/cpp" ${CP} -f "${ROOT}/usr/lib/gcc-config/wrapper" "${ROOT}/lib/cpp" for x in gcc cpp cc c++ g++ f77 g77 gcj \ ${REAL_CHOST}-gcc ${REAL_CHOST}-c++ ${REAL_CHOST}-g++ \ ${REAL_CHOST}-f77 ${REAL_CHOST}-g77 ${REAL_CHOST}-gcj do # Make sure we have no stale wrappers ${RM} -f "${ROOT}/usr/bin/${x}" [ "${x:${#x}-3}" = "gcc" -o "${x:${#x}-3}" = "g++" ] \ && ${RM} -f "${ROOT}/usr/bin/${x}"{32,64} if [ -x "${ROOT}/${GCC_BIN_PATH}/${x}" -o \ "${x}" = "c++" -o "${x}" = "${REAL_CHOST}-c++" -o \ "${x}" = "cpp" -o "${x}" = "cc" ] then # Only install a wrapper if the binary exists ... ${CP} -f "${ROOT}/usr/lib/gcc-config/wrapper" \ "${ROOT}/usr/bin/${x}" if [ "${OLD_CC_COMP}" != "${CC_COMP}" ] then ${TOUCH} -m "${ROOT}/usr/bin/${x}" fi # Install 32bit and 64bit wrappers if need be # This should probably get folded back into the wrapper ... if [ "${x:${#x}-3}" = "gcc" -o "${x:${#x}-3}" = "g++" ] then for bits in ${GCCBITS} do echo "#!/bin/sh"$'\n'"exec ${x} -m${bits} \"\$@\"" \ > "${ROOT}/usr/bin/${x}${bits}" chmod 755 "${ROOT}/usr/bin/${x}${bits}" done fi fi done if [ "${ROOT}" == "/" ] then ${ENV_UPDATE} &> /dev/null fi eend 0 if [ "${ROOT}" == "/" ] && [ "${OLD_CC_COMP}" != "${CC_COMP}" ] then echo ewarn "If you intend to use the gcc from the new profile in an already" ewarn "running shell, please remember to do:" echo ewarn " # source /etc/profile" echo fi return 0 } get_current_profile() { if [ ! -f "${GCC_ENV_D}/config" ] then eerror "$0: No gcc profile is active!" return 1 fi source "${GCC_ENV_D}/config" if [ -z "${CURRENT}" ] then eerror "$0: No gcc profile is active!" return 1 fi echo "${CURRENT}" return 0 } list_profiles() { local i=1 if [ ! -f "${GCC_ENV_D}/config" ] then eerror "$0: No gcc profile is active; please select one!" else get_current_profile > /dev/null fi if [ "${ROOT}" != "/" ] then echo "Using gcc-config info in ${ROOT}" fi for x in "${GCC_ENV_D}"/* do if [ -f "${x}" -a "${x}" != "${GCC_ENV_D}/config" ] then x="${x##*/}" [ "${x}" == "${CURRENT}" ] && x="${x} *" echo "[${i}] ${x}" i=$((i + 1)) fi done } print_environ() { local OLDPATH="${PATH}" local ENV_CMD= local SET_ELEMENT= source "${GCC_ENV_D}/${CC_COMP}" case ${SHELL} in */csh|*/tsch) ENV_CMD="setenv" SET_ELEMENT=" " ;; *) ENV_CMD="export" SET_ELEMENT="=" ;; esac echo "${ENV_CMD} PATH${SET_ELEMENT}\"${PATH}:${OLDPATH}\"" # if [ -z "${LD_LIBRARY_PATH}" ] # then # echo "${ENV_CMD} LD_LIBRARY_PATH${SET_ELEMENT}\"${LDPATH}\"" # else # echo "${ENV_CMD} LD_LIBRARY_PATH${SET_ELEMENT}\"${LDPATH}:${LD_LIBRARY_PATH}\"" # fi # echo "${ENV_CMD} CC${SET_ELEMENT}\"${CC}\"" # echo "${ENV_CMD} CXX${SET_ELEMENT}\"${CXX}\"" } get_bin_path() { if [ -e "${GCC_ENV_D}/${CC_COMP}" ] ; then source "${GCC_ENV_D}/${CC_COMP}" echo "${PATH}" else echo "no-config" echo "${GCC_ENV_D}/${CC_COMP} doesnt exist" 1>&2 fi return 0 } get_lib_path() { if [ -e "${GCC_ENV_D}/${CC_COMP}" ] ; then source "${GCC_ENV_D}/${CC_COMP}" echo "${LDPATH}" else echo "no-config" echo "${GCC_ENV_D}/${CC_COMP} doesnt exist" 1>&2 fi return 0 } get_stdcxx_incdir() { if [ -e "${GCC_ENV_D}/${CC_COMP}" ] ; then source "${GCC_ENV_D}/${CC_COMP}" echo "${LDPATH}/include/${STDCXX_INCDIR}" else echo "no-config" echo "${GCC_ENV_D}/${CC_COMP} doesnt exist" 1>&2 fi return 0 } NEED_ACTION="yes" DOIT="switch_profile" CHECK_CHOST="no" CC_COMP= [ -z "${ROOT}" ] && ROOT="/" ENV_D="${ROOT}etc/env.d" GCC_ENV_D="${ENV_D}/gcc" for x in "$@" do case "${x}" in # Only use specified compiler if one is not already selected. -O|--use-old) if get_current_profile &> /dev/null then CC_COMP="$(get_current_profile)" fi ;; -P|--use-portage-chost) CHECK_CHOST="yes" ;; -c|--get-current-profile) if [ "${NEED_ACTION}" = "yes" ] then NEED_ACTION="no" DOIT="get_current_profile" fi ;; -l|--list-profiles) if [ "${NEED_ACTION}" = "yes" ] then NEED_ACTION="no" DOIT="list_profiles" fi ;; -E|--print-environ) if [ "${NEED_ACTION}" = "yes" ] then NEED_ACTION="no" DOIT="print_environ" fi ;; -B|--get-bin-path) if [ "${NEED_ACTION}" = "yes" ] then NEED_ACTION="no" DOIT="get_bin_path" fi ;; -L|--get-lib-path) if [ "${NEED_ACTION}" = "yes" ] then NEED_ACTION="no" DOIT="get_lib_path" fi ;; -X|--get-stdcxx-incdir) if [ "${NEED_ACTION}" = "yes" ] then NEED_ACTION="no" DOIT="get_stdcxx_incdir" fi ;; -h|--help) usage exit 0 ;; -v|--version) echo "gcc-config-PORTAGE-VERSION" exit 0 ;; -*) eerror "$0: Invalid switch! Run $0 without parameters for help." exit 1 ;; *) if [ -z "${CC_COMP}" ] then if [ -z "$(echo ${x} | tr -d '[:digit:]')" ] then # User gave us a # representing the profile i=1 for y in "${GCC_ENV_D}"/* do [ "${y}" == "${GCC_ENV_D}/config" ] && continue if [ -f "${y}" ] && [ "${x}" -eq "${i}" ] then CC_COMP="${y##*/}" break fi i=$((i + 1)) done else # User gave us a full HOST-gccver x="${x##*/}" if [ ! -f "${GCC_ENV_D}/${x}" ] then eerror "$0: Could not locate '$x' in '${GCC_ENV_D}/'!" exit 1 fi CC_COMP="${x}" fi else eerror "$0: Too many arguments! Run $0 without parameters for help." exit 1 fi ;; esac done if [ "${DOIT}" = "switch_profile" -a -z "${CC_COMP}" ] then usage fi if [ -z "${CC_COMP}" ] then if get_current_profile &> /dev/null then CC_COMP="$(get_current_profile)" else list_profiles exit 1 fi fi CC_COMP_NO_SPECS=$(echo ${CC_COMP} | awk -F- '{ print $1"-"$2"-"$3"-"$4"-"$5 }') GCC_LIB=$(source "${GCC_ENV_D}/${CC_COMP}" cmd_setup echo ${LDPATH} | ${AWK} -F/ '{ print "/"$2"/"$3"/"$4"/" }') if [ ! -d "${ROOT}/${GCC_LIB}/${CC_COMP_NO_SPECS%-*}/${CC_COMP_NO_SPECS##*-}" -o \ ! -f "${GCC_ENV_D}/${CC_COMP}" ] then eerror "$0: Profile does not exist or invalid setting for ${GCC_ENV_D}/${CC_COMP}" 1>&2 #exit 1 fi if [ "${CHECK_CHOST}" = "yes" ] then # Chosen CHOST are not the same as the real CHOST according to # make.conf, and --use-portage-chost option was given, so do nothing get_real_chost [ "${CC_COMP%-*}" != "${REAL_CHOST}" ] && exit 0 fi eval ${DOIT} # vim:ts=4