#!/usr/bin/make -f

SPACE := $(EMPTY) $(EMPTY)
COMMA := ,

include /usr/share/dpkg/architecture.mk
include /usr/share/dpkg/pkg-info.mk
include /usr/share/dpkg/vendor.mk

export DEB_BUILD_MAINT_OPTIONS = hardening=-all,+format

# The top-level configure script fails to pass these down properly ...
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
ifneq (,$(filter $(DEB_HOST_ARCH),ppc64el))
  export DEB_BUILD_MAINT_OPTIONS += optimize=-lto
endif

DPKG_EXPORT_BUILDFLAGS = 1
include /usr/share/dpkg/buildflags.mk

CXXFLAGS += -fPIC
CFLAGS += -fPIC
export $(DPKG_BUILDFLAGS_LIST)

# Ensure texlive respects DEB_TIMESTAMP
export FORCE_SOURCE_DATE=1
# Also force "TeX output" string in dvi file, thus %DVIPSSource in the ps file
FAKETIME = TZ=UTC faketime "$(shell TZ=UTC date +"%Y-%m-%d %T" --date=@$(DEB_TIMESTAMP))"

# Rather paranoid than sorry. Make the shell exit with an error if an
# untested command fails.
SHELL += -e

export INSTALL = /usr/bin/install -p

derivative   := $(shell if dpkg-vendor --derives-from Ubuntu; then echo Ubuntu; \
			elif dpkg-vendor --derives-from Debian; then echo Debian; \
			else echo Unknown; fi)

# Support parallel=<n> in DEB_BUILD_OPTIONS (see #209008)
ifneq (,$(filter parallel=%,$(subst $(COMMA), ,$(DEB_BUILD_OPTIONS))))
  NJOBS := -j $(subst parallel=,,$(filter parallel=%,$(subst $(COMMA), ,$(DEB_BUILD_OPTIONS))))
endif

ifneq (,$(filter nodoc, $(DEB_BUILD_PROFILES)))
  nodoc_profile = yes
endif

# Don't include docs with GFDL invariant sections
GFDL_INVARIANT_FREE := yes
ifeq ($(derivative),Ubuntu)
  GFDL_INVARIANT_FREE := no
  FORCE_CONTROL = FORCE
endif
ifneq ($(GFDL_INVARIANT_FREE),yes)
  ifneq ($(nodoc_profile),yes)
    with_doc := yes
  endif
endif

# ---------- settings for cross builds ----------

# Cross configuration support.  Check for an environment variable
# $GDB_TARGET, or a file debian/target.
ifndef GDB_TARGET
DEBIAN_TARGET_FILE := $(strip $(shell cat debian/target 2>/dev/null))
ifneq ($(DEBIAN_TARGET_FILE),)
GDB_TARGET := $(DEBIAN_TARGET_FILE)
endif
endif

DEB_TARGET_ALIAS ?= $(DEB_TARGET_GNU_TYPE)

ifneq ($(GDB_TARGET),)
  configure_target_args = --with-gdb-datadir="\$${prefix}/share/gdb-$(DEB_TARGET_GNU_TYPE)"
endif

ifeq ($(DEB_TARGET_ARCH),)
$(error GDB_TARGET value "$(GDB_TARGET)" is not a valid Debian architecture)
endif

ifdef GDB_TARGET
  DEB_CROSS = yes
  # TP: Target Prefix. Used primarily as a prefix for cross tool
  #     names (e.g. powerpc-linux-gcc).
  # TS: Target Suffix. Used primarily at the end of cross compiler
  #     package names (e.g. gcc-powerpc).
  TP = $(DEB_TARGET_ALIAS)-
  TS = -$(DEB_TARGET_ALIAS)
  FORCE_CONTROL = FORCE
endif

# ---------- configure options, architecture specific ----------

ifeq ($(DEB_HOST_GNU_CPU),ia64)
  arch_config_args := --with-libunwind-ia64
endif

arch_config_args += --with-babeltrace

# Enable Intel Processor Trace (PT) on Linux x86 platform
ifneq (,$(filter $(DEB_HOST_ARCH),amd64 i386))
  arch_config_args += --with-intel-pt
endif

ifdef GDB_TARGET
  arch_config_args += --program-prefix=$(TP) \
    --target=$(DEB_TARGET_ALIAS) --with-sysroot=/usr/$(DEB_TARGET_ALIAS)
else
  # To avoid file conflicts, only enable the global gdbinit file for native
  # debuggers.
  arch_config_args += --with-system-gdbinit=/etc/gdb/gdbinit --with-system-gdbinit-dir=/etc/gdb/gdbinit.d
endif

# ---------- running tests? ----------

