#!/usr/bin/make -f
#
# build script for GROMACS

PACKAGE := gromacs

include /usr/share/dpkg/architecture.mk
DEB_DISTRO  ?= $(shell lsb_release -si)
DEB_VERSION ?= $(shell dpkg-parsechangelog -S version)

# add hardening flags, using dpkg-buildflags
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
DPKG_EXPORT_BUILDFLAGS = 1
include /usr/share/dpkg/buildflags.mk
#653916 and http://www.cmake.org/Bug/view.php?id=12928 and https://gitlab.kitware.com/cmake/cmake/-/issues/12928
CFLAGS   += $(CPPFLAGS)
CXXFLAGS += $(CPPFLAGS)

# DEB_BUILD_OPTIONS boilerplate.
ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS)))
	CFLAGS += -g -Wall
endif
ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
	CFLAGS += -O0
endif
ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
	NUMJOBS = $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
	MAKE += -j$(NUMJOBS)
endif

DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH)
ifeq ($(DEB_HOST_ARCH),ppc64el)
    export PATH := $(CURDIR)/debian/toolchain:$(PATH)
endif

# General configuration options used for all builds.
COMMON_CONFIG_PARAMS = \
	$(CURDIR) \
	-DCMAKE_VERBOSE_MAKEFILE=ON \
	-DCMAKE_RULE_MESSAGES=OFF \
	-DCMAKE_INSTALL_PREFIX="/usr" \
	-DCMAKE_EXE_LINKER_FLAGS="$(LDFLAGS)" \
	-DCMAKE_SKIP_RPATH=ON \
	-DGMX_EXTERNAL_ZLIB=ON \
	-DGMX_USE_MUPARSER=EXTERNAL \
	-DGMX_VERSION_STRING_OF_FORK="$(DEB_DISTRO)-$(DEB_VERSION)" \
	-DGMX_GIT_VERSION_INFO=OFF \
	-DGMX_HWLOC=ON \
	-DGMXAPI=OFF

# Specific options for the MPI-enabled builds.
MPI_CONFIG_PARAMS = \
	-DGMX_MPI=ON \
	-DMPIEXEC="/usr/bin/mpiexec"

# For compatibility reasons, disable SIMD CPU optimizations EXCEPT
# for SSE4.1 on amd64, and NEON on arm64.
# For local compilations, set DEB_BUILD_OPTIONS=cpuopt for automatic
# detection of the best available option.
# See https://manual.gromacs.org/documentation/current/user-guide/mdrun-performance.html#intra-core-parallelization
# and https://manual.gromacs.org/documentation/current/install-guide/index.html#gmx-simd-support
ifeq (,$(findstring cpuopt,$(DEB_BUILD_OPTIONS)))
ifeq ($(DEB_HOST_ARCH), amd64)
	COMMON_CONFIG_PARAMS += -DGMX_SIMD=SSE4.1
else ifeq ($(DEB_HOST_ARCH), arm64)
	COMMON_CONFIG_PARAMS += -DGMX_SIMD=ARM_NEON_ASIMD
else
	COMMON_CONFIG_PARAMS += -DGMX_SIMD=None
endif
endif

# Include "gpu" in DEB_BUILD_OPTIONS to build GPU-accelerated binaries as well.
# This build option is not always well tested, please send comments.
# You must have the packages "nvidia-cuda-toolkit" and "nvidia-cuda-dev"
# installed. Those are not official build dependencies to keep the package in
# Debian main!
#
# If you use this option, it is strongly recommended that you also set
# DEB_BUILD_OPTIONS=cpuopt, assuming you are compiling and running on the same
# machine.
#
# Further details at
# https://manual.gromacs.org/documentation/current/user-guide/mdrun-performance.html#running-mdrun-with-gpus
GPU_CONFIG_PARAMS =
ifneq (,$(findstring gpu,$(DEB_BUILD_OPTIONS)))
	GPU_CONFIG_PARAMS += -DGMX_GPU=ON
endif

# Improve display of build-time tests.
export GTEST_COLOR=no
export CTEST_OUTPUT_ON_FAILURE=1

#######################################################################

build: build-arch build-indep

build-arch: configure-stamp build-basic build-mpi
build-indep: build-manual

configure: configure-stamp
configure-stamp:
	dh_testdir
ifeq ($(DEB_HOST_ARCH),ppc64el)
	mkdir -p debian/toolchain
	ln -s /usr/bin/gcc-11 debian/toolchain/cc
	ln -s /usr/bin/gcc-11 debian/toolchain/gcc
	ln -s /usr/bin/g++-11 debian/toolchain/c++
	ln -s /usr/bin/g++-11 debian/toolchain/g++
endif
	(mkdir -p build/basic; cd build/basic; cmake \
	$(COMMON_CONFIG_PARAMS) $(GPU_CONFIG_PARAMS) -DGMX_MPI=OFF -DGMX_INSTALL_LEGACY_API=ON )
	(mkdir -p build/basic-dp; cd build/basic-dp; cmake \
	$(COMMON_CONFIG_PARAMS) -DGMX_MPI=OFF -DGMX_DOUBLE=ON)
	(mkdir -p build/mpi; cd build/mpi; CC=/usr/bin/mpicc CXX=/usr/bin/mpicxx cmake \
	$(COMMON_CONFIG_PARAMS) $(MPI_CONFIG_PARAMS) $(GPU_CONFIG_PARAMS))
	(mkdir -p build/mpi-dp; cd build/mpi-dp; CC=/usr/bin/mpicc CXX=/usr/bin/mpicxx cmake \
	$(COMMON_CONFIG_PARAMS) $(MPI_CONFIG_PARAMS) -DGMX_DOUBLE=ON)
	touch $@

# Standard builds, in single and double precision.
build-basic: configure-stamp
	dh_testdir
	$(MAKE) -C build/basic
	$(MAKE) -C build/basic-dp
ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
	$(MAKE) -C build/basic tests
	(cd build/basic;    LD_LIBRARY_PATH=$(CURDIR)/build/basic/lib    ctest -V)
	$(MAKE) -C build/basic-dp tests
	(cd build/basic-dp; LD_LIBRARY_PATH=$(CURDIR)/build/basic-dp/lib ctest -V)
endif
	touch $@

# MPI-enabled build.  Separated from the build-basic target mostly for ease of testing.
build-mpi: configure-stamp
	dh_testdir
	$(MAKE) -C build/mpi
	$(MAKE) -C build/mpi-dp
# Testing the single precision build only is sufficient to exercise the MPI-specific tests.
ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
# rsh_agent: https://bugs.debian.org/494046
# oversubscribe: https://bugs.debian.org/850229#51
# Applicable only to OpenMPI, but no-ops on MPICH architectures
	$(MAKE) -C build/mpi tests
	(cd build/mpi ; LD_LIBRARY_PATH=$(CURDIR)/build/mpi/lib \
                        OMPI_MCA_plm_rsh_agent=/bin/false \
                        OMPI_MCA_rmaps_base_oversubscribe=1 \
                        ctest -V)
endif
	touch $@

# Documentation.
build-manual:
ifeq (,$(filter nodoc,$(DEB_BUILD_OPTIONS)))
	dh_testdir
# Build speedy, stripped-down version just for documentation generation.
# Derived from (former) admin/build-docs.sh
	(mkdir -p build/documentation ; cd build/documentation; LD_LIBRARY_PATH=$(CURDIR)/build/documentation/lib \
	cmake $(CURDIR) -DCMAKE_BUILD_TYPE=Debug -DGMX_OPENMP=OFF -DGMX_SIMD=None \
	-DGMX_GPU=OFF -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_RULE_MESSAGES=OFF -DGMX_BUILD_MANUAL=ON \
	-DGMX_BUILD_HELP=ON -DGMX_VERSION_STRING_OF_FORK="$(DEB_DISTRO)-$(DEB_VERSION)")
# Generate PDF
	$(MAKE) manual -C build/documentation
# Generate man pages
	$(MAKE) man -C build/documentation
# Generate HTML
	$(MAKE) webpage -C build/documentation
endif
	touch $@

# Rules in this target largely handle the executable and library packages and arch-indep data (but not documentation).
install: build-arch
	dh_testdir
	dh_testroot
	dh_prep
	dh_installdirs

	$(MAKE) -C build/mpi      install DESTDIR=$(CURDIR)/debian/tmp
	$(MAKE) -C build/mpi-dp   install DESTDIR=$(CURDIR)/debian/tmp
	$(MAKE) -C build/basic    install DESTDIR=$(CURDIR)/debian/tmp
	$(MAKE) -C build/basic-dp install DESTDIR=$(CURDIR)/debian/tmp

# concatenate bash completions into a single file; not just "cat * >" because they don't end in newlines
	perl -lne 'print' $(CURDIR)/debian/tmp/usr/bin/gmx-completion.bash \
	                  $(CURDIR)/debian/tmp/usr/bin/gmx-completion-*.bash > \
	                  $(CURDIR)/debian/tmp/usr/bin/gmx-completion-concat

# rename a pair of Perl scripts to drop the .pl extension (Policy 10.4)
	mv $(CURDIR)/debian/tmp/usr/bin/demux.pl     $(CURDIR)/debian/tmp/usr/bin/demux
	mv $(CURDIR)/debian/tmp/usr/bin/xplor2gmx.pl $(CURDIR)/debian/tmp/usr/bin/xplor2gmx

	dh_install -a
	dh_installdocs -a
	dh_installchangelogs -a
	dh_installman -a
	dh_bash-completion -a
	dh_lintian -a
	dh_link -a

binary-indep: build-arch build-indep install
	dh_testdir -i
	dh_testroot -i
	dh_installdirs -i
	dh_install -i
	dh_installdocs -i
	dh_installchangelogs -i
	dh_installman -i
# dh_doxygen expects a different location of index.html, so perform its function manually.
	-find $(CURDIR)/debian/gromacs-data/usr/share/doc/gromacs/html/doxygen/ -type f -a \( -name '*.md5' -o -name '*.map' \) -delete
	rdfind -outputname /dev/null -makesymlinks true $(CURDIR)/debian/gromacs-data/usr/share/doc/
	symlinks -r -s -c $(CURDIR)/debian/gromacs-data/usr/share/doc/
	dh_bash-completion -i
	dh_lintian -i
	dh_link -i
	dh_strip_nondeterminism -i
	dh_compress -i -X.pdf
	dh_fixperms -i
	dh_missing -i
	dh_installdeb -i
	dh_gencontrol -i
	dh_md5sums -i
	dh_builddeb -i

binary-arch: build-arch install
	dh_testdir -a
	dh_testroot -a
	dh_installchangelogs -a
	dh_installdocs -a
	dh_strip_nondeterminism -a
	dh_compress -a
	dh_fixperms -a
	dh_missing -a
	dh_dwz -a
	dh_strip -A
	dh_makeshlibs -a
	dh_shlibdeps -plibgromacs8 -L libgromacs8 -l debian/libgromacs8/usr/lib
	dh_shlibdeps -plibnblib-gmx0 -L libnblib-gmx0 -l debian/libnblib-gmx0/usr/lib:debian/libgromacs8/usr/lib
	dh_shlibdeps -pgromacs -L libgromacs8 -l debian/libgromacs8/usr/lib:debian/gromacs/usr/lib
	dh_installdeb -a
	dh_gencontrol -a
	dh_md5sums -a
	dh_builddeb -a

binary: binary-indep binary-arch

clean:
	dh_testdir
	dh_testroot
	dh_clean build-basic build-mpi build-manual build/
# some specific leftovers in 2023-beta1 - will probably go away later
	rm -rf admin/containers/__pycache__/*.cpython-31*.pyc \
	admin/__pycache__/*.cpython-31*.pyc \
	docs/__pycache__/gmxsphinx.cpython-31*.pyc \
	docs/doxygen/__pycache__/

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