#!/usr/bin/make -f

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

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

# The top-level configure script fails to pass these down properly ...
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
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

nodoc_profile = $(if $(filter nodoc,$(DEB_BUILD_PROFILES)),no,yes)

# Don't include docs with GFDL invariant sections
GFDL_INVARIANT_FREE = yes
ifeq ($(derivative),Ubuntu)
  GFDL_INVARIANT_FREE = no
endif

with_doc = no
ifneq ($(GFDL_INVARIANT_FREE),yes)
  ifneq ($(nodoc_profile),yes)
    with_doc = yes
  endif
endif

with_multiarch = $(if $(filter pkg.gdb.no-multiarch,$(DEB_BUILD_PROFILES)),no,yes)

# ---------- 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)
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

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

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-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) \

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

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

%:
	dh $@

# There's no need to run autoreconf as upstream already ships a
# working configure script.
override_dh_autoreconf:

# Configure GDB.
# First and only argument is the build directory.
define configure-gdb
mkdir -p $(builddir_$(1))
@echo "gdb-$(1): configure with: $(subst ___, ,$(foreach i,$($(1)_configure_args),$(i)\n\t))"
cd $(builddir_$(1)) && ../../configure $(subst ___,$(SPACE),$($(1)_configure_args))
endef

override_dh_auto_configure-arch:
	$(call configure-gdb,default)
ifeq ($(with_multiarch),yes)
	$(call configure-gdb,multiarch)
endif

override_dh_auto_configure-indep:

# Build GDB.
# First and only argument is the build directory.
define build-gdb
$(MAKE) V=1 -C $(builddir_$(1)) $(NJOBS)
endef

override_dh_auto_build-arch:
	$(call build-gdb,default)
ifeq ($(with_multiarch),yes)
	$(call build-gdb,multiarch)
endif
	$(FAKETIME) $(MAKE) -C $(builddir_default)/gdb/doc refcard.dvi refcard.ps
ifeq ($(with_doc),yes)
	$(MAKE) -C $(builddir_default) info
	$(MAKE) -C $(builddir_default)/gdb/doc pdf html
endif

override_dh_auto_build-indep:

# 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

define test-gdb
$(MAKE) -C $(builddir_$(1))/gdb \
	check//unix check//native-gdbserver check//native-extended-gdbserver \
	TESTS="$(TESTS_NON_FLAKY)"
endef

override_dh_auto_test-arch:
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.
	$(call test-gdb,default)
ifeq ($(with_multiarch),yes)
	$(call test-gdb,multiarch)
endif
else
	@echo "***Tests disabled: $(run_tests) ***"
endif

override_dh_auto_test-indep:

execute_after_dh_clean: debian/control
	rm -rf build

	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

override_dh_install-arch:
	# gdb install
	$(MAKE) -C $(builddir_default) install DESTDIR=$(CURDIR)/debian/tmp

	# Remove files that we don't ship.
	find $(CURDIR)/debian/tmp/usr/share/locale -type f \
		\( -name "bfd.mo" -or -name "opcodes.mo" \) -delete
	find $(CURDIR)/debian/tmp/usr/share/locale -type d -empty -delete
	rm -rfv $(CURDIR)/debian/tmp/usr/include/*.h \
		$(CURDIR)/debian/tmp/usr/include/sim/ \
		$(CURDIR)/debian/tmp/usr/share/doc/ppc/ \
		$(CURDIR)/debian/tmp/usr/lib/*.a \
		$(CURDIR)/debian/tmp/usr/lib/*.la
ifeq ($(with_doc),no)
	rm -fv $(CURDIR)/debian/tmp/usr/share/info/*.info
endif

	dh_install

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

	mkdir -p 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
ifeq ($(with_doc),yes)
	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
endif

ifneq ($(GFDL_INVARIANT_FREE),yes)
	mkdir -p 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.
	mkdir -p debian/gdb$(TS)/etc/gdb/gdbinit.d
	install -m 644 debian/gdbinit debian/gdb$(TS)/etc/gdb/
	# Likewise gdb-add-index
	mv -v $(CURDIR)/debian/tmp/usr/bin/gdb-add-index debian/gdb$(TS)/usr/bin/gdb-add-index
endif

ifeq ($(with_multiarch),yes)
	# gdb-multiarch install
	mkdir -p debian/gdb-multiarch/usr/bin
	install -m 755 $(builddir_multiarch)/gdb/gdb debian/gdb-multiarch/usr/bin/gdb-multiarch
endif

ifneq (,$(filter $(DEB_HOST_ARCH),$(LIBINPROCTRACE_AVAILABLE_ARCHITECTURES)))
	# libinproctrace (gdbserver) install
	mkdir -p debian/gdbserver/usr/lib
	mv -v $(CURDIR)/debian/tmp/usr/lib/libinproctrace.so debian/gdbserver/usr/lib/
endif

ifneq ($(GFDL_INVARIANT_FREE),yes)
	mkdir -p 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)
	mkdir -p 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 -fv debian/gdb-doc/usr/share/info/annota*
	rm -rfv debian/gdb-doc/usr/share/doc/gdb-doc/*/annota*

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

	# Symlink stuff into gdb's doc directory
	mkdir -p 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

override_dh_install-indep:
	# gdb-source install
	mkdir -p 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
	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

execute_after_dh_installdocs:
	dh_installdocs -pgdb$(TS) \
		gdb/NEWS gdb/README gdb/doc/refcard.tex \
		$(builddir_default)/gdb/doc/refcard.dvi \
		$(builddir_default)/gdb/doc/refcard.ps
