#!/usr/bin/make -f

export DH_VERBOSE=1
export DEB_BUILD_OPTIONS=noddebs

# Bazel wants to create stuff in $HOME
# Workaround so it can run in pbuilder
ifeq ($(HOME),/nonexistent)
export HOME=$(CURDIR)
endif

# Fails in cowbuilder too because this variable
# is not removed inside the chroot
unexport JAVA_HOME

# Get version from changelog as well as lsb_release
# to compute unique build version (useful for repo mirroring systems doing file pooling)
PKG_VERSION  := $(shell dpkg-parsechangelog | egrep '^Version:' | cut -f 2 -d ' ')
DIST_NAME    := $(shell lsb_release -si)
DIST_RELEASE := $(shell lsb_release -sc)
DIST_VERSION := $(shell lsb_release -sr)

PY2VERS	:= $(shell pyversions -rv)
PY3VERS	:= $(shell py3versions -rv)

PY2PACKAGES := $(shell grep '^Package: python-' debian/control | cut -d':' -f2 | sed 's/ //g')
PY3PACKAGES := $(shell grep '^Package: python3-' debian/control | cut -d':' -f2 | sed 's/ //g')

# See ./tensorflow/tools/pip_package/setup.py for dependencies
# It's an absolute nightmare to deal with dh_pythonN, bazel shitty
# build system, python3.6, etc, so I'll just handle that by myself
#
# First I'll compute interpreter dependencies like python3 >= 3.5~, python3 << 3.7
# According to pyverions/py3versions
#
# Then I'll turn this into python2custom:Depends and python3custom:Depends substvars
PY2MINVER := $(shell pyversions -rv -rv | rev | cut -d' ' -f1 | rev)
PY2MAXSUP := $(shell pyversions -rv -rv | cut -d' ' -f1)
PY2MAXVER := $(shell python -c 'print(float('$(PY2MAXSUP)') + 0.1)')
PY3MINVER := $(shell py3versions -rv -rv | rev | cut -d' ' -f1 | rev)
PY3MAXSUP := $(shell py3versions -rv -rv | cut -d' ' -f1)
PY3MAXVER := $(shell python -c 'print(float('$(PY3MAXSUP)') + 0.1)')
SUBSTVARS_PY2DEPS := -Vpython2custom:Depends="python (>= $(PY2MINVER)~), python (<< $(PY2MAXVER)),
SUBSTVARS_PY2DEPS += python-numpy (>= 1.11.0),
SUBSTVARS_PY2DEPS += python-six (>= 1.10.0),
SUBSTVARS_PY2DEPS += python-protobuf (>= 3.2.0),
SUBSTVARS_PY2DEPS += python-werkzeug (>= 0.11.10),
SUBSTVARS_PY2DEPS += python-html5lib (>= 0.9999999),
SUBSTVARS_PY2DEPS += python-bleach (>= 1.5.0),
SUBSTVARS_PY2DEPS += python-backports.weakref (>= 1.0~rc1),
# This one is for python2 only, see upstream setup.py
SUBSTVARS_PY2DEPS += python-mock (>= 2.0.0)"
SUBSTVARS_PY3DEPS := -Vpython3custom:Depends="python3 (>= $(PY3MINVER)~), python3 (<< $(PY3MAXVER)),
SUBSTVARS_PY3DEPS += python3-numpy (>= 1.11.0),
SUBSTVARS_PY3DEPS += python3-six (>= 1.10.0),
SUBSTVARS_PY3DEPS += python3-protobuf (>= 3.2.0),
SUBSTVARS_PY3DEPS += python3-werkzeug (>= 0.11.10),
SUBSTVARS_PY3DEPS += python3-html5lib (>= 0.9999999),
SUBSTVARS_PY3DEPS += python3-bleach (>= 1.5.0),
SUBSTVARS_PY3DEPS += python3-backports.weakref (>= 1.0~rc1)"

# Various set of CPU optimization
OPTFLAGS1 := -mavx -mavx2 -mfma -msse4.1 -msse4.2
OPTFLAGS2 := -mavx -msse4.1 -msse4.2

# CUDA related configuration
CUDNN_PACKAGE := $(shell dpkg-query -W -f='$${Package}' libcudnn?)
CUDNN_VERSION := $(shell dpkg-query -W -f='$${Version}' libcudnn?)