run_tests := yes
ifneq (,$(filter nocheck, $(DEB_BUILD_OPTIONS)))
  run_tests := disabled by DEB_BUILD_OPTIONS
endif

ifeq (,$(findstring linux, $(DEB_HOST_GNU_SYSTEM)))
  run_tests := only enabled for linux targets
endif

# FIXME: hanging on the Ubuntu buildds?
#ifneq (,$(filter armhf, $(DEB_HOST_ARCH)))
#  run_tests := not enabled for $(DEB_HOST_ARCH)
#endif

ifdef GDB_TARGET
  run_tests := disabled for cross builds
endif

# List of architectures where tests are flaky (and therefore
# disabled).
FLAKY_TEST_ARCHITECTURES = \
	alpha \
	hppa \
	sparc64 \
	x32

ifneq (,$(filter $(DEB_HOST_ARCH),$(FLAKY_TEST_ARCHITECTURES)))
  run_tests := disable on $(DEB_HOST_ARCH) due to flakiness
endif

# Architectures where gdbserver's libinproctrace is available.
LIBINPROCTRACE_AVAILABLE_ARCHITECTURES = \
	amd64 \
	arm64 \
	i386 \
	ppc64el \
	s390x \
	powerpc \
	ppc64 \
	x32

# ---------- configure options, for all variants ----------

variants = default multiarch

# We pass srcdir explicitly to avoid an extra '/.' at the end of it.  That
# causes a harmless, but ugly, testsuite failure in maint.exp.
common_configure_args = \
	--build=$(DEB_BUILD_GNU_TYPE) \
	--host=$(DEB_HOST_GNU_TYPE) \
	--prefix=/usr \
	--libexecdir="\$${prefix}/lib/gdb" \
	--disable-werror \
	--disable-maintainer-mode \
	--disable-dependency-tracking \
	--disable-silent-rules \
	--disable-gdbtk \
	--disable-shared \
	--with-pkgversion='$(DEB_VENDOR)___$(DEB_VERSION)' \
	--srcdir=$(CURDIR) \
	--disable-readline \
	--with-system-readline \
	--with-expat \
	--with-system-zlib \
	--without-guile \
	--without-babeltrace \
	$(if $(filter linux, $(DEB_HOST_ARCH_OS)),--with-debuginfod) \
	$(arch_config_args) \

#	$(if $(filter $(DEB_HOST_ARCH), armhf arm64 mips mipsel ppc64el riscv64),--disable-sim) \

default_configure_args = \
	$(common_configure_args) \
	$(configure_target_args) \
	--enable-tui \
	--with-lzma \
	--with-python=python3 \
	--with-xxhash \
	--enable-64-bit-bfd

multiarch_configure_args = \
	$(default_configure_args) \
	--enable-targets=all \
	--enable-obsolete \
	--disable-sim

# ---------- configure and build targets ----------

builddir_default	= build/default
builddir_multiarch	= build/multiarch
builddir_source		= build/gdb

stamps/configure-%:
	@mkdir -p stamps
	rm -f gdb/doc/GDBvn.texi
	rm -rf $(builddir_$*)
	mkdir -p $(builddir_$*)
	@echo "gdb-$*: configured with: $(subst ___, ,$(foreach i,$($*_configure_args),$(i)\n\t))"
	cd $(builddir_$*) && CFLAGS="$(CFLAGS)" \
	  ../../configure $(subst ___,$(SPACE),$($*_configure_args))
	touch $@

stamps/build-%: stamps/configure-%
	V=1 $(MAKE) -C $(builddir_$*) $(NJOBS)
	$(if $(filter yes, $(nodoc_profile)),, \
	  $(if $(filter default, $*), \
	    $(MAKE) -C $(builddir_default) info))
	$(if $(filter yes, $(nodoc_profile)),, \
	  $(if $(filter default, $*), \
	    $(FAKETIME) $(MAKE) -C $(builddir_$*)/gdb/doc refcard.dvi refcard.ps))
	touch $@

# GDB's testsuite has historically been flaky and its results haven't
# been very trustworthy.  Instead of running the entire testsuite (and
# wasting a lot of time and CPU), pick only a subset of tests that are
# known to be non-flaky.  If any of these fail, something is really
# wrong.
#
# This list was inspired by
# https://sourceware.org/git/?p=builder.git;a=blob;f=builder/master.cfg
TESTS_NON_FLAKY = \
	gdb.base/break-always.exp \
	gdb.base/break-caller-line.exp \
	gdb.base/break-entry.exp \
	gdb.base/break.exp \
	gdb.base/break-fun-addr.exp \
	gdb.base/break-idempotent.exp \
	gdb.base/break-include.exp \
	gdb.base/break-inline.exp \
	gdb.base/break-main-file-remove-fail.exp \
	gdb.base/break-on-linker-gcd-function.exp \
	gdb.base/breakpoint-in-ro-region.exp \
	gdb.base/breakpoint-shadow.exp \
	gdb.base/break-probes.exp \
	gdb.gdb/unittest.exp \
	gdb.server/unittest.exp

