SUMMARY="C/C++ compiler for target ${effectiveTargetMachineTriple}"
DESCRIPTION="The standard compiler for non-legacy Haiku (i.e. for all \
architectures other than x86_gcc2)."
HOMEPAGE="http://gcc.gnu.org"

srcGitRev="1a00a76b58ae57d24bd4d774f6323c4ea62dd1e7"
SOURCE_URI="https://github.com/haiku/buildtools/archive/$srcGitRev.tar.gz"
CHECKSUM_SHA256="822f5944c9866eebbe293edcc6ba524e5b1e409114350a681ec88e4d6b747dc2"
REVISION="1"
LICENSE="
	GNU GPL v2
	GNU LGPL v2
	"
COPYRIGHT="1988-2014 Free Software Foundation, Inc."

if [ $effectiveTargetArchitecture = x86_64 ]; then
	PATCHES="gcc-4.8.3_buildfixes_for_x86_64.patchset"
fi

ARCHITECTURES="x86 x86_64 arm"
if [ $effectiveTargetArchitecture != x86_gcc2 ]; then
	# x86_gcc2 is fine as primary target architecture as long as we're building
	# for a different secondary architecture.
	ARCHITECTURES="$ARCHITECTURES x86_gcc2"
fi
SECONDARY_ARCHITECTURES="x86"

libstdcxxSoVersion="6"
libstdcxxLibVersion="6.0.19"

libgccSoVersion="1"
libgccLibVersion="1"

PROVIDES="
	gcc$secondaryArchSuffix = $portVersion compat >= 4
	cmd:c++$secondaryArchSuffix = $portVersion compat >= 4
	cmd:cc$secondaryArchSuffix = $portVersion compat >= 4
	cmd:cpp$secondaryArchSuffix = $portVersion compat >= 4
	cmd:g++$secondaryArchSuffix = $portVersion compat >= 4
	cmd:gcc$secondaryArchSuffix = $portVersion compat >= 4
	cmd:gcc_4.8.4$secondaryArchSuffix = $portVersion compat >= 4
	cmd:gcov$secondaryArchSuffix = $portVersion compat >= 4
	"
REQUIRES="
	haiku$secondaryArchSuffix
	cmd:as$secondaryArchSuffix
	"
BUILD_REQUIRES="
	"
BUILD_PREREQUIRES="
	haiku${secondaryArchSuffix}_devel
	cmd:autoconf
	cmd:awk
	cmd:find
	cmd:flex
	cmd:gcc$secondaryArchSuffix
	cmd:ld$secondaryArchSuffix
	cmd:make
	cmd:makeinfo
	cmd:sed
	cmd:strip
	cmd:tar
	cmd:xargs
	"

SOURCE_DIR="buildtools-$srcGitRev/gcc"

sourceDir=$(pwd)
relativeInstallDir="develop/tools$secondaryArchSubDir"
installDir="$prefix/$relativeInstallDir"
objectsDir=$(pwd)/../${portVersionedName}-obj
gccVersion=$(echo $portVersion | cut -d_ -f1)

BUILD()
{
	rm -rf $objectsDir

	# Touch some files generated by bison, so that bison won't run to update
	# them. Fixes issues with newer bison versions.
	# And while at it, touch gperf target, too (as gperf may not be installed).
	(cd $sourceDir/gcc; touch c-parse.c c-parse.h cexp.c cp/parse.c \
		cp/parse.h c-gperf.h)

	mkdir -p $objectsDir
	cd $objectsDir

	local additionalConfigureFlags
	if [ -n "$secondaryArchSuffix" ]; then
		additionalConfigureFlags="\
			--with-hybrid-secondary=${effectiveTargetArchitecture}"
	fi
	local kernelCcFlags="-D_KERNEL_MODE"
	if [ $effectiveTargetArchitecture == x86_64 ]; then
		# disable multilib support, as x86_64 by default tries to build the
		# 32-bit libraries, too, which fails as no 32-bit libroot is available
		additionalConfigureFlags+=" --disable-multilib"

		# deactivate red zone for x86_64
		kernelCcFlags="$kernelCcFlags -mno-red-zone"
	fi

	"$sourceDir/configure" \
		--build=$effectiveTargetMachineTriple \
		--prefix=$installDir --libexecdir=$installDir/lib --mandir=$manDir \
		--docdir=$docDir --enable-threads=posix \
		--disable-nls --enable-shared --with-gnu-ld --with-gnu-as \
		--enable-version-specific-runtime-libs \
		--enable-languages=c,c++ --enable-lto --enable-frame-pointer \
		--with-pkgversion=$(echo $portVersion | cut -d_ -f2-) \
		--enable-__cxa-atexit \
		$additionalConfigureFlags

	make $jobArgs
	
	echo "######################## building special libraries ################"

	echo "### libgcc"

	# build kernel versions of libgcc.a and libgcc_eh.a (no threads or TLS)
	cd $objectsDir/$effectiveTargetMachineTriple/libgcc
	mkdir -p saved
	mv libgcc.a libgcc_eh.a libgcc_s* libgcov* saved/
	make clean
	ln -sfn "$sourceDir/libgcc/gthr-single.h" gthr-default.h
	make CFLAGS="-O2 $kernelCcFlags" CXXFLAGS="-O2 $kernelCcFlags"
	mv libgcc.a libgcc-kernel.a
	mv libgcc_eh.a libgcc_eh-kernel.a
	ln -sfn "$sourceDir/libgcc/gthr-posix.h" gthr-default.h
	mv saved/* .
	rmdir saved

	echo "### libsupc++"

	# Build a shared libsupc++ from libsupc++.a (hacking the gcc build system
	# to build a shared libsupc++ yields pretty much the same result, so we
	# use this simpler approach).
	cd $objectsDir/$effectiveTargetMachineTriple/libstdc++-v3/libsupc++
	gcc -nodefaultlibs -shared -o .libs/libsupc++.so -Xlinker --whole-archive \
		.libs/libsupc++.a
	# build kernel version of libsupc++.a (without threads or TLS)
	mkdir -p saved
	mv .libs/libsupc++* saved/
	cp "../include/$effectiveTargetMachineTriple/bits/gthr-default.h" \
		"../config.h" \
		"../include/$effectiveTargetMachineTriple/bits/c++config.h" \
		saved/
	make clean
	cp "../include/$effectiveTargetMachineTriple/bits/gthr-single.h" \
		"../include/$effectiveTargetMachineTriple/bits/gthr-default.h"
	sed -i -e 's,#define _GLIBCXX_HAS_GTHREADS 1,/* #undef _GLIBCXX_HAS_GTHREADS */,' \
		"../config.h"
	sed -i -e 's,#define _GLIBCXX_HAVE_TLS 1,/* #undef _GLIBCXX_HAVE_TLS */,' \
		"../include/$effectiveTargetMachineTriple/bits/c++config.h"
	make CFLAGS="-O2 $kernelCcFlags" CXXFLAGS="-O2 $kernelCcFlags"
	mv .libs/libsupc++.a .libs/libsupc++-kernel.a
	mv saved/libsupc++* .libs/
	mv saved/gthr-default.h "../include/$effectiveTargetMachineTriple/bits/"
	mv saved/config.h ..
	mv saved/c++config.h "../include/$effectiveTargetMachineTriple/bits/"
	rmdir saved
}

INSTALL()
{
	cd $objectsDir

	make install
	make install-html

	### HTML documentation ####################################

	echo "Organizing HTML documentation..."
	cd $docDir
	for dir in gmp libquadmath mpc mpfr; do
		mv ${dir}.html $dir
		ln -s $dir/index.html ${dir}.html
	done

	### Libraries #############################################

	echo "Moving libraries around"

	# Move/copy libraries such that copies of the runtime (shared) libs exist 
	# in $libDir and copies of static libraries exist in $developLibDir. These
	# are put into separate packages gcc_syslibs and gcc_syslibs_devel, which
	# are both used by Haiku's build system.
	mkdir -p $libDir
	mkdir -p $developLibDir
	cd $installDir
	gccLibDir=lib/gcc/$effectiveTargetMachineTriple/$gccVersion

	# libstdc++
	strip --strip-debug $gccLibDir/libstdc++.so.$libstdcxxLibVersion
	cp -d $gccLibDir/libstdc++.so \
		$gccLibDir/libstdc++.so.$libstdcxxSoVersion \
		$gccLibDir/libstdc++.so.$libstdcxxLibVersion \
		$libDir/
	cp $gccLibDir/libstdc++*.a $developLibDir/

	# libsupc++
	libstdcxxDir=$objectsDir/$effectiveTargetMachineTriple/libstdc++-v3
	cp $libstdcxxDir/libsupc++/.libs/libsupc++-kernel.a \
		$libstdcxxDir/libsupc++/.libs/libsupc++.so \
		$gccLibDir/
	strip --strip-debug $gccLibDir/libsupc++.so
	cp $gccLibDir/libsupc++.so $libDir/
	cp $gccLibDir/libsupc++*.a $developLibDir/

	# libgcc
	cp $objectsDir/$effectiveTargetMachineTriple/libgcc/libgcc-kernel.a \
		$objectsDir/$effectiveTargetMachineTriple/libgcc/libgcc_eh-kernel.a \
		$gccLibDir/
	strip --strip-debug $gccLibDir/libgcc_s.so.$libgccSoVersion
	cp -d $gccLibDir/libgcc_s.so \
		$gccLibDir/libgcc_s.so.$libgccSoVersion \
		$libDir/
	cp $gccLibDir/libgcc*.a $developLibDir/
	
	# gcc and c++ headers
	mkdir -p $includeDir/gcc
	cp -r $gccLibDir/include $includeDir/gcc/
	cp -r $gccLibDir/include-fixed $includeDir/gcc/
	mv $includeDir/gcc/include/c++ $includeDir/

	### Strip #################################################

	echo "Strip"

	cd $installDir
	strip bin/*
	for f in cc1 cc1plus collect2 lto1 lto-wrapper; do
		strip $gccLibDir/$f
	done

	strip --strip-debug lib/*.a \
		$gccLibDir/*.a \
		$developLibDir/*.a

	### Disable ASLR ##########################################

	echo "Add SYS:ENV attribute to disable ASLR"

	cd $installDir
	for f in bin/*; do
		if [ -r "$f" ]; then
			addattr SYS:ENV DISABLE_ASLR=1 $f
		fi
	done
	for f in cc1 cc1plus collect2 lto1; do
		addattr SYS:ENV DISABLE_ASLR=1 \
			$gccLibDir/$f
	done

	### Symlinks ##############################################

	echo "Creating required symlinks"

	# create missing cc symlink
	ln -sf gcc $installDir/bin/cc

	# make all tools available via default paths
	mkdir -p $binDir
	for f in c++ cc cpp g++ gcc gcov; do
		symlinkRelative -sfn $installDir/bin/$f $binDir
	done
	
	### Cleanup ###############################################

	echo "Cleanup"
	rm -rf $installDir/info
	rm -rf $installDir/share

	### Sub Packages ##########################################

	packageEntries "syslibs" \
		$relativeLibDir/libgcc_s.so \
		$relativeLibDir/libgcc_s.so.$libgccSoVersion \
		$relativeLibDir/libstdc++.so \
		$relativeLibDir/libstdc++.so.$libstdcxxSoVersion \
		$relativeLibDir/libstdc++.so.$libstdcxxLibVersion \
		$relativeLibDir/libsupc++.so

	packageEntries "syslibs_devel" \
		$relativeDevelopLibDir/libgcc.a \
		$relativeDevelopLibDir/libgcc-kernel.a \
		$relativeDevelopLibDir/libgcc_eh.a \
		$relativeDevelopLibDir/libgcc_eh-kernel.a \
		$relativeDevelopLibDir/libstdc++.a \
		$relativeDevelopLibDir/libsupc++.a \
		$relativeDevelopLibDir/libsupc++-kernel.a \
		$relativeIncludeDir
		
	rm -rf $includeDir
	rm -rf $developLibDir
}

# ----- syslibs package -----------------------------------------------------

SUMMARY_syslibs="C/C++-runtime shared libraries, needed to execute C/C++ programs"
DESCRIPTION_syslibs="The c/c++-runtime libraries that are part of the gcc \
distribution. This package contains the shared libraries for the runtime \
loader, so it is required for executing most c/c++ programs."

PROVIDES_syslibs="
	gcc_syslibs$secondaryArchSuffix = $portVersion compat >= 4
	lib:libgcc_s$secondaryArchSuffix = $portVersion compat >= 4
	lib:libstdc++$secondaryArchSuffix = $portVersion compat >= 4
	lib:libsupc++$secondaryArchSuffix = $portVersion compat >= 4
	"
REQUIRES_syslibs="
	haiku$secondaryArchSuffix
	"

# ----- syslibs_devel package -----------------------------------------------

SUMMARY_syslibs_devel="C/C++-runtime static libraries and c++ headers, needed to build Haiku"
DESCRIPTION_syslibs_devel="This package is not of general interest - it \
contains the set of gcc's C/C++-runtime libraries and headers that is \
required by Haiku's build system when building Haiku."

PROVIDES_syslibs_devel="
	gcc_syslibs_devel$secondaryArchSuffix = $portVersion compat >= 4
	"
REQUIRES_syslibs_devel=""
