#!/usr/bin/make -f
include /usr/share/dpkg/architecture.mk
include /usr/share/dpkg/buildopts.mk
include /usr/share/dpkg/pkg-info.mk
DEB_BUILD_OPTION_PARALLEL ?= 1

# Some GCC sources use non-string literals as format strings,
# for example to define their own wrapper functions.
export DEB_BUILD_MAINT_OPTIONS = hardening=+all,-format

gnu_type = riscv32-pico-elf
gcc-version-major != sed -En 's/.*gcc-(.*)-source.*/\1/p' debian/control

gcc-version	!= dpkg-query -Wf'$${source:Version}' gcc-$(gcc-version-major)-source
gdb-version	!= dpkg-query -Wf'$${source:Version}' gdb-source
newlib-upstream-version	!= dpkg-query -Wf'$${source:Upstream-Version}' newlib-source
newlib-source-version != dpkg-query -Wf'$${source:Version}' newlib-source

# https://gcc.gnu.org/install/configure.html recommends out-of-tree builds.
%:
	dh $@

execute_before_dh_update_autotools_config: src
src:
	tar -xf /usr/src/gcc-$(gcc-version-major)/gcc-*.tar.xz
	mv gcc-* $@
	rm -rf $@/zlib
# Patches shipped by gcc-N-source itself are rooted at the parent of src/
# (the patch headers carry an "a/src/", "b/src/" prefix that `patch -p1`
# strips), so they must be applied from the package root rather than from
# inside src/.  The first patch may be empty.
	patch -p1 -i /usr/src/gcc-$(gcc-version-major)/patches/git-updates.diff || true;
	patch -p1 -i /usr/src/gcc-$(gcc-version-major)/patches/gcc-gfdl-build.diff
# Patches under debian/local-patches/ are reserved for changes that are
# local to this cross-toolchain (e.g. ISA extension support that has not
# yet landed in the gcc-N-source we are building against).  They are
# expected to be standard "git format-patch"-style patches rooted at the
# gcc source root, mirroring the convention used by
# binutils-riscv32-pico-elf/debian/local-patches/.
	for patch in debian/local-patches/[0-9]*.patch; do \
		[ -e "$$patch" ] || continue; \
		echo "Applying local patch $$patch"; \
		patch -d $@ -p1 < "$$patch"; \
	done
	tar -xf /usr/src/newlib/newlib-*.tar.xz
	tar -xf /usr/src/gdb.tar.xz
	rm -rf gdb*/readline gdb*/zlib
# Symbolically link directories from GDB and Newlib into the GCC tree.
	cd $@ && for i in ../gdb*/* ../newlib*/*; \
	do \
		if [ ! -e `basename "$$i"` -a -d "$$i" ]; \
		then ln -s "$$i" . || exit 1; \
		fi; \
	done
# gcc's configure script is too old to build GDB right.
	cd $@ && rm -f Makefile.def Makefile.in configure
	cd $@ && cp ../gdb*/Makefile.def ../gdb*/Makefile.in ../gdb*/configure .

# Avoid dh_auto_*, see
# https://gcc.gnu.org/legacy-ml/gcc/2013-04/msg00171.html.

