#!/usr/bin/make -f

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

export CC = gcc-11
export CXX = g++-11

export DEB_BUILD_MAINT_OPTIONS = hardening=+all

builtins := /usr/share/nodejs/node

# source equivalent of nodejs -e 'console.log(process.versions.modules)'
ABI = $(shell awk '/^#define NODE_MODULE_VERSION/ {print $$3}' src/node_version.h)

# archs
ARCHS := amd64 arm64 armel armhf i386 kfreebsd-i386 kfreebsd-amd64 mips mips64el mips64r6el mipsel ppc64 ppc64el riscv64 s390x

# branch
BRANCH := $(word 1, $(subst .,$(space), $(DEB_UPSTREAM_VERSION)))

LANG=C
export LANG
DEB_CONFIGURE_NORMAL_ARGS =
DEB_CONFIGURE_EXTRA_FLAGS = \
--verbose \
--without-npm \
--without-corepack \
--shared \
--shared-zlib \
--shared-cares \
--shared-nghttp2 \
--shared-nghttp3 \
--shared-ngtcp2 \
--shared-brotli \
--shared-builtin-undici/undici-path=/usr/share/nodejs/undici/undici-fetch.js \
--shared-builtin-acorn-path=/usr/share/nodejs/acorn/dist/acorn.js \
--shared-builtin-acorn_walk-path=/usr/share/nodejs/acorn-walk/dist/walk.js \
--shared-builtin-cjs_module_lexer/lexer-path=/usr/share/nodejs/cjs-module-lexer/lexer.js \
--shared-builtin-cjs_module_lexer/dist/lexer-path=/usr/share/nodejs/cjs-module-lexer/dist/lexer.js \
--with-intl=system-icu \
--prefix=/usr \
--shared-openssl \
--openssl-use-def-ca-store \
--arch-triplet=$(DEB_HOST_MULTIARCH) \
--node-relative-path="lib/$(DEB_HOST_MULTIARCH)/nodejs:share/nodejs" \
--shared-libuv

ifneq ($(filter pkg.nodejs.nobuiltin,$(DEB_BUILD_PROFILES)),)
	DEB_CONFIGURE_EXTRA_FLAGS += --node-builtin-modules-path=$(builtins)
endif

# map HOST ARCH AND OS, and if unknown let upstream guess

destCpu =
destCpu := $(or $(destCpu),$(if $(filter i386,$(DEB_HOST_ARCH)),ia32))
destCpu := $(or $(destCpu),$(if $(filter x32,$(DEB_HOST_ARCH)),x32))
destCpu := $(or $(destCpu),$(if $(filter kfreebsd-i386,$(DEB_HOST_ARCH)),ia32))
destCpu := $(or $(destCpu),$(if $(filter hurd-i386,$(DEB_HOST_ARCH)),ia32))
destCpu := $(or $(destCpu),$(if $(filter amd64,$(DEB_HOST_ARCH)),x64))
destCpu := $(or $(destCpu),$(if $(filter kfreebsd-amd64,$(DEB_HOST_ARCH)),x64))
destCpu := $(or $(destCpu),$(if $(filter armel,$(DEB_HOST_ARCH)),arm))
destCpu := $(or $(destCpu),$(if $(filter armhf,$(DEB_HOST_ARCH)),arm))
destCpu := $(or $(destCpu),$(if $(filter aarch64,$(DEB_HOST_ARCH)),arm64))
destCpu := $(or $(destCpu),$(if $(filter mipsel,$(DEB_HOST_ARCH)),mipsel))
destCpu := $(or $(destCpu),$(if $(filter mips64el,$(DEB_HOST_ARCH)),mips64el))
destCpu := $(or $(destCpu),$(if $(filter mips64r6el,$(DEB_HOST_ARCH)),mips64el))
destCpu := $(or $(destCpu),$(if $(filter mips,$(DEB_HOST_ARCH)),mips))
destCpu := $(or $(destCpu),$(if $(filter powerpc,$(DEB_HOST_ARCH)),ppc))
destCpu := $(or $(destCpu),$(if $(filter ppc64,$(DEB_HOST_ARCH)),ppc64))
destCpu := $(or $(destCpu),$(if $(filter riscv64,$(DEB_HOST_ARCH)),riscv64))
destCpu := $(or $(destCpu),$(if $(filter s390x,$(DEB_HOST_ARCH)),s390x))

# solaris freebsd openbsd linux
destOs =
destOs := $(or $(destOs),$(if $(filter linux,$(DEB_HOST_ARCH_OS)),linux))
destOs := $(or $(destOs),$(if $(filter kfreebsd,$(DEB_HOST_ARCH_OS)),freebsd))

ifneq (, $(destOs))
DEB_CONFIGURE_EXTRA_FLAGS += --dest-os=$(destOs)
endif
ifeq (unsupported, $(destCpu))
$(error "nodejs cannot run on $(DEB_HOST_ARCH), please consult maintainers")
endif
ifneq (, $(destCpu))
DEB_CONFIGURE_EXTRA_FLAGS += --dest-cpu=$(destCpu)
endif

ifeq (freebsd, $(destOs))
LDFLAGS += -lbsd
endif

# mips and fpu
# https://github.com/paul99/v8m-rb/issues/192
# https://bugs.debian.org/800410
# mips and big binaries
# http://gcc.gnu.org/wiki/DebugFission
# https://bugs.debian.org/829139

# use r2, which is the supported variant for these architectures
# https://lists.debian.org/debian-mips/2016/07/msg00000.html
ifeq (mipsel, $(DEB_HOST_ARCH))
DEB_CONFIGURE_EXTRA_FLAGS += --with-mips-arch-variant=r2 --with-mips-fpu-mode=fpxx
CFLAGS += -gsplit-dwarf
CPPFLAGS += -gsplit-dwarf
endif
ifeq (mips, $(DEB_HOST_ARCH))
DEB_CONFIGURE_EXTRA_FLAGS += --with-mips-arch-variant=r2 --with-mips-fpu-mode=fpxx
CFLAGS += -gsplit-dwarf
CPPFLAGS += -gsplit-dwarf
endif

# mips32r1 or greater, detected at runtime
ifeq (mips64el, $(DEB_HOST_ARCH))
DEB_CONFIGURE_EXTRA_FLAGS += --with-mips-arch-variant=rx --with-mips-fpu-mode=fp64
CFLAGS += -gsplit-dwarf
CPPFLAGS += -gsplit-dwarf
endif
ifeq (mips64r6el, $(DEB_HOST_ARCH))
DEB_CONFIGURE_EXTRA_FLAGS += --with-mips-arch-variant=rx --with-mips-fpu-mode=fp64
CFLAGS += -gsplit-dwarf
CPPFLAGS += -gsplit-dwarf
endif

ifeq (armel, $(DEB_HOST_ARCH))
DEB_CONFIGURE_EXTRA_FLAGS += --with-arm-float-abi=softfp
ifeq ($(shell dpkg-vendor --is ubuntu && echo true),true)
# Ubuntu targets armv7+ with VFP and thumb2 support by default for armel
DEB_CONFIGURE_EXTRA_FLAGS += --with-arm-fpu=vfpv3
else
# debian armel version
# v8 supports armv6k (must be set explicitely) + vfpv2 (selected by default)
# armv6k is only not available on ARM1136JF-S r0p2, and available on r1p0.
DEB_CONFIGURE_EXTRA_FLAGS += --with-arm-fpu=vfpv2 --with-arm-version=6
CFLAGS += -march=armv6k -mfpu=vfpv2
CPPFLAGS += -march=armv6k -mfpu=vfpv2
endif
endif

ifeq (armhf, $(DEB_HOST_ARCH))
DEB_CONFIGURE_EXTRA_FLAGS += --with-arm-float-abi=hard
ifeq ($(shell dpkg-vendor --derives-from raspbian && echo true),true)
# enable vfp, disable armv7
DEB_CONFIGURE_EXTRA_FLAGS += --with-arm-fpu=vfp
else
# enable armv7 vfpv3
DEB_CONFIGURE_EXTRA_FLAGS += --with-arm-fpu=vfpv3
endif
endif

DEB_DESTDIR = $(CURDIR)/debian/tmp
DEB_MAKE_CLEAN_TARGET = clean
DEB_MAKE_BUILD_TARGET = build

#  relax regression tests when targeted experimental suite
export HOME = $(CURDIR)/tmp
export FLAKY_TESTS = dontcare
export TEST_CI_ARGS = --arch=$(destCpu) --timeout=3000
export CI_JS_SUITES = message parallel sequential
export NODE_TEST_DIR = $(CURDIR)/tmp
export NODE_TEST_NO_INTERNET = 1
# needed for tests to avoid "ee key too small" errors
export OPENSSL_CONF = $(CURDIR)/deps/openssl/openssl/apps/openssl.cnf
# keep in mind ./debian/rules check is also invoked by adt-run, see debian/tests/
exp-relax-check := $(if $(shell dpkg-parsechangelog | grep -x 'Distribution: \(experimental\|UNRELEASED\)'),-i)
DEB_MAKE_CHECK_TARGET = $(exp-relax-check) test-ci-js

