#!/usr/bin/make -f

#
# CONTENTS:
#
# 1. DEFINITIONS
# 2. GENERATE FILES
#    Targets to auto-generate files
# 3. PACKAGE BUILD
#    Mostly standard targets that are used during package build
# 4. TEST SUITE
# 5. MAINTAINER TARGETS
#    Convenience targets to be used by maintainers
#    Some are explained at https://wiki.debian.org/DebianScience/Sage
#

###############################################################################
# 1. DEFINITIONS
###############################################################################

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

ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
NUMJOBS = $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
else
NUMJOBS = 1
endif

# Some buildds are a bit slow, see https://buildd.debian.org/status/logs.php?pkg=gcc-7 for a fuller list
ifneq (,$(filter $(DEB_BUILD_ARCH),armel armhf mips mipsel mips64el))
export SAGE_TIMEOUT_LONG = 7200
else
export SAGE_TIMEOUT_LONG = 3600
endif

export DOT_SAGE = $(CURDIR)/debian/test

%:
	dh $@ --with=python3

###############################################################################
# 2. GENERATE FILES
###############################################################################

binary build clean install: debian/control

debian/control: debian/control.in
	cat $^ > "$@"
	sed -i -e '/RUNTIME_DEPENDS/ {' -e 'r debian/control.runtime-depends' -e 'd' -e '}' "$@"
	sed -i -e '/RUNTIME_RECOMMENDS/ {' -e 'r debian/control.runtime-recommends' -e 'd' -e '}' "$@"
	sed -i -e '/JUPYTER_DEPENDS/ {' -e 'r debian/control.jupyter-depends' -e 'd' -e '}' "$@"

###############################################################################
# 3. PACKAGE BUILD
###############################################################################

run_build = \
	MAKE='make -j$(NUMJOBS)' \
	  $(MAKE) --directory=sage

override_dh_auto_configure:
	cd sage && ./bootstrap
	cd sage && ./configure --enable-build-as-root
	debian/depcheck.py

clean:

override_dh_auto_build-arch:
	$(run_build) build

override_dh_auto_build-indep:
ifeq (,$(filter nodoc,$(DEB_BUILD_OPTIONS)))
	$(run_build) doc
	cd sage/local/share/doc/sagemath/html && \
	for statdir in */*/_static; do ln -s /usr/share/javascript/mathjax "$$statdir"; done && \
	for statdir in */_static; do ln -s /usr/share/javascript/mathjax "$$statdir"; done
endif

override_dh_auto_install:
	mkdir -p debian/tmp
	mv sage/local debian/tmp/usr
	mv debian/tmp/usr/lib/python3.* debian/tmp/usr/lib/python3
	mv debian/tmp/usr/lib/python3/site-packages debian/tmp/usr/lib/python3/dist-packages
	mkdir -p debian/tmp/usr/share/sagemath/bin
	cp sage/src/bin/sage-* debian/tmp/usr/share/sagemath/bin
	rm -f debian/tmp/usr/bin/sage-*
	rm -f debian/tmp/usr/share/sagemath/bin/sage-env*
	rm -f debian/tmp/usr/share/sagemath/bin/sage-*.bat
# We built .pyo to make the docbuild/tests go faster, but as per Debian policy
# we don't distribute them.
	find debian/tmp '(' -name '*.pyc' -o -name '*.pyo' ')' -delete
# Install (renamed) icons.
	mkdir -p debian/tmp/usr/share/icons/hicolor/64x64/apps
	mkdir -p debian/tmp/usr/share/icons/hicolor/scalable/apps
	cp -f sage/src/sage/ext_data/notebook-ipython/logo-64x64.png debian/tmp/usr/share/icons/hicolor/64x64/apps/sagemath.png
	cp -f sage/src/sage/ext_data/notebook-ipython/logo.svg debian/tmp/usr/share/icons/hicolor/scalable/apps/sagemath.svg
# Fix up jupyter kernel installation
	rm -f debian/tmp/usr/share/jupyter/nbextensions/jsmol
	rm -f debian/tmp/usr/share/jupyter/kernels/sagemath/logo*
	rm -f debian/tmp/usr/share/jupyter/kernels/sagemath/doc
	ln -s /usr/share/doc/sagemath/html/en debian/tmp/usr/share/jupyter/kernels/sagemath/doc
	ln -s /usr/share/icons/hicolor/64x64/apps/sagemath.png debian/tmp/usr/share/jupyter/kernels/sagemath/logo-64x64.png
	ln -s /usr/share/icons/hicolor/scalable/apps/sagemath.svg debian/tmp/usr/share/jupyter/kernels/sagemath/logo.svg
	sed -E 's|\[\".+bin/sage\",|\[\"/usr/bin/sage\",|' -i debian/tmp/usr/share/jupyter/kernels/sagemath/kernel.json

#override_dh_auto_clean:
#	dh_auto_clean -Dsage -- maintainer-clean
#	rm -f sage/config.status

override_dh_install-indep:
	dh_install --package sagemath-common -X.so
	dh_install --remaining-packages --list-missing
# Basic version of deduplicating the docs, for a much smaller install size.
# Upstream bug report is at https://trac.sagemath.org/ticket/22088
# Hard links do work in Debian packages, but only within packages.
	rdfind -outputname /dev/null -makehardlinks true debian/sagemath-doc; \

override_dh_python3-arch:
	dh_python3
	dh_numpy3 --package sagemath # stop lintian complaining at us

override_dh_shlibdeps:
	dh_shlibdeps -l debian/tmp/usr/lib

override_dh_compress:
# We probably don't need to install the pickle/doctree files but let's exempt
# them from compression anyway for now, so the build goes quicker.
	dh_compress -X.pdf -X.pickle -X.doctree

override_dh_clean:
	rm -rf $(DOT_SAGE)
	dh_clean

override_dh_strip_nondeterminism:
	dh_strip_nondeterminism -X.png # On png files it sometimes fails claiming it's not a png file.

###############################################################################
# 4. TEST SUITE
###############################################################################

MAX_TEST_FAILURES_RERUN = $(shell expr 2 \* $(MAX_TEST_FAILURES))

ifeq (,$(filter pkg.sagemath.nolongcheck,$(DEB_BUILD_PROFILES)))
SAGE_TEST_FLAGS_ARCH = --optional=sage,python3,memlimit --long
SAGE_TEST_FLAGS_INDEP = --optional=sage,python3,memlimit,dochtml --long
else
SAGE_TEST_FLAGS_ARCH = --optional=sage,python3,memlimit
SAGE_TEST_FLAGS_INDEP = --optional=sage,python3,memlimit,dochtml
endif

TESTS_MK = $(MAKE) -s --no-print-directory -f debian/tests.mk LOGFILE=$(LOGFILE)
failed-tests%:
	@$(TESTS_MK) "$@"

# We used to set this for i386 but it seems to be OK now.
# Perhaps we should set it for armhf, let's see the buildd test results...
ifneq (,$(filter $(DEB_BUILD_ARCH),))
IGNORE_FAILURES = | sed -e '0,/Timed out/{//d;}' -e '0,/Timed out/{//d;}' -e '0,/Timed out/{//d;}'
else
IGNORE_FAILURES =
endif
had-few-failures:
	if ! test -f $(LOGFILE); then echo "Error: log file $(LOGFILE) not found"; false; fi
	N_TEST_FAILURES="$$($(TESTS_MK) failed-tests-total-normal)"; \
	  if ! test $${N_TEST_FAILURES} -le $(MAX_TEST_FAILURES); then \
	    echo "Error: $${N_TEST_FAILURES} tests failed, up to $(MAX_TEST_FAILURES) failures are tolerated"; \
	    false; \
	  else \
	    echo "Success: $${N_TEST_FAILURES} tests failed, up to $(MAX_TEST_FAILURES) failures are tolerated"; \
	  fi
	if ! test -z "$$($(TESTS_MK) failed-tests-special $(IGNORE_FAILURES))"; then \
	  echo "Error: critical test failures (e.g. timeout, segfault, etc.)"; false; fi

had-not-too-many-failures:
	echo "Checking number of failed tests to determine whether to rerun tests in series..."
	if ! test -f $(LOGFILE); then echo "Error: log file $(LOGFILE) not found"; false; fi
	N_TEST_FAILURES="$$($(TESTS_MK) failed-tests-total-normal)"; \
	  if ! test $${N_TEST_FAILURES} -le $(MAX_TEST_FAILURES_RERUN); then \
	    echo "No: $${N_TEST_FAILURES} tests failed, up to $(MAX_TEST_FAILURES_RERUN) failures are tolerated for rerun"; \
	    false; \
	  else \
	    echo "Yes: $${N_TEST_FAILURES} tests failed, up to $(MAX_TEST_FAILURES_RERUN) failures are tolerated for rerun"; \
	  fi

run_tests = \
	cd sage && ./sage -t -p $(NUMJOBS) --logfile=logs/ptestlong-$(1).log $(2)
# If tests fail but not by too many more, then retry them once not in parallel
# i386 seems to have issues running parallel tests - TODO: investigate this in more detail
check_test_log = debian/rules -s LOGFILE=sage/logs/ptestlong-$(1).log MAX_TEST_FAILURES=$(3)
run_tests_with_retry = \
	$(run_tests); cd "$(CURDIR)" && \
	if $(check_test_log) had-few-failures; then :; else \
	  $(check_test_log) had-not-too-many-failures && \
	  mv sage/logs/ptestlong-$(1).log sage/logs/ptestlong-$(1).log.1 && \
	  { $(run_tests) -p 1 -f; cd "$(CURDIR)" && \
	  $(check_test_log) had-few-failures; }; \
	fi

override_dh_auto_test-arch:
ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
	$(call run_tests_with_retry,arch,$(SAGE_TEST_FLAGS_ARCH) src/sage,200)
endif

override_dh_auto_test-indep:
ifeq (,$(filter nodoc,$(DEB_BUILD_OPTIONS)))
ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
	$(call run_tests_with_retry,indep,$(SAGE_TEST_FLAGS_INDEP) src/doc src/sage/misc/sagedoc.py,25)
	# Sometimes, parts of the docbuild fail with MemoryError or OSError but
	# Sage doesn't detect this. Here we detect it and fail the build if so.
	# Also filter out some false positives that are not hard errors.
	! (grep Error sage/logs/dochtml.log | grep -v "citation not found: .*Error\|Citation \[.*Error\] is not referenced")
endif
endif

# manual target to re-run only failed tests
check-failed:
	$(call run_tests,all,--all -f)

###############################################################################
# 5. MAINTAINER TARGETS
###############################################################################

distclean:
	rm -f debian/control
	cd sage; git clean -fdx && git reset --hard HEAD && git submodule update --force
	# don't git reset --hard on purpose, so it's easier to test
	git clean -fdx
	debian/rules debian/control

build-dep-maint:
	sudo apt-get install --no-install-recommends equivs devscripts git iso-codes python3 quilt

build-dep: debian/control
	if which aptitude >/dev/null; then sudo -E mk-build-deps -ir -t 'aptitude -R'; \
	else sudo -E mk-build-deps -ir; fi

get-orig-source: .git/modules/sage/HEAD
	cd sage && git archive --prefix=sagemath_$(DEB_VERSION_UPSTREAM)/sage/ \
	  --format=tar HEAD | xz -zf > ../../sagemath_$(DEB_VERSION_UPSTREAM).orig.tar.xz