CONFIG_OPTS = \
	--build=$(DEB_BUILD_GNU_TYPE) \
	--host=$(DEB_HOST_GNU_TYPE) \
	--target=$(gnu_type) \
	SED=/bin/sed \
	SHELL=/bin/sh \
	BASH=/bin/bash \
	CONFIG_SHELL=/bin/bash \
	--prefix=/usr \
	--disable-gdb \
	--disable-libcc1 \
	--enable-languages=c,c++,lto \
	--enable-lto \
	--with-gcc-major-version-only \
	--without-included-gettext \
	--with-pkgversion='GCC $(gcc-version) Debian $(DEB_VERSION)' \
	--with-bugurl="https://www.debian.org/Bugs/" \
	--with-system-zlib \
	--with-newlib \
	--disable-shared \
	--disable-threads \
	--disable-libmudflap \
	--disable-libssp \
	--disable-libquadmath \
	--disable-libgomp \
	--disable-nls \
	--disable-tm-clone-registry \
	--with-arch=rv32ima_zicsr_zifencei_zba_zbb_zbs_zbkb_zca_zcb_zcmp \
	--with-abi=ilp32 \
	--with-multilib-generator="rv32ima_zicsr_zifencei_zba_zbb_zbs_zbkb_zca_zcb_zcmp-ilp32--;rv32imac_zicsr_zifencei_zba_zbb_zbs_zbkb-ilp32--;rv32ima_zicsr_zifencei_zilsd_zba_zbb_zbs_zbkb_zbkx_zca_zcb_zclsd_zcmp_zibi-ilp32--" \
	--enable-newlib-io-long-double \
	--enable-newlib-io-long-long \
	--enable-newlib-io-c99-formats \
	--enable-newlib-register-fini \
	CFLAGS_FOR_TARGET="-O2 -D_POSIX_MODE -ffunction-sections -fdata-sections" \
	CXXFLAGS_FOR_TARGET="-O2 -D_POSIX_MODE -ffunction-sections -fdata-sections"

override_dh_auto_configure: bld
bld:
	mkdir -p $@
	if echo $(DEB_BUILD_OPTIONS) | grep -q terse; \
	then QUIET_OPTS='--quiet --enable-silent-rules'; \
	fi; \
	cd $@ && ../src/configure $(CONFIG_OPTS) $$QUIET_OPTS

override_dh_auto_build:
	$(MAKE) -C bld -j$(DEB_BUILD_OPTION_PARALLEL)

override_dh_auto_test:

override_dh_auto_install:
	$(MAKE) -C bld install DESTDIR=$(CURDIR)/debian/gcc-$(gnu_type)
# Documentation is empty due to being licensed GFDL with invariant sections;
# localization files are provided by gcc-*-locales.  The generated man pages
# are stubs — our own replacements are installed via dh_installman.
	rm -rf debian/gcc-$(gnu_type)/usr/share/info \
		debian/gcc-$(gnu_type)/usr/share/locale \
		debian/gcc-$(gnu_type)/usr/share/man
# The *.la files are unnecessary and strongly discouraged from being distributed in Debian.
	find debian/gcc-$(gnu_type) -name '*.la' -type f -exec rm {} \;
	$(MAKE) -C bld install-target-newlib DESTDIR=$(CURDIR)/debian/libnewlib-$(gnu_type)-dev
# We installed everything into gcc-riscv32-pico-elf and now prune out Newlib.
	cd debian/libnewlib-$(gnu_type)-dev && find * -type f -exec rm -rf ../gcc-$(gnu_type)/{} \;
	find debian/gcc-$(gnu_type) debian/libnewlib-$(gnu_type)-dev -type d -empty -delete
	if ! echo $(DEB_BUILD_OPTIONS) | grep -q nostrip; \
	then find debian/libnewlib-$(gnu_type)-dev/ -name '*.a' -exec \
		$(gnu_type)-strip --strip-unneeded --remove-section=.comment --remove-section=.note {} + ; \
	fi
# Build and merge newlib-nano.
	$(MAKE) -f debian/rules newlib-nano-install
# Man pages are provided by debian/man/ and installed via dh_installman.

# --- Newlib-nano second pass ---
NANO_SRCDIR = newlib-nano-src
NANO_BLDDIR = newlib-nano-bld
NANO_DESTDIR = $(CURDIR)/newlib-nano-install

