#!/usr/bin/make -f

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


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 [0-9]+/ {print $$3}' src/node_version.h)

# archs
ARCHS := amd64 arm64 armel armhf i386 mips64el mips64r6el loong64 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-zstd \
--shared-cares \
--shared-ngtcp2 \
--shared-nghttp3 \
--shared-nghttp2 \
--shared-brotli \
--shared-simdjson \
--shared-sqlite \
--shared-builtin-amaro/dist/index-path=/usr/share/nodejs/amaro/dist/index.js \
--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 \
--shared-builtin-minimatch-path=/usr/share/nodejs/minimatch/dist/cjs/index.bundle.js \
--shared-openssl \
--openssl-use-def-ca-store \
--with-intl=system-icu \
--prefix=/usr \
--arch-triplet=$(DEB_HOST_MULTIARCH) \
--node-relative-path="lib/$(DEB_HOST_MULTIARCH)/nodejs:share/nodejs" \
--dest-os=linux

ifneq ($(DEB_HOST_ARCH),i386)
	DEB_CONFIGURE_EXTRA_FLAGS += --shared-libuv
endif

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 hurd-i386,$(DEB_HOST_ARCH)),ia32))
destCpu := $(or $(destCpu),$(if $(filter 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 mips64el,$(DEB_HOST_ARCH)),mips64el))
destCpu := $(or $(destCpu),$(if $(filter mips64r6el,$(DEB_HOST_ARCH)),mips64el))
destCpu := $(or $(destCpu),$(if $(filter loong64,$(DEB_HOST_ARCH)),loong64))
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))

ifneq (, $(destCpu))
DEB_CONFIGURE_EXTRA_FLAGS += --dest-cpu=$(destCpu)
endif

# mips32r1 or greater, detected at runtime
ifeq (mips64el, $(DEB_HOST_ARCH))
DEB_CONFIGURE_EXTRA_FLAGS += --with-mips-arch-variant=r2 --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=r6 --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-d16
DEB_CONFIGURE_EXTRA_FLAGS += --with-arm-fpu=vfpv3-d16
endif
endif

DEB_DESTDIR = $(CURDIR)/debian/tmp

# Compiled without amaro - no ts support
skipTests += parallel/test-util-getcallsites
skipTests += parallel/test-worker-eval-typescript
skipTests += parallel/test-node-output-eval
# tests using npm
skipTests += parallel/test-npm-install
skipTests += parallel/test-npm-version
skipTests += parallel/test-release-npm
# tests using network
skipTests += parallel/test-dns
skipTests += parallel/test-net-connect-immediate-finish
skipTests += parallel/test-net-better-error-messages-port-hostname
skipTests += parallel/test-https-connect-address-family
skipTests += parallel/test-tls-connect-address-family
skipTests += parallel/test-dns-cancel-reverse-lookup
skipTests += parallel/test-dns-resolveany-bad-ancount
# bad test
skipTests += parallel/test-child-process-stdio-overlapped
# requires corepack
skipTests += parallel/test-corepack-yarn-install
skipTests += parallel/test-corepack-version
# fail on buildd
skipTests += sequential/test-force-repl
skipTests += sequential/test-performance
# hangs https://github.com/nodejs/node/issues/44898
skipTests += sequential/test-watch-mode
skipTests += sequential/test-watch-mode-inspect
# CVE-2024-22017 shared libuv cannot guarantee io_uring is disabled
skipTests += parallel/test-process-uid-gid
skipTests += parallel/test-process-initgroups
skipTests += parallel/test-process-setgroups
skipTests += parallel/test-process-euid-egid
# sea requires postject
skipTests += parallel/test-single-executable-application
# loading of openssl for tests make this test fail
skipTests += parallel/test-strace-openat-openssl
# Might fail on slow architectures
flakyTests += parallel/test-runner-output
flakyTests += sequential/test-tls-session-timeout
# https://bugs.debian.org/919588
# flaky on some user environments
flakyTests += parallel/test-net-listen-after-destroying-stdin
# fails when running with eatmydata
skipTests += parallel/test-fs-error-messages
# need privileges
skipTests += parallel/test-cluster-bind-privileged-port
skipTests += parallel/test-cluster-shared-handle-bind-privileged-port
skipTests += parallel/test-debugger-preserve-breaks
# issues on 32-bit archs
skipTests += parallel/test-debugger-heap-profiler
skipTests += parallel/test-fs-utimes
skipTests += parallel/test-fs-utimes-y2K38
skipTests += parallel/test-debug-args
# https://github.com/nodejs/node/issues/27611#issuecomment-613100468
skipTests += sequential/test-cpu-prof-dir-absolute
# Flaky in build servers
flakyTests += parallel/test-process-config
flakyTests += parallel/test-regress-GH-746
flakyTests += parallel/test-stdout-close-unref
flakyTests += sequential/test-fs-watch
flakyTests += sequential/test-http2-session-timeout
flakyTests += sequential/test-debugger-preserve-breaks
flakyTests += sequential/test-debugger-exec-scope
flakyTests += sequential/test-worker-heapsnapshot-options
# flaky on buildd https://github.com/nodejs/node/issues/39655
flakyTests += parallel/test-cluster-primary-error
flakyTests += parallel/test-cluster-primary-kill

ifeq ($(DEB_HOST_ARCH), riscv64)
flakyTests += sequential/test-diagnostic-dir-cpu-prof
flakyTests += sequential/test-cpu-prof-worker-argv
flakyTests += sequential/test-cpu-prof-dir-and-name
flakyTests += sequential/test-cpu-prof-exit
flakyTests += sequential/test-cpu-prof-kill
flakyTests += sequential/test-cpu-prof-name
flakyTests += sequential/test-diagnostic-dir-cpu-prof
flakyTests += sequential/test-debugger-auto-resume
flakyTests += sequential/test-debugger-preserve-breaks
flakyTests += sequential/test-cpu-prof-dir-relative
flakyTests += sequential/test-cpu-prof-drained
flakyTests += sequential/test-worker-prof
flakyTests += sequential/test-vm-timeout-escape-promise-module-2
flakyTests += sequential/test-cpu-prof-dir-absolute
flakyTests += parallel/test-fetch
flakyTests += parallel/test-net-socket-connect-without-cb
flakyTests += parallel/test-runner-inspect
flakyTests += parallel/test-runner-output
flakyTests += parallel/test-tcp-wrap-listen
flakyTests += parallel/test-wasm-web-api
flakyTests += parallel/test-vm-timeout-escape-promise-module
flakyTests += parallel/test-crypto-sign-verify
flakyTests += parallel/test-freeze-intrinsics
flakyTests += parallel/test-tls-root-certificates
flakyTests += parallel/test-vm-global-non-writable-properties
flakyTests += parallel/test-vm-global-setter
flakyTests += parallel/test-vm-module-synthetic
flakyTests += parallel/test-vm-strict-assign
endif

ifeq ($(DEB_HOST_ARCH), loong64)
flakyTests += parallel/test-crypto-sign-verify
flakyTests += parallel/test-freeze-intrinsics
flakyTests += parallel/test-tls-root-certificates
flakyTests += parallel/test-vm-global-non-writable-properties
flakyTests += parallel/test-vm-global-setter
flakyTests += parallel/test-vm-module-synthetic
flakyTests += parallel/test-vm-strict-assign
flakyTests += sequential/test-worker-prof
flakyTests += sequential/test-cpu-prof-name
flakyTests += sequential/test-cpu-prof-dir-relative
flakyTests += sequential/test-diagnostic-dir-cpu-prof
endif

ifeq ($(DEB_HOST_ARCH), mips64el)
flakyTests += sequential/test-worker-prof
flakyTests += sequential/test-cpu-prof-dir-relative
endif

export HOME = $(CURDIR)/tmp
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)/debian/openssl.cnf
# relax regression tests when targeted experimental suite
exp-relax-check := $(if $(shell dpkg-parsechangelog | grep -x 'Distribution: \(experimental\|UNRELEASED\)'),-i)
DEB_MAKE_CHECK_TARGET = $(exp-relax-check) test-ci-js
# Makefile pass these already
comma := ,
empty :=
space := $(empty) $(empty)
export CI_SKIP_TESTS = $(subst $(space),$(comma),$(skipTests))
# Run flaky tests but ignore failures
export FLAKY_TESTS = dontcare

TEST_CI_ARGS = --arch=$(destCpu) --timeout=6000 --flaky-tests=$(subst $(space),$(comma),$(flakyTests))

# override Node.js path when running under adt-run (no build directory present)
ifeq (,$(wildcard $(CURDIR)/out))
TEST_CI_ARGS += --shell=/usr/bin/node
else
TEST_CI_ARGS += --shell=out/Release/node
endif
export TEST_CI_ARGS

# 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 $@ $(DH_FLAGS)

# properly clean files from build, test, python
execute_after_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
	rm -rf deps/openssl/

# remove *.json files from documentation
execute_after_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

execute_before_dh_auto_build-arch:
	mkdir -p deps/openssl/ && touch deps/openssl/nodejs-openssl.cnf
	pkver=`dpkg-query --showformat='$${source:Upstream-Version}' --show node-acorn | sed -E 's/^([0-9]+\.[0-9]+\.[0-9]+).*/\1/g'`; \
	sed -i -e "s/[0-9]\+\.[0-9]\+\.[0-9]\+/$${pkver}/" src/acorn_version.h
	pkver=`dpkg-query --showformat='$${source:Upstream-Version}' --show node-cjs-module-lexer | sed -E 's/^([0-9]+\.[0-9]+\.[0-9]+).*/\1/g'`; \
	sed -i -e "s/[0-9]\+\.[0-9]\+\.[0-9]\+/$${pkver}/" src/cjs_module_lexer_version.h
	pkver=`dpkg-query --showformat='$${source:Upstream-Version}' --show node-undici | sed -E 's/^([0-9]+\.[0-9]+\.[0-9]+).*/\1/g'`; \
	sed -i -e "s/[0-9]\+\.[0-9]\+\.[0-9]\+/$${pkver}/" src/undici_version.h

execute_after_dh_auto_build-arch:
ifeq ($(filter nodoc,$(DEB_BUILD_PROFILES)),)
	./out/Release/node --completion-bash > ./debian/nodejs.bash-completion
endif

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/
	ln -sf /usr/share/nodejs/cjs-module-lexer node_modules/
	ln -sf /usr/share/nodejs/minimatch node_modules/
	$(MAKE) doc-only

override_dh_auto_test-indep:
	# skip tests

# called by dpkg-buildpackage and by autopkgtest
override_dh_auto_test-arch:
ifeq ($(filter nocheck,$(DEB_BUILD_PROFILES)),)
	mkdir -p $(NODE_TEST_DIR)
	$(MAKE) $(DEB_MAKE_CHECK_TARGET)
	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.in > 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'][:-1]));")"; \
	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 '{}' \;
