# Maintainer: Márcio Silva <coadde@lavabit.com>
# Contributor: André Silva <emulatorman@parabola.nu>

# toolchain build order: linux-api-headers->glibc->binutils->gcc->binutils->glibc

# +-------------+-------------+-----------------------------------------------------------+-----------+---------+
# | -march      | CARCH       | CHOST (_target)                                           | Multilib  | QEMU    |
# +-------------+-------------+-------------+----------+----------------------------------+-----------+---------+
# | _arch       | _CARCH      | _host       | _machine | _system (GNU/*)                  | _multilib | -       |
# +-------------+-------------+-------------+----------+----------------------------------+-----------+---------+
# | mips64el    | mips64el    | mips64el    | unknown  | linux-gnu|elf                    | yes       | sys     |
# | mips64      | mips64      | mips64      | unknown  | linux-gnu|elf                    | yes       | sys     |
# | *           | mipsel      | mipsel      | unknown  | elf                              | no        | bin/sys |
# | *           | mips        | mips        | unknown  | elf                              | no        | bin/sys |
# | x86_64      | x86_64      | x86_64      | unknown  | linux-gnu|gnu<|elf               | yes       | bin/sys |
# | i[5-7]86    | i[5-7]86    | i[5-7]86    | pc       | linux-gnu|gnu|                   | no        | bin/sys |
# | *           | i386        | i386        | unknown  | elf                              | no        | bin/sys |
# | armv8-a     | aarch64     | aarch64     | unknown  | linux-gnu|elf                    | yes       | -       |
# | armv8-a     | aarch64_be  | aarch64_be  | unknown  | linux-gnu|elf                    | yes       | -       |
# | armv7-a     | armv7h      | armv7l      | unknown  | linux-gnueabihf                  | no        | bin/sys |
# | armv6       | armv6h      | armv6l      | unknown  | linux-gnueabihf                  | no        | bin/sys |
# | armv5te     | arm         | armv5tel    | unknown  | linux-gnueabi                    | no        | bin/sys |
# | *           | arm         | arm         | unknown  | eabi                             | no        | bin/sys |
# | arm         | armeb       | armeb       | unknown  | linux-gnueabi|eabi               | no        | bin     |
# | sparc64     | sparc64     | sparc64     | unknown  | linux-gnu                        | yes       | bin/sys |
# | sparc       | sparc       | sparc       | unknown  | linux-gnu                        | no        | bin/sys |
# | -           | ia64        | ia64        | unknown  | linux-gnu                        | yes       | -       |
# | -           | s390        | s390        | unknown  | linux-gnu                        | no        | -       |
# | -           | s390x       | s390x       | unknown  | linux-gnu                        | no        | bin/sys |
# | powerpc64   | powerpc64   | powerpc64   | unknown  | linux-gnu|linux-gnueabi|elf|eabi | yes       | bin/sys |
# | powerpc64le | powerpc64le | powerpc64le | unknown  | linux-gnu|linux-gnueabi|elf|eabi | yes       | -       |
# | powerpc     | powerpc     | powerpc     | unknown  | linux-gnu|linux-gnueabi|elf|eabi | no        | bin/sys |
# | powerpcle   | powerpcle   | powerpcle   | unknown  | linux-gnu|linux-gnueabi|elf|eabi | no        | -       |
# | -           | spu         | spu         | unknown  | elf                              | no        | -       |
# | -           | sh64        | sh64        | unknown  | linux-gnu|elf                    | yes       | -       |
# | -           | sh64l       | sh64l       | unknown  | linux-gnu|elf                    | yes       | -       |
# | -           | sh4         | sh4         | unknown  | linux-gnu                        | no        | bin/sys |
# | -           | sh4l        | sh4l        | unknown  | linux-gnu                        | no        | bin/sys |
# | -           | sh          | sh          | unknown  | elf                              | no        | - @     |
# | -           | shl         | shl         | unknown  | elf                              | no        | - @     |
# | -           | xtensa      | xtensa      | unknown  | elf                              | no        | sys     |
# | *           | m68k        | m68k        | unknown  | elf                              | no        | bin/sys |
# | -           | lm32        | lm32        | unknown  | linux-gnu|elf                    | no        | sys     |
# | -           | or32        | or32        | unknown  | linux-gnu<|elf<                  | no        | bin/sys |
# +-------------+-------------+-------------+----------+----------------------------------+-----------+---------+