CUDA_VERSION    := $(shell dpkg-query -W -f='$${Version}' nvidia-cuda-toolkit | cut -d. -f1,2)
CUDA_REQ_LIBS   := libcublas libcudart libcufft libcurand libcusolver
# List of CUDA level according to CUDA version
ifeq ($(CUDA_VERSION),8.0)
CUDA_CAP        := 3.0,3.5,3.7,5.0,5.2,5.3,6.0,6.1
else ifeq ($(CUDA_VERSION),7.5)
# 6.0 and 6.1 not supported
CUDA_CAP        := 3.0,3.5,3.7,5.0,5.2,5.3
else
CUDA_CAP        := Unsupported CUDA $(CUDA_VERSION). Please fix debian/rules
endif
SUBSTVARS_CUDNN := -Vcudnn:Depends="$(CUDNN_PACKAGE) (= $(CUDNN_VERSION))"

%:
	dh $@


### Prepare CUDA stuff so it looks like a tarball coming from nvidia
cuda-$(CUDA_VERSION):
	
	# Prepare tree
	mkdir -p "$(CURDIR)/$@/lib64"
	mkdir -p "$(CURDIR)/$@/include"
	mkdir -p "$(CURDIR)/$@/bin"
	mkdir -p "$(CURDIR)/$@/extras/CUPTI/lib64"
	mkdir -p "$(CURDIR)/$@/extras/CUPTI/include"
	
	# Real libraries
	for package in $(CUDA_REQ_LIBS); do \
		for file in `dpkg -L "$${package}$(CUDA_VERSION)"`; do \
			if `echo "$${file}" | grep -q '^/usr/lib/x86_64-linux-gnu/'`; then \
				base_filename=`basename "$${file}"`; \
				ln -s "$${file}" "$(CURDIR)/$@/lib64/"; \
			fi \
		done \
	done
	
	# .so links and headers in nvidia-cuda-dev package
	# Not sure why but .so ln sometimes say the file already exists
	for file in `dpkg -L "nvidia-cuda-dev"`; do \
		if `echo "$${file}" | grep -q '^/usr/lib/x86_64-linux-gnu/'`; then \
			base_filename=`basename "$${file}"`; \
			ln -s "$${file}" "$(CURDIR)/$@/lib64/" || true; \
		elif `echo "$${file}" | grep -q '^/usr/include/'`; then \
			base_filename=`basename "$${file}"`; \
			ln -s "$${file}" "$(CURDIR)/$@/include/"; \
		fi \
	done
	
	# tools in nvidia-cuda-toolkit package
	for file in `dpkg -L "nvidia-cuda-toolkit"`; do \
		if `echo "$${file}" | grep -q '^/usr/bin/'`; then \
			base_filename=`basename "$${file}"`; \
			ln -s "$${file}" "$(CURDIR)/$@/bin/"; \
		fi \
	done
	
	# Same shit for libcupti
	for file in `dpkg -L "libcupti$(CUDA_VERSION)"`; do \
		if `echo "$${file}" | grep -q '^/usr/lib/x86_64-linux-gnu/'`; then \
			base_filename=`basename "$${file}"`; \
			ln -s "$${file}" "$(CURDIR)/$@/extras/CUPTI/lib64/"; \
		fi \
	done \
	
	for file in `dpkg -L "libcupti-dev"`; do \
		if `echo "$${file}" | grep -q '^/usr/lib/x86_64-linux-gnu/'`; then \
			base_filename=`basename "$${file}"`; \
			ln -s "$${file}" "$(CURDIR)/$@/extras/CUPTI/lib64/"; \
		elif `echo "$${file}" | grep -q '^/usr/include/'`; then \
			base_filename=`basename "$${file}"`; \
			ln -s "$${file}" "$(CURDIR)/$@/extras/CUPTI/include/"; \
		fi \
	done

mkldnn:
	
	# Prepare a fake tree looking like a shitty hand made install
	mkdir -p "$(CURDIR)/$@/lib"
	mkdir -p "$(CURDIR)/$@/include"
	
	# Create libs and headers symlinks
	for package in libmkldnn0-nonfree-mkl libmkldnn-nonfree-dev; do \
		for file in `dpkg -L "$${package}"`; do \
			if `echo "$${file}" | grep -q '^/usr/lib/.*so.*'`; then \
				base_filename=`basename "$${file}"`; \
				ln -s "$${file}" "$(CURDIR)/$@/lib/"; \
			elif `echo "$${file}" | grep -q '^/usr/include/'`; then \
				base_filename=`basename "$${file}"`; \
				ln -s "$${file}" "$(CURDIR)/$@/include/"; \
			fi \
		done \
	done

override_dh_auto_configure: cuda-$(CUDA_VERSION) mkldnn

### Build for supported Python 2/3 versions
override_dh_auto_install: $(PY2VERS:%=build-py2-%) $(PY3VERS:%=build-py3-%)

# So what's the hell is going here ?
#
# I'm going to build several time tensorflow with different
# GCC optimization flags.
#
# nVidia CUDA support variants will be built too.
#
# build_pip_package script has been patched to output classic Python
# package without the WHL container.
build-py2-%:
	# -mavx -msse4.1 -msse4.2
	debian/configure-expect.sh $* "$(OPTFLAGS2)" No No "" "" No ""
	bazel build --config=opt //tensorflow/tools/pip_package:build_pip_package --verbose_failures
	bazel-bin/tensorflow/tools/pip_package/build_pip_package "$(CURDIR)/debian/python-tensorflow-avx-sse42/"
	# This shitty bazel stuff cannot install proper permissions
	find "$(CURDIR)/debian/python-tensorflow-avx-sse42/" -type d -exec chmod 0755 {} \;
	find "$(CURDIR)/debian/python-tensorflow-avx-sse42/" -type f -exec chmod 0644 {} \;
	# Installed in tensorflow-tools package
	rm -rf "$(CURDIR)/debian/python-tensorflow-avx-sse42/usr/bin"
	# Run dh_python to rename .so file with their Python version so next iteration can provide a different version variant
	dh_python2 -ppython-tensorflow-avx-sse42 --no-guessing-deps --verbose
	
	# -mavx -msse4.1 -msse4.2 CUDA
	debian/configure-expect.sh $* "$(OPTFLAGS2)" Yes No "$(CURDIR)/cuda-$(CUDA_VERSION)" "$(CUDA_CAP)" No ""
	bazel build --config=opt --config=cuda //tensorflow/tools/pip_package:build_pip_package --verbose_failures
	bazel-bin/tensorflow/tools/pip_package/build_pip_package "$(CURDIR)/debian/python-tensorflow-cuda-avx-sse42/"
	# This shitty bazel stuff cannot install proper permissions
	find "$(CURDIR)/debian/python-tensorflow-cuda-avx-sse42/" -type d -exec chmod 0755 {} \;
	find "$(CURDIR)/debian/python-tensorflow-cuda-avx-sse42/" -type f -exec chmod 0644 {} \;
	# Installed in tensorflow-tools package
	rm -rf "$(CURDIR)/debian/python-tensorflow-cuda-avx-sse42/usr/bin"
	# Run dh_python to rename .so file with their Python version so next iteration can provide a different version variant
	dh_python2 -ppython-tensorflow-cuda-avx-sse42 --no-guessing-deps --verbose
	
	## -mavx -mavx2 -mfma -msse4.1 -msse4
	debian/configure-expect.sh $* "$(OPTFLAGS1)" No No "" "" No ""
	bazel build --config=opt //tensorflow/tools/pip_package:build_pip_package --verbose_failures
	bazel-bin/tensorflow/tools/pip_package/build_pip_package "$(CURDIR)/debian/python-tensorflow-avx2-sse42-fma/"
	# This shitty bazel stuff cannot install proper permissions
	find "$(CURDIR)/debian/python-tensorflow-avx2-sse42-fma/" -type d -exec chmod 0755 {} \;
	find "$(CURDIR)/debian/python-tensorflow-avx2-sse42-fma/" -type f -exec chmod 0644 {} \;
	# Installed in tensorflow-tools package
	rm -rf "$(CURDIR)/debian/python-tensorflow-avx2-sse42-fma/usr/bin"
	# Run dh_python to rename .so file with their Python version so next iteration can provide a different version variant
	dh_python2 -ppython-tensorflow-avx2-sse42-fma --no-guessing-deps --verbose
	
	## -mavx -mavx2 -mfma -msse4.1 -msse4 + Intel MKL DNN
	debian/configure-expect.sh $* "$(OPTFLAGS1)" No No "" "" Yes "$(CURDIR)/mkldnn"
	bazel build --config=opt --config=mkl //tensorflow/tools/pip_package:build_pip_package --verbose_failures
	bazel-bin/tensorflow/tools/pip_package/build_pip_package "$(CURDIR)/debian/python-tensorflow-avx2-sse42-fma-mkl-dnn/"
	# This shitty bazel stuff cannot install proper permissions
	find "$(CURDIR)/debian/python-tensorflow-avx2-sse42-fma-mkl-dnn/" -type d -exec chmod 0755 {} \;
	find "$(CURDIR)/debian/python-tensorflow-avx2-sse42-fma-mkl-dnn/" -type f -exec chmod 0644 {} \;
	# Installed in tensorflow-tools package
	rm -rf "$(CURDIR)/debian/python-tensorflow-avx2-sse42-fma-mkl-dnn/usr/bin"
	# Run dh_python to rename .so file with their Python version so next iteration can provide a different version variant
	dh_python2 -ppython-tensorflow-avx2-sse42-fma-mkl-dnn --no-guessing-deps --verbose
	
	## -mavx -mavx2 -mfma -msse4.1 -msse4 CUDA
	debian/configure-expect.sh $* "$(OPTFLAGS1)" Yes No "$(CURDIR)/cuda-$(CUDA_VERSION)" "$(CUDA_CAP)" No ""
	bazel build --config=opt --config=cuda //tensorflow/tools/pip_package:build_pip_package --verbose_failures
	bazel-bin/tensorflow/tools/pip_package/build_pip_package "$(CURDIR)/debian/python-tensorflow-cuda-avx2-sse42-fma/"
	# This shitty bazel stuff cannot install proper permissions
	find "$(CURDIR)/debian/python-tensorflow-cuda-avx2-sse42-fma/" -type d -exec chmod 0755 {} \;
	find "$(CURDIR)/debian/python-tensorflow-cuda-avx2-sse42-fma/" -type f -exec chmod 0644 {} \;
	# Installed in tensorflow-tools package
	rm -rf "$(CURDIR)/debian/python-tensorflow-cuda-avx2-sse42-fma/usr/bin"
	# Run dh_python to rename .so file with their Python version so next iteration can provide a different version variant
	dh_python2 -ppython-tensorflow-cuda-avx2-sse42-fma --no-guessing-deps --verbose
	
	## -mavx -mavx2 -mfma -msse4.1 -msse4 CUDA + Intel MKL DNN
	debian/configure-expect.sh $* "$(OPTFLAGS1)" Yes No "$(CURDIR)/cuda-$(CUDA_VERSION)" "$(CUDA_CAP)" Yes "$(CURDIR)/mkldnn"
	bazel build --config=opt --config=cuda --config=mkl //tensorflow/tools/pip_package:build_pip_package --verbose_failures
	bazel-bin/tensorflow/tools/pip_package/build_pip_package "$(CURDIR)/debian/python-tensorflow-cuda-avx2-sse42-fma-mkl-dnn/"
	# This shitty bazel stuff cannot install proper permissions
	find "$(CURDIR)/debian/python-tensorflow-cuda-avx2-sse42-fma-mkl-dnn/" -type d -exec chmod 0755 {} \;
	find "$(CURDIR)/debian/python-tensorflow-cuda-avx2-sse42-fma-mkl-dnn/" -type f -exec chmod 0644 {} \;
	# Installed in tensorflow-tools package
	rm -rf "$(CURDIR)/debian/python-tensorflow-cuda-avx2-sse42-fma-mkl-dnn/usr/bin"
	# Run dh_python to rename .so file with their Python version so next iteration can provide a different version variant
	dh_python2 -ppython-tensorflow-cuda-avx2-sse42-fma-mkl-dnn --no-guessing-deps --verbose
	
	touch $@

build-py3-%:
	# -mavx -msse4.1 -msse4.2
	debian/configure-expect.sh $* "$(OPTFLAGS2)" No No "" "" No ""
	bazel build --config=opt //tensorflow/tools/pip_package:build_pip_package --verbose_failures
	bazel-bin/tensorflow/tools/pip_package/build_pip_package "$(CURDIR)/debian/python3-tensorflow-avx-sse42/"
	# This shitty bazel stuff cannot install proper permissions
	find "$(CURDIR)/debian/python3-tensorflow-avx-sse42/" -type d -exec chmod 0755 {} \;
	find "$(CURDIR)/debian/python3-tensorflow-avx-sse42/" -type f -exec chmod 0644 {} \;
	# We need to install command line tools once
	mkdir -p "$(CURDIR)/debian/tensorflow-tools/usr/"
	mv -v "$(CURDIR)/debian/python3-tensorflow-avx-sse42/usr/bin/" "$(CURDIR)/debian/tensorflow-tools/usr/"
	# Run dh_python to rename .so file with their Python version so next iteration can provide a different version variant
	dh_python3 -ppython3-tensorflow-avx-sse42 --no-guessing-deps --verbose
	dh_python3 -ptensorflow-tools --no-guessing-deps --verbose
	
	# -mavx -msse4.1 -msse4.2 CUDA
	debian/configure-expect.sh $* "$(OPTFLAGS2)" Yes No "$(CURDIR)/cuda-$(CUDA_VERSION)" "$(CUDA_CAP)" No ""
	bazel build --config=opt --config=cuda //tensorflow/tools/pip_package:build_pip_package --verbose_failures
	bazel-bin/tensorflow/tools/pip_package/build_pip_package "$(CURDIR)/debian/python3-tensorflow-cuda-avx-sse42/"
	# This shitty bazel stuff cannot install proper permissions
	find "$(CURDIR)/debian/python3-tensorflow-cuda-avx-sse42/" -type d -exec chmod 0755 {} \;
	find "$(CURDIR)/debian/python3-tensorflow-cuda-avx-sse42/" -type f -exec chmod 0644 {} \;
	# Installed in tensorflow-tools package
	rm -rf "$(CURDIR)/debian/python3-tensorflow-cuda-avx-sse42/usr/bin"
	# Run dh_python to rename .so file with their Python version so next iteration can provide a different version variant
	dh_python3 -ppython3-tensorflow-cuda-avx-sse42 --no-guessing-deps --verbose
	
	## -mavx -mavx2 -mfma -msse4.1 -msse4.2
	debian/configure-expect.sh $* "$(OPTFLAGS1)" No No "" "" No ""
	bazel build --config=opt //tensorflow/tools/pip_package:build_pip_package --verbose_failures
	bazel-bin/tensorflow/tools/pip_package/build_pip_package "$(CURDIR)/debian/python3-tensorflow-avx2-sse42-fma/"
	# This shitty bazel stuff cannot install proper permissions
	find "$(CURDIR)/debian/python3-tensorflow-avx2-sse42-fma/" -type d -exec chmod 0755 {} \;
	find "$(CURDIR)/debian//python3-tensorflow-avx2-sse42-fma/" -type f -exec chmod 0644 {} \;
	# Installed in tensorflow-tools package
	rm -rf "$(CURDIR)/debian/python3-tensorflow-avx2-sse42-fma/usr/bin"
	# Run dh_python to rename .so file with their Python version so next iteration can provide a different version variant
	dh_python3 -ppython3-tensorflow-avx2-sse42-fma --no-guessing-deps --verbose
	
	## -mavx -mavx2 -mfma -msse4.1 -msse4.2 + Intel MKL DNN
	debian/configure-expect.sh $* "$(OPTFLAGS1)" No No "" "" Yes "$(CURDIR)/mkldnn"
	bazel build --config=opt --config=mkl //tensorflow/tools/pip_package:build_pip_package --verbose_failures
	bazel-bin/tensorflow/tools/pip_package/build_pip_package "$(CURDIR)/debian/python3-tensorflow-avx2-sse42-fma-mkl-dnn/"
	# This shitty bazel stuff cannot install proper permissions
	find "$(CURDIR)/debian/python3-tensorflow-avx2-sse42-fma-mkl-dnn/" -type d -exec chmod 0755 {} \;
	find "$(CURDIR)/debian//python3-tensorflow-avx2-sse42-fma-mkl-dnn/" -type f -exec chmod 0644 {} \;
	# Installed in tensorflow-tools package
	rm -rf "$(CURDIR)/debian/python3-tensorflow-avx2-sse42-fma-mkl-dnn/usr/bin"
	# Run dh_python to rename .so file with their Python version so next iteration can provide a different version variant
	dh_python3 -ppython3-tensorflow-avx2-sse42-fma-mkl-dnn --no-guessing-deps --verbose
	
	## -mavx -mavx2 -mfma -msse4.1 -msse4.2 CUDA
	debian/configure-expect.sh $* "$(OPTFLAGS1)" Yes No "$(CURDIR)/cuda-$(CUDA_VERSION)" "$(CUDA_CAP)" No ""
	bazel build --config=opt --config=cuda //tensorflow/tools/pip_package:build_pip_package --verbose_failures
	bazel-bin/tensorflow/tools/pip_package/build_pip_package "$(CURDIR)/debian/python3-tensorflow-cuda-avx2-sse42-fma/"
	# This shitty bazel stuff cannot install proper permissions
	find "$(CURDIR)/debian/python3-tensorflow-cuda-avx2-sse42-fma/" -type d -exec chmod 0755 {} \;
	find "$(CURDIR)/debian/python3-tensorflow-cuda-avx2-sse42-fma/" -type f -exec chmod 0644 {} \;
	# Installed in tensorflow-tools package
	rm -rf "$(CURDIR)/debian/python3-tensorflow-cuda-avx2-sse42-fma/usr/bin"
	# Run dh_python to rename .so file with their Python version so next iteration can provide a different version variant
	dh_python3 -ppython3-tensorflow-cuda-avx2-sse42-fma --no-guessing-deps --verbose
	
	## -mavx -mavx2 -mfma -msse4.1 -msse4.2 CUDA + Intel MKL DNN
	debian/configure-expect.sh $* "$(OPTFLAGS1)" Yes No "$(CURDIR)/cuda-$(CUDA_VERSION)" "$(CUDA_CAP)" Yes "$(CURDIR)/mkldnn"
	bazel build --config=opt --config=cuda --config=mkl //tensorflow/tools/pip_package:build_pip_package --verbose_failures
	bazel-bin/tensorflow/tools/pip_package/build_pip_package "$(CURDIR)/debian/python3-tensorflow-cuda-avx2-sse42-fma-mkl-dnn/"
	# This shitty bazel stuff cannot install proper permissions
	find "$(CURDIR)/debian/python3-tensorflow-cuda-avx2-sse42-fma-mkl-dnn/" -type d -exec chmod 0755 {} \;
	find "$(CURDIR)/debian/python3-tensorflow-cuda-avx2-sse42-fma-mkl-dnn/" -type f -exec chmod 0644 {} \;
	# Installed in tensorflow-tools package
	rm -rf "$(CURDIR)/debian/python3-tensorflow-cuda-avx2-sse42-fma-mkl-dnn/usr/bin"
	# Run dh_python to rename .so file with their Python version so next iteration can provide a different version variant
	dh_python3 -ppython3-tensorflow-cuda-avx2-sse42-fma-mkl-dnn --no-guessing-deps --verbose
	
	touch $@

override_dh_auto_clean:
	dh_auto_clean
	rm -f .bazelrc .tf_configure.bazelrc tensorflow/tools/git/gen/spec.json tools/python_bin_path.sh
	rm -f build-py build-py3 build-py2-* build-py3-*
	rm -f bazel-*
	rm -rf cuda-$(CUDA_VERSION)
	rm -rf mkldnn
	rm -rf third_party/eigen3/mkl_include third_party/mkl/include third_party/mkl/libdl.so.2 third_party/mkl/libmklml_intel.so third_party/mkl/libiomp5.so third_party/mkl/mkl.config

override_dh_gencontrol:
	dh_gencontrol -- -v"$(PKG_VERSION)+$(DIST_NAME)-$(DIST_RELEASE)-$(DIST_VERSION)" $(SUBSTVARS_CUDNN) $(SUBSTVARS_PY2DEPS) $(SUBSTVARS_PY3DEPS)

override_dh_strip:

# This has been done already
override_dh_python2:
override_dh_python3:
