#!/bin/bash

# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

. "$(dirname "$0")/common.sh" || exit 1
. "${SRC_ROOT}/platform/dev/toolchain_utils.sh" || exit 1

# Script must run inside the chroot
restart_in_chroot_if_needed "$@"

assert_not_root_user

# Developer-visible flags.
DEFINE_string board "$DEFAULT_BOARD" \
  "The name of the board to set up."
DEFINE_string board_root "" \
  "Path of the board root to install into.  Defaults to /build/<board>."
DEFINE_boolean configure $FLAGS_TRUE \
  "Update config files in <board_root>/etc after installation."
DEFINE_boolean force $FLAGS_FALSE \
  "Install toolchain even if already up to date."
DEFINE_string toolchain "" \
  "Toolchain.  For example: i686-pc-linux-gnu, armv7a-softfloat-linux-gnueabi"


FLAGS_HELP="usage: $(basename $0) [flags]

Installs cross toolchain libraries into a board_root.  This script is not
meant to be used by developers directly.  Run at your own risk.
"

show_help_if_requested "$@"

# Parse command line flags
FLAGS "$@" || exit 1
eval set -- "${FLAGS_ARGV}"

# Only now can we die on error.  shflags functions leak non-zero error codes,
# so will die prematurely if 'switch_to_strict_mode' is specified before now.
switch_to_strict_mode

# Get the version number of a toolchain package.
cross_get_version() {
  local pkg=$1
  local toolchain=${2:-${FLAGS_toolchain}}
  local cpv
  if [[ "$CHOST" != "${toolchain}" ]]; then
    if [[  "$pkg" = "gcc" ]]; then
      # Users can install multiple versions of gcc at once, so we need to call
      # gcc-config to find out which installed version is selected.
      local path=$(CTARGET="${toolchain}" gcc-config -B || true)
      cpv=$(portageq owners / "$path" | sed -e '/^\t/d')
    else
      cpv=$(portageq match / "cross-${toolchain}/${pkg}" || true)
    fi
  else
    if [[ "$pkg" = glibc ]] ; then
      cpv=$(portageq match / sys-libs/glibc || true)
    elif [[ "$pkg" = gcc ]] ; then
      cpv=$(portageq match / sys-devel/gcc || true)
    else
      die "Unknown pkg ${pkg}"
    fi
  fi
  local cp=$(echo $cpv | sed -e 's/-r[0-9]*$//; s/-[^-]*$//')
  local result="${cpv#$cp-}"
  local count="$(echo $result | wc -w)"
  if [ "$count" -gt "1" ]; then
    die "Multiple versions of $pkg installed"
  elif [ "$count" -lt "1" ]; then
    die "Cannot find $pkg"
  fi
  echo $result
}

# Checks whether the libc version installed in the board
# matches the one installed by the toolchain.
board_needs_libc_update() {
  if [[ ! -e "${BOARD_SETUP}" ]]; then
    return 0
  fi

  local board_version=$(. "${BOARD_SETUP}"; echo "${LIBC_VERSION:-}")
  local toolchain_version=$(cross_get_version glibc)
  if [[ "${board_version}" = "${toolchain_version}" ]]; then
    return 1
  fi
  return 0
}

install_toolchain_in_provided() {
  local gcc_ver="$1"
  local glibc_ver="$2"
  # Tell portage that toolchain packages are already installed in the sysroot.
  sudo mkdir -p "$BOARD_PROFILE"
  sudo_clobber "$BOARD_PROFILE/package.provided" << EOF
sys-devel/gcc-$gcc_ver
sys-libs/glibc-$glibc_ver
EOF
}

# Install all of the stuff that depends on the toolchain versions
# into the board root.
install_toolchain_in_board() {
  local cmds
  local gcc_ver=$(cross_get_version gcc)
  local libc_ver=$(cross_get_version glibc)
  if [[ -z ${gcc_ver} || -z ${libc_ver} ]]; then
    die "Cannot find toolchain to install into board root"
  fi
  echo "Installing the toolchain into the board root."
  # Untar glibc to get most of the headers required to build.
  local libc_tar="glibc-${libc_ver}.tbz2"

  # Install libc libraries.
  if [ "${CHOST}" != "$FLAGS_toolchain" ] ; then
    local libc_path="${PKGDIR}/cross-${FLAGS_toolchain}/${libc_tar}"
    cmds=(
      "tar jxpf '${libc_path}' -C '${BOARD_ROOT}' \
          './usr/${FLAGS_toolchain}' --strip-components=3"
      "mkdir -p '${BOARD_ROOT}/usr/lib/debug'"
      "tar jxpf '${libc_path}' -C '${BOARD_ROOT}/usr/lib/debug' \
          './usr/lib/debug/usr/${FLAGS_toolchain}' --strip-components=6 \
          || echo 'WARNING: libc debug info not copied.' >&2"
    )
    # TODO(asharif): Remove this hack after a while.
    local board_gcc_dir="${BOARD_ROOT}/usr/lib/gcc"
    if [[ -L "${board_gcc_dir}" ]] ; then
      cmd+=("rm -f '${board_gcc_dir}'")
    fi
    sudo_multi "${cmds[@]}"
  else
    cmds=(
      "mkdir -p '${BOARD_ROOT}'{/usr,}/lib64 '${BOARD_ROOT}/usr/lib/debug'"
      "ln -sfT '${BOARD_ROOT}/usr/lib64' '${BOARD_ROOT}/usr/lib'"
      "ln -sfT '${BOARD_ROOT}/lib64' '${BOARD_ROOT}/lib'"
      "emerge --oneshot --nodeps -k --root='${BOARD_ROOT}' \
          =sys-libs/glibc-${libc_ver}"
    )
    sudo_multi "${cmds[@]}"
  fi

  # Some header files are needed also for rpcbind (NFS support)
  # TODO: Figure out a better way of doing this too?
  cmds=(
    "cp -a /usr/include/rpcsvc/mount.h '${BOARD_ROOT}/usr/include/rpcsvc'"
    "cp -a /usr/include/rpcsvc/rquota.h '${BOARD_ROOT}/usr/include/rpcsvc'"
    "cp -a /usr/include/rpcsvc/nfs_prot.h '${BOARD_ROOT}/usr/include/rpcsvc'"
    "cp -a /usr/include/rpcsvc/yppasswd.h '${BOARD_ROOT}/usr/include/rpcsvc'"
  )
  sudo_multi "${cmds[@]}"

  if [[ ${FLAGS_configure} -eq ${FLAGS_TRUE} ]]; then
    install_toolchain_in_provided "$gcc_ver" "$libc_ver"

    # Configure new libc version in make.conf.board_setup.
    if [[ -e ${BOARD_SETUP} ]]; then
      sudo sed -i -e "/^LIBC_VERSION=/d" "${BOARD_SETUP}"
    fi
    echo "LIBC_VERSION=\"$libc_ver\"" | sudo_append "$BOARD_SETUP"
  fi
}

set -u

if [ -z "$FLAGS_board" ] ; then
  die "--board required."
fi

get_board_and_variant $FLAGS_board ""

BOARD_ROOT="${FLAGS_board_root:-/build/${BOARD_VARIANT}}"
BOARD_ETC="${BOARD_ROOT}/etc"
BOARD_SETUP="${BOARD_ETC}/make.conf.board_setup"
BOARD_PROFILE="${BOARD_ETC}/portage/profile"

all_toolchains=( $(get_all_board_toolchains "${BOARD}") )
: ${FLAGS_toolchain:=${all_toolchains[0]}}

if [ -z "${FLAGS_toolchain}" ]; then
  die "No toolchain specified in board overlay or on command line."
fi

eval "$(portageq envvar -v CHOST PKGDIR)"

if [[ ${FLAGS_force} -eq ${FLAGS_TRUE} ]] || \
    board_needs_libc_update; then
  info "Updating libc in the board."
  install_toolchain_in_board
else
  info "Cross toolchain already up to date.  Nothing to do."
fi