# For "DOSBox"
# +-------------+-------------+-------------+----------+----------------------------------+-----------+---------+
# | *           | i386        | i386        | pc       | msdosdjgpp                       | no        | bin/sys |
# +-------------+-------------+-------------+----------+----------------------------------+-----------+---------+

# For "Wine"
# +-------------+-------------+-------------+----------+----------------------------------+-----------+---------+
# | *           | x86_64      | x86_64      | unknown  | mingw64                          | yes       | bin/sys |
# | *           | i386        | i386        | unknown  | mingw32                          | no        | bin/sys |
# +-------------+-------------+-------------+----------+----------------------------------+-----------+---------+

# * : Any supported by architecture.
# - : None.
# @ : bin/sys (Only sh4 and sh4l support)
# < : I will support it. (future)

_carch_list=('mips64el' 'mips64' 'x86_64' 'i786' 'i686' 'i586' 'i486' 'i386' 'aarch64' 'aarch64_be'
             'armv7l' 'armv6l' 'armv5tel' 'armeb' 'sparc64' 'sparc' 'ia64' 's390' 's390x'
             'powerpc64' 'powerpc64le' 'powerpc' 'powerpcle' 'sh64' 'sh64l' 'sh4' 'sh4l' 'lm32' 'or32')
_multilib_list=('mips64el' 'mips64' 'x86_64' 'aarch64' 'aarch64_be' 'sparc64' 'ia64' 'powerpc64' 'powerpc64le''sh64' 'sh64l')

#---------------------------------------------------------------------------------------------------------------------------------------------

### Base FLAGS: ###
# For custom name.
_pkgname="binutils"
_pkgver="2.23.2"
_pkgrel="2"
# For binutils-common ("${_pkgname}-common${_pkgflag}${_verflag}") release.
_pkgrelb="2"
# For _target-binutils ("${_target}-${_pkgname}${_multilib_name}${_ath9k_htc_name}${_pkgflag}${_verflag}") release.
_pkgrelc="2"
# For older version.
_add_version_name="no"
# For custom pkg.
_pkgflag=""

### Architecture FLAGS: ###
# CARCH flag 
_CARCH="mips64"
# CHOST flags
_host="${_CARCH}"
_machine="unknown"
_system="linux-gnu"
# Multilib flag
_multilib="yes"

### Patch FLAGS: ###
_patch_ath9k_htc_fw="no"

#---------------------------------------------------------------------------------------------------------------------------------------------

# For older version.
[[ ${_add_version_name} == yes ]] && _verflag="-v${_pkgver}"

# For Architecture.
_target="${_host}-${_machine}-${_system}"

# For "_patch_ath9k_htc_fw"
[[ ${_CARCH} != xtensa ]] && _patch_ath9k_htc_fw="no"
[[ ${_patch_ath9k_htc_fw} == "yes" ]] && {
  _ath9k_htc_name="-ath9k-htc"
  _ath9k_htc_desc=" adapted for ath9k-htc firmware"
  _multilib="no"
}

# For "_multilib"
[[ ${_CARCH} != $(echo ${_multilib_list[@]} | sed 's| |\n|g' | grep -x ${_CARCH}) ]] && _multilib="no"
[[ ${_multilib} == "yes" ]] && {
  _multilib_name="-multilib"
  _multilib_desc=" for multilib"
}

#---------------------------------------------------------------------------------------------------------------------------------------------

pkgname=(
  "${_target}-${_pkgname}${_multilib_name}${_ath9k_htc_name}${_pkgflag}${_verflag}"
  "${_pkgname}-common${_pkgflag}${_verflag}"
)
pkgver=${_pkgver}
pkgrel=${_pkgrel}
arch=("${_carch_list[@]}")
url="http://www.gnu.org/software/${_pkgname}/"
license=('GPL2')
groups=('cross-devel')
checkdepends=('dejagnu' 'bc')
# Make sure we compile this with {$CHOST-,}gcc-multilib
[[ ${_multilib} == "yes" ]] && makedepends=('gcc-multilib') # makedepends=("$CHOST-gcc-multilib")
options=('!libtool' '!distcc' '!ccache')
source=(ftp://ftp.gnu.org/gnu/${_pkgname}/${_pkgname}-${pkgver}.tar.bz2{,.sig}
        ${_pkgname}-2.23.2-texinfo-5.0.patch)
md5sums=('4f8fa651e35ef262edc01d60fb45702e'
         'dfde4428f08d91f309cdcfe92bf28d08'
         '34e439ce23213a91e2af872dfbb5094c')

[[ ${_patch_ath9k_htc_fw} == "yes" ]] && {
  source+=("_patch_ath9k_htc_fw.patch::https://raw.github.com/qca/open-ath9k-htc-firmware/1.3.2/local/patches/${_pkgname}.patch")
  md5sums+=('7077126d96e9a755a0eaddb5505efe68')
}

#---------------------------------------------------------------------------------------------------------------------------------------------

prepare() {
  cd ${srcdir}/${_pkgname}-${pkgver}

  msg "http://sourceware.org/git/?p=${_pkgname}.git;a=patch;h=e02bf935"
  msg "http://sourceware.org/git/?p=${_pkgname}.git;a=patch;h=935f8542"
  patch -p1 -i ${srcdir}/${_pkgname}-2.23.2-texinfo-5.0.patch

  [[ ${_patch_ath9k_htc_fw} == "yes" ]] && {
    patch -p1 -i ${srcdir}/_patch_ath9k_htc_fw.patch
  }

  msg "hack! - libiberty configure tests for header files using" "$CPP $CPPFLAGS"
  sed -i "/ac_cpp=/s/\$CPPFLAGS/\$CPPFLAGS -O2/" libiberty/configure

  mkdir -v ${srcdir}/${_pkgname}-build
}

#---------------------------------------------------------------------------------------------------------------------------------------------

build() {
  cd ${srcdir}/${_pkgname}-build

  [[ $CARCH != ${_CARCH} ]] && _TARGET="--target=${_target}"
  if [[ ${_CARCH} == $(echo ${_multilib_list[@]} | sed 's| |\n|g' | grep -x ${_CARCH}) ]]; then
    _LIB_PATH="--with-lib-path=/usr/lib:/usr/lib32:/usr/local/lib:/usr/local/lib32:/usr/${_target}/lib:/usr/${_target}/lib32"
  else
    _LIB_PATH="--with-lib-path=/usr/lib:/usr/local/lib:/usr/${_target}/lib"
  fi

  if [[ ${_multilib} == "yes" ]]; then
    _MULTILIB='--enable-multilib'
  else
    _MULTILIB='--disable-multilib'
  fi

  ${srcdir}/${_pkgname}-${pkgver}/configure --prefix=/opt/${pkgname[0]/${_verflag}/}/${pkgver} \
    $_TARGET $_LIB_PATH \
    --program-prefix=${_target}- \
    --program-suffix=${_multilib_name}${_ath9k_htc_name}-${pkgver} \
    --with-bugurl=https://labs.parabola.nu/ \
    --enable-ld=default --enable-gold \
    --enable-plugins --enable-threads \
    --with-pic --enable-shared \
    --disable-werror ${_MULTILIB}
    # !!! Disabled, due which problematic libretools (prepare() and build() with --bindir, --includedir and --datarootdir)" !!!
    #--bindir=/usr/bin --includedir=/usr/include --datarootdir=/usr/share \

  msg "Check the host environment and makes sure all the necessary tools are available"
  make configure-host

  make tooldir=/opt/${pkgname[0]/${_verflag}/}/${pkgver}
}

#---------------------------------------------------------------------------------------------------------------------------------------------

check() {
  cd ${srcdir}/${_pkgname}-build
  
  msg "Unset LDFLAGS as testsuite makes assumptions about which ones are active"
  msg "do not abort on errors - manually check log files"
  make LDFLAGS="" -k check || true
}

#---------------------------------------------------------------------------------------------------------------------------------------------

_target-binutils() {
  pkgrel=${_pkgrelc}
  pkgdesc="A set of programs to assemble and manipulate binary and object files${_multilib_desc}${_ath9k_htc_desc}. (${_target} architecture)"
  depends=('glibc>=2.17' 'zlib' "${_pkgname}-common")
  [[ $CHOST == ${_target} ]] && provides=("${_pkgname}=${pkgver}")
  if [[ ${_multilib} == "yes" ]]; then
    groups+=('multilib-devel')
  else
    groups+=('base-devel')
  fi
  groups+=("${_target}-devel")
  install="${_target}-${_pkgname}${_multilib_name}${_ath9k_htc_name}.install"

  cd ${srcdir}/${_pkgname}-build
  make prefix=${pkgdir}/opt/${pkgname/${_verflag}/}/${pkgver} tooldir=${pkgdir}/opt/${pkgname/${_verflag}/}/${pkgver} install

  # temp #
  msg "!!! Move 'bin', 'include' and 'share' dir to /usr, !!!"
  msg "!!! due which problematic libretools ('prepare()' and 'build()' with --bindir, --includedir and --datarootdir) !!!"
  install -vd ${pkgdir}/usr
  if [[ $CARCH == ${_CARCH} ]]; then
    mv -v ${pkgdir}/{opt/${pkgname}/${pkgver}/{bin,include,share},usr}
  else
    mv -v ${pkgdir}/{opt/${pkgname}/${pkgver}/{bin,$CHOST/${_target}/include,share},usr}
  fi
  # temp #

  [[ $CARCH != ${_CARCH} ]] && {
    msg "Move 'lib' files and directories, and remove architecture directories"
    mv -v ${pkgdir}/opt/${pkgname/${_verflag}/}/${pkgver}/{$CHOST/${_target}/lib/*,lib}
    rmdir -v ${pkgdir}/opt/${pkgname/${_verflag}/}/${pkgver}/$CHOST/{${_target}/{lib,},}
  }

  msg "Change lib-path on ldscripts files"
  sed -i "/^SEARCH_DIR/ s|/${pkgver}/${_target}/lib|/${pkgver}/lib|g;
          /^SEARCH_DIR/ s|/${pkgver}/lib|/${pkgver}/lib32|g;
          /^SEARCH_DIR/ s|/${pkgver}/lib3264|/${pkgver}/lib|g;
          /^SEARCH_DIR/ s|/${pkgver}/lib32x32|/${pkgver}/lib|g;
         " ${pkgdir}/opt/${pkgname/${_verflag}/}/${pkgver}/lib/ldscripts/*

  _removebin=(ar as nm objcopy objdump ranlib strip)
  for _rbin in ${_removebin[@]}; do
    msg "Remove conflicting binaries"
    rm -v ${pkgdir}/usr/bin/${_rbin[@]}
  done

  msg "Create links for libraries"
  install -vd ${pkgdir}/{usr/${_target},etc/ld.so.conf.d}
  ln -vs ../lib ${pkgdir}/usr/${_target}/lib
  echo /opt/${pkgname/${_verflag}/}/${pkgver}/lib > ${pkgdir}/etc/ld.so.conf.d/${pkgname}-${pkgver}.conf

  msg "Install PIC libiberty.a"
  install -vm644 libiberty/pic/libiberty.a ${pkgdir}/opt/${pkgname/${_verflag}/}/${pkgver}/lib

  msg "Remove unnecessaries manuals and create links for manuals"
  _man=$(ls -1A ${pkgdir}/usr/share/man/man1)
  for _man_stage1 in ${_man[@]}; do
    _man_stage2=${_man_stage1/${_multilib_name}${_ath9k_htc_name}-${pkgver}/}
    _manuals=${_man_stage2/${_target}-/}
    rm -v ${pkgdir}/usr/share/man/man1/${_man_stage1}
    ln -vs ${_manuals}.gz ${pkgdir}/usr/share/man/man1/${_man_stage1}.gz
  done

  msg "Remove unnecessaries files and directories"
  rm -vr ${pkgdir}/usr/{include,share/{info,locale}}
}

#---------------------------------------------------------------------------------------------------------------------------------------------

# GNU/Linux-libre
package_mips64el-unknown-linux-gnu-binutils() { _target-binutils; }
package_mips64el-unknown-linux-gnu-binutils-multilib() { _target-binutils; }
package_mips64-unknown-linux-gnu-binutils() { _target-binutils; }
package_mips64-unknown-linux-gnu-binutils-multilib() { _target-binutils; }
package_x86_64-unknown-linux-gnu-binutils() { _target-binutils; }
package_x86_64-unknown-linux-gnu-binutils-multilib() { _target-binutils; }
package_i786-pc-linux-gnu-binutils() { _target-binutils; }
package_i686-pc-linux-gnu-binutils() { _target-binutils; }
package_i586-pc-linux-gnu-binutils() { _target-binutils; }
package_aarch64-unknown-linux-gnu-binutils() { _target-binutils; }
package_aarch64-unknown-linux-gnu-binutils-multilib() { _target-binutils; }
package_aarch64_be-unknown-linux-gnu-binutils() { _target-binutils; }
package_aarch64_be-unknown-linux-gnu-binutils-multilib() { _target-binutils; }
package_arm7l-unknown-linux-gnueabi-binutils() { _target-binutils; }
package_arm6l-unknown-linux-gnueabi-binutils() { _target-binutils; }
package_arm5tel-unknown-linux-gnueabi-binutils() { _target-binutils; }
package_armeb-unknown-linux-gnueabi-binutils() { _target-binutils; }
package_sparc64-unknown-linux-gnu-binutils() { _target-binutils; }
package_sparc64-unknown-linux-gnu-binutils-multilib() { _target-binutils; }
package_sparc-unknown-linux-gnu-binutils() { _target-binutils; }
package_ia64-unknown-linux-gnu-binutils() { _target-binutils; }
package_ia64-unknown-linux-gnu-binutils-multilib() { _target-binutils; }
package_s390-unknown-linux-gnu-binutils() { _target-binutils; }
package_s390x-unknown-linux-gnu-binutils() { _target-binutils; }
package_sparc64-unknown-linux-gnu-binutils() { _target-binutils; }
package_sparc64-unknown-linux-gnu-binutils-multilib() { _target-binutils; }
package_powerpc64-unknown-linux-gnu-binutils() { _target-binutils; }
package_powerpc64-unknown-linux-gnu-binutils-multilib() { _target-binutils; }
package_powerpc64le-unknown-linux-gnu-binutils() { _target-binutils; }
package_powerpc64le-unknown-linux-gnu-binutils-multilib() { _target-binutils; }
package_powerpc-unknown-linux-gnu-binutils() { _target-binutils; }
package_powerpcle-unknown-linux-gnu-binutils() { _target-binutils; }
package_sh64-unknown-linux-gnu-binutils() { _target-binutils; }
package_sh64-unknown-linux-gnu-binutils-multilib() { _target-binutils; }
package_sh64l-unknown-linux-gnu-binutils() { _target-binutils; }
package_sh64l-unknown-linux-gnu-binutils-multilib() { _target-binutils; }
package_sh4-unknown-linux-gnu-binutils() { _target-binutils; }
package_sh4l-unknown-linux-gnu-binutils() { _target-binutils; }
package_lm32-unknown-linux-gnu-binutils() { _target-binutils; }
package_or32-unknown-linux-gnu-binutils() { _target-binutils; }

# GNU
package_x86_64-unknown-gnu-binutils() { _target-binutils; }
package_x86_64-unknown-gnu-binutils-multilib() { _target-binutils; }
package_i786-pc-gnu-binutils() { _target-binutils; }
package_i686-pc-gnu-binutils() { _target-binutils; }
package_i586-pc-gnu-binutils() { _target-binutils; }

# ELF or EABI only
package_mips64el-unknown-elf-binutils() { _target-binutils; }
package_mips64el-unknown-elf-binutils-multilib() { _target-binutils; }
package_mips64-unknown-elf-binutils() { _target-binutils; }
package_mips64-unknown-elf-binutils-multilib() { _target-binutils; }
package_mipsel-unknown-elf-binutils() { _target-binutils; }
package_mips-unknown-elf-binutils() { _target-binutils; }
package_x86_64-unknown-elf-binutils() { _target-binutils; }
package_x86_64-unknown-elf-binutils-multilib() { _target-binutils; }
package_i386-unknown-elf-binutils() { _target-binutils; }
package_aarch64-unknown-elf-binutils() { _target-binutils; }
package_aarch64-unknown-elf-binutils-multilib() { _target-binutils; }
package_aarch64_be-unknown-elf-binutils() { _target-binutils; }
package_aarch64_be-unknown-elf-binutils-multilib() { _target-binutils; }
package_arm-unknown-eabi-binutils() { _target-binutils; }
package_armeb-unknown-eabi-binutils() { _target-binutils; }
package_powerpc64-unknown-elf-binutils() { _target-binutils; }
package_powerpc64-unknown-elf-binutils-multilib() { _target-binutils; }
package_powerpc64-unknown-eabi-binutils() { _target-binutils; }
package_powerpc64-unknown-eabi-binutils-multilib() { _target-binutils; }
package_powerpc64le-unknown-elf-binutils() { _target-binutils; }
package_powerpc64le-unknown-elf-binutils-multilib() { _target-binutils; }
package_powerpc64le-unknown-eabi-binutils() { _target-binutils; }
package_powerpc64le-unknown-eabi-binutils-multilib() { _target-binutils; }
package_powerpc-unknown-elf-binutils() { _target-binutils; }
package_powerpc-unknown-eabi-binutils() { _target-binutils; }
package_powerpcle-unknown-elf-binutils() { _target-binutils; }
package_powerpcle-unknown-eabi-binutils() { _target-binutils; }
package_spu-unknown-elf-binutils() { _target-binutils; }
package_sh64-unknown-elf-binutils() { _target-binutils; }
package_sh64-unknown-elf-binutils-multilib() { _target-binutils; }
package_sh64l-unknown-elf-binutils() { _target-binutils; }
package_sh64l-unknown-elf-binutils-multilib() { _target-binutils; }
package_sh-unknown-elf-binutils() { _target-binutils; }
package_shl-unknown-elf-binutils() { _target-binutils; }
package_xtensa-unknown-elf-binutils() { _target-binutils; }
package_xtensa-unknown-elf-binutils-ath9k_htc() { _target-binutils; }
package_m68k-unknown-elf-binutils() { _target-binutils; }
package_lm32-unknown-elf-binutils() { _target-binutils; }
package_or32-unknown-elf-binutils() { _target-binutils; }

#---------------------------------------------------------------------------------------------------------------------------------------------

package_binutils-common() {
  pkgrel=${_pkgrelb}
  pkgdesc="A set of programs to assemble and manipulate binary and object files. (headers, docs and locales files only)"
  arch=('any')
  depends=('linktools')
  install="${_pkgname}.install"

  cd ${srcdir}/${_pkgname}-build
  make prefix=${pkgdir}/opt/${pkgname/${_verflag}/}/${pkgver} tooldir=${pkgdir}/opt/${pkgname/${_verflag}/}/${pkgver} install

  [[ $CARCH != ${_CARCH} ]] && {
    msg "Move 'include' files and directories"
    mv -v ${pkgdir}/opt/${pkgname/${_verflag}/}/${pkgver}/{$CHOST/${_target}/include,}
  }

  msg "Add some useful headers"
  install -vm644 ${srcdir}/${_pkgname}-${pkgver}/include/{demangle,libiberty}.h ${pkgdir}/opt/${pkgname/${_verflag}/}/${pkgver}/include

  msg "Remove unnecessaries files and directories"
  rm -vr ${pkgdir}/opt/${pkgname/${_verflag}/}/${pkgver}/{bin,lib}
  [[ $CARCH != ${_CARCH} ]] && {
    rm -vr ${pkgdir}/opt/${pkgname/${_verflag}/}/${pkgver}/$CHOST
  }

  msg "Rename manuals"
  _man=$(ls -1A ${pkgdir}/opt/${pkgname/${_verflag}/}/${pkgver}/share/man/man1)
  for _man_stage1 in ${_man[@]}; do
    _man_stage2=${_man_stage1/${_multilib_name}${_ath9k_htc_name}-${pkgver}/}
    _manuals=${_man_stage2/${_target}-/}
    mv -v ${pkgdir}/opt/${pkgname/${_verflag}/}/${pkgver}/share/man/man1/{${_man_stage1},${_manuals}}
  done
}