#!/usr/bin/make -f

# POSIX.1-2008:
#   If the pathname does not begin with a '/' it shall be treated as relative to
#   the current working directory of the process, not relative to the directory
#   containing the makefile.
include ../source.mk
include ../targets.mk

# Hardcode the targets to allow only native compilers for now.
configure_targets = configure-$(OPK_HOST_ARCH)
build_targets = build-$(OPK_HOST_ARCH)
buildnative_targets = buildnative-$(OPK_HOST_ARCH)
buildcross_targets = buildcross-$(OPK_HOST_ARCH)
install_targets = install-$(OPK_HOST_ARCH)
installnative_targets = installnative-$(OPK_HOST_ARCH)
installcross_targets = installcross-$(OPK_HOST_ARCH)

version = $$(printf '%s\n' '$(OPK_SOURCE_VERSION_UPSTREAM)' | sed 's/+sip.*//')
base_version = $$(printf '%s\n' '$(OPK_SOURCE)' | sed 's/^gcc-//')

target = $$(printf '%s' '$@' | sed 's/^[a-z]*-//')
target_gnu = $$(oh-architecture $(target))

builddir = obj-$(target)
destdir = dest-$(target)

# /usr/lib/<target>/ld.so is a symbolic link for use by GCC to find the system's
# dynamic linker.  It should be provided by the development package of any
# standard C library.
# ProteanOS GCC should build binaries with an ELF INTERP field as follows:
#   /lib/<target>/<soname>
# <soname> is the SONAME of the target's dynamic linker.
elf_interp = /lib/$(target)/$(elf_interp_soname)
elf_interp_soname = $$(readelf -d "/usr/lib/$(target)/ld.so" | \
	sed -n 's/^.*(SONAME).*\[\([^]]*\)\].*$$/\1/p')

common_opts = \
	--with-pkgversion='GCC for ProteanOS' \
	--program-suffix="-$(base_version)" \
	--enable-linker-build-id \
	--with-system-zlib \
	--disable-multilib \
	--enable-multiarch \
	--without-included-gettext \
	--with-nls \
	--with-sysroot="$${OPK_SYSROOT}" \
	--with-gxx-include-dir="/usr/include/c++-$(base_version)" \
	--enable-clocale=gnu

full_opts = \
	$(common_opts) \
	--enable-shared \
	--enable-threads=posix \
	--enable-languages=c,c++

bootstrap1_opts = \
	$(common_opts) \
	--without-headers \
	--with-newlib \
	--disable-shared \
	--disable-threads \
	--enable-languages=c,c++ \
	--disable-libgomp \
	--disable-libssp

libdir    = /usr/lib/$(OPK_HOST_ARCH)
tgtlibdir = /usr/lib/$(OPK_HOST_ARCH)/$(target)/gcc-$(base_version)
tgtincdir = /usr/include/$(target)/c++-$(base_version)
libsuffix = $$(g++ -print-multi-os-directory)
dir_macros = \
	user_tooldir_prefix=$(tgtlibdir) \
	gcc_gxx_tool_include_dir=$(tgtincdir)

extra_opts =
native_target = bootstrap-lean
cross_target = all-gcc
jobs = 4
include ../local.mk

nop:
	@:

../local.mk:
	>../local.mk

$(configure_targets):
	set -e; \
	. "../targets.d/$(target).sh"; \
	if [ 'x$(OPK_HOST_PLAT)' = 'xbootstrap1' ]; then \
		oh-autoconfigure -B "$(builddir)" -t "$(target)" -- \
		$(bootstrap1_opts) \
		$${target_opts} \
		$(extra_opts); \
	else \
		oh-autoconfigure -B "$(builddir)" -t "$(target)" -- \
		$(full_opts) \
		$${target_opts} \
		$(extra_opts); \
	fi
	touch $@

configure: $(configure_targets)
	touch $@