# build -fPIC
CFLAGS += -fPIC
CPPFLAGS += -fPIC

ifeq ($(DEB_HOST_ARCH_BITS),32)
CFLAGS += -g1
CPPFLAGS += -g1
DH_FLAGS += --max-parallel=1
export JOBS = 1
else
CFLAGS += -g
CPPFLAGS += -g
endif


# hardening gyp
CXXFLAGS += $(CPPFLAGS)

export CPPFLAGS
export CXXFLAGS
export CFLAGS
export LDFLAGS

export PYTHON = python3

%:
	dh $@ --with bash-completion $(DH_FLAGS)

# properly clean files from build, test, python
override_dh_auto_clean:
	dh_auto_clean
	rm -f node_trace.1.log
	rm -f icu_config.gypi
	rm -rf test/addons/doc-*
	rm -f test/addons/.buildstamp
	rm -f test/addons/.docbuildstamp
	rm -rf test/addons/*/build
	rm -f config.gypi
	rm -f config.mk
	rm -f config.status
	rm -f test/fixtures/hello.txt
	rm -rf $(NODE_TEST_DIR)
	find . -name "*.pyc" -delete
	rm -rf out
	rm -rf node_modules
	rm -f debian/libnode$(ABI).install
	rm -f debian/libnode-dev.links
	rm -f debian/nodejs.install
	rm -f debian/nodejs.bash-completion

# remove *.json files from documentation
override_dh_installdocs:
	dh_installdocs
	find debian/nodejs-doc/usr/share/doc/nodejs-doc -name *.json -delete || true

override_dh_auto_configure:
# gyp    | debian
# -------+-------
# target | host
# host   | build

ifneq ($(DEB_BUILD_ARCH),$(DEB_HOST_ARCH))
	CC=$(CC) CXX=$(CXX) PKG_CONFIG=$(PKG_CONFIG) CC_host=$(CC_FOR_BUILD) CXX_host=$(CXX_FOR_BUILD) ./configure --cross-compiling $(DEB_CONFIGURE_EXTRA_FLAGS)
else
	./configure $(DEB_CONFIGURE_EXTRA_FLAGS)
endif

override_dh_auto_build-arch:
	dh_auto_build
	./out/Release/node --completion-bash > ./debian/nodejs.bash-completion

override_dh_auto_build-indep:
	mkdir -p node_modules
	ln -sf /usr/share/nodejs/marked node_modules/
	ln -sf /usr/share/nodejs/acorn node_modules/
	ln -sf /usr/share/nodejs/js-yaml node_modules/
	$(MAKE) doc-only

override_dh_auto_test-indep:
	# skip tests

override_dh_auto_test-arch:
ifeq ($(filter nocheck,$(DEB_BUILD_PROFILES)),)
	-ln -s /usr/bin/node node
	mkdir -p $(NODE_TEST_DIR)
	$(MAKE) $(DEB_MAKE_CHECK_TARGET)
	rm -f node
	rm -rf $(NODE_TEST_DIR)
endif

override_dh_auto_install-indep:
	# skip install all

override_dh_auto_install-arch:
	dh_auto_install

override_dh_install-arch:
	sed 's/@DEB_HOST_MULTIARCH@/$(DEB_HOST_MULTIARCH)/g' debian/libnode.install > debian/libnode$(ABI).install
	sed -e 's/@DEB_HOST_MULTIARCH@/$(DEB_HOST_MULTIARCH)/g' -e 's/@ABI@/$(ABI)/g' debian/libnode-dev.links.in > debian/libnode-dev.links
	cp debian/nodejs.install.in debian/nodejs.install
ifneq ($(filter pkg.nodejs.nobuiltin,$(DEB_BUILD_PROFILES)),)
	echo "./lib $(builtins)/" >> debian/nodejs.install
	deps_files="$(shell $(PYTHON) -c "import ast; d = ast.literal_eval(open('node.gyp').read()); print(' '.join(d['variables']['deps_files']));")"; \
	for src in $$deps_files; do \
		dst=`dirname $$src`; \
		echo "./$$src $(builtins)/$$dst" >> debian/nodejs.install; \
	done
endif
	dh_install

override_dh_dwz:
	# Double up the limit of debug information entries
	# Also, ignore failures (on 32-bit archs it might fail)
	-dh_dwz -- --max-die-limit 100000000

override_dh_gencontrol:
	dh_gencontrol -- \
	 -V"types:Node=$(shell jq --raw-output .version <types-node/package.json)~$(DEB_VERSION)"

execute_after_dh_fixperms-arch:
	find $(CURDIR)/debian/nodejs/usr/share/nodejs/@types/node -type f -exec chmod a-x '{}' \;
