USE_WXNEEDED =		Yes

COMMENT =		javascript engine

# same as www/chromium
V=			150.0.7871.100

# make v8-deps
V8_V=			968f19a8970f8d91702d86f0ec1522f3909781b7
#https://chromium.googlesource.com/v8/v8/+/968f19a8970f8d91702d86f0ec1522f3909781b7/DEPS
BUILD_V=		b787aa6672fcf87221cdb63da9c2523878a6d267
BUILDTOOLS_V=		17495e454aae81b581e8b3caccbb53054509b280
GN_V=			3357c4f51b1a9e676378c695dd9c7e9911c35ee6
ABSEIL_V=		d16e32215c3ab90ba57c2e904a5344d85c7353e4
SIMDUTF_V=		f7356eed293f8208c40b3c1b344a50bd70971983
PARTITION_ALLOC_V=	ff3b8b885b8374cbd3902642d94dc737bda93d5d
ICU_V=			ee5f27adc28bd3f15b2c293f726d14d2e336cbd5
PROTOBUF_V=		96835044c7edeb1cfa2b2dbfd3057c51588952b3
PROTOC_WRAPPER_V=	418c65786fdf6fc5f10cb008c252c2b12c4713a6
FUZZTEST_V=		3744152a16ad03e389ab3a75234bfa572e367763
FUZZTEST_SRC_V=		da27bcae1a8902af1ae6a5c55d3674f22709bbf5
GOOGLETEST_V=		4fe3307fb2d9f86d19777c7eb0e4809e9694dde7
DRAGONBOX_V=		beeeef91cf6fef89a4d4ba5e95d47ca64ccb3a44
FP16_V=			3d2de1816307bac63c16a297e8c4dc501b4076df
FASTFLOAT_V=		05087a303dad9c98768b33c829d398223a649bc6
HIGHWAY_V=		2607d3b5b0113992fe84d3848859eae13b3b52c1
JSONCPP_V=		d4d072177213b117fb81d4cfda140de090616161
RE2_V=			972a15cedd008d846f1a39b2e88ce48d7f166cbd
ZLIB_V=			3246f1b60849cc505e231c5d19d0cbf358093555
LIBCXX_V=		5abc7f839700f0f17338434e1c1c6a8c87c00c11
LIBCXXABI_V=		8f11bb1d4438d0239d0dfc1bd9456a9f31629dda
LIBUNWIND_V=		d6c7a21e978f0adaa43accaad53bc64f0b64f6ec
LLVM_LIBC_V=		9309c117ebae84dd2f9df1ef99de4782162527d5
# wasm archives checked by tools/make-v8.sh
WASM_JS_H=		fa1dbb5717f58043b2d3c01c4c331b206adedac8
WASM_SPEC_H=		bd7805d59032f25f7a3d7069b189f9e2d87e4f01

DISTNAME =		v8-${V}

CATEGORIES =	lang

HOMEPAGE =	https://v8.dev/

# BSD-like
PERMIT_PACKAGE =	Yes

SITES =			https://chromium.googlesource.com/v8/v8/+archive/
DISTFILES =		v8-{}${V8_V}.tar.gz

SITES.chromium = 	https://chromium.googlesource.com/chromium/
TEMPLATE_DISTFILES.chromium = \
	v8-<project>-{<account>/<project>/+archive/}<id>.tar.gz

SITES.chromium-ext =	https://chromium.googlesource.com/external/github.com/
TEMPLATE_DISTFILES.chromium-ext = \
	v8-<project>-{<account>/<project>/+archive/}<id>.tar.gz

# chromium.googlesource.com/chromium/
# build: Chromium build configuration and scripts; BSD-3-Clause
# buildtools: Common build tooling for Chromium; BSD-3-Clause
# abseil-cpp: Abseil Common Libraries (C++); Apache-2.0
# simdutf: Unicode validation and transcoding; Apache-2.0/MIT
# partition_allocator: PartitionAlloc memory allocator; BSD-3-Clause
# protobuf: Protocol Buffers data serialization; BSD-3-Clause
# protoc_wrapper: Chromium protoc wrapper script; BSD-3-Clause
# icu: International Components for Unicode; Unicode-3.0
# fuzztest: Chromium mirror metadata for FuzzTest; BSD-3-Clause
# zlib: unobtrusive compression library; Zlib (BSD-like)
DIST_TUPLE+= \
chromium src build ${BUILD_V} build \
chromium src buildtools ${BUILDTOOLS_V} buildtools \
chromium src/third_party abseil-cpp ${ABSEIL_V} third_party/abseil-cpp \
chromium src/third_party simdutf ${SIMDUTF_V} third_party/simdutf \
chromium src/base/allocator partition_allocator ${PARTITION_ALLOC_V} \
	third_party/partition_alloc \
chromium src/third_party protobuf ${PROTOBUF_V} third_party/protobuf \
chromium src/tools protoc_wrapper ${PROTOC_WRAPPER_V} tools/protoc_wrapper \
chromium deps icu ${ICU_V} third_party/icu \
chromium src/third_party fuzztest ${FUZZTEST_V} third_party/fuzztest \
chromium src/third_party zlib ${ZLIB_V} third_party/zlib

# fuzztest-src: C++ framework for writing and running fuzz tests; Apache-2.0
# googletest: Google Test: Google's C++ Testing Framework; BSD-3-Clause
# jsoncpp: JSON parser and generator for C++; MIT
# re2: An efficient, principled regular expression library; BSD-3-Clause
DIST_TUPLE+= \
github google fuzztest ${FUZZTEST_SRC_V} third_party/fuzztest/src \
github google googletest ${GOOGLETEST_V} third_party/googletest/src \
github open-source-parsers jsoncpp ${JSONCPP_V} third_party/jsoncpp/source \
github google re2 ${RE2_V} third_party/re2/src

# chromium.googlesource.com/external/github.com/
# libcxx: LLVM C++ standard library; Apache-2.0 WITH LLVM-exception
# libcxxabi: LLVM C++ low level support; Apache-2.0 WITH LLVM-exception
# libunwind: LLVM stack unwinding library; Apache-2.0 WITH LLVM-exception
# llvm-libc: LLVM C library components; Apache-2.0 WITH LLVM-exception
# dragonbox: Reference implementation of Dragonbox; Apache-2.0/BSL-1.0
# fp16: Conversion to/from half-precision floating point; MIT
# fast_float: Fast number parsing library; Apache-2.0/BSL-1.0/MIT
# highway: Performance-portable SIMD library; Apache-2.0/BSD-3-Clause
_LLVM=llvm/llvm-project
DIST_TUPLE+= \
chromium-ext ${_LLVM} libcxx ${LIBCXX_V} third_party/libc++/src \
chromium-ext ${_LLVM} libcxxabi ${LIBCXXABI_V} third_party/libc++abi/src \
chromium-ext ${_LLVM} libunwind ${LIBUNWIND_V} third_party/libunwind/src \
chromium-ext ${_LLVM} libc ${LLVM_LIBC_V} third_party/llvm-libc/src \
chromium-ext jk-jeon dragonbox ${DRAGONBOX_V} third_party/dragonbox/src \
chromium-ext Maratyszcza FP16 ${FP16_V} third_party/fp16/src \
chromium-ext fastfloat fast_float ${FASTFLOAT_V} third_party/fast_float/src \
chromium-ext google highway ${HIGHWAY_V} third_party/highway/src

# gn: Meta-build system that generates NinjaBuild files; BSD-3-Clause
SITES.gn =		https://gn.googlesource.com/gn/+archive/
DISTFILES.gn =		v8-gn-${GN_V}.tar.gz{${GN_V}.tar.gz}

# storage.googleapis.com/v8-wasm-spec-tests
# wasm-js: WebAssembly JavaScript API tests; Apache-2.0/BSD-3-Clause
# wasm-spec-tests: WebAssembly specification tests; Apache-2.0
SITES.v8wasm =		https://storage.googleapis.com/v8-wasm-spec-tests/
DISTFILES.v8wasm =	v8-wasm-js-${WASM_JS_H}.tar.gz{${WASM_JS_H}} \
			v8-wasm-spec-tests-${WASM_SPEC_H}.tar.gz{${WASM_SPEC_H}}

EXTRACT_CASES += v8-*)						\
	d=$$(basename $$archive .tar.gz | sed 's/^v8-//') ;	\
	case "$$archive" in					\
	v8-${V8_V}.tar.gz)					\
		t=${WRKSRC} ;;					\
	v8-gn-${GN_V}.tar.gz)					\
		t=${WRKSRC}/tools/gn ;;				\
	v8-wasm-js-*)						\
		t=${WRKSRC}/test/wasm-js ;;			\
	v8-wasm-spec-tests-*)					\
		t=${WRKSRC}/test/wasm-spec-tests ;;		\
	*)							\
		t=${WRKDIR}/$$d ;;				\
	esac ;							\
	mkdir -p $$t ;						\
	${GZIP_CMD} -d <${FULLDISTDIR}/$$archive |		\
	    ${TAR} -xf - -C $$t ;;

COMPILER =		ports-clang

MODULES =		lang/clang \
			lang/python
MODCLANG_VERSION =	22
MODPY_RUNDEP =		No

BUILD_DEPENDS =		devel/ninja

CONFIGURE_STYLE =	none

BUILDTYPE =		Release
BUILDDIR =		${WRKSRC}/out/${BUILDTYPE}
GN =			${WRKSRC}/tools/gn/out/gn
ALL_TARGET =		d8 cctest inspector-test

TEST_ENV =		${MAKE_ENV} HOME=${WRKSRC} CI=true
TEST_SUITE =		mjsunit cctest inspector
TEST_OPTIONS =		-j1 -t 30 --progress=verbose \
			--exit-after-n-failures=0

.if ${MACHINE_ARCH} == "amd64"
V8_TARGET_CPU =		x64
.elif ${MACHINE_ARCH} == "i386"
V8_TARGET_CPU =		x86
.elif ${MACHINE_ARCH} == "aarch64"
V8_TARGET_CPU =		arm64
.endif

EXTRA_CPPFLAGS =	-idirafter ${LOCALBASE}/include \
			-idirafter ${X11BASE}/include
_EXTRA_LDFLAGS =	-L${LOCALBASE}/lib -L${X11BASE}/lib
.if ${MACHINE_ARCH} == "i386"
_EXTRA_LDFLAGS +=	-Wl,--no-keep-memory
.endif

GN_ARGS =	is_official_build=true \
		symbol_level=0 \
		target_cpu=\"${V8_TARGET_CPU}\" \
		v8_target_cpu=\"${V8_TARGET_CPU}\" \
		clang_use_chrome_plugins=false \
		enable_backup_ref_ptr_support=false \
		fatal_linker_warnings=false \
		icu_use_data_file=false \
		treat_warnings_as_errors=false \
		use_allocator_shim=false \
		use_custom_libunwind=true \
		use_sysroot=false \
		use_thin_lto=false \
		extra_cppflags=\"${EXTRA_CPPFLAGS}\" \
		extra_ldflags=\"${_EXTRA_LDFLAGS}\" \
		v8_enable_cet_ibt=true

# temporal_capi is a Rust dependency not bundled in this standalone port
# XXX unbreak build, to review, looks not needed vor d8/tests
GN_ARGS+=	v8_enable_temporal_support=false

# differ from www/chromium
GN_ARGS+=	chrome_pgo_phase=0
GN_ARGS+=	enable_rust=false # Chromium true, but Rust/Temporal not needed
GN_ARGS+=	use_siso=false # port Ninja, not Siso
GN_ARGS+=	use_udev=false # standalone V8, no Chromium/content
GN_ARGS+=	use_dbus=false \
		use_gio=false \
		use_glib=false

.if exists(${.CURDIR}/patches/chromium)
ALL_PATCHFILES+=	${PATCHDIR}/chromium/patch-*
PATCH_CASES+=		${PATCHDIR}/chromium/patch-*) \
			    ${PATCH} ${PATCH_DIST_ARGS} \
			    -z .orig.chromium \
			    -d ${WRKSRC} <$$patchfile ;;
.endif

pre-configure:
	cd ${WRKSRC}/tools/gn && ${SETENV} ${MAKE_ENV} GN_VERSION=${GN_V} \
		${MODPY_BIN} build/gen.py --platform openbsd
	cd ${WRKSRC}/tools/gn && ${SETENV} ${MAKE_ENV} \
		ninja -j ${MAKE_JOBS} -C out gn
	ln -fs ${GN} ${WRKDIR}/bin/gn

do-configure:
	touch ${WRKSRC}/build/config/gclient_args.gni
	cd ${WRKSRC} && ${SETENV} ${CONFIGURE_ENV} \
		${GN} gen out/${BUILDTYPE} --args="${GN_ARGS}"

do-build:
	cd ${WRKSRC} && ${SETENV} ${MAKE_ENV} \
		ninja -j ${MAKE_JOBS} -C out/${BUILDTYPE} ${ALL_TARGET}

do-test:
	cd ${WRKSRC} && \
	ulimit -n $$(ulimit -Hn) && \
	ulimit -d $$(ulimit -Hd) && \
	${SETENV} ${TEST_ENV} ${MODPY_BIN} tools/run-tests.py \
		--outdir=out/${BUILDTYPE} ${TEST_OPTIONS} ${TEST_SUITE} \
		--log-test-schedule=${WRKDIR}/test-schedule.log

### targets for port maintainer(s)

_TMP=		/tmp/${DISTNAME}
_CHROMIUM_RAW=	https://chromium.googlesource.com/chromium/src/+/refs/tags/${V}
_V8_RAW=	https://chromium.googlesource.com/v8/v8/+

_CHROMIUM_PATCH_DATE=	2026-07-08 13:16 UTC

# make gn_args-diff, compare configured GN args against www/chromium
_GN_ARGS_DIR=		${WRKDIR}/gn_args
_GN_ARGS_CHROMIUM_LIST=	${_GN_ARGS_DIR}/gn_args-chromium.list
_GN_ARGS_V8_LIST=	${_GN_ARGS_DIR}/gn_args-v8.list
_GN_ARGS_DIFF=		${_GN_ARGS_DIR}/gn_args.diff

_gn_args-v8-list:
# run under _pbuild
	# ${_GN_ARGS_V8_LIST}
	@if [ ! -e "${_GN_ARGS_V8_LIST}" ] ; then \
		mkdir -p ${_GN_ARGS_DIR} ; \
		cd ${WRKSRC} && ${SETENV} ${CONFIGURE_ENV} \
			${GN} args out/${BUILDTYPE} --list \
			| sed -E '/^[[:space:]]+From/s/\:[[:digit:]]+$$//' \
			> ${_GN_ARGS_V8_LIST} ; \
	fi

_gn_args-chromium-list:
# run under _pbuild
	# ${_GN_ARGS_CHROMIUM_LIST}
	@if [ ! -e "${_GN_ARGS_CHROMIUM_LIST}" ] ; then \
		mkdir -p ${_GN_ARGS_DIR} ; \
		cd ${PORTSDIR}/www/chromium ; \
		_wrksrc=$$(${MAKE} show=WRKSRC) ; \
		_gn=$$_wrksrc/out/${BUILDTYPE}/gn ; \
		cd $$_wrksrc && ${SETENV} ${CONFIGURE_ENV} \
			$$_gn args out/${BUILDTYPE} --list \
			| sed -E \
			    -e '/^[[:space:]]+From/s/\:[[:digit:]]+$$//' \
			    -e 's|From //v8/|From //|' \
			    -e 's|From //base/allocator/|From //third_party/|' \
			> ${_GN_ARGS_CHROMIUM_LIST} ; \
	fi

gn_args-diff:
	${MAKE} configure
	${_PBUILD} ${MAKE} _gn_args-v8-list
	# configure www/chromium in order to compare
	cd ${PORTSDIR}/www/chromium && ${MAKE} configure
	${_PBUILD} ${MAKE} _gn_args-chromium-list
	# ${_GN_ARGS_DIFF}
	@${_PBUILD} sh -c \
	"diff -uN ${_GN_ARGS_CHROMIUM_LIST} ${_GN_ARGS_V8_LIST} > \
		${_GN_ARGS_DIFF}" || wc -l ${_GN_ARGS_DIFF}

v8-deps:
	# make v8-deps
	@set -e ;							\
	mkdir -p ${_TMP}/v8-deps ;					\
	cd ${_TMP}/v8-deps ;						\
	chromium_deps=${_CHROMIUM_RAW}/DEPS?format=TEXT ;		\
	ftp -VMo chromium.DEPS.b64 "$$chromium_deps" ;			\
	openssl enc -base64 -d -A -in chromium.DEPS.b64			\
	    -out chromium.DEPS ;					\
	v8_v=$$(sed -n "s/^  'v8_revision': '\([0-9a-f]*\)',/\1/p"	\
	    chromium.DEPS) ;						\
	test -n "$$v8_v" ;						\
	v8_raw=${_V8_RAW}/$$v8_v ;					\
	v8_deps=$$v8_raw/DEPS?format=TEXT ;				\
	ftp -VMo DEPS.b64 "$$v8_deps" ;					\
	openssl enc -base64 -d -A -in DEPS.b64 -out DEPS ;		\
	dep_sha() {							\
		printf "%s=\t%s\n" "$$1" $$(grep -A3 "^  '$$2':"	\
		    DEPS | awk -F"'" '/@/ {print $$(NF - 1); exit}') ;	\
	} ;								\
	dep_var() {							\
		printf "%s=\t%s\n" "$$1" $$(sed -n			\
		    "s/^  '$$2': '\([0-9a-f]*\)',/\1/p" DEPS) ;		\
	} ;								\
	dep_git_revision() {						\
		printf "%s=\t%s\n" "$$1" $$(sed -n			\
		    "s/^  '$$2': 'git_revision:\([0-9a-f]*\)',/\1/p"	\
		    DEPS) ;						\
	} ;								\
	wasm_hash() {							\
		_h=$$(grep -A12 "'name': '$$2'" DEPS) ;			\
		_s=$$(printf "%s\n" "$$_h" |				\
		    sed -n "s/.*'-s', '\([^']*\)'.*/\1/p") ;		\
		ftp -VMo "$$1.sha1.b64" "$$v8_raw/$$_s?format=TEXT" ;	\
		openssl enc -base64 -d -A -in "$$1.sha1.b64"		\
		    -out "$$1.sha1" ;					\
		printf "%s_H=\t%s\n" "$$1" $$(sed -n '1p' "$$1.sha1") ;	\
	} ;								\
	printf "#%s\n" "$$chromium_deps" ;				\
	printf "V8_V=\t\t\t%s\n" "$$v8_v" ;				\
	printf "# %s\n" "$$v8_deps" ;					\
	dep_sha BUILD_V build ;						\
	dep_sha BUILDTOOLS_V buildtools ;				\
	dep_git_revision GN_V gn_version ;				\
	dep_sha ABSEIL_V third_party/abseil-cpp ;			\
	dep_sha SIMDUTF_V third_party/simdutf ;				\
	dep_var PARTITION_ALLOC_V partition_alloc_version ;		\
	dep_sha ICU_V third_party/icu ;					\
	dep_sha PROTOBUF_V third_party/protobuf ;			\
	dep_sha PROTOC_WRAPPER_V tools/protoc_wrapper ;			\
	dep_sha FUZZTEST_V third_party/fuzztest ;			\
	dep_sha FUZZTEST_SRC_V third_party/fuzztest/src ;		\
	dep_sha GOOGLETEST_V third_party/googletest/src ;		\
	dep_sha DRAGONBOX_V third_party/dragonbox/src ;			\
	dep_sha FP16_V third_party/fp16/src ;				\
	dep_sha FASTFLOAT_V third_party/fast_float/src ;		\
	dep_sha HIGHWAY_V third_party/highway/src ;			\
	dep_sha JSONCPP_V third_party/jsoncpp/source ;			\
	dep_sha RE2_V third_party/re2/src ;				\
	dep_sha ZLIB_V third_party/zlib ;				\
	dep_sha LIBCXX_V third_party/libc++/src ;			\
	dep_sha LIBCXXABI_V third_party/libc++abi/src ;			\
	dep_sha LIBUNWIND_V third_party/libunwind/src ;			\
	dep_sha LLVM_LIBC_V third_party/llvm-libc/src ;			\
	printf "# wasm archives checked by tools/make-v8.sh\n" ;	\
	wasm_hash WASM_JS wasm_js ;					\
	wasm_hash WASM_SPEC wasm_spec_tests

chromium-patches:
	@${MAKE} extract
	# cvs co -D "${_CHROMIUM_PATCH_DATE}" -d chromium ports/www/chromium
	# remember to update _CHROMIUM_PATCH_DATE if targeted version change
	@if [ -d ${_TMP}/chromium ]; then				\
		echo "${_TMP}/chromium exists, skip cvs co" ;		\
	else								\
		mkdir -p ${_TMP} && cd ${_TMP} &&			\
		cvs co -D "${_CHROMIUM_PATCH_DATE}" -d chromium		\
		    ports/www/chromium ;				\
	fi
	# rebase chromium patches into the standalone V8 tree
	rm -rf ${_TMP}/patches/chromium*
	mkdir -p ${_TMP}/patches/chromium{,.rej,.miss,.new,.tmp,.orig}
	@for p in ${_TMP}/chromium/patches/patch-*; do			\
		[ -f $${p} ] || continue ;				\
		b=$$(basename $${p}) ;					\
		orig=$$(grep -m1 'Index: ' $${p} | sed -e 's/.*: //') ;	\
		pp=${_TMP}/patches/chromium.tmp/$${b} ;			\
		case "$${orig}" in					\
		v8/*)							\
			f=$${orig#v8/} ;				\
			sed -e "s|^\(Index: \)v8/|\1|"			\
			    -e "s|^\(--- \)v8/|\1|"			\
			    -e "s|^\(+++ \)v8/|\1|"			\
			    $${p} > $${pp} ;;				\
		base/allocator/partition_allocator/*)			\
			_from=base/allocator/partition_allocator ;	\
			_to=third_party/partition_alloc ;		\
			f=$${_to}/$${orig#$${_from}/} ;			\
			sed -E						\
			    "s|^(Index: |--- |\+\+\+ )$${_from}/|\1$${_to}/|" \
			    $${p} > $${pp} ;;				\
		*)							\
			f=$${orig} ;					\
			cp $${p} $${pp} ;;				\
		esac ;							\
		if grep -q "@@ -0,0" $${pp}; then			\
			cp $${pp} ${_TMP}/patches/chromium/ ;		\
			cp $${pp} ${_TMP}/patches/chromium.new/ ;	\
		elif [ -f "${WRKSRC}/$${f}" ]; then			\
			${PATCH} ${PATCH_DIST_ARGS} -sfC		\
			    -z .orig.chromium				\
			    -d ${WRKSRC} < $${pp} >/dev/null 2>&1 &&	\
			cp $${pp} ${_TMP}/patches/chromium/ ||		\
			cp $${pp} ${_TMP}/patches/chromium.rej/ ;	\
		else							\
			echo "missing $${orig} -> ${WRKSRC}/$${f}" ;	\
			cp $${pp} ${_TMP}/patches/chromium.miss/ ;	\
		fi ;							\
	done
	@for p in ${_TMP}/patches/chromium.rej/patch-*; do		\
		[ -f $${p} ] || continue ;				\
		b=$$(basename $${p}) ;					\
		f=$$(grep -m1 'Index: ' $${p} | sed -e 's/.*: //') ;	\
		o=${_TMP}/patches/chromium.orig/$${b} ;		\
		if [ -f "${WRKSRC}/$${f}.orig.chromium" ]; then		\
			rm -rf $${o} ;					\
			mkdir -p $${o}/$${f%/*} ;			\
			cp "${WRKSRC}/$${f}.orig.chromium" $${o}/$${f} ;\
			if ${PATCH} ${PATCH_DIST_ARGS} -sfC		\
			    -d $${o} < $${p} >/dev/null 2>&1; then	\
				echo "valid on .orig* ${WRKSRC}/$${f}" ;\
				cp $${p} ${_TMP}/patches/chromium/ ;	\
				rm -f $${p} ;				\
			fi ;						\
		fi ;							\
	done
	@echo "rejected:"
	@ls ${_TMP}/patches/chromium.rej
	# if ok, copy ${_TMP}/patches/chromium into port && make clean

.include <bsd.port.mk>