stamps/check: stamps/build-default
ifeq ($(run_tests),yes)
#	Run the non-flaky tests.
#
#	Don't parallelize because things can get racy, and we're not
#	dealing with that many tests anyway.
	$(MAKE) -C $(builddir_default)/gdb \
		check//unix check//native-gdbserver check//native-extended-gdbserver \
		TESTS="$(TESTS_NON_FLAKY)"
	@echo "===== TEST SUMMARY BEGIN ====="
	-cat $(builddir_default)/gdb/testsuite/gdb.sum
	@echo "===== TEST SUMMARY END ====="
else
	@echo "***Tests disabled: $(run_tests) ***"
endif
	touch $@

stamps/build-doc: stamps/build-default
	$(MAKE) -C $(builddir_default)/gdb/doc pdf html

# ---------- installation and packaging targets ----------

clean: debian/control
	dh_clean
	rm -rf stamps build
	rm -f debian/files

	if test -f gdb/version.in.backup; then \
	  mv -f gdb/version.in.backup gdb/version.in; \
	fi

	# Prevent gratuitous rebuilds of the BFD documentation, since it
	# updates the copy in the source directory.
	find bfd -name bfd.info\* | xargs --no-run-if-empty touch

install-pre:
	dh_prep

install: install-pre
	: # gdb install
	$(MAKE) -C $(builddir_default) install DESTDIR=$(CURDIR)/debian/tmp
	rm -rf debian/gdb-doc/usr/share/man

	dh_install

ifeq (,$(filter $(DEB_HOST_ARCH),hurd-amd64))
	install -m 755 debian/tmp/usr/bin/gcore debian/gdb$(TS)/usr/bin/gcore
endif

	install -d debian/gdb$(TS)/usr/share/man/man1; \
	install -m 644 debian/gcore.1 debian/gdb$(TS)/usr/share/man/man1/.

	if [ -x debian/tmp/usr/bin/run ]; then \
		mv debian/tmp/usr/bin/run \
		  debian/gdb$(TS)/usr/bin/$(DEB_TARGET_ALIAS)-run; \
	fi
	if [ -r debian/tmp/usr/share/man/man1/run.1 ]; then \
		mv debian/tmp/usr/share/man/man1/run.1 \
		  debian/gdb$(TS)/usr/share/man/man1/$(DEB_TARGET_ALIAS)-run.1; \
	fi
# FIXME: now in gdb.install
#ifneq ($(GFDL_INVARIANT_FREE),yes)
#	install -d debian/gdb$(TS)/usr/share/man/man5
#	install -m 644 $(builddir_default)/gdb/doc/gdbinit.5 \
#		debian/gdb$(TS)/usr/share/man/man5/.
#	install -m 644 $(builddir_default)/gdb/doc/gdb.1 \
#		debian/gdb$(TS)/usr/share/man/man1/.
#	install -m 644 $(builddir_default)/gdb/doc/gdb-add-index.1 \
#		debian/gdb$(TS)/usr/share/man/man1/.
#endif

ifneq ($(DEB_CROSS),yes)
	: # Only ship a global gdbinit for the native GDB.
	install -d debian/gdb$(TS)/etc/gdb
	install -d debian/gdb$(TS)/etc/gdb/gdbinit.d
	install -m 644 debian/gdbinit debian/gdb$(TS)/etc/gdb/
	: # Likewise gdb-add-index
	install -m 755 gdb/contrib/gdb-add-index.sh debian/gdb$(TS)/usr/bin/gdb-add-index
endif

	rm -f debian/gdb$(TS)/usr/bin/$(TP)gdbtui
	install -m 755 debian/gdbtui debian/gdb$(TS)/usr/bin/$(TP)gdbtui

	: # gdb-multiarch install
	install -d debian/gdb-multiarch/usr/bin
	install -m 755 $(builddir_multiarch)/gdb/gdb debian/gdb-multiarch/usr/bin/gdb-multiarch

	: # gdbserver install
ifneq (,$(filter $(DEB_HOST_ARCH),$(LIBINPROCTRACE_AVAILABLE_ARCHITECTURES)))
	install -d debian/gdbserver/usr/lib
	install debian/tmp/usr/lib/libinproctrace.so debian/gdbserver/usr/lib/
endif

ifneq ($(GFDL_INVARIANT_FREE),yes)
	install -d debian/gdbserver/usr/share/man/man1
	install -m 644 $(builddir_default)/gdb/doc/gdbserver.1 \
		debian/gdbserver/usr/share/man/man1/.