NANO_CONFIG_OPTS = \
	--build=$(DEB_BUILD_GNU_TYPE) \
	--host=$(DEB_HOST_GNU_TYPE) \
	--target=$(gnu_type) \
	--prefix=/usr \
	--disable-newlib-supplied-syscalls \
	--enable-newlib-reent-small \
	--disable-newlib-fvwrite-in-streamio \
	--disable-newlib-fseek-optimization \
	--disable-newlib-wide-orient \
	--enable-newlib-nano-malloc \
	--disable-newlib-unbuf-stream-opt \
	--enable-lite-exit \
	--enable-newlib-global-atexit \
	--enable-newlib-nano-formatted-io \
	--disable-nls \
	CFLAGS_FOR_TARGET="-Oz -ffunction-sections -fdata-sections" \
	CXXFLAGS_FOR_TARGET="-Oz -ffunction-sections -fdata-sections"

# The staged gcc resolves its internal assembler/linker search path relative
# to its own binary: …/usr/riscv32-pico-elf/bin/{as,ld,…}.  That directory
# does not exist in the staged tree, so gcc falls back to the host "as" on
# PATH — the x86_64 assembler, which cannot handle RISC-V -march options.
# Create temporary symlinks so the staged gcc finds the system cross-binutils.
STAGED_TARGET_BIN = debian/gcc-$(gnu_type)/usr/$(gnu_type)/bin

stage-target-binutils:
	mkdir -p $(STAGED_TARGET_BIN)
	for tool in ar as ld ld.bfd nm objcopy objdump ranlib readelf strip; do \
		ln -sf /usr/bin/$(gnu_type)-$$tool $(STAGED_TARGET_BIN)/$$tool; \
	done

unstage-target-binutils:
	rm -rf $(STAGED_TARGET_BIN)

newlib-nano-configure: $(NANO_BLDDIR)/Makefile
$(NANO_BLDDIR)/Makefile: stage-target-binutils
	mkdir -p $(NANO_SRCDIR)
	tar -C $(NANO_SRCDIR) --strip-components=1 -xf /usr/src/newlib/newlib-*.tar.xz
	mkdir -p $(NANO_BLDDIR)
	cd $(NANO_BLDDIR) && \
		PATH="$(CURDIR)/debian/gcc-$(gnu_type)/usr/bin:$$PATH" \
		../$(NANO_SRCDIR)/configure $(NANO_CONFIG_OPTS)

newlib-nano-build: $(NANO_BLDDIR)/Makefile
	PATH="$(CURDIR)/debian/gcc-$(gnu_type)/usr/bin:$$PATH" \
		$(MAKE) -C $(NANO_BLDDIR) -j$(DEB_BUILD_OPTION_PARALLEL)

newlib-nano-install: newlib-nano-build
	rm -rf $(NANO_DESTDIR)
	PATH="$(CURDIR)/debian/gcc-$(gnu_type)/usr/bin:$$PATH" \
		$(MAKE) -C $(NANO_BLDDIR) install DESTDIR=$(NANO_DESTDIR)
# Merge nano libraries alongside full newlib with _nano suffix.
	for multidir in $$(PATH="$(CURDIR)/debian/gcc-$(gnu_type)/usr/bin:$$PATH" \
		$(gnu_type)-gcc -print-multi-lib | sed 's/;.*//'); do \
		nano_libdir=$(NANO_DESTDIR)/usr/$(gnu_type)/lib/$$multidir; \
		dest_libdir=$(CURDIR)/debian/libnewlib-$(gnu_type)-dev/usr/$(gnu_type)/lib/$$multidir; \
		if [ -d "$$nano_libdir" ]; then \
			for lib in c m g gloss; do \
				if [ -f "$$nano_libdir/lib$${lib}.a" ]; then \
					cp "$$nano_libdir/lib$${lib}.a" "$$dest_libdir/lib$${lib}_nano.a"; \
				fi; \
			done; \
		fi; \
	done
# Copy newlib-nano's newlib.h so the SDK can detect the nano configuration.
	nano_incdir=$(NANO_DESTDIR)/usr/$(gnu_type)/include/newlib.h; \
	if [ -f "$$nano_incdir" ]; then \
		mkdir -p $(CURDIR)/debian/libnewlib-$(gnu_type)-dev/usr/$(gnu_type)/include/newlib-nano; \
		cp "$$nano_incdir" \
			$(CURDIR)/debian/libnewlib-$(gnu_type)-dev/usr/$(gnu_type)/include/newlib-nano/newlib.h; \
	fi
# Strip nano libraries.
	if ! echo $(DEB_BUILD_OPTIONS) | grep -q nostrip; \
	then find $(CURDIR)/debian/libnewlib-$(gnu_type)-dev/ -name '*_nano.a' -exec \
		$(gnu_type)-strip --strip-unneeded --remove-section=.comment --remove-section=.note {} + ; \
	fi
	$(MAKE) -f debian/rules unstage-target-binutils

# Shipping copyright information applicable to the binaries is required by Debian Policy.
execute_before_dh_installdocs: debian/gcc-$(gnu_type).copyright debian/libnewlib-$(gnu_type)-dev.copyright
debian/gcc-$(gnu_type).copyright: debian/copyright /usr/share/doc/gcc-$(gcc-version-major)-source/copyright /usr/share/doc/gdb-source/copyright
	cp debian/copyright $@
	printf -- "\n-----BEGIN GCC-$(gcc-version-major)-SOURCE COPYRIGHT INFORMATION-----\n" >> $@
	cat /usr/share/doc/gcc-$(gcc-version-major)-source/copyright >> $@
	printf -- "-----END GCC-$(gcc-version-major)-SOURCE COPYRIGHT INFORMATION-----\n" \
		"\n-----BEGIN GDB-SOURCE COPYRIGHT INFORMATION-----\n" >> $@
	cat /usr/share/doc/gdb-source/copyright >> $@
	printf -- "-----END GDB-SOURCE COPYRIGHT INFORMATION-----\n" >> $@
debian/libnewlib-$(gnu_type)-dev.copyright: debian/copyright /usr/share/doc/newlib-source/copyright
	cp debian/copyright $@
	printf -- "\n-----BEGIN NEWLIB-SOURCE COPYRIGHT INFORMATION-----\n" >> $@
	cat /usr/share/doc/newlib-source/copyright >> $@
	printf -- "-----END NEWLIB-SOURCE COPYRIGHT INFORMATION-----\n" >> $@

# dh_strip uses the host strip which cannot handle RISC-V target objects.
# Exclude the target library paths and strip them separately with the cross tool.
override_dh_strip:
	dh_strip -Xusr/lib/gcc/$(gnu_type) -Xusr/$(gnu_type)/lib
	if ! echo $(DEB_BUILD_OPTIONS) | grep -q nostrip; \
	then find debian/gcc-$(gnu_type)/usr/lib/gcc/$(gnu_type) \
		debian/gcc-$(gnu_type)/usr/$(gnu_type)/lib \
		-name '*.a' -exec \
		$(gnu_type)-strip --strip-unneeded --remove-section=.comment --remove-section=.note {} + ; \
	fi

# liblto_plugin.so is installed 0755 by the build; dh_fixperms does not
# correct it, so fix after dh_fixperms runs.
execute_after_dh_fixperms:
	chmod 0644 debian/gcc-$(gnu_type)/usr/libexec/gcc/$(gnu_type)/*/liblto_plugin.so

# The private shared library does not need ldconfig triggers.
override_dh_makeshlibs:
	dh_makeshlibs --no-scripts

override_dh_gencontrol:
	dh_gencontrol -p gcc-$(gnu_type) -- -v$(gcc-version)+$(DEB_VERSION) \
		-Vgcc-version=$(gcc-version) \
		-Vgcc-version-major=$(gcc-version-major) \
		-Vgdb-version=$(gdb-version)
	dh_gencontrol -p libnewlib-$(gnu_type)-dev -- -v$(newlib-upstream-version)+$(DEB_VERSION) \
		-Vnewlib-source-version=$(newlib-source-version)