$(build_targets): configure
	# Set the default dynamic linker path inserted into ELF INTERP fields.
	# These default values are in header files in gcc/config.  They must be
	# edited here rather than in a patch because any given GCC target
	# configuration can be used by multiple ProteanOS targets.
	# These commands run once per target, but they modify files in the src/
	# directory that other targets might also use, so backups are made.
	set -e; \
	. "../targets.d/$(target).sh"; \
	[ -e "src/gcc/config/$${gcc_config_file}.orig" ] || \
		mv "src/gcc/config/$${gcc_config_file}" \
			"src/gcc/config/$${gcc_config_file}.orig"; \
	define_pattern=".define $${gcc_config_interp_macro}"; \
	sed "s|^\($${define_pattern}\) \".*\"$$|\1 \"$(elf_interp)\"|" \
		"src/gcc/config/$${gcc_config_file}.orig" \
		>"src/gcc/config/$${gcc_config_file}"; \
	[ -e "src/gcc/config/$${gcc_config_fragment}.orig" ] || \
		mv "src/gcc/config/$${gcc_config_fragment}" \
			"src/gcc/config/$${gcc_config_fragment}.orig"; \
	sed "$${gcc_config_fragment_script}" \
		"src/gcc/config/$${gcc_config_fragment}.orig" \
		>"src/gcc/config/$${gcc_config_fragment}"; \
	printf '\nMULTIARCH_DIRNAME = %s\n' "$(target)" \
		>>"src/gcc/config/$${gcc_config_fragment}"
	if [ "x$(target)" = 'x$(OPK_HOST_ARCH)' ]; then \
		$(MAKE) -f ../build "buildnative-$(target)"; \
	else \
		$(MAKE) -f ../build "buildcross-$(target)"; \
	fi
	touch $@

$(buildnative_targets):
	oh-autobuild -B "$(builddir)" -T $(native_target) -- \
		-j $${JOBS:-$(jobs)} \
		$(dir_macros)
	#if [ '$(OPK_BUILD_ARCH)' = '$(OPK_HOST_ARCH)' ]; then \
	#	cd "$(builddir)" && make -k check; \
	#fi

$(buildcross_targets):
	oh-autobuild -B "$(builddir)" -T $(cross_target) -- \
		-j $${JOBS:-$(jobs)} \
		$(dir_macros)

build: $(build_targets)
	touch $@

$(install_targets): build
	if [ "x$(target)" = 'x$(OPK_HOST_ARCH)' ]; then \
		$(MAKE) -f ../build "installnative-$(target)"; \
	else \
		$(MAKE) -f ../build "installcross-$(target)"; \
	fi

$(installnative_targets):
	# The -T option is necessary because otherwise:
	#   * oh-autoinstall checks for an "install" target by running make with
	#     the -n option,
	#   * Many commands in GCC makefiles contain the "$(MAKE)" macro
	#     expansion, and
	#   * GNU Make executes any commands that contain "$(MAKE)", even if -n
	#     is specified.
	# See also: <http://gcc.gnu.org/ml/gcc/2013-04/msg00171.html>.
	oh-autoinstall -B "$(builddir)" -d "$(destdir)" -T install -- \
		$(dir_macros)
	# Change the target architecture prefix of files in /usr/bin.
	rm -f $(destdir)/usr/bin/$(target_gnu)-*
	for f in $(destdir)/usr/bin/*; do f="$${f##*/}"; \
		mv $(destdir)/usr/bin/$${f} $(destdir)/usr/bin/$(target)-$${f};\
		ln -s $(target)-$${f} $(destdir)/usr/bin/$${f}; \
	done
	rm -f $(destdir)/usr/bin/$(target)-c++-$(base_version)
	ln -s $(target)-g++-$(base_version) \
		$(destdir)/usr/bin/$(target)-c++-$(base_version)
	# Move files into ProteanOS-style directories.
	mkdir -p $(destdir)$(tgtlibdir)
	mv $(destdir)$(libdir)/gcc/$(target_gnu)/$(version)/* \
		$(destdir)$(tgtlibdir)
	mkdir -p $(destdir)$(libdir)
	mv $(destdir)$(libdir)/$(libsuffix)/* $(destdir)$(libdir)
	mkdir -p $(destdir)$(tgtincdir)
	mv $(destdir)/usr/include/c++-$(base_version)/$(target_gnu)/* \
		$(destdir)$(tgtincdir)
	# Remove libitm files.
	rm -f $(destdir)$(libdir)/libitm.*
	# Remove libquadmath files.
	rm -f $(destdir)$(libdir)/libquadmath.*
	# Remove libtool archives and static libraries.
	rm -f \
		$(destdir)$(libdir)/*.la \
		$(destdir)$(libdir)/*.a \
		$(destdir)$(tgtlibdir)/*.la \
		$(destdir)$(tgtlibdir)/plugin/*.la
	# Remove the info directory node.
	rm -f $(destdir)/usr/share/info/dir
	# Remove empty documentation files.
	find $(destdir)/usr/share/man -type f -a -size 0c -a \
		-exec rm -f '{}' ';'
	find $(destdir)/usr/share/info -type f -a -size 0c -a \
		-exec rm -f '{}' ';'
	# TODO: Provide these files in a fixincludes package (arch:any,
	# target-specific?).
	rm -Rf $(destdir)$(tgtlibdir)/install-tools/
	# TODO: Provide these files in a libstdc++-*-dbg package.
	rm -f $(destdir)$(libdir)/libstdc++.so.*-gdb.py
	rm -Rf $(destdir)/usr/share/gcc-$(version)/python/libstdcxx/
	# TODO: Provide these files in a doc package.
	rm -Rf $(destdir)/usr/share/man/ $(destdir)/usr/share/info/
	# TODO: Provide these files in a gcc-*-plugin-dev package.
	rm -Rf $(destdir)$(tgtlibdir)/plugin/
	oh-fixperms -d "$(destdir)"
	oh-strip -d "$(destdir)"
	OPK_PACKAGES="\
		$$(printf '%s\n' $${OPK_PACKAGES} | \
			grep -Ev "(gcc|g++)-$(base_version)-.*-.*-.*") \
		gcc-$(base_version)-$(target) \
		g++-$(base_version)-$(target) \
		" oh-installfiles -d "$(destdir)"
	oh-shlibdeps

$(installcross_targets):
	oh-autoinstall -B "$(builddir)" -d "$(destdir)" -T install-gcc -- \
		$(dir_macros)
	# Change the target architecture prefix of files in /usr/bin.
	rm -f $(destdir)/usr/bin/$(target_gnu)-*
	for f in $(destdir)/usr/bin/*; do f="$${f##*/}"; \
		mv $(destdir)/usr/bin/$${f} $(destdir)/usr/bin/$(target)-$${f};\
	done
	rm -f $(destdir)/usr/bin/$(target)-c++-$(base_version)
	ln -s $(target)-g++-$(base_version) \
		$(destdir)/usr/bin/$(target)-c++-$(base_version)
	# Move files into ProteanOS-style directories.
	mkdir -p $(destdir)$(tgtlibdir)
	mv $(destdir)$(libdir)/gcc/$(target_gnu)/$(version)/* \
		$(destdir)$(tgtlibdir)
	rm -Rf \
		$(destdir)$(tgtlibdir)/*.la \
		$(destdir)$(tgtlibdir)/install-tools \
		$(destdir)$(tgtlibdir)/plugin \
		$(destdir)/usr/share/locale \
		$(destdir)/usr/share/man \
		$(destdir)/usr/share/info
	oh-fixperms -d "$(destdir)"
	oh-strip -d "$(destdir)"
	OPK_PACKAGES="\
		gcc-$(base_version)-$(target) \
		g++-$(base_version)-$(target) \
		" oh-installfiles -d "$(destdir)"
	oh-shlibdeps

install: $(install_targets)