# Contributor: Márcio Silva <coadde@hyperbola.info>
# Maintainer: David P. <megver83@parabola.nu>

# toolchain build order: {kernel}-api-headers->glibc->binutils->gcc->binutils->glibc

# toolchain (for cross-compiler) build order:
#  {kernel}-api-headers(host system)->glibc(host system)
# ->binutils(host system)->gcc(host system)->binutils(host system)->glibc(host system)
# ->binutils(cross)->gcc(cross)
# ->kernel-api-headers(target system)->glibc(target system)
# ->binutils(target system)->gcc(target system)->binutils(target system)
# ->glibc(target system)

# NOTE: libtool requires rebuilt with each new gcc version

#--------------------------------------------------------------------------------
#  cross-compile table
#--------------------------------------------------------------------------------

# +-------------+-------------+-----------------------------------------------------------------------------------------------------+-----------+---------+
# | -march      | CARCH       | CTARGET (_CTARGET)                                                                                  | Multilib  | QEMU    |
# +-------------+-------------+-------------+-----------+---------------------------------------------------------------------------+-----------+---------+
# | _march      | CARCH       | _arch       | <machine> | _os_target (GNU/*)                                                        | _multilib | -       |
# +-------------+-------------+-------------+-----------+---------------------------------------------------------------------------+-----------+---------+
# | x86_64      | x86_64      | x86_64      | unknown   | {linux,kfreebsd,kopenbsd,knetbsd,kdragonflybsd,kopensolaris}-gnu|elf      | yes       | bin/sys |
# | i[3-7]86    | i[3-7]86    | i[3-7]86    | pc        | gnu|{linux,kfreebsd,kopenbsd,knetbsd,kopensolaris}-gnu|elf                | no        | bin/sys |
# | armv8-a     | aarch64     | aarch64     | unknown   | {linux,kfreebsd,knetbsd}-gnu|elf                                          | no        | bin/sys |
# | armv8-a     | aarch64_be  | aarch64_be  | unknown   | {linux,kfreebsd,knetbsd}-gnu|elf                                          | no        | bin/sys |
# | armv7-a     | armv7h      | armv7l      | unknown   | {linux,kfreebsd,kopenbsd,knetbsd,kopensolaris}-gnueabihf|elf              | no        | bin/sys |
# | armv6       | armv6h      | armv6l      | unknown   | {linux,kfreebsd,kopenbsd,knetbsd,kopensolaris}-gnueabihf|elf              | no        | bin/sys |
# | armv5te     | arm         | armv5tel    | unknown   | {linux,kfreebsd,kopenbsd,knetbsd,kopensolaris}-gnueabi                    | no        | bin/sys |
# | *           | arm         | arm         | unknown   | eabi                                                                      | no        | bin/sys |
# | arm         | armeb       | armeb       | unknown   | {linux,kfreebsd,kopenbsd,knetbsd}-gnueabi|eabi                            | no        | bin     |
# | mips64el    | mips64el    | mips64el    | unknown   | {linux,kfreebsd,kopenbsd,knetbsd}-gnu|elf                                 | no        | bin/sys |
# | mips64      | mips64      | mips64      | unknown   | {linux,kfreebsd,kopenbsd,knetbsd}-gnu|elf                                 | no        | bin/sys |
# | *           | mipsel      | mipsel      | unknown   | {linux,kfreebsd,kopenbsd,knetbsd}-gnu|elf                                 | no        | bin/sys |
# | *           | mips        | mips        | unknown   | {linux,kfreebsd,kopenbsd,knetbsd}-gnu|elf                                 | no        | bin/sys |
#v| powerpc64   | powerpc64   | powerpc64   | unknown   | {linux,kfreebsd,kopenbsd,knetbsd}-gnu{,eabi}|{elf,eabi}                   | no        | bin/sys |x|eabi
#x| powerpc64le | powerpc64le | powerpc64le | unknown   | {linux,kfreebsd,kopenbsd,knetbsd}-gnu{,eabi}|{elf,eabi}                   | no        | bin     |
# | powerpc     | powerpc     | powerpc     | unknown   | {linux,kfreebsd,kopenbsd,knetbsd}-gnu{,eabi}|{elf,eabi}                   | no        | bin/sys |
# | powerpcle   | powerpcle   | powerpcle   | unknown   | {linux,kfreebsd,kopenbsd,knetbsd}-gnu{,eabi}|{elf,eabi}                   | no        | -       |
# | -           | spu         | spu         | unknown   | elf                                                                       | no        | -       |
# | -           | sh64        | sh64        | unknown   | {linux,kopenbsd,knetbsd}-gnu|elf                                          | no        | -       |
# | -           | sh64le      | sh64le      | unknown   | {linux,kopenbsd,knetbsd}-gnu|elf                                          | no        | -       |
# | -           | sh4         | sh4         | unknown   | {linux,kopenbsd,knetbsd}-gnu|elf                                          | no        | bin/sys |
# | -           | sh4le       | sh4le       | unknown   | {linux,kopenbsd,knetbsd}-gnu|elf                                          | no        | bin/sys |
# | -           | sh          | sh          | unknown   | {linux,kopenbsd,knetbsd}-gnu|elf                                          | no        | - @     |
# | -           | shle        | shle        | unknown   | {linux,kopenbsd,knetbsd}-gnu|elf                                          | no        | - @     |
# | -           | m68k        | m68k        | unknown   | gnu|{linux,knetbsd}-gnu|elf                                               | no        | bin/sys |
# | -           | avr         | avr         | unknown   | linux-gnu|elf                                                             | no        | -       |
# | -           | xtensa      | xtensa      | unknown   | linux-gnu|elf                                                             | no        | sys     |
# | -           | lm32        | lm32        | unknown   | linux-gnu|elf                                                             | no        | sys     |
# | -           | or32        | or32        | unknown   | linux-gnu|elf                                                             | no        | bin/sys |x|linux-gnu
# +-------------+-------------+-------------+-----------+---------------------------------------------------------------------------+-----------+---------+

