diff --git a/Mk/Scripts/electron-create-mtree.sh b/Mk/Scripts/npm-create-mtree.sh similarity index 76% rename from Mk/Scripts/electron-create-mtree.sh rename to Mk/Scripts/npm-create-mtree.sh index 6e213f0d5b23..44e33462b9c9 100644 --- a/Mk/Scripts/electron-create-mtree.sh +++ b/Mk/Scripts/npm-create-mtree.sh @@ -1,34 +1,34 @@ #!/bin/sh # # MAINTAINER: tagattie@FreeBSD.org PATH=/bin:/usr/bin:/usr/sbin set -e set -o pipefail -[ -n "${DEBUG_MK_SCRIPTS}" -o -n "${DEBUG_MK_SCRIPTS_ELECTRON_CREATE_MTREE}" ] && set -x +[ -n "${DEBUG_MK_SCRIPTS}" -o -n "${DEBUG_MK_SCRIPTS_NPM_CREATE_MTREE}" ] && set -x PREFETCH_TIMESTAMP=61171200 # 1971-12-10 00:00:00 GMT set -u usage() { cat <[,ARGS] -# Valid ARGS: , build, run, test, env +# Usage: USES=electron:[,arg,...] +# Valid ARGS: , build, run, test # -# : A specific major version of Electron the port is based on. -# The port must specify exactly a single major version. +# : A major version of Electron the port is based on. The port must +# specify exactly a single major version. # build: Electron is needed at build time. Adds it to BUILD_DEPENDS. # run: Electron is needed at run time. Adds it to RUN_DEPENDS. # test: Electron is needed at test time. Adds it to TEST_DEPENDS. -# env: Electron is not needed at any of build, run, or test time. -# However, the port needs USE_ELECTRON features. # -# NOTE 1: {build, run, test} and env are mutually exclusive. If the port -# specifies both of them, env takes precedence. -# -# NOTE 2: If the port specifies none of build, run or test, we assume the port +# NOTE: If the port specifies none of build, run, or test, we assume the port # requires all those dependencies. # # Variables, which may be set by the port: # -# USE_ELECTRON: A list of additional features and functionalities to -# enable. Supported features are: -# -# npm: A node package manager the port uses. -# Supported package managers are: -# -# npm: The port uses NPM as package manager. -# yarn1: The port uses Yarn (v1) as package manager. -# yarn2: The port uses Yarn (v2 or v3) as package manager. -# yarn4: The port uses Yarn (v4+) as package manager. -# pnpm: The port uses PNPM as package manager. -# -# NOTE: The port must specify exactly a single package manager. -# Multiple package managers cannot be specified. -# -# Other valid arguments are: -# -# fetch, extract, build, run, and test, -# -# each of which corresponds to respective dependency. If the port -# does not specify any of those dependencies, we assume only -# build time dependency is required. +# USE_ELECTRON: A list of additional features and functionalities to enable. +# Supported features are: # # appbuilder: An app-builder version the port uses. Supported # arguments are: # # release: The port uses released version of app-builder and add # devel/app-builder to BUILD_DEPENDS. # devel: The port uses development version of app-builder and add # devel/app-builder-devel to BUILD_DEPENDS. # # NOTE: If the port specifies none of those arguments, we assume # release has been specified. # -# prefetch: Downloads node modules the port uses according to the -# pre-stored package.json (and package-lock.json, -# yarn.lock, or pnpm-lock.yaml depending on the node -# package manager used) in PKGJSONSDIR. Downloaded node -# modules are archived into a single tarball as one of -# the DISTFILES. -# -# NOTE 1: If the source directory of the port has other relevant -# files than package.json and lockfile, the relevant files must -# also be copied into PKGJSONSDIR. (Examples of relevant files -# includes .npmrc, .yarnrc, and pnpm-workspace.yaml.) -# -# NOTE 2: If the source directory of the port contains multiple -# package.json's and/or lockfiles, all files needed for generating -# node modules archive must be copied into PKGJSONSDIR with -# directory hierarchy preserved. -# -# extract: Installs the prefetched node modules into the port's -# working source directory. -# # rebuild: Rebuilds native node modules against nodejs or electron. # Supported arguments are: # # nodejs: Rebuilds native node modules against the version of # nodejs installed before pre-build phase so that nodejs # can execute the native modules during build. # electron: Rebuilds native node modules against the version of # electron the port uses before do-build phase so that # the native modules can be executed with electron on run # time. # # NOTE: If the port specifies none of those arguments, we assume # only electron has been specified. # # build: Prepares an electron application in a distributable # format using the specified package builder as an # argument. Supported arguments are: # # builder: Uses electron-builder for packaging. # forge: Uses electron-forge for packaging. # packager: Uses electron-packager for packaging. # # NOTE: The port must specify exactly a single argument. Multiple # package builders cannot be specified. # -# NPM_VER: A version of node package manager the port uses. If yarn -# 2 or later, or pnpm is used for the package manager, the -# framework requires the variable to be set so that it can -# bootstrap the correct version of package manager. -# -# It is usually specified as the key "packageManager" in -# package.json and the framework tries to automatically -# detect the version. Auto-detection can be overridden by -# manually specifying the value in Makefile. -# # UPSTREAM_ELECTRON_VER: # UPSTREAM_CHROMEDRIVER_VER: # UPSTREAM_MKSNAPSHOT_VER: -# Electron, chromedriver, and mksnapshot versions the port -# depends on. Those versions are usually specified in -# either package-lock.json, yarn.lock, or pnpm-lock.yaml -# file in the port's source directory. -# -# The build process tries to automatically detect those -# versions so the port does not usually have to specify -# the values. Auto-detection can be overridden by manually -# specifying the values in Makefile. -# -# The build process will generate a zip archive and a -# checksum file of electron/chromedriver/mksnapshot to -# prevent the build phase from trying to download binary -# distribution files from GitHub. -# -# ELECTRON_MAKE_FLAGS: Additional command-line flags to pass to the specified -# package builder when build feature is used. The default -# flags are defined in this file. +# Electron, chromedriver, and mksnapshot versions the port depends +# on. Those versions are usually specified in either +# package-lock.json, yarn.lock, or pnpm-lock.yaml file in the +# port's source directory. +# +# The build process tries to automatically detect those versions +# so the port does not usually have to specify the values. +# Auto-detection can be overridden by manually specifying the +# values in Makefile. +# +# The build process will generate a zip archive and a checksum +# file of electron/chromedriver/mksnapshot to prevent the build +# phase from trying to download binary distribution files from +# GitHub. +# +# ELECTRON_MAKE_FLAGS: +# Additional command-line flags to pass to the specified package +# builder when build feature is used. The default flags are +# defined in this file. # # MAINTAINER: tagattie@FreeBSD.org .if !defined(_INCLUDE_USES_ELECTRON_MK) _INCLUDE_USES_ELECTRON_MK= yes -# Electron uses Node.js (actually a node package manager) for build -.include "${USESDIR}/nodejs.mk" +# Electron depends on Node.js package manager +.include "${USESDIR}/npm.mk" _VALID_ELECTRON_VERSIONS= 37 38 39 40 41 42 -_VALID_ELECTRON_FEATURES= npm appbuilder prefetch extract rebuild build -_VALID_ELECTRON_FEATURES_NPM= npm yarn1 yarn2 yarn4 pnpm +_VALID_ELECTRON_FEATURES= appbuilder rebuild build _VALID_ELECTRON_FEATURES_APPBUILDER=release devel _VALID_ELECTRON_FEATURES_REBUILD=nodejs electron _VALID_ELECTRON_FEATURES_BUILD= builder forge packager _ELECTRON_CMD_BASE= electron _ELECTRON_PORT_BASE= devel/electron _ELECTRON_DOWNLOAD_URL_BASE= https://github.com/electron/electron/releases/download -_NODEJS_PKGNAME= node${NODEJS_VERSION} -_NODEJS_PORT= www/node${NODEJS_VERSION} # Process USES=electron[:ARGS] # Detect build, run, test, or env dependency _ELECTRON_ARGS= ${electron_ARGS:S/,/ /g} . if ${_ELECTRON_ARGS:Mbuild} _ELECTRON_BUILD_DEP= yes _ELECTRON_ARGS:= ${_ELECTRON_ARGS:Nbuild} . endif . if ${_ELECTRON_ARGS:Mrun} _ELECTRON_RUN_DEP= yes _ELECTRON_ARGS:= ${_ELECTRON_ARGS:Nrun} . endif . if ${_ELECTRON_ARGS:Mtest} _ELECTRON_TEST_DEP= yes _ELECTRON_ARGS:= ${_ELECTRON_ARGS:Ntest} . endif -. if ${_ELECTRON_ARGS:Menv} -_ELECTRON_NO_DEP= yes -_ELECTRON_ARGS:= ${_ELECTRON_ARGS:Nenv} -. endif # If no dependencies are specified, assume build, run, and test are required . if !defined(_ELECTRON_BUILD_DEP) && !defined(_ELECTRON_RUN_DEP) && \ - !defined(_ELECTRON_TEST_DEP) && !defined(_ELECTRON_NO_DEP) + !defined(_ELECTRON_TEST_DEP) _ELECTRON_BUILD_DEP= yes _ELECTRON_RUN_DEP= yes _ELECTRON_TEST_DEP= yes . endif -# Now _ELECTRON_ARGS should contain a single major version unless env is set -. if !defined(_ELECTRON_NO_DEP) -. if ${_VALID_ELECTRON_VERSIONS:M${_ELECTRON_ARGS}} +# Now _ELECTRON_ARGS should contain a major version of electron +. if ${_VALID_ELECTRON_VERSIONS:M${_ELECTRON_ARGS}} _ELECTRON_VERSION= ${_ELECTRON_ARGS} _ELECTRON_PORTDIR= ${_ELECTRON_PORT_BASE}${_ELECTRON_VERSION} . include "${PORTSDIR}/${_ELECTRON_PORTDIR}/Makefile.version" -. elif empty(_ELECTRON_ARGS) +. elif empty(_ELECTRON_ARGS) IGNORE= does not specify a major version of electron with USES=electron -. else +. else IGNORE= specifies unknown USES=electron arguments: ${_ELECTRON_ARGS} -. endif . endif # Detect features used with USE_ELECTRON . for var in ${USE_ELECTRON} . if empty(_VALID_ELECTRON_FEATURES:M${var:C/\:.*//}) _INVALID_ELECTRON_FEATURES+= ${var} . endif . endfor . if !empty(_INVALID_ELECTRON_FEATURES) IGNORE= uses unknown USE_ELECTRON features: ${_INVALID_ELECTRON_FEATURES} . endif # Make each individual feature available as _ELECTRON_FEATURE_ . for var in ${USE_ELECTRON} _ELECTRON_FEATURE_${var:C/\:.*//:tu}= ${var} . endfor -. if !defined(_ELECTRON_FEATURE_NPM) -IGNORE= does not specify a single node package manager with USE_ELECTRON=npm -. endif - -# Process USE_ELECTRON=npm[:ARGS] -# Detect fetch, extract, build, run, or test dependency -_NODEJS_NPM?= -. if defined(_ELECTRON_FEATURE_NPM) -_ELECTRON_FEATURE_NPM:= ${_ELECTRON_FEATURE_NPM:S/,/ /g} -. if ${_ELECTRON_FEATURE_NPM:Mfetch} -_ELECTRON_FEATURE_NPM_FETCH= yes -_ELECTRON_FEATURE_NPM:= ${_ELECTRON_FEATURE_NPM:Nfetch} -. endif -. if ${_ELECTRON_FEATURE_NPM:Mextract} -_ELECTRON_FEATURE_NPM_EXTRACT= yes -_ELECTRON_FEATURE_NPM:= ${_ELECTRON_FEATURE_NPM:Nextract} -. endif -. if ${_ELECTRON_FEATURE_NPM:Mbuild} -_ELECTRON_FEATURE_NPM_BUILD= yes -_ELECTRON_FEATURE_NPM:= ${_ELECTRON_FEATURE_NPM:Nbuild} -. endif -. if ${_ELECTRON_FEATURE_NPM:Mrun} -_ELECTRON_FEATURE_NPM_RUN= yes -_ELECTRON_FEATURE_NPM:= ${_ELECTRON_FEATURE_NPM:Nrun} -. endif -. if ${_ELECTRON_FEATURE_NPM:Mtest} -_ELECTRON_FEATURE_NPM_TEST= yes -_ELECTRON_FEATURE_NPM:= ${_ELECTRON_FEATURE_NPM:Ntest} -. endif -# If no dependencies are specified, we assume only build dep is required -. if !defined(_ELECTRON_FEATURE_NPM_FETCH) && !defined(_ELECTRON_FEATURE_NPM_EXTRACT) && \ - !defined(_ELECTRON_FEATURE_NPM_BUILD) && !defined(_ELECTRON_FEATURE_NPM_RUN) && \ - !defined(_ELECTRON_FEATURE_NPM_TEST) -_ELECTRON_FEATURE_NPM_BUILD= yes -. endif -# Now _ELECTRON_FEATURE_NPM should contain a single package manager -. if ${_VALID_ELECTRON_FEATURES_NPM:M${_ELECTRON_FEATURE_NPM:C/^[^\:]*(\:|\$)//}} -_NODEJS_NPM= ${_ELECTRON_FEATURE_NPM:C/^[^\:]*(\:|\$)//} -. if ${_NODEJS_NPM} == npm -_NPM_PKGNAME= ${_NODEJS_NPM}${NODEJS_SUFFIX} -_NPM_PORTDIR= www/${_NODEJS_NPM}${NODEJS_SUFFIX} -. elif ${_NODEJS_NPM} == yarn1 -_NPM_PKGNAME= yarn${NODEJS_SUFFIX} -_NPM_PORTDIR= www/yarn${NODEJS_SUFFIX} -. endif -. elif empty(_ELECTRON_FEATURES_NPM) -IGNORE= does not specify a single node package manager with USE_ELECTRON=npm -. else -IGNORE= specifies unknown USE_ELECTRON=npm arguments: ${_ELECTRON_FEATURE_NPM} -. endif -. endif # Process USE_ELECTRON=appbuilder[:ARGS] -# Detect stable or devel argument of appbuilder feature +# Detect release or devel argument of appbuilder feature . if defined(_ELECTRON_FEATURE_APPBUILDER) _ELECTRON_FEATURE_APPBUILDER:= ${_ELECTRON_FEATURE_APPBUILDER:C/^[^\:]*(\:|\$)//} . if ${_ELECTRON_FEATURE_APPBUILDER:Mrelease} _ELECTRON_FEATURE_APPBUILDER_RELEASE= yes _ELECTRON_FEATURE_APPBUILDER:= ${_ELECTRON_FEATURE_APPBUILDER:Nrelease} . endif . if ${_ELECTRON_FEATURE_APPBUILDER:Mdevel} _ELECTRON_FEATURE_APPBUILDER_DEVEL= yes _ELECTRON_FEATURE_APPBUILDER:= ${_ELECTRON_FEATURE_APPBUILDER:Ndevel} . endif # If no arguments are specified, we assume release is specified . if !defined(_ELECTRON_FEATURE_APPBUILDER_RELEASE) && \ !defined(_ELECTRON_FEATURE_APPBUILDER_DEVEL) _ELECTRON_FEATURE_APPBUILDER_RELEASE= yes . endif . if !empty(_ELECTRON_FEATURE_APPBUILDER) IGNORE= specifies unknown USE_ELECTRON=appbuilder arguments: ${_ELECTRON_FEATURE_APPBUILDER} . endif . endif # Process USE_ELECTRON=rebuild[:ARGS] # Detect nodejs or electron argument of rebuild feature . if defined(_ELECTRON_FEATURE_REBUILD) _ELECTRON_FEATURE_REBUILD:= ${_ELECTRON_FEATURE_REBUILD:C/^[^\:]*(\:|\$)//:S/,/ /g} . if ${_ELECTRON_FEATURE_REBUILD:Mnodejs} _ELECTRON_FEATURE_REBUILD_NODEJS= yes _ELECTRON_FEATURE_REBUILD:= ${_ELECTRON_FEATURE_REBUILD:Nnodejs} . endif . if ${_ELECTRON_FEATURE_REBUILD:Melectron} _ELECTRON_FEATURE_REBUILD_ELECTRON= yes _ELECTRON_FEATURE_REBUILD:= ${_ELECTRON_FEATURE_REBUILD:Nelectron} . endif # If no arguments are specified, we assume electron is specified . if !defined(_ELECTRON_FEATURE_REBUILD_NODEJS) && \ !defined(_ELECTRON_FEATURE_REBUILD_ELECTRON) _ELECTRON_FEATURE_REBUILD_ELECTRON= yes . endif . if !empty(_ELECTRON_FEATURE_REBUILD) IGNORE= specifies unknown USE_ELECTRON=rebuild arguments: ${_ELECTRON_FEATURE_REBUILD} . endif . endif # Process USE_ELECTRON=build:ARG # Detect builder used with USE_ELECTRON=builder . if defined(_ELECTRON_FEATURE_BUILD) . if ${_VALID_ELECTRON_FEATURES_BUILD:M${_ELECTRON_FEATURE_BUILD:C/^[^\:]*(\:|\$)//}} _ELECTRON_FEATURE_BUILD:= ${_ELECTRON_FEATURE_BUILD:C/^[^\:]*(\:|\$)//} . else IGNORE= specifies unknown USE_ELECTRON=build arguments: ${_ELECTRON_FEATURE_BUILD} . endif . endif # Setup dependencies . for stage in BUILD RUN TEST -. if defined(_ELECTRON_${stage}_DEP) && ${_ELECTRON_${stage}_DEP} == yes +. if defined(_ELECTRON_${stage}_DEP) ${stage}_DEPENDS+= ${_ELECTRON_CMD_BASE}${ELECTRON_VER_MAJOR}:${_ELECTRON_PORTDIR} . endif . endfor -. for stage in FETCH EXTRACT BUILD RUN TEST -. if defined(_ELECTRON_FEATURE_NPM_${stage}) && ${_ELECTRON_FEATURE_NPM_${stage}} == yes -. if ${_NODEJS_NPM} == npm || ${_NODEJS_NPM} == yarn1 -${stage}_DEPENDS+= ${_NPM_PKGNAME}>0:${_NPM_PORTDIR} -. elif ${_NODEJS_NPM} == yarn2 || ${_NODEJS_NPM} == yarn4 || ${_NODEJS_NPM} == pnpm -${stage}_DEPENDS+= ${_NODEJS_PKGNAME}>0:${_NODEJS_PORT} -. endif -. endif -. endfor . if defined(_ELECTRON_FEATURE_APPBUILDER_RELEASE) && ${_ELECTRON_FEATURE_APPBUILDER_RELEASE} == yes BUILD_DEPENDS+= app-builder:devel/app-builder . elif defined(_ELECTRON_FEATURE_APPBUILDER_DEVEL) && ${_ELECTRON_FEATURE_APPBUILDER_DEVEL} == yes BUILD_DEPENDS+= app-builder:devel/app-builder-devel . endif -# Define variables related to node package manager -NPM_FETCH_FLAGS?= -NPM_EXTRACT_FLAGS?= -NPM_EXEC_FLAGS?= -NPM_REBUILD_FLAGS?= - -NPM_PKGFILE?= package.json -. if ${_NODEJS_NPM} == npm -NPM_LOCKFILE?= package-lock.json -NPM_MODULE_CACHE?= node_modules -NPM_CMDNAME?= npm -NPM_CACHE_SETUP_CMD?= ${DO_NADA} -NPM_FETCH_CMD?= ${NPM_CMDNAME} ci -NPM_FETCH_FLAGS+= --ignore-scripts --no-progress --no-audit --no-fund --no-update-notifier --loglevel=error -NPM_EXEC_CMD?= ${NPM_CMDNAME} exec -NPM_EXEC_FLAGS+= --no-update-notifier -NPM_REBUILD_CMD?= ${NPM_CMDNAME} rebuild -NPM_REBUILD_FLAGS+= --no-update-notifier -. elif ${_NODEJS_NPM:Myarn*} -NPM_LOCKFILE?= yarn.lock -NPM_MODULE_CACHE?= yarn-offline-cache -NPM_CMDNAME?= yarn -NPM_FETCH_CMD?= ${NPM_CMDNAME} install -NPM_EXTRACT_CMD?= ${NPM_CMDNAME} install -NPM_EXEC_CMD?= ${NPM_CMDNAME} exec -. if ${_NODEJS_NPM} == yarn1 -NPM_CACHE_SETUP_CMD?= ${ECHO_CMD} 'yarn-offline-mirror "./${NPM_MODULE_CACHE}"' >> .yarnrc -NPM_FETCH_FLAGS+= --frozen-lockfile --ignore-scripts --silent -NPM_EXTRACT_FLAGS+= ${NPM_FETCH_FLAGS} --offline -. elif ${_NODEJS_NPM} == yarn2 -NPM_CACHE_SETUP_CMD?= ${NPM_CMDNAME} config set cacheFolder "./${NPM_MODULE_CACHE}" -NPM_FETCH_FLAGS+= --immutable --mode=skip-build --silent -NPM_EXTRACT_SETUP_CMD?= ${SH} -c "${NPM_CMDNAME} config set enableNetwork false; \ - ${NPM_CMDNAME} config set enableInlineBuilds true" -NPM_EXTRACT_FLAGS+= ${NPM_FETCH_FLAGS} --immutable-cache -NPM_REBUILD_CMD?= ${NPM_CMDNAME} rebuild -. elif ${_NODEJS_NPM} == yarn4 -NPM_CACHE_SETUP_CMD?= ${SH} -c "${NPM_CMDNAME} config set enableGlobalCache false; \ - ${NPM_CMDNAME} config set cacheFolder \"./${NPM_MODULE_CACHE}\"" -NPM_FETCH_FLAGS+= --immutable --mode=skip-build --silent -NPM_EXTRACT_SETUP_CMD?= ${SH} -c "${NPM_CMDNAME} config set enableNetwork false; \ - ${NPM_CMDNAME} config set enableInlineBuilds true" -NPM_EXTRACT_FLAGS+= ${NPM_FETCH_FLAGS} --immutable-cache -NPM_REBUILD_CMD?= ${NPM_CMDNAME} rebuild -. endif -. elif ${_NODEJS_NPM} == pnpm -NPM_LOCKFILE?= pnpm-lock.yaml -NPM_MODULE_CACHE?= pnpm-store -NPM_CMDNAME?= pnpm -NPM_CACHE_SETUP_CMD?= ${DO_NADA} -NPM_FETCH_CMD?= ${NPM_CMDNAME} fetch -NPM_FETCH_FLAGS+= --frozen-lockfile --ignore-scripts --loglevel=error \ - --store-dir ${WRKDIR}/node-modules-cache/${NPM_MODULE_CACHE} -NPM_EXTRACT_CMD?= ${NPM_CMDNAME} install -NPM_EXTRACT_FLAGS+= ${NPM_FETCH_FLAGS} --offline -NPM_EXEC_CMD?= ${NPM_CMDNAME} exec -NPM_REBUILD_CMD?= ${NPM_CMDNAME} rebuild -. endif - -# Define user-accessible variables -JQ_CMD?= ${LOCALBASE}/bin/jq -YQ_CMD?= ${LOCALBASE}/bin/yq -APP_BUILDER_CMD?= ${LOCALBASE}/bin/app-builder - ELECTRON_ARCH= ${ARCH:S/aarch64/arm64/:S/amd64/x64/:S/i386/ia32/} - -PKGJSONSDIR?= ${FILESDIR}/packagejsons -NPM_VER?= -NPM_EXTRACT_WRKSRC?= ${WRKSRC} -NPM_REBUILD_WRKSRC_NODEJS?= ${WRKSRC} -NPM_REBUILD_WRKSRC_ELECTRON?= ${WRKSRC} - -# Check existence of package.json -_EXISTS_NPM_PKGFILE?= -. if exists(${PKGJSONSDIR}/${NPM_PKGFILE}) -_EXISTS_NPM_PKGFILE= 1 -. endif - -# If yarn 2+ or pnpm is used, we need to know the version of node package -# manager. It is usually specified as the key "packageManager", so try to -# automatically detect the version. -. if ${_NODEJS_NPM} == yarn2 || ${_NODEJS_NPM} == yarn4 || ${_NODEJS_NPM} == pnpm -. if ${_EXISTS_NPM_PKGFILE} == 1 && empty(NPM_VER) -NPM_VER!= ${CAT} ${PKGJSONSDIR}/${NPM_PKGFILE} | \ - ${TR} -d '\n\r\t' | ${SED} -e 's/ //g; s/"//g' | \ - ${SED} -E -e ' \ - /devEngines:\{packageManager:\{/ { \ - s/.*devEngines:\{packageManager:\{([^}]+)\}\}.*/\1/; \ - h; \ - s/.*name:([^,}]+).*/\1/p; \ - g; \ - s/.*version:([^+,}]+).*/@\1/p; \ - d; \ - }; \ - /packageManager:/ { \ - s/.*packageManager:([^+,}]+).*/\1/p; d; \ - }' | \ - ${CUT} -f 2 -d '@' -. endif -. if empty(NPM_VER) -IGNORE= does not specity version of ${NPM_CMDNAME} used for prefetching node modules -. endif - -_USES_fetch+= 490:electron-fetch-node-package-manager - -DISTFILES+= ${NPM_CMDNAME}-${NPM_VER}.tgz:prefetch -FETCH_DEPENDS+= ${_NODEJS_PKGNAME}>0:${_NODEJS_PORT} - -electron-fetch-node-package-manager: - @${ECHO_MSG} "===> Fetching and setting up ${NPM_CMDNAME} version ${NPM_VER}" - @${MKDIR} ${DISTDIR}/${DIST_SUBDIR} ${WRKDIR}/.bin - @${SETENV} ${MAKE_ENV} corepack enable --install-directory ${WRKDIR}/.bin - @if [ ! -f ${DISTDIR}/${DIST_SUBDIR}/${NPM_CMDNAME}-${NPM_VER}.tgz ]; then \ - cd ${WRKDIR} && \ - ${SETENV} ${MAKE_ENV} corepack pack ${NPM_CMDNAME}@${NPM_VER} && \ - ${TAR} -xzf corepack.tgz && \ - ${SETENV} SCRIPTSDIR=${SCRIPTSDIR} WRKDIR=${WRKDIR} \ - ${SH} ${SCRIPTSDIR}/electron-create-mtree.sh ${NPM_CMDNAME} > \ - ${NPM_CMDNAME}.mtree && \ - ${SETENV} LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 \ - ${TAR} -cz --options 'gzip:!timestamp' \ - -f ${DISTDIR}/${DIST_SUBDIR}/${NPM_CMDNAME}-${NPM_VER}.tgz @${NPM_CMDNAME}.mtree; \ - fi - @${SETENV} ${MAKE_ENV} corepack install -g ${DISTDIR}/${DIST_SUBDIR}/${NPM_CMDNAME}-${NPM_VER}.tgz -. endif - -# When prefetch feature is used, downloads node modules the port uses according -# to the pre-stored package.json. -. if defined(_ELECTRON_FEATURE_PREFETCH) -. if empty(_EXISTS_NPM_PKGFILE) -IGNORE= does not store ${NPM_PKGFILE} in ${PKGJSONSDIR} for prefetching node modules -. endif - -_USES_fetch+= 491:electron-fetch-node-modules \ - 492:electron-archive-node-modules - -_DISTFILE_prefetch= ${PKGNAMEPREFIX}${PORTNAME}${PKGNAMESUFFIX}-${DISTVERSION}-node-modules${EXTRACT_SUFX} -DISTFILES+= ${_DISTFILE_prefetch}:prefetch - -. if ${_NODEJS_NPM} == npm || ${_NODEJS_NPM} == yarn1 -FETCH_DEPENDS+= ${_NPM_PKGNAME}>0:${_NPM_PORTDIR} -. elif ${_NODEJS_NPM} == pnpm -FETCH_DEPENDS+= ${JQ_CMD}:textproc/jq -. if ${NPM_VER:R:R} >= 11 -FETCH_DEPENDS+= sqlite3:databases/sqlite3 -. endif -. endif - -electron-fetch-node-modules: - @${MKDIR} ${DISTDIR}/${DIST_SUBDIR} - @if [ ! -f ${DISTDIR}/${DIST_SUBDIR}/${_DISTFILE_prefetch} ]; then \ - ${ECHO_MSG} "===> Setting up node modules cache directory"; \ - ${MKDIR} ${WRKDIR}/node-modules-cache; \ - ${TAR} -cf - -C ${PKGJSONSDIR} . | ${TAR} -xf - -C ${WRKDIR}/node-modules-cache; \ - cd ${WRKDIR}/node-modules-cache && ${SETENV} ${MAKE_ENV} ${NPM_CACHE_SETUP_CMD}; \ - ${ECHO_MSG} "===> Prefetching node modules"; \ - for dir in `${FIND} ${WRKDIR}/node-modules-cache -type f -name ${NPM_LOCKFILE} -exec ${DIRNAME} {} ';'`; do \ - cd $${dir} && \ - ${SETENV} ${MAKE_ENV} ${NPM_FETCH_CMD} ${NPM_FETCH_FLAGS}; \ - ${RM} $${dir}/${NPM_MODULE_CACHE}/.gitignore; \ - done; \ - fi - -electron-archive-node-modules: -. if ${_NODEJS_NPM} == npm - @if [ ! -f ${DISTDIR}/${DIST_SUBDIR}/${_DISTFILE_prefetch} ] && [ -d ${WRKDIR}/node-modules-cache ]; then \ - ${ECHO_MSG} "===> Archiving prefetched node modules"; \ - for dir in `${FIND} -s ${WRKDIR}/node-modules-cache -type d -name ${NPM_MODULE_CACHE} -print | \ - ${GREP} -ve '${NPM_MODULE_CACHE}/.*/${NPM_MODULE_CACHE}'`; do \ - ${SETENV} SCRIPTSDIR=${SCRIPTSDIR} WRKDIR=${WRKDIR} \ - ${SH} ${SCRIPTSDIR}/electron-create-mtree.sh $${dir} >> \ - ${WRKDIR}/node-modules-cache.mtree; \ - done; \ - ${SETENV} LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 \ - ${TAR} -cz --options 'gzip:!timestamp' \ - -f ${DISTDIR}/${DIST_SUBDIR}/${_DISTFILE_prefetch} \ - -C ${WRKDIR} @node-modules-cache.mtree; \ - if [ ${TMPDIR} != ${WRKDIR} ]; then \ - ${RM} -r ${WRKDIR}; \ - fi; \ - fi -. elif ${_NODEJS_NPM:Myarn*} || ${_NODEJS_NPM} == pnpm -. if ${_NODEJS_NPM} == pnpm -. if ${NPM_VER:R:R} >= 11 - @if [ ! -f ${DISTDIR}/${DIST_SUBDIR}/${_DISTFILE_prefetch} ] && [ -d ${WRKDIR}/node-modules-cache ]; then \ - ${ECHO_MSG} "===> Normalizing timestamps and permissions of prefetched node modules"; \ - tmpdir=${WRKDIR}/pnpm_tmp; \ - input_db=${WRKDIR}/node-modules-cache/${NPM_MODULE_CACHE}/v11/index.db; \ - output_db=$${tmpdir}/index.db; \ - output_db_dump=${WRKDIR}/node-modules-cache/${NPM_MODULE_CACHE}/v11/index_dump.sql; \ - ${MKDIR} $${tmpdir}; \ - cd $${tmpdir} && ${SETENV} ${MAKE_ENV} ${NPM_CMDNAME} add --ignore-scripts --silent msgpackr; \ - sqlite3 $${input_db} \ - "SELECT writefile('$${tmpdir}/' || row_number() OVER (ORDER BY key ASC) || '.msgpack', data) FROM package_index;" > /dev/null; \ - sqlite3 $${input_db} \ - "SELECT key FROM package_index ORDER BY key ASC;" > $${tmpdir}/keys_list.txt; \ - counter=1; \ - while IFS= read -r key; do \ - ${PRINTF} "%s" "$${key}" > $${tmpdir}/$${counter}.key; \ - counter=$$((counter + 1)); \ - done < $${tmpdir}/keys_list.txt; \ - for file in $${tmpdir}/*.msgpack; do \ - base=$${file%.msgpack}; \ - node -e " \ - const fs = require('fs'); \ - const { Unpackr } = require('msgpackr'); \ - const unpackr = new Unpackr({}); \ - const buf = fs.readFileSync(0); \ - const data = unpackr.unpack(buf); \ - console.log(JSON.stringify(data, (key, value) => { \ - if (value instanceof Map) { \ - return { __type: 'Map', data: Array.from(value.entries()) }; \ - } \ - return value; \ - })); \ - " < $${file} > $${base}.msgpack.json; \ - ${JQ_CMD} -S ' \ - walk( \ - if type == "object" then \ - if has("checkedAt") then .checkedAt = 0 else . end | \ - if has("mode") then \ - if (.mode / 16 | floor) % 2 == 1 then .mode = .mode - 16 else . end \ - else \ - . \ - end \ - else \ - . \ - end \ - ) \ - ' $${base}.msgpack.json > $${base}.normalized.json; \ - node -e " \ - const fs = require('fs'); \ - const { Packr } = require('msgpackr'); \ - const packr = new Packr({ structuredClone: true }); \ - const rawJson = JSON.parse(fs.readFileSync(0, 'utf-8')); \ - const restoreMaps = (obj) => { \ - if (obj && typeof obj === 'object') { \ - if (obj.__type === 'Map') { \ - return new Map(obj.data.map(([k, v]) => [k, restoreMaps(v)])); \ - } \ - for (let k in obj) { \ - obj[k] = restoreMaps(obj[k]); \ - } \ - } \ - return obj; \ - }; \ - const restoredData = restoreMaps(rawJson); \ - process.stdout.write(packr.pack(restoredData)); \ - " < $${base}.normalized.json > $${base}.normalized.msgpack; \ - done; \ - sqlite3 $${output_db} \ - "CREATE TABLE package_index (key TEXT PRIMARY KEY, data BLOB) WITHOUT ROWID;" > /dev/null 2>&1; \ - sqlite3 $${output_db} \ - "PRAGMA page_size = 4096; PRAGMA journal_mode = DELETE; PRAGMA auto_vacuum = NONE; PRAGMA secure_delete = ON;" > /dev/null 2>&1; \ - total_files=$$((counter - 1)); \ - i=1; \ - while [ $${i} -le $${total_files} ]; do \ - real_key=`${CAT} $${tmpdir}/$${i}.key`; \ - { \ - ${PRINTF} "INSERT INTO package_index (key, data) VALUES ('%s', x'" "$${real_key}"; \ - hexdump -v -e '/1 "%02x"' $${tmpdir}/$${i}.normalized.msgpack; \ - ${PRINTF} "');\n"; \ - } | sqlite3 $${output_db}; \ - i=$$((i + 1)); \ - done; \ - sqlite3 $${output_db} "REINDEX; VACUUM;"; \ - sqlite3 $${output_db} ".dump" > $${output_db_dump}; \ - ${RM} $${input_db}; \ - fi -. else - @if [ ! -f ${DISTDIR}/${DIST_SUBDIR}/${_DISTFILE_prefetch} ] && [ -d ${WRKDIR}/node-modules-cache ]; then \ - ${ECHO_MSG} "===> Normalizing timestamps and permissions of prefetched node modules"; \ - ${FIND} ${WRKDIR}/node-modules-cache/${NPM_MODULE_CACHE} \ - -type f -name '*.json' -exec ${SH} -c ' \ - for f do \ - ${JQ_CMD} -c "walk(if type == \"object\" and has(\"checkedAt\") then .checkedAt = 0 else . end)" $${f} > $${f}.tmp && mv $${f}.tmp $${f}; \ - done \ - ' ${SH} {} ';'; \ - for dir in projects tmp; do \ - ${RM} -r ${WRKDIR}/node-modules-cache/${NPM_MODULE_CACHE}/*/$${dir}; \ - done; \ - fi -. endif -. endif - @if [ ! -f ${DISTDIR}/${DIST_SUBDIR}/${_DISTFILE_prefetch} ] && [ -d ${WRKDIR}/node-modules-cache ]; then \ - ${ECHO_MSG} "===> Archiving prefetched node modules"; \ - cd ${WRKDIR}/node-modules-cache && \ - ${SETENV} SCRIPTSDIR=${SCRIPTSDIR} WRKDIR=${WRKDIR} \ - ${SH} ${SCRIPTSDIR}/electron-create-mtree.sh ${NPM_MODULE_CACHE} > \ - node-modules-cache.mtree && \ - ${SETENV} LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 \ - ${TAR} -cz --options 'gzip:!timestamp' \ - -f ${DISTDIR}/${DIST_SUBDIR}/${_DISTFILE_prefetch} @node-modules-cache.mtree; \ - if [ ${TMPDIR} != ${WRKDIR} ]; then \ - ${RM} -r ${WRKDIR}; \ - fi; \ - fi -. endif -. endif # _FEATURE_ELECTRON_PREFETCH - -# When extract feature is used, installs the prefetched node modules into the -# port's working source directory. -. if defined(_ELECTRON_FEATURE_EXTRACT) -_USES_extract+= 600:electron-extract-node-package-manager \ - 601:electron-copy-package-file \ - 602:electron-install-node-modules - -. if ${_NODEJS_NPM} == yarn1 -EXTRACT_DEPENDS+= ${_NPM_PKGNAME}>0:${_NPM_PORTDIR} -. elif ${_NODEJS_NPM} == yarn2 || ${_NODEJS_NPM} == yarn4 || ${_NODEJS_NPM} == pnpm -EXTRACT_DEPENDS+= ${_NODEJS_PKGNAME}>0:${_NODEJS_PORT} -. endif -. if ${_NODEJS_NPM} == pnpm && ${NPM_VER:R:R} >= 11 -EXTRACT_DEPENDS+= sqlite3:databases/sqlite3 -. if ${NPM_VER:R} >= 11.3 -NPM_EXTRACT_FLAGS+= --trust-lockfile -. endif -. endif - -electron-extract-node-package-manager: -. if ${_NODEJS_NPM} == yarn2 || ${_NODEJS_NPM} == yarn4 || ${_NODEJS_NPM} == pnpm - @${ECHO_MSG} "===> Setting up ${NPM_CMDNAME} version ${NPM_VER}" - @${MKDIR} ${WRKDIR}/.bin - @${SETENV} ${MAKE_ENV} corepack enable --install-directory ${WRKDIR}/.bin - @${SETENV} ${MAKE_ENV} corepack install -g ${DISTDIR}/${DIST_SUBDIR}/${NPM_CMDNAME}-${NPM_VER}.tgz -. else - @${DO_NADA} -. endif - -electron-copy-package-file: -. if ${_EXISTS_NPM_PKGFILE} == 1 - @${ECHO_MSG} "===> Copying ${NPM_PKGFILE} and ${NPM_LOCKFILE} to ${NPM_EXTRACT_WRKSRC}" - @for f in `${FIND} ${PKGJSONSDIR} -type f \( -name ${NPM_PKGFILE} -o -name ${NPM_LOCKFILE} \) -print | ${SED} -e 's|${PKGJSONSDIR}/||'`; do \ - ${MKDIR} -p `${DIRNAME} ${NPM_EXTRACT_WRKSRC}/$${f}`; \ - if [ -f ${NPM_EXTRACT_WRKSRC}/$${f} ]; then \ - ${MV} -f ${NPM_EXTRACT_WRKSRC}/$${f} ${NPM_EXTRACT_WRKSRC}/$${f}.bak; \ - fi; \ - ${CP} ${PKGJSONSDIR}/$${f} ${NPM_EXTRACT_WRKSRC}/$${f}; \ - done -. endif - -electron-install-node-modules: -. if ${_NODEJS_NPM} == npm - @${ECHO_MSG} "===> Moving prefetched node modules to ${NPM_EXTRACT_WRKSRC}" - @if [ -d ${EXTRACT_WRKDIR}/node-modules-cache ]; then \ - for dir in `${FIND} -s ${EXTRACT_WRKDIR}/node-modules-cache -type d -name ${NPM_MODULE_CACHE} -print | \ - ${GREP} -ve '${NPM_MODULE_CACHE}/.*/${NPM_MODULE_CACHE}'`; do \ - ${MV} $${dir} `${ECHO_CMD} $${dir} | sed -e 's|${EXTRACT_WRKDIR}/node-modules-cache|${NPM_EXTRACT_WRKSRC}|'`; \ - done; \ - fi -. elif ${_NODEJS_NPM:Myarn*} - @${ECHO_MSG} "===> Installing node modules from prefetched cache" - @if [ -d ${EXTRACT_WRKDIR}/${NPM_MODULE_CACHE} ]; then \ - ${MV} ${EXTRACT_WRKDIR}/${NPM_MODULE_CACHE} ${NPM_EXTRACT_WRKSRC}; \ - fi - @cd ${NPM_EXTRACT_WRKSRC} && ${SETENV} ${MAKE_ENV} ${NPM_CACHE_SETUP_CMD} -. if defined(NPM_EXTRACT_SETUP_CMD) && !empty(NPM_EXTRACT_SETUP_CMD) - @${ECHO_MSG} "===> Setting up ${NPM_CMDNAME} command options" - @cd ${NPM_EXTRACT_WRKSRC} && ${SETENV} ${MAKE_ENV} ${NPM_EXTRACT_SETUP_CMD} -. endif - @if [ -d ${PKGJSONSDIR} ]; then \ - cd ${PKGJSONSDIR} && \ - for dir in `${FIND} . -type f -name ${NPM_LOCKFILE} -exec ${DIRNAME} {} ';'`; do \ - cd ${NPM_EXTRACT_WRKSRC}/$${dir} && \ - ${SETENV} ${MAKE_ENV} ${NPM_EXTRACT_CMD} ${NPM_EXTRACT_FLAGS}; \ - done; \ - else \ - cd ${NPM_EXTRACT_WRKSRC} && \ - ${SETENV} ${MAKE_ENV} ${NPM_EXTRACT_CMD} ${NPM_EXTRACT_FLAGS}; \ - fi -. elif ${_NODEJS_NPM} == pnpm - @${ECHO_MSG} "===> Installing node modules from prefetched cache" -. if ${NPM_VER:R:R} >= 11 - @if [ -d ${EXTRACT_WRKDIR}/${NPM_MODULE_CACHE} ]; then \ - normalized_db_dump=${EXTRACT_WRKDIR}/${NPM_MODULE_CACHE}/v11/index_dump.sql; \ - index_db=${EXTRACT_WRKDIR}/${NPM_MODULE_CACHE}/v11/index.db; \ - sqlite3 $${index_db} < $${normalized_db_dump}; \ - fi -. endif - @if [ -d ${EXTRACT_WRKDIR}/${NPM_MODULE_CACHE} ]; then \ - ${MKDIR} ${WRKDIR}/node-modules-cache; \ - ${MV} ${EXTRACT_WRKDIR}/${NPM_MODULE_CACHE} ${WRKDIR}/node-modules-cache; \ - fi - @if [ -d ${PKGJSONSDIR} ]; then \ - cd ${PKGJSONSDIR} && \ - for dir in `${FIND} . -type f -name ${NPM_LOCKFILE} -exec ${DIRNAME} {} ';'`; do \ - cd ${NPM_EXTRACT_WRKSRC}/$${dir} && \ - ${SETENV} ${MAKE_ENV} ${NPM_EXTRACT_CMD} ${NPM_EXTRACT_FLAGS}; \ - done; \ - else \ - cd ${NPM_EXTRACT_WRKSRC} && \ - ${SETENV} ${MAKE_ENV} ${NPM_EXTRACT_CMD} ${NPM_EXTRACT_FLAGS}; \ - fi -. endif -. endif # _ELECTRON_FEATURE_EXTRACT +ELECTRON_REBUILD_WRKSRC_NODEJS?= ${WRKSRC} +ELECTRON_REBUILD_WRKSRC_ELECTRON?= ${WRKSRC} # Always generate distribution zip files from installed electron package # directory. This is necessary to prevent the build phase from downloading # binary distribution files from GitHub. _USES_build+= 290:electron-generate-electron-zip BUILD_DEPENDS+= zip:archivers/zip -. if ${_NODEJS_NPM} == npm -BUILD_DEPENDS+= ${JQ_CMD}:textproc/jq -. elif ${_NODEJS_NPM} == yarn2 || ${_NODEJS_NPM} == yarn4 || ${_NODEJS_NPM} == pnpm -BUILD_DEPENDS+= ${YQ_CMD}:textproc/yq +. if ${NPM_NAME} == npm +BUILD_DEPENDS+= jq:textproc/jq +. elif ${NPM_NAME} == yarn2 || ${NPM_NAME} == yarn4 || ${NPM_NAME} == pnpm +BUILD_DEPENDS+= yq:textproc/yq . endif . if !defined(UPSTREAM_ELECTRON_VER) -. if ${_EXISTS_NPM_PKGFILE} == 1 -. if ${_NODEJS_NPM} == npm && exists(${JQ_CMD}) -UPSTREAM_ELECTRON_VER!= ${JQ_CMD} -r \ +. if ${_NPM_EXISTS_PKGFILE} == yes +. if ${NPM_NAME} == npm && exists(${LOCALBASE}/bin/jq) +UPSTREAM_ELECTRON_VER!= jq -r \ '.packages | \ to_entries | \ map(if(.key | test("electron$$")) then .value.version else empty end) | \ .[]' ${PKGJSONSDIR}/${NPM_LOCKFILE} | \ ${SORT} -n | \ ${TAIL} -n 1 -. elif ${_NODEJS_NPM} == yarn1 +. elif ${NPM_NAME} == yarn1 UPSTREAM_ELECTRON_VER!= ${GREP} -e 'resolved.*/electron/' ${PKGJSONSDIR}/${NPM_LOCKFILE} | \ ${AWK} -F- '{print $$NF}' | \ ${SED} -E 's/\.[a-z]+.*$$//' | \ ${SORT} -n | \ ${TAIL} -n 1 -. elif (${_NODEJS_NPM} == yarn2 || ${_NODEJS_NPM} == yarn4) && exists(${YQ_CMD}) -UPSTREAM_ELECTRON_VER!= ${YQ_CMD} -r \ +. elif (${NPM_NAME} == yarn2 || ${NPM_NAME} == yarn4) && exists(${LOCALBASE}/bin/yq) +UPSTREAM_ELECTRON_VER!= yq -r \ '. | \ to_entries | \ map(if(.key | test("^electron@")) then .value.version else empty end) | \ .[]' ${PKGJSONSDIR}/${NPM_LOCKFILE} | \ ${SORT} -n | \ ${TAIL} -n 1 -. elif ${_NODEJS_NPM} == pnpm && exists(${YQ_CMD}) -UPSTREAM_ELECTRON_VER!= ${YQ_CMD} -r \ +. elif ${NPM_NAME} == pnpm && exists(${LOCALBASE}/bin/yq) +UPSTREAM_ELECTRON_VER!= yq -r \ '.packages | \ to_entries | \ map(if(.key | test("^electron@")) then .key else empty end) | \ .[]' ${PKGJSONSDIR}/${NPM_LOCKFILE} | \ ${CUT} -f 2 -d '@' | \ ${SORT} -n | \ ${TAIL} -n 1 . endif . endif . endif ELECTRON_DOWNLOAD_URL= ${_ELECTRON_DOWNLOAD_URL_BASE}/v${UPSTREAM_ELECTRON_VER} ELECTRON_DOWNLOAD_URL_HASH!= ${SHA256} -q -s ${ELECTRON_DOWNLOAD_URL} ELECTRON_DOWNLOAD_CACHE_DIR= .cache/electron/${ELECTRON_DOWNLOAD_URL_HASH} . if !defined(UPSTREAM_CHROMEDRIVER_VER) -. if ${_EXISTS_NPM_PKGFILE} == 1 +. if ${_NPM_EXISTS_PKGFILE} == yes UPSTREAM_CHROMEDRIVER_VER!= ${GREP} -e 'resolved.*/electron-chromedriver/' ${PKGJSONSDIR}/${NPM_LOCKFILE} | \ ${HEAD} -n 1 | ${AWK} -F- '{print $$NF}' | ${SED} -E 's/\.[a-z]+.*$$//' . endif . endif CHROMEDRIVER_DOWNLOAD_URL= ${_ELECTRON_DOWNLOAD_URL_BASE}/v${UPSTREAM_CHROMEDRIVER_VER} CHROMEDRIVER_DOWNLOAD_URL_HASH!=${SHA256} -q -s ${CHROMEDRIVER_DOWNLOAD_URL} CHROMEDRIVER_DOWNLOAD_CACHE_DIR=.cache/electron/${CHROMEDRIVER_DOWNLOAD_URL_HASH} . if !defined(UPSTREAM_MKSNAPSHOT_VER) -. if ${_EXISTS_NPM_PKGFILE} == 1 +. if ${_NPM_EXISTS_PKGFILE} == yes UPSTREAM_MKSNAPSHOT_VER!= ${GREP} -e 'resolved.*/electron-mksnapshot/' ${PKGJSONSDIR}/${NPM_LOCKFILE} | \ ${HEAD} -n 1 | ${AWK} -F- '{print $$NF}' | ${SED} -E 's/\.[a-z]+.*$$//' . endif . endif MKSNAPSHOT_DOWNLOAD_URL= ${_ELECTRON_DOWNLOAD_URL_BASE}/v${UPSTREAM_MKSNAPSHOT_VER} MKSNAPSHOT_DOWNLOAD_URL_HASH!= ${SHA256} -q -s ${MKSNAPSHOT_DOWNLOAD_URL} MKSNAPSHOT_DOWNLOAD_CACHE_DIR= .cache/electron/${MKSNAPSHOT_DOWNLOAD_URL_HASH} electron-generate-electron-zip: @if [ -d ${LOCALBASE}/share/electron${ELECTRON_VER_MAJOR} ]; then \ ${ECHO_MSG} "===> Preparing distribution files of electron/chromedriver/mksnapshot"; \ ${RM} -r ${WRKDIR}/electron-dist; \ ${MKDIR} ${WRKDIR}/electron-dist; \ ${TAR} -cf - -C ${LOCALBASE}/share/electron${ELECTRON_VER_MAJOR} . | \ ${TAR} -xf - -C ${WRKDIR}/electron-dist; \ cd ${WRKDIR}/electron-dist && \ ${FIND} . -type f -perm ${BINMODE} -exec ${CHMOD} 755 {} ';'; \ ${MKDIR} ${WRKDIR}/${ELECTRON_DOWNLOAD_CACHE_DIR}; \ cd ${WRKDIR}/electron-dist && \ zip -q -r ${WRKDIR}/${ELECTRON_DOWNLOAD_CACHE_DIR}/electron-v${UPSTREAM_ELECTRON_VER}-linux-${ELECTRON_ARCH}.zip .; \ cd ${WRKDIR}/${ELECTRON_DOWNLOAD_CACHE_DIR} && \ ${SHA256} -r *.zip | \ ${SED} -e 's/ / */' > SHASUMS256.txt-${UPSTREAM_ELECTRON_VER}; \ cd ${WRKDIR}/${ELECTRON_DOWNLOAD_CACHE_DIR} && \ ${SHA256} -r *.zip | \ ${SED} -e 's/ / */' > SHASUMS256.txt; \ fi . if defined(UPSTREAM_CHROMEDRIVER_VER) && !empty(UPSTREAM_CHROMEDRIVER_VER) @if [ -d ${LOCALBASE}/share/electron${ELECTRON_VER_MAJOR} ]; then \ ${MKDIR} ${WRKDIR}/${CHROMEDRIVER_DOWNLOAD_CACHE_DIR}; \ cd ${WRKDIR}/electron-dist && \ zip -q -r ${WRKDIR}/${CHROMEDRIVER_DOWNLOAD_CACHE_DIR}/chromedriver-v${UPSTREAM_CHROMEDRIVER_VER}-freebsd-${ELECTRON_ARCH}.zip .; \ cd ${WRKDIR}/${CHROMEDRIVER_DOWNLOAD_CACHE_DIR} && \ ${SHA256} -r *.zip | \ ${SED} -e 's/ / */' > SHASUMS256.txt-${UPSTREAM_CHROMEDRIVER_VER}; \ cd ${WRKDIR}/${CHROMEDRIVER_DOWNLOAD_CACHE_DIR} && \ ${SHA256} -r *.zip | \ ${SED} -e 's/ / */' > SHASUMS256.txt; \ fi . endif . if defined(UPSTREAM_MKSNAPSHOT_VER) && !empty(UPSTREAM_MKSNAPSHOT_VER) @if [ -d ${LOCALBASE}/share/electron${ELECTRON_VER_MAJOR} ]; then \ ${MKDIR} ${WRKDIR}/${MKSNAPSHOT_DOWNLOAD_CACHE_DIR}; \ cd ${WRKDIR}/electron-dist && \ zip -q -r ${WRKDIR}/${MKSNAPSHOT_DOWNLOAD_CACHE_DIR}/mksnapshot-v${UPSTREAM_MKSNAPSHOT_VER}-freebsd-${ELECTRON_ARCH}.zip .; \ cd ${WRKDIR}/${MKSNAPSHOT_DOWNLOAD_CACHE_DIR} && \ ${SHA256} -r *.zip | \ ${SED} -e 's/ / */' > SHASUMS256.txt-${UPSTREAM_MKSNAPSHOT_VER}; \ cd ${WRKDIR}/${MKSNAPSHOT_DOWNLOAD_CACHE_DIR} && \ ${SHA256} -r *.zip | \ ${SED} -e 's/ / */' > SHASUMS256.txt; \ fi . endif # When rebuild feature is used, rebuilds native node modules against nodejs or # electron. . if defined(_ELECTRON_FEATURE_REBUILD) _USES_build+= 291:electron-rebuild-native-node-modules-for-node \ 490:electron-rebuild-native-node-modules-for-electron -. if ${_NODEJS_NPM} == npm || ${_NODEJS_NPM} == yarn1 -BUILD_DEPENDS+= ${_NPM_PKGNAME}>0:${_NPM_PORTDIR} -. elif ${_NODEJS_NPM} == yarn2 || ${_NODEJS_NPM} == yarn4 || ${_NODEJS_NPM} == pnpm -BUILD_DEPENDS+= ${_NODEJS_PKGNAME}>0:${_NODEJS_PORT} -. endif -. if ${_NODEJS_NPM} == yarn1 +. if ${NPM_NAME} == yarn1 # jq is needed for detecting native node modules needing build -BUILD_DEPENDS+= ${JQ_CMD}:textproc/jq +BUILD_DEPENDS+= jq:textproc/jq # npm is needed for executing "npm rebuild" command BUILD_DEPENDS+= npm${NODEJS_SUFFIX}>0:www/npm${NODEJS_SUFFIX} . endif electron-rebuild-native-node-modules-for-node: . if defined(_ELECTRON_FEATURE_REBUILD_NODEJS) && \ ${_ELECTRON_FEATURE_REBUILD_NODEJS} == yes @${ECHO_MSG} "===> Rebuilding native node modules for nodejs" -. if ${_NODEJS_NPM} == yarn1 - @cd ${NPM_REBUILD_WRKSRC_NODEJS} && \ +. if ${NPM_NAME} == yarn1 + @cd ${ELECTRON_REBUILD_WRKSRC_NODEJS} && \ ${SETENV} ${MAKE_ENV} ${NODEJS_REBUILD_ENV} npm rebuild . else - @cd ${NPM_REBUILD_WRKSRC_NODEJS} && \ + @cd ${ELECTRON_REBUILD_WRKSRC_NODEJS} && \ ${SETENV} ${MAKE_ENV} ${NODEJS_REBUILD_ENV} ${NPM_CMDNAME} rebuild . endif . else @${DO_NADA} . endif electron-rebuild-native-node-modules-for-electron: . if defined(_ELECTRON_FEATURE_REBUILD_ELECTRON) && \ ${_ELECTRON_FEATURE_REBUILD_ELECTRON} == yes -. if ${_NODEJS_NPM} == pnpm - @for dir in `${APP_BUILDER_CMD} node-dep-tree --dir ${NPM_REBUILD_WRKSRC_ELECTRON} | ${JQ_CMD} -r '.[] | { dir: .dir, name: .deps[].name } | .dir + "/" + .name'`; do \ +. if ${NPM_NAME} == pnpm + @for dir in `app-builder node-dep-tree --dir ${ELECTRON_REBUILD_WRKSRC_ELECTRON} | jq -r '.[] | { dir: .dir, name: .deps[].name } | .dir + "/" + .name'`; do \ for subdir in `${FIND} $${dir} -type f -name binding.gyp -exec ${DIRNAME} {} ';' 2> /dev/null`; do \ cd $${subdir} && \ ${ECHO_MSG} "===> Rebuilding native node modules for electron in $${subdir}" && \ ${SETENV} ${MAKE_ENV} ${ELECTRON_REBUILD_ENV} ${NPM_REBUILD_CMD} ${NPM_REBUILD_FLAGS}; \ done \ done . else - @for dir in `${APP_BUILDER_CMD} node-dep-tree --dir ${NPM_REBUILD_WRKSRC_ELECTRON} | ${JQ_CMD} -r '.[] | { dir: .dir, name: .deps[].name } | .dir + "/" + .name'`; do \ + @for dir in `app-builder node-dep-tree --dir ${ELECTRON_REBUILD_WRKSRC_ELECTRON} | jq -r '.[] | { dir: .dir, name: .deps[].name } | .dir + "/" + .name'`; do \ for subdir in `${FIND} $${dir} -type f -name binding.gyp -exec ${DIRNAME} {} ';' 2> /dev/null`; do \ cd $${subdir} && \ ${ECHO_MSG} "===> Rebuilding native node modules for electron in $${subdir}" && \ ${SETENV} ${MAKE_ENV} ${ELECTRON_REBUILD_ENV} ${NPM_EXEC_CMD} ${NPM_EXEC_FLAGS} node-gyp rebuild; \ done \ done . endif . else @${DO_NADA} . endif . endif # _ELECTRON_FEATURE_REBUILD _USES_build+= 499:clean-up-backup-files clean-up-backup-files: @${ECHO_MSG} "===> Cleaning up backup files in ${WRKSRC}" @${FIND} ${WRKSRC} -type f \( -name '*.bak' -o -name '*.orig' \) -delete # When build feature is used, prepares an electron application in a # distributable format using the specified package builder. . if defined(_ELECTRON_FEATURE_BUILD) ELECTRON_MAKE_FLAGS?= . if ${_ELECTRON_FEATURE_BUILD} == builder ELECTRON_MAKE_CMD?= ${NPM_EXEC_CMD} ${NPM_EXEC_FLAGS} electron-builder ELECTRON_MAKE_FLAGS+= --linux \ --dir \ --publish never \ --config.npmRebuild=false \ --config.electronVersion=${ELECTRON_VER} \ --config.electronDist=${WRKDIR}/electron-dist DO_MAKE_BUILD= ${SETENV} ${MAKE_ENV} ${ELECTRON_MAKE_CMD} ${ELECTRON_MAKE_FLAGS} ELECTRON_BUILDER_APP_OUT_DIR= linux-${ARCH:S/aarch64/arm64-/:S/amd64//:S/i386/ia32-/}unpacked . elif ${_ELECTRON_FEATURE_BUILD} == packager ELECTRON_MAKE_CMD?= ${NPM_EXEC_CMD} ${NPM_EXEC_FLAGS} electron-packager ELECTRON_MAKE_FLAGS+= --platform=linux \ --no-download \ --electron-version=${ELECTRON_VER} \ --electron-zip-dir=${WRKDIR}/${ELECTRON_DOWNLOAD_CACHE_DIR} \ --prune \ --overwrite DO_MAKE_BUILD= ${SETENV} ${MAKE_ENV} ${ELECTRON_MAKE_CMD} . ${ELECTRON_MAKE_FLAGS} . elif ${_ELECTRON_FEATURE_BUILD} == forge ELECTRON_MAKE_CMD?= ${NPM_EXEC_CMD} ${NPM_EXEC_FLAGS} electron-forge package ELECTRON_MAKE_FLAGS+= --platform=linux DO_MAKE_BUILD= ${SETENV} ${MAKE_ENV} ${ELECTRON_MAKE_CMD} ${ELECTRON_MAKE_FLAGS} . endif -. if ${_NODEJS_NPM} == npm || ${_NODEJS_NPM} == yarn1 +. if ${NPM_NAME} == npm || ${NPM_NAME} == yarn1 ELECTRON_MAKE_CMD+= -- . endif ALL_TARGET= # empty . endif NODEJS_REBUILD_ENV+= npm_config_nodedir=${LOCALBASE} ELECTRON_REBUILD_ENV+= npm_config_runtime=electron ELECTRON_REBUILD_ENV+= npm_config_target=${ELECTRON_VER} ELECTRON_REBUILD_ENV+= npm_config_nodedir=${LOCALBASE}/share/electron${ELECTRON_VER_MAJOR}/node_headers MAKE_ENV+= ELECTRON_OVERRIDE_DIST_PATH=${WRKDIR}/electron-dist MAKE_ENV+= ELECTRON_SKIP_BINARY_DOWNLOAD=1 # don't download electron binary distribution MAKE_ENV+= PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 # don't download browser for playwright MAKE_ENV+= PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1 # don't download chromium for puppeteer MAKE_ENV+= SASS_FORCE_BUILD=true # always rebuild native node-sass module MAKE_ENV+= USE_SYSTEM_APP_BUILDER=true # always use system app-builder for electron-builder MAKE_ENV+= npm_config_build_from_source=true SUB_LIST+= ELECTRON_VER_MAJOR=${ELECTRON_VER_MAJOR} .endif # _INCLUDE_USES_ELECTRON_MK diff --git a/Mk/Uses/npm.mk b/Mk/Uses/npm.mk new file mode 100644 index 000000000000..769d7c9e07d7 --- /dev/null +++ b/Mk/Uses/npm.mk @@ -0,0 +1,516 @@ +# Provides support for ports using Node.js package manager +# +# Feature: npm +# Usage: USES=npm:npm-name[,arg,...] +# Valid ARGS: , fetch, extract, build, run, test +# +# : The name of Node.js package manager (NPM) the port depends on. +# Supported package managers are: +# +# npm: The port uses NPM as package manager. +# yarn1: The port uses Yarn (v1) as package manager. +# yarn2: The port uses Yarn (v2 or v3) as package manager. +# yarn4: The port uses Yarn (v4+) as package manager. +# pnpm: The port uses PNPM as package manager. +# +# NOTE: The port must specify exactly a single package manager. +# Multiple package managers cannot be specified. +# +# fetch: NPM is needed at fetch time. Adds it to FETCH_DEPENDS. +# extract: NPM is needed at extract time. Adds it to EXTRACT_DEPENDS. +# build: NPM is needed at build time. Adds it to BUILD_DEPENDS. +# run: NPM is needed at run time. Adds it to RUN_DEPENDS. +# test: NPM is needed at test time. Adds it to TEST_DEPENDS. +# +# NOTE: If the port specifies none of fetch, extract, build, run or test, we +# assume the port requires build and test dependencies. +# +# Variables, which may be set by the port: +# +# NPM_VER: A version of node package manager the port uses. If yarn >2, or +# pnpm is used for the package manager, the framework requires the +# variable to be set so that it can bootstrap the correct version +# of package manager. +# +# It is usually specified in package.json and the framework tries +# to automatically detect the version. Auto-detection can be +# overridden by manually specifying the value in Makefile. +# +# Targets, which may be used by the port (ON by default, setting the variables +# to "no" disable the targets): +# +# NPM_PREFETCH: Downloads node modules the port uses according to the pre-stored +# package.json (and package-lock.json, yarn.lock, or +# pnpm-lock.yaml depending on the node package manager used) in +# PKGJSONSDIR. Downloaded node modules are archived into a single +# tarball as one of the DISTFILES. +# +# NOTE 1: If the source directory of the port has other relevant files +# than package.json and lockfile, the relevant files must also be copied +# into PKGJSONSDIR. (Examples of relevant files includes .npmrc, .yarnrc, +# and pnpm-workspace.yaml.) +# +# NOTE 2: If the source directory of the port contains multiple +# package.json's and/or lockfiles, all files needed for generating node +# modules archive must be copied into PKGJSONSDIR with directory hierarchy +# preserved. +# +# NPM_EXTRACT: Installs the prefetched node modules into the port's working +# source directory. +# +# MAINTAINER: tagattie@FreeBSD.org + +.if !defined(_INCLUDE_USES_NPM_MK) +_INCLUDE_USES_NPM_MK= yes + +# Node.js package manager depends on Node.js +.include "${USESDIR}/nodejs.mk" +_NODEJS_PKGNAME=node${NODEJS_VERSION} +_NODEJS_PORT= www/node${NODEJS_VERSION} + +_VALID_NPM_NAMES=npm yarn1 yarn2 yarn4 pnpm + +# Process USES=npm:ARG +# Detect fetch, extract, build, run, or test dependency +_NPM_ARGS= ${npm_ARGS:S/,/ /g} +. if ${_NPM_ARGS:Mfetch} +_NPM_FETCH_DEP= yes +_NPM_ARGS:= ${_NPM_ARGS:Nfetch} +. endif +. if ${_NPM_ARGS:Mextract} +_NPM_EXTRACT_DEP=yes +_NPM_ARGS:= ${_NPM_ARGS:Nextract} +. endif +. if ${_NPM_ARGS:Mbuild} +_NPM_BUILD_DEP= yes +_NPM_ARGS:= ${_NPM_ARGS:Nbuild} +. endif +. if ${_NPM_ARGS:Mrun} +_NPM_RUN_DEP= yes +_NPM_ARGS:= ${_NPM_ARGS:Nrun} +. endif +. if ${_NPM_ARGS:Mtest} +_NPM_TEST_DEP= yes +_NPM_ARGS:= ${_NPM_ARGS:Ntest} +. endif +# If no dependencies are specified, assume build and test are required +. if !defined(_NPM_FETCH_DEP) && !defied(_NPM_EXTRACT_DEP) && \ + !defined(_NPM_BUILD_DEP) && !defined(_NPM_RUN_DEP) && \ + !defined(_NPM_TEST_DEP) +_NPM_BUILD_DEP= yes +_NPM_TEST_DEP= yes +. endif +# Now _NPM_ARGS should contain a name of node package manager +. if ${_VALID_NPM_NAMES:M${_NPM_ARGS}} +_NPM_NAME= ${_NPM_ARGS} +. elif empty(_NPM_ARGS) +IGNORE= does not specify a name of node package manager +. else +IGNORE= specifies unknown USES=npm arguments: ${_NPM_ARGS} +. endif +. if ${_NPM_NAME} == npm +_NPM_PKGNAME= ${_NPM_NAME}${NODEJS_SUFFIX} +_NPM_PORTDIR= www/${_NPM_NAME}${NODEJS_SUFFIX} +. elif ${_NPM_NAME} == yarn1 +_NPM_PKGNAME= yarn${NODEJS_SUFFIX} +_NPM_PORTDIR= www/yarn${NODEJS_SUFFIX} +. endif + +# Setup dependencies +. for stage in FETCH EXTRACT BUILD RUN TEST +. if defined(_NPM_${stage}_DEP) +. if ${_NPM_NAME} == npm || ${_NPM_NAME} == yarn1 +${stage}_DEPENDS+= ${_NPM_PKGNAME}>0:${_NPM_PORTDIR} +. else +${stage}_DEPENDS+= ${_NODEJS_PKGNAME}>0:${_NODEJS_PORT} +. endif +. endif +. endfor + +# Try to detect the version of package manager from the pre-stored package.json +# if it is not specified by a port. (If yarn >2 or pnpm is used, the framework +# needs to know the version for correctly boostrap the package manager.) +PKGJSONSDIR?= ${FILESDIR}/packagejsons +NPM_PKGFILE?= package.json +NPM_VER?= + +_NPM_EXISTS_PKGFILE?= no +. if exists(${PKGJSONSDIR}/${NPM_PKGFILE}) +_NPM_EXISTS_PKGFILE= yes +. endif +. if (${_NPM_NAME} == yarn2 || ${_NPM_NAME} == yarn4 || ${_NPM_NAME} == pnpm) && \ + ${_NPM_EXISTS_PKGFILE} == yes && empty(NPM_VER) +NPM_VER!= ${CAT} ${PKGJSONSDIR}/${NPM_PKGFILE} | \ + ${TR} -d '\n\r\t' | ${SED} -e 's/ //g; s/"//g' | \ + ${SED} -E -e ' \ + /devEngines:\{packageManager:\{/ { \ + s/.*devEngines:\{packageManager:\{([^}]+)\}\}.*/\1/; \ + h; \ + s/.*name:([^,}]+).*/\1/p; \ + g; \ + s/.*version:([^+,}]+).*/@\1/p; \ + d; \ + }; \ + /packageManager:/ { \ + s/.*packageManager:([^+,}]+).*/\1/p; d; \ + }' | \ + ${CUT} -f 2 -d '@' +. if empty(NPM_VER) +IGNORE= does not specity version of ${NPM_CMDNAME} used for prefetching node modules +. endif +. endif + +# Define variables related to node package manager +NPM_NAME= ${_NPM_NAME} +NPM_FETCH_FLAGS?= +NPM_EXTRACT_FLAGS?= +NPM_EXTRACT_WRKSRC?= ${WRKSRC} +. if ${_NPM_NAME} == npm +NPM_LOCKFILE?= package-lock.json +NPM_MODULE_CACHE?= node_modules +NPM_CMDNAME?= npm +NPM_CACHE_SETUP_CMD?= ${DO_NADA} +NPM_FETCH_CMD?= ${NPM_CMDNAME} ci +NPM_FETCH_FLAGS+= --ignore-scripts --no-progress --no-audit --no-fund \ + --no-update-notifier --loglevel=error +NPM_EXEC_CMD?= ${NPM_CMDNAME} exec +NPM_EXEC_FLAGS+= --no-update-notifier +NPM_REBUILD_CMD?= ${NPM_CMDNAME} rebuild +NPM_REBUILD_FLAGS+= --no-update-notifier +. elif ${_NPM_NAME:Myarn*} +NPM_LOCKFILE?= yarn.lock +NPM_MODULE_CACHE?= yarn-offline-cache +NPM_CMDNAME?= yarn +NPM_FETCH_CMD?= ${NPM_CMDNAME} install +NPM_EXTRACT_CMD?= ${NPM_CMDNAME} install +NPM_EXEC_CMD?= ${NPM_CMDNAME} exec +. if ${_NPM_NAME} == yarn1 +NPM_CACHE_SETUP_CMD?= ${ECHO_CMD} 'yarn-offline-mirror "./${NPM_MODULE_CACHE}"' >> .yarnrc +NPM_FETCH_FLAGS+= --frozen-lockfile --ignore-scripts --silent +NPM_EXTRACT_FLAGS+= ${NPM_FETCH_FLAGS} --offline +. elif ${_NPM_NAME} == yarn2 +NPM_CACHE_SETUP_CMD?= ${NPM_CMDNAME} config set cacheFolder "./${NPM_MODULE_CACHE}" +NPM_FETCH_FLAGS+= --immutable --mode=skip-build --silent +NPM_EXTRACT_SETUP_CMD?= ${SH} -c "${NPM_CMDNAME} config set enableNetwork false; \ + ${NPM_CMDNAME} config set enableInlineBuilds true" +NPM_EXTRACT_FLAGS+= ${NPM_FETCH_FLAGS} --immutable-cache +NPM_REBUILD_CMD?= ${NPM_CMDNAME} rebuild +. elif ${_NPM_NAME} == yarn4 +NPM_CACHE_SETUP_CMD?= ${SH} -c "${NPM_CMDNAME} config set enableGlobalCache false; \ + ${NPM_CMDNAME} config set cacheFolder \"./${NPM_MODULE_CACHE}\"" +NPM_FETCH_FLAGS+= --immutable --mode=skip-build --silent +NPM_EXTRACT_SETUP_CMD?= ${SH} -c "${NPM_CMDNAME} config set enableNetwork false; \ + ${NPM_CMDNAME} config set enableInlineBuilds true" +NPM_EXTRACT_FLAGS+= ${NPM_FETCH_FLAGS} --immutable-cache +NPM_REBUILD_CMD?= ${NPM_CMDNAME} rebuild +. endif +. elif ${_NPM_NAME} == pnpm +NPM_LOCKFILE?= pnpm-lock.yaml +NPM_MODULE_CACHE?= pnpm-store +NPM_CMDNAME?= pnpm +NPM_CACHE_SETUP_CMD?= ${DO_NADA} +NPM_FETCH_CMD?= ${NPM_CMDNAME} fetch +NPM_FETCH_FLAGS+= --frozen-lockfile --ignore-scripts --loglevel=error \ + --store-dir ${WRKDIR}/node-modules-cache/${NPM_MODULE_CACHE} +NPM_EXTRACT_CMD?= ${NPM_CMDNAME} install +NPM_EXTRACT_FLAGS+= ${NPM_FETCH_FLAGS} --offline +NPM_EXEC_CMD?= ${NPM_CMDNAME} exec +NPM_REBUILD_CMD?= ${NPM_CMDNAME} rebuild +. endif + +# Use utility targets? +NPM_PREFETCH?= ${_NPM_EXISTS_PKGFILE} +NPM_EXTRACT?= ${NPM_PREFETCH} + +# Bootstrap node package manager for yarn >2 or pnpm +. if ${_NPM_NAME} == yarn2 || ${_NPM_NAME} == yarn4 || ${_NPM_NAME} == pnpm +_USES_fetch+= 490:npm-fetch-node-package-manager + +DISTFILES+= ${NPM_CMDNAME}-${NPM_VER}.tgz:prefetch +FETCH_DEPENDS+= ${_NODEJS_PKGNAME}>0:${_NODEJS_PORT} + +npm-fetch-node-package-manager: + @${ECHO_MSG} "===> Fetching and setting up ${NPM_CMDNAME} version ${NPM_VER}" + @${MKDIR} ${DISTDIR}/${DIST_SUBDIR} ${WRKDIR}/.bin + @${SETENV} ${MAKE_ENV} corepack enable --install-directory ${WRKDIR}/.bin + @if [ ! -f ${DISTDIR}/${DIST_SUBDIR}/${NPM_CMDNAME}-${NPM_VER}.tgz ]; then \ + cd ${WRKDIR} && \ + ${SETENV} ${MAKE_ENV} corepack pack ${NPM_CMDNAME}@${NPM_VER} && \ + ${TAR} -xzf corepack.tgz && \ + ${SETENV} SCRIPTSDIR=${SCRIPTSDIR} WRKDIR=${WRKDIR} \ + ${SH} ${SCRIPTSDIR}/npm-create-mtree.sh ${NPM_CMDNAME} > \ + ${NPM_CMDNAME}.mtree && \ + ${SETENV} LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 \ + ${TAR} -cz --options 'gzip:!timestamp' \ + -f ${DISTDIR}/${DIST_SUBDIR}/${NPM_CMDNAME}-${NPM_VER}.tgz @${NPM_CMDNAME}.mtree; \ + fi + @${SETENV} ${MAKE_ENV} corepack install -g ${DISTDIR}/${DIST_SUBDIR}/${NPM_CMDNAME}-${NPM_VER}.tgz +. endif + +. if ${NPM_PREFETCH:tl} == yes +. if ${_NPM_EXISTS_PKGFILE} == no +IGNORE= does not store ${NPM_PKGFILE} in ${PKGJSONSDIR} for prefetching node modules +. endif + +_USES_fetch+= 491:npm-fetch-node-modules \ + 492:npm-archive-node-modules + +_DISTFILE_prefetch= ${PKGNAMEPREFIX}${PORTNAME}${PKGNAMESUFFIX}-${DISTVERSION}-node-modules${EXTRACT_SUFX} +DISTFILES+= ${_DISTFILE_prefetch}:prefetch + +. if ${_NPM_NAME} == npm || ${_NPM_NAME} == yarn1 +FETCH_DEPENDS+= ${_NPM_PKGNAME}>0:${_NPM_PORTDIR} +. elif ${_NPM_NAME} == pnpm +FETCH_DEPENDS+= jq:textproc/jq +. if ${NPM_VER:R:R} >= 11 +FETCH_DEPENDS+= sqlite3:databases/sqlite3 +. endif +. endif + +npm-fetch-node-modules: + @${MKDIR} ${DISTDIR}/${DIST_SUBDIR} + @if [ ! -f ${DISTDIR}/${DIST_SUBDIR}/${_DISTFILE_prefetch} ]; then \ + ${ECHO_MSG} "===> Setting up node modules cache directory"; \ + ${MKDIR} ${WRKDIR}/node-modules-cache; \ + ${TAR} -cf - -C ${PKGJSONSDIR} . | ${TAR} -xf - -C ${WRKDIR}/node-modules-cache; \ + cd ${WRKDIR}/node-modules-cache && ${SETENV} ${MAKE_ENV} ${NPM_CACHE_SETUP_CMD}; \ + ${ECHO_MSG} "===> Prefetching node modules"; \ + for dir in `${FIND} ${WRKDIR}/node-modules-cache -type f -name ${NPM_LOCKFILE} -exec ${DIRNAME} {} ';'`; do \ + cd $${dir} && \ + ${SETENV} ${MAKE_ENV} ${NPM_FETCH_CMD} ${NPM_FETCH_FLAGS}; \ + ${RM} $${dir}/${NPM_MODULE_CACHE}/.gitignore; \ + done; \ + fi + +npm-archive-node-modules: +. if ${_NPM_NAME} == npm + @if [ ! -f ${DISTDIR}/${DIST_SUBDIR}/${_DISTFILE_prefetch} ] && [ -d ${WRKDIR}/node-modules-cache ]; then \ + ${ECHO_MSG} "===> Archiving prefetched node modules"; \ + for dir in `${FIND} -s ${WRKDIR}/node-modules-cache -type d -name ${NPM_MODULE_CACHE} -print | \ + ${GREP} -ve '${NPM_MODULE_CACHE}/.*/${NPM_MODULE_CACHE}'`; do \ + ${SETENV} SCRIPTSDIR=${SCRIPTSDIR} WRKDIR=${WRKDIR} \ + ${SH} ${SCRIPTSDIR}/npm-create-mtree.sh $${dir} >> \ + ${WRKDIR}/node-modules-cache.mtree; \ + done; \ + ${SETENV} LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 \ + ${TAR} -cz --options 'gzip:!timestamp' \ + -f ${DISTDIR}/${DIST_SUBDIR}/${_DISTFILE_prefetch} \ + -C ${WRKDIR} @node-modules-cache.mtree; \ + if [ ${TMPDIR} != ${WRKDIR} ]; then \ + ${RM} -r ${WRKDIR}; \ + fi; \ + fi +. elif ${_NPM_NAME:Myarn*} || ${_NPM_NAME} == pnpm +. if ${_NPM_NAME} == pnpm +. if ${NPM_VER:R:R} >= 11 + @if [ ! -f ${DISTDIR}/${DIST_SUBDIR}/${_DISTFILE_prefetch} ] && [ -d ${WRKDIR}/node-modules-cache ]; then \ + ${ECHO_MSG} "===> Normalizing timestamps and permissions of prefetched node modules"; \ + tmpdir=${WRKDIR}/pnpm_tmp; \ + input_db=${WRKDIR}/node-modules-cache/${NPM_MODULE_CACHE}/v11/index.db; \ + output_db=$${tmpdir}/index.db; \ + output_db_dump=${WRKDIR}/node-modules-cache/${NPM_MODULE_CACHE}/v11/index_dump.sql; \ + ${MKDIR} $${tmpdir}; \ + cd $${tmpdir} && ${SETENV} ${MAKE_ENV} ${NPM_CMDNAME} add --ignore-scripts --silent msgpackr; \ + sqlite3 $${input_db} \ + "SELECT writefile('$${tmpdir}/' || row_number() OVER (ORDER BY key ASC) || '.msgpack', data) FROM package_index;" > /dev/null; \ + sqlite3 $${input_db} \ + "SELECT key FROM package_index ORDER BY key ASC;" > $${tmpdir}/keys_list.txt; \ + counter=1; \ + while IFS= read -r key; do \ + ${PRINTF} "%s" "$${key}" > $${tmpdir}/$${counter}.key; \ + counter=$$((counter + 1)); \ + done < $${tmpdir}/keys_list.txt; \ + for file in $${tmpdir}/*.msgpack; do \ + base=$${file%.msgpack}; \ + node -e " \ + const fs = require('fs'); \ + const { Unpackr } = require('msgpackr'); \ + const unpackr = new Unpackr({}); \ + const buf = fs.readFileSync(0); \ + const data = unpackr.unpack(buf); \ + console.log(JSON.stringify(data, (key, value) => { \ + if (value instanceof Map) { \ + return { __type: 'Map', data: Array.from(value.entries()) }; \ + } \ + return value; \ + })); \ + " < $${file} > $${base}.msgpack.json; \ + jq -S ' \ + walk( \ + if type == "object" then \ + if has("checkedAt") then .checkedAt = 0 else . end | \ + if has("mode") then \ + if (.mode / 16 | floor) % 2 == 1 then .mode = .mode - 16 else . end \ + else \ + . \ + end \ + else \ + . \ + end \ + ) \ + ' $${base}.msgpack.json > $${base}.normalized.json; \ + node -e " \ + const fs = require('fs'); \ + const { Packr } = require('msgpackr'); \ + const packr = new Packr({ structuredClone: true }); \ + const rawJson = JSON.parse(fs.readFileSync(0, 'utf-8')); \ + const restoreMaps = (obj) => { \ + if (obj && typeof obj === 'object') { \ + if (obj.__type === 'Map') { \ + return new Map(obj.data.map(([k, v]) => [k, restoreMaps(v)])); \ + } \ + for (let k in obj) { \ + obj[k] = restoreMaps(obj[k]); \ + } \ + } \ + return obj; \ + }; \ + const restoredData = restoreMaps(rawJson); \ + process.stdout.write(packr.pack(restoredData)); \ + " < $${base}.normalized.json > $${base}.normalized.msgpack; \ + done; \ + sqlite3 $${output_db} \ + "CREATE TABLE package_index (key TEXT PRIMARY KEY, data BLOB) WITHOUT ROWID;" > /dev/null 2>&1; \ + sqlite3 $${output_db} \ + "PRAGMA page_size = 4096; PRAGMA journal_mode = DELETE; PRAGMA auto_vacuum = NONE; PRAGMA secure_delete = ON;" > /dev/null 2>&1; \ + total_files=$$((counter - 1)); \ + i=1; \ + while [ $${i} -le $${total_files} ]; do \ + real_key=`${CAT} $${tmpdir}/$${i}.key`; \ + { \ + ${PRINTF} "INSERT INTO package_index (key, data) VALUES ('%s', x'" "$${real_key}"; \ + hexdump -v -e '/1 "%02x"' $${tmpdir}/$${i}.normalized.msgpack; \ + ${PRINTF} "');\n"; \ + } | sqlite3 $${output_db}; \ + i=$$((i + 1)); \ + done; \ + sqlite3 $${output_db} "REINDEX; VACUUM;"; \ + sqlite3 $${output_db} ".dump" > $${output_db_dump}; \ + ${RM} $${input_db}; \ + fi +. else + @if [ ! -f ${DISTDIR}/${DIST_SUBDIR}/${_DISTFILE_prefetch} ] && [ -d ${WRKDIR}/node-modules-cache ]; then \ + ${ECHO_MSG} "===> Normalizing timestamps and permissions of prefetched node modules"; \ + ${FIND} ${WRKDIR}/node-modules-cache/${NPM_MODULE_CACHE} \ + -type f -name '*.json' -exec ${SH} -c ' \ + for f do \ + jq -c "walk(if type == \"object\" and has(\"checkedAt\") then .checkedAt = 0 else . end)" $${f} > $${f}.tmp && mv $${f}.tmp $${f}; \ + done \ + ' ${SH} {} ';'; \ + for dir in projects tmp; do \ + ${RM} -r ${WRKDIR}/node-modules-cache/${NPM_MODULE_CACHE}/*/$${dir}; \ + done; \ + fi +. endif +. endif + @if [ ! -f ${DISTDIR}/${DIST_SUBDIR}/${_DISTFILE_prefetch} ] && [ -d ${WRKDIR}/node-modules-cache ]; then \ + ${ECHO_MSG} "===> Archiving prefetched node modules"; \ + cd ${WRKDIR}/node-modules-cache && \ + ${SETENV} SCRIPTSDIR=${SCRIPTSDIR} WRKDIR=${WRKDIR} \ + ${SH} ${SCRIPTSDIR}/npm-create-mtree.sh ${NPM_MODULE_CACHE} > \ + node-modules-cache.mtree && \ + ${SETENV} LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 \ + ${TAR} -cz --options 'gzip:!timestamp' \ + -f ${DISTDIR}/${DIST_SUBDIR}/${_DISTFILE_prefetch} @node-modules-cache.mtree; \ + if [ ${TMPDIR} != ${WRKDIR} ]; then \ + ${RM} -r ${WRKDIR}; \ + fi; \ + fi +. endif +. endif + +. if ${NPM_EXTRACT:tl} == yes +_USES_extract+= 600:npm-extract-node-package-manager \ + 601:npm-copy-package-file \ + 602:npm-install-node-modules + +. if ${_NPM_NAME} == yarn1 +EXTRACT_DEPENDS+= ${_NPM_PKGNAME}>0:${_NPM_PORTDIR} +. elif ${_NPM_NAME} == yarn2 || ${_NPM_NAME} == yarn4 || ${_NPM_NAME} == pnpm +EXTRACT_DEPENDS+= ${_NODEJS_PKGNAME}>0:${_NODEJS_PORT} +. if ${_NPM_NAME} == pnpm && ${NPM_VER:R:R} >= 11 +EXTRACT_DEPENDS+= sqlite3:databases/sqlite3 +. if ${NPM_VER:R} >= 11.3 +NPM_EXTRACT_FLAGS+= --trust-lockfile +. endif +. endif +. endif + +npm-extract-node-package-manager: +. if ${_NPM_NAME} == yarn2 || ${_NPM_NAME} == yarn4 || ${_NPM_NAME} == pnpm + @${ECHO_MSG} "===> Setting up ${NPM_CMDNAME} version ${NPM_VER}" + @${MKDIR} ${WRKDIR}/.bin + @${SETENV} ${MAKE_ENV} corepack enable --install-directory ${WRKDIR}/.bin + @${SETENV} ${MAKE_ENV} corepack install -g ${DISTDIR}/${DIST_SUBDIR}/${NPM_CMDNAME}-${NPM_VER}.tgz +. else + @${DO_NADA} +. endif + +npm-copy-package-file: +. if ${_NPM_EXISTS_PKGFILE} == yes + @${ECHO_MSG} "===> Copying ${NPM_PKGFILE} and ${NPM_LOCKFILE} to ${NPM_EXTRACT_WRKSRC}" + @for f in `${FIND} ${PKGJSONSDIR} -type f \( -name ${NPM_PKGFILE} -o -name ${NPM_LOCKFILE} \) -print | ${SED} -e 's|${PKGJSONSDIR}/||'`; do \ + ${MKDIR} -p `${DIRNAME} ${NPM_EXTRACT_WRKSRC}/$${f}`; \ + if [ -f ${NPM_EXTRACT_WRKSRC}/$${f} ]; then \ + ${MV} -f ${NPM_EXTRACT_WRKSRC}/$${f} ${NPM_EXTRACT_WRKSRC}/$${f}.bak; \ + fi; \ + ${CP} ${PKGJSONSDIR}/$${f} ${NPM_EXTRACT_WRKSRC}/$${f}; \ + done +. endif + +npm-install-node-modules: +. if ${_NPM_NAME} == npm + @${ECHO_MSG} "===> Moving prefetched node modules to ${NPM_EXTRACT_WRKSRC}" + @if [ -d ${EXTRACT_WRKDIR}/node-modules-cache ]; then \ + for dir in `${FIND} -s ${EXTRACT_WRKDIR}/node-modules-cache -type d -name ${NPM_MODULE_CACHE} -print | \ + ${GREP} -ve '${NPM_MODULE_CACHE}/.*/${NPM_MODULE_CACHE}'`; do \ + ${MV} $${dir} `${ECHO_CMD} $${dir} | sed -e 's|${EXTRACT_WRKDIR}/node-modules-cache|${NPM_EXTRACT_WRKSRC}|'`; \ + done; \ + fi +. elif ${_NPM_NAME:Myarn*} + @${ECHO_MSG} "===> Installing node modules from prefetched cache" + @if [ -d ${EXTRACT_WRKDIR}/${NPM_MODULE_CACHE} ]; then \ + ${MV} ${EXTRACT_WRKDIR}/${NPM_MODULE_CACHE} ${NPM_EXTRACT_WRKSRC}; \ + fi + @cd ${NPM_EXTRACT_WRKSRC} && ${SETENV} ${MAKE_ENV} ${NPM_CACHE_SETUP_CMD} +. if defined(NPM_EXTRACT_SETUP_CMD) && !empty(NPM_EXTRACT_SETUP_CMD) + @${ECHO_MSG} "===> Setting up ${NPM_CMDNAME} command options" + @cd ${NPM_EXTRACT_WRKSRC} && ${SETENV} ${MAKE_ENV} ${NPM_EXTRACT_SETUP_CMD} +. endif + @if [ -d ${PKGJSONSDIR} ]; then \ + cd ${PKGJSONSDIR} && \ + for dir in `${FIND} . -type f -name ${NPM_LOCKFILE} -exec ${DIRNAME} {} ';'`; do \ + cd ${NPM_EXTRACT_WRKSRC}/$${dir} && \ + ${SETENV} ${MAKE_ENV} ${NPM_EXTRACT_CMD} ${NPM_EXTRACT_FLAGS}; \ + done; \ + else \ + cd ${NPM_EXTRACT_WRKSRC} && \ + ${SETENV} ${MAKE_ENV} ${NPM_EXTRACT_CMD} ${NPM_EXTRACT_FLAGS}; \ + fi +. elif ${_NPM_NAME} == pnpm + @${ECHO_MSG} "===> Installing node modules from prefetched cache" +. if ${NPM_VER:R:R} >= 11 + @if [ -d ${EXTRACT_WRKDIR}/${NPM_MODULE_CACHE} ]; then \ + normalized_db_dump=${EXTRACT_WRKDIR}/${NPM_MODULE_CACHE}/v11/index_dump.sql; \ + index_db=${EXTRACT_WRKDIR}/${NPM_MODULE_CACHE}/v11/index.db; \ + sqlite3 $${index_db} < $${normalized_db_dump}; \ + fi +. endif + @if [ -d ${EXTRACT_WRKDIR}/${NPM_MODULE_CACHE} ]; then \ + ${MKDIR} ${WRKDIR}/node-modules-cache; \ + ${MV} ${EXTRACT_WRKDIR}/${NPM_MODULE_CACHE} ${WRKDIR}/node-modules-cache; \ + fi + @if [ -d ${PKGJSONSDIR} ]; then \ + cd ${PKGJSONSDIR} && \ + for dir in `${FIND} . -type f -name ${NPM_LOCKFILE} -exec ${DIRNAME} {} ';'`; do \ + cd ${NPM_EXTRACT_WRKSRC}/$${dir} && \ + ${SETENV} ${MAKE_ENV} ${NPM_EXTRACT_CMD} ${NPM_EXTRACT_FLAGS}; \ + done; \ + else \ + cd ${NPM_EXTRACT_WRKSRC} && \ + ${SETENV} ${MAKE_ENV} ${NPM_EXTRACT_CMD} ${NPM_EXTRACT_FLAGS}; \ + fi +. endif +. endif + +.endif # _INCLUDE_USES_NPM_MK