endif

ifeq ($(with_doc),yes)
	install -d debian/gdb-doc/usr/share/info
	install -m 644 debian/tmp/usr/share/info/gdb.info debian/gdb-doc/usr/share/info/.
	install -m 644 debian/tmp/usr/share/info/stabs.info debian/gdb-doc/usr/share/info/.

	$(MAKE) -C $(builddir_default)/gdb/doc DESTDIR=$(CURDIR)/debian/gdb-doc \
		pdfdir=/usr/share/doc/gdb-doc/pdf \
		htmldir=/usr/share/doc/gdb-doc/html \
		install-html install-pdf

	: # This manual documents a long-obsolete facility
	rm -f debian/gdb-doc/usr/share/info/annota*
	rm -rf debian/gdb-doc/usr/share/doc/gdb-doc/*/annota*

	rm -f debian/gdb-doc/usr/share/info/dir*

	: # Symlink stuff into gdb's doc directory
	install -d debian/gdb-doc/usr/share/doc/gdb
	ln -s ../gdb-doc/html debian/gdb-doc/usr/share/doc/gdb/html
	ln -s ../gdb-doc/pdf debian/gdb-doc/usr/share/doc/gdb/pdf
endif

install-indep: install-pre
	: # gdb-source install
	install -d debian/gdb-source/usr/src
	mkdir -p $(builddir_source)
	tar --exclude build --exclude stamps --exclude .git -cf - . \
	  | (cd $(builddir_source) && tar -xf -)
	cd $(builddir_source) && debian/rules clean
	cd $(dir $(builddir_source)) \
	  && tar cfJ $(CURDIR)/debian/gdb-source/usr/src/gdb.tar.xz \
	     --format=gnu \
	     --mode=755 \
	     --mtime="@$(DEB_TIMESTAMP)" --clamp-mtime \
	     --numeric-owner --owner=0 --group=0 \
	     --sort=name \
	     $(notdir $(builddir_source))


debian/control: debian/control.in debian/control.doc $(FORCE_CONTROL)
	cat debian/control.in \
		| sed "s/@TS@/$(TS)/g" \
		> debian/control
ifeq ($(with_doc),yes)
	cat debian/control.doc >> debian/control
endif
ifeq ($(DEB_CROSS),yes)
	sed -i "/Package: gdb-multiarch/,\$$ d" debian/control
	sed "s+/gdb+/$(TP)gdb+g; s+usr/share/$(TP)gdb+usr/share/gdb$(TS)+g" \
		debian/gdb.install > debian/gdb$(TS).install
endif


gdb_substvars =

build-indep: $(foreach v,$(variants),stamps/build-$(v)) $(if $(filter yes,$(with_doc)),stamps/build-doc)
build-arch: $(foreach v,$(variants),stamps/build-$(v)) stamps/check
build: build-arch build-indep

binary-indep: build-indep install install-indep
	dh_installdocs -i
	dh_installchangelogs -i
	dh_strip -i
	dh_link -i
	dh_compress -i -X.pdf
	dh_fixperms -i
	dh_installdeb -i
	dh_shlibdeps -i
	dh_gencontrol -i
	dh_md5sums -i
	dh_builddeb -i

binary-arch: build-arch install
	dh_installdocs -pgdb$(TS) \
		gdb/NEWS gdb/README gdb/doc/refcard.tex \
		$(if $(filter yes, $(nodoc_profile)),, \
		  $(builddir_default)/gdb/doc/refcard.dvi \
		  $(builddir_default)/gdb/doc/refcard.ps) \
		gdb/contrib/

	dh_installdocs -pgdbserver gdbserver/README
	dh_installchangelogs -pgdbserver -pgdb$(TS)
	dh_lintian

	install -d debian/gdb-multiarch/usr/share/doc
	ln -s gdb debian/gdb-multiarch/usr/share/doc/gdb-multiarch

	dh_dwz -a
	dh_strip -pgdb$(TS)
	dh_strip -a -Ngdb$(TS)
	dh_link -a
	dh_compress -a
	dh_fixperms -a
	dh_installdeb -a
	dh_shlibdeps -a
	dh_gencontrol -a -- $(gdb_substvars)
	dh_md5sums -a
	dh_builddeb -a

binary: binary-indep binary-arch

remove-gfdl-files:
ifeq ($(GFDL_INVARIANT_FREE),yes)
	rm -vf gdb/doc/*.1
	rm -vf gdb/doc/*.5
	rm -vf gdb/doc/*.info*
	rm -vf readline/readline/doc/*.info
	rm -vf zlib/contrib/dotzlib/DotZLib.chm
endif

.PHONY: build build-arch build-indep clean binary-indep binary-arch binary install

.PHONY: FORCE
FORCE:
