#!/usr/bin/make -f
# Copyright (C) 2020-2021 OpenCFD Ltd.
# SPDX-License-Identifier: (GPL-3.0+)

DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH)
DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
DEB_TARGET_MULTIARCH ?= $(shell dpkg-architecture -qDEB_TARGET_MULTIARCH)
VENDOR := $(shell dpkg-vendor --derives-from ubuntu 2>/dev/null && echo ubuntu || echo debian)
DISTRO := $(shell sed -ne 's/^VERSION_CODENAME=//p' /etc/os-release)

DEBIAN_DIR := $(patsubst %/,%,$(dir $(firstword $(MAKEFILE_LIST))))
ifeq (,$(DEBIAN_DIR))
    DEBIAN_DIR := debian
endif

ifeq (,$(VENDOR))
    VENDOR := generic
endif
ifeq (,$(DISTRO))
    DISTRO := $(VENDOR)
endif

# Install to usr/lib/openfoam (default) or somewhere else (eg, opt)
ifeq (,$(INSTALL_PREFIX))
    INSTALL_PREFIX := usr/lib/openfoam
endif

export DEB_BUILD_MAINT_OPTIONS := hardening=+all

# # Reduced debug info to avoid running out of address space during build
# Prefer higher-level runtime debug flags in OpenFOAM (not gdb) anyhow
export DEB_CXXFLAGS_MAINT_APPEND := -g1

# Propagate into OpenFOAM build system
export FOAM_EXTRA_CFLAGS   := $(shell dpkg-buildflags --get CFLAGS)
export FOAM_EXTRA_CXXFLAGS := $(shell dpkg-buildflags --get CXXFLAGS)

CPPFLAGS := $(shell dpkg-buildflags --get CPPFLAGS)
CFLAGS   := $(FOAM_EXTRA_CFLAGS) $(CPPFLAGS)
CXXFLAGS := $(FOAM_EXTRA_CXXFLAGS) $(CPPFLAGS)
LDFLAGS  := $(shell dpkg-buildflags --get LDFLAGS)

# Build options
NUMJOBS := 1
ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
    NUMJOBS := $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
endif
# Limit parallel build to 2 processes on Ubuntu
ifeq (ubuntu,$(VENDOR))
    NUMJOBS := $(shell if test $(NUMJOBS) -gt 2; then echo 2 ; else echo $(NUMJOBS); fi)
endif

# Sanity checks, manual overrides of the above logic
ifeq (0,$(NUMJOBS))
    NUMJOBS := $(shell getconf _NPROCESSORS_ONLN)
else
    # No negative values
    NUMJOBS := $(subst -,,$(NUMJOBS))
endif


# ---------------------------------------------------------------------------
%:
	dh $@

# OpenFOAM version (api) from META-INFO or from changelog
FOAM_API := $(shell $(DEBIAN_DIR)/scripts/get-foam-api)

# The main package name
export PACKAGE := openfoam

# The package install location and version-specific backend
export FOAM_PACKAGE := openfoam$(FOAM_API)

# Can add fallback for finding files with a reduced environment
# via -DFOAM_CONFIGURED_PROJECT_DIR=\"/$(INSTALL_PREFIX)/$(FOAM_PACKAGE)\"
# but this will likely change to a configure script in the near future

# Follow the OpenFOAM internal naming, as make variables
export WM_ARCH := $(shell $(DEBIAN_DIR)/scripts/get-foam-arch)
export WM_COMPILER := Gcc
export WM_COMPILER_LIB_ARCH := 64
# Special cases (i686), which is not lib64
ifeq (linux,$(WM_ARCH))
    export WM_COMPILER_LIB_ARCH :=
endif
export WM_COMPILE_OPTION := Opt
export WM_PRECISION_OPTION := DP
export WM_LABEL_SIZE := 32
export WM_LABEL_OPTION := Int$(WM_LABEL_SIZE)

# OpenFOAM naming for TARGET_MULTIARCH
FOAM_ARCH := $(WM_ARCH)$(WM_COMPILER)

# Suffix naming like OpenFOAM WM_OPTIONS to distinguish float/int/optimization
COMPILE_FLAVOUR := $(WM_PRECISION_OPTION)$(WM_LABEL_OPTION)$(WM_COMPILE_OPTION)

# Target installation platform - same as WM_OPTIONS used internally by OpenFOAM
FOAM_PLATFORM := $(FOAM_ARCH)$(COMPILE_FLAVOUR)

# Build location (for multi-build with NFS shares?)
# export WM_OPTIONS := $(DISTRO)-$(DEB_TARGET_MULTIARCH).$(COMPILE_FLAVOUR)
export WM_OPTIONS := $(FOAM_PLATFORM)

export FOAM_APPBIN := $(CURDIR)/platforms/$(WM_OPTIONS)/bin
export FOAM_LIBBIN := $(CURDIR)/platforms/$(WM_OPTIONS)/lib
export FOAM_SITE_APPBIN := $(FOAM_APPBIN)
export FOAM_SITE_LIBBIN := $(FOAM_LIBBIN)
export FOAM_USER_APPBIN := $(FOAM_APPBIN)
export FOAM_USER_LIBBIN := $(FOAM_LIBBIN)

# No ThirdParty software, unless within the OpenFOAM directory
export WM_THIRD_PARTY_DIR := $(WM_PROJECT_DIR)/ThirdParty
unexport FOAM_EXT_LIBBIN

# <runtime only>
# export FOAM_APP := $(CURDIR)/applications
# export FOAM_RUN := $(CURDIR)/run
# export FOAM_SRC := $(CURDIR)/src
# export FOAM_ETC := $(CURDIR)/etc
# export FOAM_SOLVERS := $(CURDIR)/applications/solvers
# export FOAM_UTILITIES := $(CURDIR)/applications/utilities
# </runtime only>

# Project
export WM_PROJECT := OpenFOAM
export WM_PROJECT_DIR := $(CURDIR)
export WM_DIR := $(CURDIR)/wmake
export WM_PROJECT_USER_DIR := $(CURDIR)/debian/tmp
export WM_PROJECT_VERSION := $(FOAM_API)

# MPI
export FOAM_MPI := sys-openmpi
export WM_MPLIB := SYSTEMOPENMPI
export MPI_ARCH_PATH := $(shell $(DEBIAN_DIR)/scripts/get-openmpi-path)

# Pre-v2012 naming for SYSTEMOPENMPI
ifeq (1,$(shell expr $(FOAM_API) \< 2012))
    export FOAM_MPI := openmpi-system
endif


# Internal library paths
ORIG_LIBPATH := $(LD_LIBRARY_PATH)
FOAM_LIBPATH := $(FOAM_LIBBIN)/$(FOAM_MPI):$(FOAM_LIBBIN):$(FOAM_LIBBIN)/dummy
export LD_LIBRARY_PATH := $(FOAM_LIBPATH):$(ORIG_LIBPATH)

# Normally with verbose make information
## export WM_QUIET := true
unexport MAKEFLAGS

# ---------------------------------------------------------------------------
.PHONY: prepare

prepare:
	@if [ -x "$(DEBIAN_DIR)/scripts/update-control" ]; then \
	    $(DEBIAN_DIR)/scripts/update-control \
	        --package openfoam \
	        --with-api '$(FOAM_API)' \
	        ; \
	else \
	    echo "No debian/ directory?"; \
	fi

# ---------------------------------------------------------------------------
.PHONY: show-compile config config-foam config-debian config-tests

# Display compilation flags
show-compile:
	@PATH=$(PATH):$(WM_DIR) wmake -show-compile-cxx

config-foam:
	@if [ -x bin/tools/foamConfigurePaths ]; then \
	    echo "Use system packages"; \
	    bin/tools/foamConfigurePaths \
	        -system-compiler $(WM_COMPILER) \
	        -boost  boost-system \
	        -cgal   cgal-system \
	        -fftw   fftw-system \
	        -kahip  kahip-none \
	        -metis  metis-system \
	        -scotch scotch-system \
	        ; \
	fi
	@if [ -x bin/tools/create-mpi-config ]; then \
	    echo "Configure path to system openmpi"; \
	    bin/tools/create-mpi-config -write-openmpi; \
	fi
	@$(DEBIAN_DIR)/scripts/foam-config
	@echo "Directories for special generated output"
	@for i in man1 doc-man1 scripts; do \
	    mkdir -p "$(CURDIR)/build/package-tmp/$$i"; \
	done
	@rm -rf "$(CURDIR)/build/package-tmp/ThirdParty"
	@echo "system dependencies" >| "$(CURDIR)/build/package-tmp/ThirdParty"
	@for i in bin/tools/openfoam.in bin/tools/openfoam; do \
	    if [ -f "$$i" ]; then \
	        echo "Create openfoam session"; \
	        outdir="build/package-tmp/scripts"; \
	        sed -e 's#@PROJECT_DIR@#/$(INSTALL_PREFIX)/$(FOAM_PACKAGE)#g' \
	            "$$i" > "$$outdir/$(FOAM_PACKAGE)"; \
	        chmod 0755 "$$outdir/$(FOAM_PACKAGE)"; \
	        break; \
	    fi; \
	done
	@if [ -f doc/openfoam.1.in ]; then \
	    echo "Update version information in docs"; \
	    outdir="build/package-tmp/man1"; \
	    sed -e 's#OpenFOAM-[^\"]*#OpenFOAM-'"$(FOAM_API)#" \
	        doc/openfoam.1.in | gzip -c > "$$outdir/openfoam$(FOAM_API).1.gz"; \
	fi