# For "Wine, Darling and DOSBox"
# +-------------+-------------+-------------+-----------+---------------------------------------------------------------------------+-----------+---------+
# | x86_64      | x86_64      | x86_64      | unknown   | mingw64(Wine)|darwin                                                      | yes       | bin/sys |
# | i[3-7]86    | i[3-7]86    | i[3-7]86    | pc        | mingw32(Wine)|msdosdjgpp(DOSBox)|darwin                                   | no        | bin/sys |
# | armv7-a     | armv7h      | armv7l      | unknown   | mingw-arm(Wine)|darwin                                                    | no        | bin/sys |
# | powerpc     | powerpc     | powerpc     | unknown   | darwin                                                                    | no        | bin/sys |
# +-------------+-------------+-------------+-----------+---------------------------------------------------------------------------+-----------+---------+

# opt : Multilib is optional
# * : Any supported by architecture.
# - : None.
# @ : bin/sys (Only sh4 and sh4l support)
# < : experimental support. (future)

#--------------------------------------------------------------------------------
#  Tips for build()
#--------------------------------------------------------------------------------
# * If builing without "--disable-multilib" make sure to have "--with-python-dir=share/gcc-$_target"
# 
# * When building using `make' instead of `make all-gcc' append "--with-sysroot=/usr/$_target" and
#   "--with-native-system-header-dir=/include". You'll also have to build and add a libc implementation
#   in makedepends as $_target-<libc> (e.g. $_target-newlib or $_target-glibc)

#--------------------------------------------------------------------------------
#  Choosing the correct pkgdesc
#--------------------------------------------------------------------------------
# You must know wether your toolchain is a bare-metal one, if it's specifically for big-endian or
# little-endian order and know its full name, if possible. Here are some useful tips:
#
# * If the toolchain has no operating system (see the toolchain triplet, <_os_target>), then it's a
#   bare-metal toolchain, in which case you have to specify it in the pkgdesc
#
# * Do a bit of research in forums, wikis and documents about the target you plan to build, a good
#   idea is to see the description that other distros put (e.g. Debian) if they have the same toolchain
#
# Example: arm-linux-gnueabi-{gcc,binutils,$etc}
# This toolchain has GNU/Linux as OS, so it's not a bare-metal one. It's for armel, which
# stands for "ARM EABI little-endian", but the gnueabi part means it uses the GNU EABI. You can find
# that info in Debian's gcc-arm-linux-gnueabi and a couple of FLOSS and programmers community forums.

# Toolchain triplet: <_arch>-<machine>-<_os_target>
# <machine> is generally optional and uneeded
_target=x86_64-pc-linux-gnu

# This are some common options for names. Change $_target_name in pkgdesc according to the target architecture.
case ${_target%%-*} in
    arm*) _target_name=ARM
    ;;
    aarch64*) _target_name=ARM64
    ;;
    xtensa) _target_name=Xtensa
    ;;
    sh*) _target_name=SuperH
    ;;
    powerpc*) _target_name=PowerPC
    ;;
    riscv*) _target_name=RISC-V
    ;;
    mips*) _target_name=MIPS
    ;;
    i686) _target_name=x86
    ;;
    *) _target_name=${_target%%-*}
    ;;