config-debian:
	@echo "Set installation targets - $(DISTRO)"
	@echo "    install  = /$(INSTALL_PREFIX)/$(FOAM_PACKAGE)"
	@echo "    arch     = $(FOAM_ARCH)"
	@echo "    flavour  = $(COMPILE_FLAVOUR)"
	@echo "Define packaging templates"
	@cd debian; \
	for src in template/Package* ; do \
	    [ -f "$$src" ] || continue; \
	    dst="openfoam$$(echo "$${src#template/Package}" | sed -e 's#API#$(FOAM_API)#g')"; \
	    sed \
	        -e 's#@INSTALL_PREFIX@#$(INSTALL_PREFIX)#g' \
	        -e 's#@PACKAGE@#$(PACKAGE)#g;' \
	        -e 's#@PROJECT_DIR@#$(INSTALL_PREFIX)/$(FOAM_PACKAGE)#g' \
	        -e 's#@FOAM_PACKAGE@#$(FOAM_PACKAGE)#g;' \
	        -e 's#@FOAM_API@#$(FOAM_API)#g;' \
	        -e 's#@FOAM_ARCH@#$(FOAM_ARCH)#g;' \
	        -e 's#@FOAM_PLATFORM@#$(FOAM_PLATFORM)#g;' \
	        -e 's#@WM_OPTIONS@#$(WM_OPTIONS)#g;' \
	        "$$src" > "$$dst"; \
	    [ -x "$$src" ] && chmod 755 "$$dst"; \
	    echo "    $$dst"; \
	done

config-tests:
	@$(DEBIAN_DIR)/scripts/config-tests \
	    -binary=/usr/bin/$(FOAM_PACKAGE)

config: config-foam config-debian config-tests

override_dh_auto_configure: config


# ---------------------------------------------------------------------------
.PHONY: realclean-foam realclean-tests

# Deep-clean OpenFOAM build, platforms directory
realclean-foam:
	-rm -rf build/$(WM_OPTIONS)*
	-rm -rf platforms/$(WM_OPTIONS)
	-rm -rf platforms/tools/$(FOAM_ARCH)


# clean generated tests
realclean-tests:
	$(DEBIAN_DIR)/scripts/config-tests clean

# clean
# - Remove generated debian/*.xxx files
# - OpenFOAM uses .orig as a control file extension (in tutorials)
override_dh_clean: realclean-tests
	-rm -f $(DEBIAN_DIR)/scripts/clean-debian
	dh_clean -X "*.orig"
	#
	# Leave openfoam build/, platforms/ directories untouched in case
	# a quick rebuild is necessary
	#


# ---------------------------------------------------------------------------
.PHONY: build-foam build-man

build-foam/%:
	@if cd "$*" 2>/dev/null; then \
	    echo "wmake in $*"; \
	    PATH=$(PATH):$(WM_DIR) wmake -all -j$(NUMJOBS); \
	else \
	    echo "No such directory: $*"; \
	fi

build-foam:
	@echo "Build $(DEB_TARGET_MULTIARCH) as $(FOAM_PLATFORM)"
	PATH=$(PATH):$(WM_DIR) ./Allwmake -j$(NUMJOBS)
# -log=log.build

build-man:
	@if [ -x bin/tools/foamCreateManpage ]; then \
	    bin/tools/foamCreateManpage \
	        -gzip -output=build/package-tmp/doc-man1 \
	        -version="$(FOAM_API)" || \
	    echo "ignore problems generating manpages"; \
	fi

clean-foam/%:
	@if cd "$*" 2>/dev/null; then \
	    echo "wclean in $*"; \
	    PATH=$(PATH):$(WM_DIR) wclean -all; \
	else \
	    echo "No such directory: $*"; \
	fi

# ---------------------------------------------------------------------------

# Skip "build-man" generation of man pages for each binary.
# These will collide between versions if placed as manpages.

override_dh_auto_build: build-foam

# No symlinks to worry about, so can save some time.
override_dh_link:
	@echo "skip checking links"

# Complains about using LD_LIBRARY_PATH, but it otherwise fails
# to resolve private symbols
override_dh_shlibdeps:
	dh_shlibdeps -v \
	-l$(CURDIR)/platforms/$(WM_OPTIONS)/lib/$(FOAM_MPI) \
	-l$(CURDIR)/platforms/$(WM_OPTIONS)/lib \
	-l$(CURDIR)/platforms/$(WM_OPTIONS)/lib/dummy


# No debug packages, use higher-level runtime debug flags in OpenFOAM
override_dh_strip:
	dh_strip --no-automatic-dbgsym


override_dh_missing-arch:
	dh_missing --list-missing

# Package creation
##override_dh_builddeb:
##	mkdir -p $(CURDIR)/debian-packages/$(DISTRO)
##	dh_builddeb --destdir=debian-packages/$(DISTRO)

# ---------------------------------------------------------------------------
# NOTES
#
# When changing major versions, update the debian/control file
#
#     debian/rules prepare
#
# For partial rebuilds during development, can use 'build-foam' targets.
# For example,
#
# Rebuild all
#
#     debian/rules  build-foam
#
# Rebuild directory and sub-directories (uses wmake -all)
#
#     debian/rules  build-foam/src/finiteArea
#
# Partial clean
#
#     debian/rules  clean-foam/src/surfMesh
#
# ---------------------------------------------------------------------------