esac

# Learn more about the correct package naming here:
# https://wiki.archlinux.org/index.php/Cross-compiling_tools_package_guidelines#Package_naming
pkgname=$_target-gcc
_pkgver=10.1.0
#_snapshot=9-20190601
pkgver=$_pkgver${_snapshot/*-/+}
_islver=0.22
pkgrel=1
pkgdesc="The GNU Compiler Collection - cross compiler for $_target_name target"
arch=('i686' 'x86_64' 'armv7h' 'aarch64' 'mips64el' 'ppc64le')
url='http://gcc.gnu.org/'
license=(GPL LGPL FDL)
depends=($_target-binutils libmpc zlib)
makedepends=(gmp mpfr)
# Uncomment the following if building --with-newlib support
#optdepends=("$_target-newlib: Standard C library ($_target target)")
options=(!emptydirs !strip)
source=(https://gcc.gnu.org/pub/gcc/releases/gcc-$_pkgver/gcc-$_pkgver.tar.xz
        #https://gcc.gnu.org/pub/gcc/snapshots/$_snapshot/gcc-$_snapshot.tar.xz
        http://isl.gforge.inria.fr/isl-$_islver.tar.bz2)
sha512sums=('0cb2a74c793face751f42bc580960b00e2bfea785872a0a2155f1f1dbfaa248f9591b67f4322db0f096f8844aca9243bc02732bda106c3b6e43b02bb67eb3096'
            'fc2c9796979610dd51143dcefe4f5c989c4354571cc5a1fcc6b932fd41f42a54f6b43adfd289af61be7bd06f3a523fa6a7d7ee56680e32d8036beb4c188fa668')

if [ -n "$_snapshot" ]; then
  _basedir=gcc-$_snapshot
else
  _basedir=gcc-$_pkgver
fi

prepare() {
  cd $_basedir

  # link isl for in-tree builds
  ln -sf ../isl-$_islver isl

  echo $_pkgver > gcc/BASE-VER

  # Do not run fixincludes
  sed -i 's@\./fixinc\.sh@-c true@' gcc/Makefile.in

  # hack! - some configure tests for header files using "$CPP $CPPFLAGS"
  sed -i "/ac_cpp=/s/\$CPPFLAGS/\$CPPFLAGS -O2/" "$srcdir"/$_basedir/{libiberty,gcc}/configure

  mkdir $srcdir/gcc-build
}

build() {
  cd gcc-build

  # using -pipe causes spurious test-suite failures
  # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48565
  CFLAGS=${CFLAGS/-pipe/}
  CXXFLAGS=${CXXFLAGS/-pipe/}

  $srcdir/$_basedir/configure \
    --target=$_target \
    --prefix=/usr \
    --libexecdir=/usr/lib \
    --enable-languages=c,c++ \
    --enable-plugins \
    --enable-shared \
    --disable-decimal-float \
    --disable-libffi \
    --disable-libgomp \
    --disable-libmudflap \
    --disable-libquadmath \
    --disable-libssp \
    --disable-libstdcxx-pch \
    --disable-nls \
    --disable-threads \
    --disable-tls \
    --disable-multilib \
    --with-gnu-as \
    --with-gnu-ld \
    --with-system-zlib \
    --with-gmp \
    --with-mpfr \
    --with-mpc \
    --with-isl \
    --with-libelf \
    --enable-gnu-indirect-function

  make all-gcc
}

package() {
  # Uncomment the last part if libgcc was also built
  cd gcc-build -C make DESTDIR="$pkgdir" install-gcc # install-target-{libgcc,libstdc++-v3}

  # strip target binaries
  # add "$pkgdir"/usr/$_target/lib next to "$pkgdir"/usr/lib/gcc/$_target/ if libgcc was built
  find "$pkgdir"/usr/lib/gcc/$_target/ \
       -type f -and \( -name \*.a -or -name \*.o \) \
       -exec $_target-objcopy -R .comment -R .note -R .debug_info -R .debug_aranges \
           -R .debug_pubnames -R .debug_pubtypes -R .debug_abbrev -R .debug_line \
           -R .debug_str -R .debug_ranges -R .debug_loc '{}' \;

  # strip host binaries
  find "$pkgdir/usr/bin/" "$pkgdir/usr/lib/gcc/$_target/" -type f \
    -and \( -executable \) -exec strip '{}' \;

  # Remove files that conflict with host gcc package
  rm -r "$pkgdir/usr/share/"{man/man7,info}
}
