1-include config.mk 2 3BUILDTYPE ?= Release 4PYTHON ?= python3 5DESTDIR ?= 6SIGN ?= 7PREFIX ?= /usr/local 8FLAKY_TESTS ?= run 9TEST_CI_ARGS ?= 10STAGINGSERVER ?= node-www 11LOGLEVEL ?= silent 12OSTYPE := $(shell uname -s | tr '[:upper:]' '[:lower:]') 13ifeq ($(findstring os/390,$OSTYPE),os/390) 14OSTYPE ?= os390 15endif 16ARCHTYPE := $(shell uname -m | tr '[:upper:]' '[:lower:]') 17COVTESTS ?= test-cov 18COV_SKIP_TESTS ?= core_line_numbers.js,testFinalizer.js,test_function/test.js 19GTEST_FILTER ?= "*" 20GNUMAKEFLAGS += --no-print-directory 21GCOV ?= gcov 22PWD = $(CURDIR) 23BUILD_WITH ?= make 24FIND ?= find 25 26ifdef JOBS 27 PARALLEL_ARGS = -j $(JOBS) 28else 29 PARALLEL_ARGS = 30endif 31 32ifdef ENABLE_V8_TAP 33 TAP_V8 := --junitout $(PWD)/v8-tap.xml 34 TAP_V8_INTL := --junitout $(PWD)/v8-intl-tap.xml 35 TAP_V8_BENCHMARKS := --junitout $(PWD)/v8-benchmarks-tap.xml 36define convert_to_junit 37 @true 38endef 39endif 40 41ifdef ENABLE_CONVERT_V8_JSON_TO_XML 42 TAP_V8_JSON := $(PWD)/v8-tap.json 43 TAP_V8_INTL_JSON := $(PWD)/v8-intl-tap.json 44 TAP_V8_BENCHMARKS_JSON := $(PWD)/v8-benchmarks-tap.json 45 46 # By default, the V8's JSON test output only includes the tests which have 47 # failed. We use --slow-tests-cutoff to ensure that all tests are present 48 # in the output, including those which pass. 49 TAP_V8 := --json-test-results $(TAP_V8_JSON) --slow-tests-cutoff 1000000 50 TAP_V8_INTL := --json-test-results $(TAP_V8_INTL_JSON) --slow-tests-cutoff 1000000 51 TAP_V8_BENCHMARKS := --json-test-results $(TAP_V8_BENCHMARKS_JSON) --slow-tests-cutoff 1000000 52 53define convert_to_junit 54 export PATH="$(NO_BIN_OVERRIDE_PATH)" && \ 55 $(PYTHON) tools/v8-json-to-junit.py < $(1) > $(1:.json=.xml) 56endef 57endif 58 59V8_TEST_OPTIONS = $(V8_EXTRA_TEST_OPTIONS) 60ifdef DISABLE_V8_I18N 61 V8_BUILD_OPTIONS += i18nsupport=off 62endif 63# V8 build and test toolchains are not currently compatible with Python 3. 64# config.mk may have prepended a symlink for `python` to PATH which we need 65# to undo before calling V8's tools. 66OVERRIDE_BIN_DIR=$(dir $(abspath $(lastword $(MAKEFILE_LIST))))out/tools/bin 67NO_BIN_OVERRIDE_PATH=$(subst $() $(),:,$(filter-out $(OVERRIDE_BIN_DIR),$(subst :, ,$(PATH)))) 68 69ifeq ($(OSTYPE), darwin) 70 GCOV = xcrun llvm-cov gcov 71endif 72 73BUILDTYPE_LOWER := $(shell echo $(BUILDTYPE) | tr '[:upper:]' '[:lower:]') 74 75# Determine EXEEXT 76EXEEXT := $(shell $(PYTHON) -c \ 77 "import sys; print('.exe' if sys.platform == 'win32' else '')") 78 79NODE_EXE = node$(EXEEXT) 80NODE ?= ./$(NODE_EXE) 81NODE_G_EXE = node_g$(EXEEXT) 82NPM ?= ./deps/npm/bin/npm-cli.js 83 84# Flags for packaging. 85BUILD_DOWNLOAD_FLAGS ?= --download=all 86BUILD_INTL_FLAGS ?= --with-intl=full-icu 87BUILD_RELEASE_FLAGS ?= $(BUILD_DOWNLOAD_FLAGS) $(BUILD_INTL_FLAGS) 88 89# Default to quiet/pretty builds. 90# To do verbose builds, run `make V=1` or set the V environment variable. 91V ?= 0 92 93# Use -e to double check in case it's a broken link 94# Use $(PWD) so we can cd to anywhere before calling this 95available-node = \ 96 if [ -x $(PWD)/$(NODE) ] && [ -e $(PWD)/$(NODE) ]; then \ 97 $(PWD)/$(NODE) $(1); \ 98 elif [ -x `command -v node` ] && [ -e `command -v node` ] && [ `command -v node` ]; then \ 99 `command -v node` $(1); \ 100 else \ 101 echo "No available node, cannot run \"node $(1)\""; \ 102 exit 1; \ 103 fi; 104 105.PHONY: all 106# BUILDTYPE=Debug builds both release and debug builds. If you want to compile 107# just the debug build, run `make -C out BUILDTYPE=Debug` instead. 108ifeq ($(BUILDTYPE),Release) 109all: $(NODE_EXE) ## Default target, builds node in out/Release/node. 110else 111all: $(NODE_EXE) $(NODE_G_EXE) 112endif 113 114.PHONY: help 115# To add a target to the help, add a double comment (##) on the target line. 116help: ## Print help for targets with comments. 117 @printf "For more targets and info see the comments in the Makefile.\n\n" 118 @grep -E '^[[:alnum:]._-]+:.*?## .*$$' Makefile | sort | \ 119 awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}' 120 121# The .PHONY is needed to ensure that we recursively use the out/Makefile 122# to check for changes. 123.PHONY: $(NODE_EXE) $(NODE_G_EXE) 124 125# The -r/-L check stops it recreating the link if it is already in place, 126# otherwise $(NODE_EXE) being a .PHONY target means it is always re-run. 127# Without the check there is a race condition between the link being deleted 128# and recreated which can break the addons build when running test-ci 129# See comments on the build-addons target for some more info 130ifeq ($(BUILD_WITH), make) 131$(NODE_EXE): build_type:=Release 132$(NODE_G_EXE): build_type:=Debug 133$(NODE_EXE) $(NODE_G_EXE): config.gypi out/Makefile 134 $(MAKE) -C out BUILDTYPE=${build_type} V=$(V) 135 if [ ! -r $@ ] || [ ! -L $@ ]; then \ 136 ln -fs out/${build_type}/$(NODE_EXE) $@; fi 137else 138ifeq ($(BUILD_WITH), ninja) 139NINJA ?= ninja 140ifeq ($(V),1) 141 NINJA_ARGS := $(NINJA_ARGS) -v 142endif 143ifdef JOBS 144 NINJA_ARGS := $(NINJA_ARGS) -j$(JOBS) 145else 146 NINJA_ARGS := $(NINJA_ARGS) $(filter -j%,$(MAKEFLAGS)) 147endif 148$(NODE_EXE): config.gypi out/Release/build.ninja 149 $(NINJA) -C out/Release $(NINJA_ARGS) 150 if [ ! -r $@ ] || [ ! -L $@ ]; then ln -fs out/Release/$(NODE_EXE) $@; fi 151 152$(NODE_G_EXE): config.gypi out/Debug/build.ninja 153 $(NINJA) -C out/Debug $(NINJA_ARGS) 154 if [ ! -r $@ ] || [ ! -L $@ ]; then ln -fs out/Debug/$(NODE_EXE) $@; fi 155else 156$(NODE_EXE) $(NODE_G_EXE): 157 $(warning This Makefile currently only supports building with 'make' or 'ninja') 158endif 159endif 160 161 162ifeq ($(BUILDTYPE),Debug) 163CONFIG_FLAGS += --debug 164endif 165 166.PHONY: with-code-cache 167.PHONY: test-code-cache 168with-code-cache test-code-cache: 169 $(warning '$@' target is a noop) 170 171out/Makefile: config.gypi common.gypi node.gyp \ 172 deps/uv/uv.gyp deps/llhttp/llhttp.gyp deps/zlib/zlib.gyp \ 173 deps/simdutf/simdutf.gyp deps/ada/ada.gyp \ 174 tools/v8_gypfiles/toolchain.gypi tools/v8_gypfiles/features.gypi \ 175 tools/v8_gypfiles/inspector.gypi tools/v8_gypfiles/v8.gyp 176 $(PYTHON) tools/gyp_node.py -f make 177 178# node_version.h is listed because the N-API version is taken from there 179# and included in config.gypi 180config.gypi: configure configure.py src/node_version.h 181 @if [ -x config.status ]; then \ 182 export PATH="$(NO_BIN_OVERRIDE_PATH)" && ./config.status; \ 183 else \ 184 echo Missing or stale $@, please run ./$<; \ 185 exit 1; \ 186 fi 187 188.PHONY: install 189install: all ## Installs node into $PREFIX (default=/usr/local). 190 $(PYTHON) tools/install.py $@ '$(DESTDIR)' '$(PREFIX)' 191 192.PHONY: uninstall 193uninstall: ## Uninstalls node from $PREFIX (default=/usr/local). 194 $(PYTHON) tools/install.py $@ '$(DESTDIR)' '$(PREFIX)' 195 196.PHONY: clean 197.NOTPARALLEL: clean 198clean: ## Remove build artifacts. 199 $(RM) -r out/Makefile $(NODE_EXE) $(NODE_G_EXE) out/$(BUILDTYPE)/$(NODE_EXE) \ 200 out/$(BUILDTYPE)/node.exp 201 @if [ -d out ]; then $(FIND) out/ -name '*.o' -o -name '*.a' -o -name '*.d' | xargs $(RM) -r; fi 202 $(RM) -r node_modules 203 @if [ -d deps/icu ]; then echo deleting deps/icu; $(RM) -r deps/icu; fi 204 $(RM) test.tap 205 $(MAKE) testclean 206 $(MAKE) test-addons-clean 207 $(MAKE) bench-addons-clean 208 209.PHONY: testclean 210.NOTPARALLEL: testclean 211testclean: 212# Next one is legacy remove this at some point 213 $(RM) -r test/tmp* 214 $(RM) -r test/.tmp* 215 216.PHONY: distclean 217.NOTPARALLEL: distclean 218distclean: 219 $(RM) -r out 220 $(RM) config.gypi icu_config.gypi 221 $(RM) config.mk 222 $(RM) -r $(NODE_EXE) $(NODE_G_EXE) 223 $(RM) -r node_modules 224 $(RM) -r deps/icu 225 $(RM) -r deps/icu4c*.tgz deps/icu4c*.zip deps/icu-tmp 226 $(RM) $(BINARYTAR).* $(TARBALL).* 227 228.PHONY: check 229check: test 230 231.PHONY: coverage-clean 232.NOTPARALLEL: coverage-clean 233# Remove files generated by running coverage, put the non-instrumented lib back 234# in place 235coverage-clean: 236 $(RM) -r node_modules 237 $(RM) -r gcovr 238 $(RM) -r coverage/tmp 239 $(FIND) out/$(BUILDTYPE)/obj.target \( -name "*.gcda" -o -name "*.gcno" \) \ 240 -type f -exec $(RM) {} \; 241 242.PHONY: coverage 243# Build and test with code coverage reporting. HTML coverage reports will be 244# created under coverage/. For C++ coverage reporting, this needs to be run 245# in conjunction with configure --coverage. 246# Related CI job: node-test-commit-linux-coverage-daily 247coverage: coverage-test ## Run the tests and generate a coverage report. 248 249.PHONY: coverage-build 250coverage-build: all 251 -$(MAKE) coverage-build-js 252 if [ ! -d gcovr ]; then $(PYTHON) -m pip install -t gcovr gcovr==4.2; fi 253 $(MAKE) 254 255.PHONY: coverage-build-js 256coverage-build-js: 257 mkdir -p node_modules 258 if [ ! -d node_modules/c8 ]; then \ 259 $(NODE) ./deps/npm install c8 --no-save --no-package-lock;\ 260 fi 261 262.PHONY: coverage-test 263coverage-test: coverage-build 264 $(FIND) out/$(BUILDTYPE)/obj.target -name "*.gcda" -type f -exec $(RM) {} \; 265 -NODE_V8_COVERAGE=coverage/tmp \ 266 TEST_CI_ARGS="$(TEST_CI_ARGS) --type=coverage" $(MAKE) $(COVTESTS) 267 $(MAKE) coverage-report-js 268 -(cd out && PYTHONPATH=../gcovr $(PYTHON) -m gcovr \ 269 --gcov-exclude='.*\b(deps|usr|out|cctest|embedding)\b' -v \ 270 -r ../src/ --object-directory Release/obj.target \ 271 --html --html-details -o ../coverage/cxxcoverage.html \ 272 --gcov-executable="$(GCOV)") 273 @printf "Javascript coverage %%: " 274 @grep -B1 Lines coverage/index.html | head -n1 \ 275 | sed 's/<[^>]*>//g'| sed 's/ //g' 276 @printf "C++ coverage %%: " 277 @grep -A3 Lines coverage/cxxcoverage.html | grep style \ 278 | sed 's/<[^>]*>//g'| sed 's/ //g' 279 280.PHONY: coverage-report-js 281coverage-report-js: 282 -$(MAKE) coverage-build-js 283 $(NODE) ./node_modules/.bin/c8 report 284 285.PHONY: cctest 286# Runs the C++ tests using the built `cctest` executable. 287cctest: all 288 @out/$(BUILDTYPE)/$@ --gtest_filter=$(GTEST_FILTER) 289 @out/$(BUILDTYPE)/embedtest "require('./test/embedding/test-embedding.js')" 290 291.PHONY: list-gtests 292list-gtests: 293ifeq (,$(wildcard out/$(BUILDTYPE)/cctest)) 294 $(error Please run 'make cctest' first) 295endif 296 @out/$(BUILDTYPE)/cctest --gtest_list_tests 297 298.PHONY: v8 299# Related CI job: node-test-commit-v8-linux 300# Rebuilds deps/v8 as a git tree, pulls its third-party dependencies, and 301# builds it. 302v8: 303 export PATH="$(NO_BIN_OVERRIDE_PATH)" && \ 304 tools/make-v8.sh $(V8_ARCH).$(BUILDTYPE_LOWER) $(V8_BUILD_OPTIONS) 305 306.PHONY: jstest 307jstest: build-addons build-js-native-api-tests build-node-api-tests ## Runs addon tests and JS tests 308 $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) \ 309 $(TEST_CI_ARGS) \ 310 --skip-tests=$(CI_SKIP_TESTS) \ 311 $(JS_SUITES) \ 312 $(NATIVE_SUITES) 313 314.PHONY: tooltest 315tooltest: 316 @$(PYTHON) -m unittest discover -s ./test/tools 317 318.PHONY: coverage-run-js 319coverage-run-js: 320 $(RM) -r coverage/tmp 321 -NODE_V8_COVERAGE=coverage/tmp CI_SKIP_TESTS=$(COV_SKIP_TESTS) \ 322 TEST_CI_ARGS="$(TEST_CI_ARGS) --type=coverage" $(MAKE) jstest 323 $(MAKE) coverage-report-js 324 325.PHONY: test 326# This does not run tests of third-party libraries inside deps. 327test: all ## Runs default tests, linters, and builds docs. 328 $(MAKE) -s tooltest 329 $(MAKE) -s test-doc 330 $(MAKE) -s build-addons 331 $(MAKE) -s build-js-native-api-tests 332 $(MAKE) -s build-node-api-tests 333 $(MAKE) -s cctest 334 $(MAKE) -s jstest 335 336.PHONY: test-only 337test-only: all ## For a quick test, does not run linter or build docs. 338 $(MAKE) build-addons 339 $(MAKE) build-js-native-api-tests 340 $(MAKE) build-node-api-tests 341 $(MAKE) cctest 342 $(MAKE) jstest 343 $(MAKE) tooltest 344 345# Used by `make coverage-test` 346.PHONY: test-cov 347test-cov: all 348 $(MAKE) build-addons 349 $(MAKE) build-js-native-api-tests 350 $(MAKE) build-node-api-tests 351 $(MAKE) cctest 352 CI_SKIP_TESTS=$(COV_SKIP_TESTS) $(MAKE) jstest 353 354.PHONY: test-parallel 355test-parallel: all 356 $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) parallel 357 358.PHONY: test-valgrind 359test-valgrind: all 360 $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) --valgrind sequential parallel message 361 362.PHONY: test-check-deopts 363test-check-deopts: all 364 $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) --check-deopts parallel sequential 365 366DOCBUILDSTAMP_PREREQS = tools/doc/addon-verify.mjs doc/api/addons.md 367 368ifeq ($(OSTYPE),aix) 369DOCBUILDSTAMP_PREREQS := $(DOCBUILDSTAMP_PREREQS) out/$(BUILDTYPE)/node.exp 370endif 371ifeq ($(OSTYPE),os400) 372DOCBUILDSTAMP_PREREQS := $(DOCBUILDSTAMP_PREREQS) out/$(BUILDTYPE)/node.exp 373endif 374 375node_use_openssl = $(call available-node,"-p" \ 376 "process.versions.openssl != undefined") 377test/addons/.docbuildstamp: $(DOCBUILDSTAMP_PREREQS) tools/doc/node_modules 378 @if [ "$(shell $(node_use_openssl))" != "true" ]; then \ 379 echo "Skipping .docbuildstamp (no crypto)"; \ 380 else \ 381 $(RM) -r test/addons/??_*/; \ 382 [ -x $(NODE) ] && $(NODE) $< || node $< ; \ 383 [ $$? -eq 0 ] && touch $@; \ 384 fi 385 386ADDONS_BINDING_GYPS := \ 387 $(filter-out test/addons/??_*/binding.gyp, \ 388 $(wildcard test/addons/*/binding.gyp)) 389 390ADDONS_BINDING_SOURCES := \ 391 $(filter-out test/addons/??_*/*.cc, $(wildcard test/addons/*/*.cc)) \ 392 $(filter-out test/addons/??_*/*.h, $(wildcard test/addons/*/*.h)) 393 394ADDONS_PREREQS := config.gypi \ 395 deps/npm/node_modules/node-gyp/package.json tools/build-addons.mjs \ 396 deps/uv/include/*.h deps/v8/include/*.h \ 397 src/node.h src/node_buffer.h src/node_object_wrap.h src/node_version.h 398 399define run_build_addons 400env npm_config_loglevel=$(LOGLEVEL) npm_config_nodedir="$$PWD" \ 401 npm_config_python="$(PYTHON)" $(NODE) "$$PWD/tools/build-addons.mjs" \ 402 "$$PWD/deps/npm/node_modules/node-gyp/bin/node-gyp.js" \ 403 $1 404touch $2 405endef 406 407# Implicitly depends on $(NODE_EXE), see the build-addons rule for rationale. 408# Depends on node-gyp package.json so that build-addons is (re)executed when 409# node-gyp is updated as part of an npm update. 410test/addons/.buildstamp: $(ADDONS_PREREQS) \ 411 $(ADDONS_BINDING_GYPS) $(ADDONS_BINDING_SOURCES) \ 412 test/addons/.docbuildstamp 413 @$(call run_build_addons,"$$PWD/test/addons",$@) 414 415.PHONY: build-addons 416# .buildstamp needs $(NODE_EXE) but cannot depend on it 417# directly because it calls make recursively. The parent make cannot know 418# if the subprocess touched anything so it pessimistically assumes that 419# .buildstamp is out of date and need a rebuild. 420# Just goes to show that recursive make really is harmful... 421# TODO(bnoordhuis) Force rebuild after gyp update. 422build-addons: | $(NODE_EXE) test/addons/.buildstamp 423 424JS_NATIVE_API_BINDING_GYPS := \ 425 $(filter-out test/js-native-api/??_*/binding.gyp, \ 426 $(wildcard test/js-native-api/*/binding.gyp)) 427 428JS_NATIVE_API_BINDING_SOURCES := \ 429 $(filter-out test/js-native-api/??_*/*.c, $(wildcard test/js-native-api/*/*.c)) \ 430 $(filter-out test/js-native-api/??_*/*.cc, $(wildcard test/js-native-api/*/*.cc)) \ 431 $(filter-out test/js-native-api/??_*/*.h, $(wildcard test/js-native-api/*/*.h)) 432 433# Implicitly depends on $(NODE_EXE), see the build-js-native-api-tests rule for rationale. 434test/js-native-api/.buildstamp: $(ADDONS_PREREQS) \ 435 $(JS_NATIVE_API_BINDING_GYPS) $(JS_NATIVE_API_BINDING_SOURCES) \ 436 src/node_api.h src/node_api_types.h src/js_native_api.h \ 437 src/js_native_api_types.h src/js_native_api_v8.h src/js_native_api_v8_internals.h 438 @$(call run_build_addons,"$$PWD/test/js-native-api",$@) 439 440.PHONY: build-js-native-api-tests 441# .buildstamp needs $(NODE_EXE) but cannot depend on it 442# directly because it calls make recursively. The parent make cannot know 443# if the subprocess touched anything so it pessimistically assumes that 444# .buildstamp is out of date and need a rebuild. 445# Just goes to show that recursive make really is harmful... 446# TODO(bnoordhuis) Force rebuild after gyp or node-gyp update. 447build-js-native-api-tests: | $(NODE_EXE) test/js-native-api/.buildstamp 448 449NODE_API_BINDING_GYPS := \ 450 $(filter-out test/node-api/??_*/binding.gyp, \ 451 $(wildcard test/node-api/*/binding.gyp)) 452 453NODE_API_BINDING_SOURCES := \ 454 $(filter-out test/node-api/??_*/*.c, $(wildcard test/node-api/*/*.c)) \ 455 $(filter-out test/node-api/??_*/*.cc, $(wildcard test/node-api/*/*.cc)) \ 456 $(filter-out test/node-api/??_*/*.h, $(wildcard test/node-api/*/*.h)) 457 458# Implicitly depends on $(NODE_EXE), see the build-node-api-tests rule for rationale. 459test/node-api/.buildstamp: $(ADDONS_PREREQS) \ 460 $(NODE_API_BINDING_GYPS) $(NODE_API_BINDING_SOURCES) \ 461 src/node_api.h src/node_api_types.h src/js_native_api.h \ 462 src/js_native_api_types.h src/js_native_api_v8.h src/js_native_api_v8_internals.h 463 @$(call run_build_addons,"$$PWD/test/node-api",$@) 464 465.PHONY: build-node-api-tests 466# .buildstamp needs $(NODE_EXE) but cannot depend on it 467# directly because it calls make recursively. The parent make cannot know 468# if the subprocess touched anything so it pessimistically assumes that 469# .buildstamp is out of date and need a rebuild. 470# Just goes to show that recursive make really is harmful... 471# TODO(bnoordhuis) Force rebuild after gyp or node-gyp update. 472build-node-api-tests: | $(NODE_EXE) test/node-api/.buildstamp 473 474BENCHMARK_NAPI_BINDING_GYPS := $(wildcard benchmark/napi/*/binding.gyp) 475 476BENCHMARK_NAPI_BINDING_SOURCES := \ 477 $(wildcard benchmark/napi/*/*.c) \ 478 $(wildcard benchmark/napi/*/*.cc) \ 479 $(wildcard benchmark/napi/*/*.h) 480 481benchmark/napi/.buildstamp: $(ADDONS_PREREQS) \ 482 $(BENCHMARK_NAPI_BINDING_GYPS) $(BENCHMARK_NAPI_BINDING_SOURCES) 483 @$(call run_build_addons,"$$PWD/benchmark/napi",$@) 484 485.PHONY: clear-stalled 486clear-stalled: 487 $(info Clean up any leftover processes but don't error if found.) 488 ps awwx | grep Release/node | grep -v grep | cat 489 @PS_OUT=`ps awwx | grep Release/node | grep -v grep | awk '{print $$1}'`; \ 490 if [ "$${PS_OUT}" ]; then \ 491 echo $${PS_OUT} | xargs kill -9; \ 492 fi 493 494.PHONY: test-build 495test-build: | all build-addons build-js-native-api-tests build-node-api-tests 496 497.PHONY: test-build-js-native-api 498test-build-js-native-api: all build-js-native-api-tests 499 500.PHONY: test-build-node-api 501test-build-node-api: all build-node-api-tests 502 503.PHONY: test-all 504test-all: test-build ## Run default tests with both Debug and Release builds. 505 $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=debug,release 506 507.PHONY: test-all-valgrind 508test-all-valgrind: test-build 509 $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=debug,release --valgrind 510 511.PHONY: test-all-suites 512test-all-suites: | clear-stalled test-build bench-addons-build doc-only ## Run all test suites. 513 $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) test/* 514 515JS_SUITES ?= default 516NATIVE_SUITES ?= addons js-native-api node-api 517# CI_* variables should be kept synchronized with the ones in vcbuild.bat 518CI_NATIVE_SUITES ?= $(NATIVE_SUITES) benchmark 519CI_JS_SUITES ?= $(JS_SUITES) pummel 520ifeq ($(node_use_openssl), false) 521 CI_DOC := doctool 522else 523 CI_DOC = 524endif 525 526.PHONY: test-ci-native 527# Build and test addons without building anything else 528# Related CI job: node-test-commit-arm-fanned 529test-ci-native: LOGLEVEL := info 530test-ci-native: | benchmark/napi/.buildstamp test/addons/.buildstamp test/js-native-api/.buildstamp test/node-api/.buildstamp 531 $(PYTHON) tools/test.py $(PARALLEL_ARGS) -p tap --logfile test.tap \ 532 --mode=$(BUILDTYPE_LOWER) --flaky-tests=$(FLAKY_TESTS) \ 533 $(TEST_CI_ARGS) $(CI_NATIVE_SUITES) 534 535.PHONY: test-ci-js 536# This target should not use a native compiler at all 537# Related CI job: node-test-commit-arm-fanned 538test-ci-js: | clear-stalled 539 $(PYTHON) tools/test.py $(PARALLEL_ARGS) -p tap --logfile test.tap \ 540 --mode=$(BUILDTYPE_LOWER) --flaky-tests=$(FLAKY_TESTS) \ 541 $(TEST_CI_ARGS) $(CI_JS_SUITES) 542 $(info Clean up any leftover processes, error if found.) 543 ps awwx | grep Release/node | grep -v grep | cat 544 @PS_OUT=`ps awwx | grep Release/node | grep -v grep | awk '{print $$1}'`; \ 545 if [ "$${PS_OUT}" ]; then \ 546 echo $${PS_OUT} | xargs kill -9; exit 1; \ 547 fi 548 549.PHONY: test-ci 550# Related CI jobs: most CI tests, excluding node-test-commit-arm-fanned 551test-ci: LOGLEVEL := info 552test-ci: | clear-stalled bench-addons-build build-addons build-js-native-api-tests build-node-api-tests doc-only 553 out/Release/cctest --gtest_output=xml:out/junit/cctest.xml 554 $(PYTHON) tools/test.py $(PARALLEL_ARGS) -p tap --logfile test.tap \ 555 --mode=$(BUILDTYPE_LOWER) --flaky-tests=$(FLAKY_TESTS) \ 556 $(TEST_CI_ARGS) $(CI_JS_SUITES) $(CI_NATIVE_SUITES) $(CI_DOC) 557 out/Release/embedtest 'require("./test/embedding/test-embedding.js")' 558 $(info Clean up any leftover processes, error if found.) 559 ps awwx | grep Release/node | grep -v grep | cat 560 @PS_OUT=`ps awwx | grep Release/node | grep -v grep | awk '{print $$1}'`; \ 561 if [ "$${PS_OUT}" ]; then \ 562 echo $${PS_OUT} | xargs kill -9; exit 1; \ 563 fi 564 565.PHONY: build-ci 566# Prepare the build for running the tests. 567# Related CI jobs: most CI tests, excluding node-test-commit-arm-fanned 568build-ci: 569 $(PYTHON) ./configure --verbose $(CONFIG_FLAGS) 570 $(MAKE) 571 572.PHONY: run-ci 573# Run by CI tests, exceptions: 574# - node-test-commit-arm-fanned (Raspberry Pis), where the binaries are 575# cross-compiled, then transferred elsewhere to run different subsets 576# of tests. See `test-ci-native` and `test-ci-js`. 577# - node-test-commit-linux-coverage: where the build and the tests need 578# to be instrumented, see `coverage`. 579# 580# Using -j1 as the sub target in `test-ci` already have internal parallelism. 581# Refs: https://github.com/nodejs/node/pull/23733 582run-ci: build-ci 583 $(MAKE) test-ci -j1 584 585.PHONY: test-release 586test-release: test-build 587 $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) 588 589.PHONY: test-debug 590test-debug: test-build 591 $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=debug 592 593.PHONY: test-message 594test-message: test-build 595 $(PYTHON) tools/test.py $(PARALLEL_ARGS) message 596 597.PHONY: test-wpt 598test-wpt: all 599 $(PYTHON) tools/test.py $(PARALLEL_ARGS) wpt 600 601.PHONY: test-wpt-report 602test-wpt-report: 603 $(RM) -r out/wpt 604 mkdir -p out/wpt 605 WPT_REPORT=1 $(PYTHON) tools/test.py --shell $(NODE) $(PARALLEL_ARGS) wpt 606 607.PHONY: test-simple 608test-simple: | cctest # Depends on 'all'. 609 $(PYTHON) tools/test.py $(PARALLEL_ARGS) parallel sequential 610 611.PHONY: test-pummel 612test-pummel: all 613 $(PYTHON) tools/test.py $(PARALLEL_ARGS) pummel 614 615.PHONY: test-internet 616test-internet: all 617 $(PYTHON) tools/test.py $(PARALLEL_ARGS) internet 618 619.PHONY: test-benchmark 620test-benchmark: | bench-addons-build 621 $(PYTHON) tools/test.py $(PARALLEL_ARGS) benchmark 622 623.PHONY: test-tick-processor 624test-tick-processor: all 625 $(PYTHON) tools/test.py $(PARALLEL_ARGS) tick-processor 626 627.PHONY: test-hash-seed 628# Verifies the hash seed used by V8 for hashing is random. 629test-hash-seed: all 630 $(NODE) test/pummel/test-hash-seed.js 631 632.PHONY: test-doc 633test-doc: doc-only lint-md ## Builds, lints, and verifies the docs. 634 @if [ "$(shell $(node_use_openssl))" != "true" ]; then \ 635 echo "Skipping test-doc (no crypto)"; \ 636 else \ 637 $(PYTHON) tools/test.py $(PARALLEL_ARGS) doctool; \ 638 fi 639 640.PHONY: test-doc-ci 641test-doc-ci: doc-only 642 $(PYTHON) tools/test.py --shell $(NODE) $(TEST_CI_ARGS) $(PARALLEL_ARGS) doctool 643 644.PHONY: test-known-issues 645test-known-issues: all 646 $(PYTHON) tools/test.py $(PARALLEL_ARGS) known_issues 647 648# Related CI job: node-test-npm 649.PHONY: test-npm 650test-npm: $(NODE_EXE) ## Run the npm test suite on deps/npm. 651 $(NODE) tools/test-npm-package --install --logfile=test-npm.tap deps/npm test 652 653.PHONY: test-npm-publish 654test-npm-publish: $(NODE_EXE) 655 npm_package_config_publishtest=true $(NODE) deps/npm/test/run.js 656 657.PHONY: test-js-native-api 658test-js-native-api: test-build-js-native-api 659 $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) js-native-api 660 661.PHONY: test-js-native-api-clean 662.NOTPARALLEL: test-js-native-api-clean 663test-js-native-api-clean: 664 $(RM) -r test/js-native-api/*/build 665 $(RM) test/js-native-api/.buildstamp 666 667.PHONY: test-node-api 668test-node-api: test-build-node-api 669 $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) node-api 670 671.PHONY: test-node-api-clean 672.NOTPARALLEL: test-node-api-clean 673test-node-api-clean: 674 $(RM) -r test/node-api/*/build 675 $(RM) test/node-api/.buildstamp 676 677.PHONY: test-addons 678test-addons: test-build test-js-native-api test-node-api 679 $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) addons 680 681.PHONY: test-addons-clean 682.NOTPARALLEL: test-addons-clean 683test-addons-clean: 684 $(RM) -r test/addons/??_*/ 685 $(RM) -r test/addons/*/build 686 $(RM) test/addons/.buildstamp test/addons/.docbuildstamp 687 $(MAKE) test-js-native-api-clean 688 $(MAKE) test-node-api-clean 689 690.PHONY: test-async-hooks 691test-async-hooks: 692 $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) async-hooks 693 694.PHONY: test-with-async-hooks 695test-with-async-hooks: 696 $(MAKE) build-addons 697 $(MAKE) build-js-native-api-tests 698 $(MAKE) build-node-api-tests 699 $(MAKE) cctest 700 NODE_TEST_WITH_ASYNC_HOOKS=1 $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) \ 701 $(JS_SUITES) \ 702 $(NATIVE_SUITES) 703 704 705.PHONY: test-v8 706.PHONY: test-v8-all 707.PHONY: test-v8-benchmarks 708.PHONY: test-v8-intl 709.PHONY: test-v8-updates 710ifneq ("","$(wildcard deps/v8/tools/run-tests.py)") 711# Related CI job: node-test-commit-v8-linux 712test-v8: v8 ## Runs the V8 test suite on deps/v8. 713 export PATH="$(NO_BIN_OVERRIDE_PATH)" && \ 714 $(PYTHON) deps/v8/tools/run-tests.py --gn --arch=$(V8_ARCH) $(V8_TEST_OPTIONS) \ 715 mjsunit cctest debugger inspector message preparser \ 716 $(TAP_V8) 717 $(call convert_to_junit,$(TAP_V8_JSON)) 718 $(info Testing hash seed) 719 $(MAKE) test-hash-seed 720 721test-v8-intl: v8 722 export PATH="$(NO_BIN_OVERRIDE_PATH)" && \ 723 $(PYTHON) deps/v8/tools/run-tests.py --gn --arch=$(V8_ARCH) \ 724 intl \ 725 $(TAP_V8_INTL) 726 $(call convert_to_junit,$(TAP_V8_INTL_JSON)) 727 728test-v8-benchmarks: v8 729 export PATH="$(NO_BIN_OVERRIDE_PATH)" && \ 730 $(PYTHON) deps/v8/tools/run-tests.py --gn --arch=$(V8_ARCH) \ 731 benchmarks \ 732 $(TAP_V8_BENCHMARKS) 733 $(call convert_to_junit,$(TAP_V8_BENCHMARKS_JSON)) 734 735test-v8-updates: 736 $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) v8-updates 737 738test-v8-all: test-v8 test-v8-intl test-v8-benchmarks test-v8-updates 739# runs all v8 tests 740else 741test-v8 test-v8-intl test-v8-benchmarks test-v8-all: 742 $(warning Testing V8 is not available through the source tarball.) 743 $(warning Use the git repo instead: $$ git clone https://github.com/nodejs/node.git) 744endif 745 746apidoc_dirs = out/doc out/doc/api out/doc/api/assets 747apidoc_sources = $(wildcard doc/api/*.md) 748apidocs_html = $(addprefix out/,$(apidoc_sources:.md=.html)) 749apidocs_json = $(addprefix out/,$(apidoc_sources:.md=.json)) 750 751apiassets = $(subst api_assets,api/assets,$(addprefix out/,$(wildcard doc/api_assets/*))) 752 753tools/doc/node_modules: tools/doc/package.json 754 @if [ "$(shell $(node_use_openssl))" != "true" ]; then \ 755 echo "Skipping tools/doc/node_modules (no crypto)"; \ 756 else \ 757 cd tools/doc && $(call available-node,$(run-npm-ci)) \ 758 fi 759 760.PHONY: doc-only 761doc-only: tools/doc/node_modules \ 762 $(apidoc_dirs) $(apiassets) ## Builds the docs with the local or the global Node.js binary. 763 @if [ "$(shell $(node_use_openssl))" != "true" ]; then \ 764 echo "Skipping doc-only (no crypto)"; \ 765 else \ 766 $(MAKE) out/doc/api/all.html out/doc/api/all.json out/doc/api/stability; \ 767 fi 768 769.PHONY: doc 770doc: $(NODE_EXE) doc-only 771 772out/doc: 773 mkdir -p $@ 774 775# If it's a source tarball, doc/api already contains the generated docs. 776# Just copy everything under doc/api over. 777out/doc/api: doc/api 778 mkdir -p $@ 779 cp -r doc/api out/doc 780 781# If it's a source tarball, assets are already in doc/api/assets 782out/doc/api/assets: 783 mkdir -p $@ 784 if [ -d doc/api/assets ]; then cp -r doc/api/assets out/doc/api; fi; 785 786# If it's not a source tarball, we need to copy assets from doc/api_assets 787out/doc/api/assets/%: doc/api_assets/% | out/doc/api/assets 788 @cp $< $@ ; $(RM) out/doc/api/assets/README.md 789 790 791run-npm-ci = $(PWD)/$(NPM) ci 792 793LINK_DATA = out/doc/apilinks.json 794VERSIONS_DATA = out/previous-doc-versions.json 795gen-api = tools/doc/generate.mjs --node-version=$(FULLVERSION) \ 796 --apilinks=$(LINK_DATA) $< --output-directory=out/doc/api \ 797 --versions-file=$(VERSIONS_DATA) 798gen-apilink = tools/doc/apilinks.mjs $(LINK_DATA) $(wildcard lib/*.js) 799 800$(LINK_DATA): $(wildcard lib/*.js) tools/doc/apilinks.mjs | out/doc 801 $(call available-node, $(gen-apilink)) 802 803# Regenerate previous versions data if the current version changes 804$(VERSIONS_DATA): CHANGELOG.md src/node_version.h tools/doc/versions.mjs 805 $(call available-node, tools/doc/versions.mjs $@) 806 807node_use_icu = $(call available-node,"-p" "typeof Intl === 'object'") 808 809out/doc/api/%.json out/doc/api/%.html: doc/api/%.md tools/doc/generate.mjs \ 810 tools/doc/markdown.mjs tools/doc/html.mjs tools/doc/json.mjs \ 811 tools/doc/apilinks.mjs $(VERSIONS_DATA) | $(LINK_DATA) out/doc/api 812 @if [ "$(shell $(node_use_icu))" != "true" ]; then \ 813 echo "Skipping documentation generation (no ICU)"; \ 814 else \ 815 $(call available-node, $(gen-api)) \ 816 fi 817 818out/doc/api/all.html: $(apidocs_html) tools/doc/allhtml.mjs \ 819 tools/doc/apilinks.mjs | out/doc/api 820 @if [ "$(shell $(node_use_icu))" != "true" ]; then \ 821 echo "Skipping HTML single-page doc generation (no ICU)"; \ 822 else \ 823 $(call available-node, tools/doc/allhtml.mjs) \ 824 fi 825 826out/doc/api/all.json: $(apidocs_json) tools/doc/alljson.mjs | out/doc/api 827 @if [ "$(shell $(node_use_icu))" != "true" ]; then \ 828 echo "Skipping JSON single-file generation (no ICU)"; \ 829 else \ 830 $(call available-node, tools/doc/alljson.mjs) \ 831 fi 832 833.PHONY: out/doc/api/stability 834out/doc/api/stability: out/doc/api/all.json tools/doc/stability.mjs | out/doc/api 835 @if [ "$(shell $(node_use_icu))" != "true" ]; then \ 836 echo "Skipping stability indicator generation (no ICU)"; \ 837 else \ 838 $(call available-node, tools/doc/stability.mjs) \ 839 fi 840 841.PHONY: docopen 842docopen: out/doc/api/all.html 843 @$(PYTHON) -mwebbrowser file://$(abspath $<) 844 845.PHONY: docserve 846docserve: $(apidocs_html) $(apiassets) 847 @$(PYTHON) -m http.server 8000 --bind 127.0.0.1 --directory out/doc/api 848 849.PHONY: docclean 850.NOTPARALLEL: docclean 851docclean: 852 $(RM) -r out/doc 853 $(RM) "$(VERSIONS_DATA)" 854 855RAWVER=$(shell $(PYTHON) tools/getnodeversion.py) 856VERSION=v$(RAWVER) 857CHANGELOG=doc/changelogs/CHANGELOG_V$(firstword $(subst ., ,$(RAWVER))).md 858 859# For nightly builds, you must set DISTTYPE to "nightly", "next-nightly" or 860# "custom". For the nightly and next-nightly case, you need to set DATESTRING 861# and COMMIT in order to properly name the build. 862# For the rc case you need to set CUSTOMTAG to an appropriate CUSTOMTAG number 863 864ifndef DISTTYPE 865DISTTYPE=release 866endif 867ifeq ($(DISTTYPE),release) 868FULLVERSION=$(VERSION) 869else # ifeq ($(DISTTYPE),release) 870ifeq ($(DISTTYPE),custom) 871ifndef CUSTOMTAG 872$(error CUSTOMTAG is not set for DISTTYPE=custom) 873endif # ifndef CUSTOMTAG 874TAG=$(CUSTOMTAG) 875else # ifeq ($(DISTTYPE),custom) 876ifndef DATESTRING 877$(error DATESTRING is not set for nightly) 878endif # ifndef DATESTRING 879ifndef COMMIT 880$(error COMMIT is not set for nightly) 881endif # ifndef COMMIT 882ifneq ($(DISTTYPE),nightly) 883ifneq ($(DISTTYPE),next-nightly) 884$(error DISTTYPE is not release, custom, nightly or next-nightly) 885endif # ifneq ($(DISTTYPE),next-nightly) 886endif # ifneq ($(DISTTYPE),nightly) 887TAG=$(DISTTYPE)$(DATESTRING)$(COMMIT) 888endif # ifeq ($(DISTTYPE),custom) 889FULLVERSION=$(VERSION)-$(TAG) 890endif # ifeq ($(DISTTYPE),release) 891 892DISTTYPEDIR ?= $(DISTTYPE) 893RELEASE=$(shell sed -ne 's/\#define NODE_VERSION_IS_RELEASE \([01]\)/\1/p' src/node_version.h) 894PLATFORM=$(shell uname | tr '[:upper:]' '[:lower:]') 895ifeq ($(findstring os/390,$PLATFORM),os/390) 896PLATFORM ?= os390 897endif 898NPMVERSION=v$(shell cat deps/npm/package.json | grep '^ "version"' | sed 's/^[^:]*: "\([^"]*\)",.*/\1/') 899 900UNAME_M=$(shell uname -m) 901ifeq ($(findstring x86_64,$(UNAME_M)),x86_64) 902DESTCPU ?= x64 903else 904ifeq ($(findstring amd64,$(UNAME_M)),amd64) 905DESTCPU ?= x64 906else 907ifeq ($(findstring ppc64,$(UNAME_M)),ppc64) 908DESTCPU ?= ppc64 909else 910ifeq ($(findstring ppc,$(UNAME_M)),ppc) 911DESTCPU ?= ppc 912else 913ifeq ($(findstring s390x,$(UNAME_M)),s390x) 914DESTCPU ?= s390x 915else 916ifeq ($(findstring s390,$(UNAME_M)),s390) 917DESTCPU ?= s390 918else 919ifeq ($(findstring OS/390,$(shell uname -s)),OS/390) 920DESTCPU ?= s390x 921else 922ifeq ($(findstring arm64,$(UNAME_M)),arm64) 923DESTCPU ?= arm64 924else 925ifeq ($(findstring arm,$(UNAME_M)),arm) 926DESTCPU ?= arm 927else 928ifeq ($(findstring aarch64,$(UNAME_M)),aarch64) 929DESTCPU ?= arm64 930else 931ifeq ($(findstring powerpc,$(shell uname -p)),powerpc) 932DESTCPU ?= ppc64 933else 934ifeq ($(findstring riscv64,$(UNAME_M)),riscv64) 935DESTCPU ?= riscv64 936else 937DESTCPU ?= x86 938endif 939endif 940endif 941endif 942endif 943endif 944endif 945endif 946endif 947endif 948endif 949endif 950ifeq ($(DESTCPU),x64) 951ARCH=x64 952else 953ifeq ($(DESTCPU),arm) 954ARCH=arm 955else 956ifeq ($(DESTCPU),arm64) 957ARCH=arm64 958else 959ifeq ($(DESTCPU),ppc64) 960ARCH=ppc64 961else 962ifeq ($(DESTCPU),ppc) 963ARCH=ppc 964else 965ifeq ($(DESTCPU),s390) 966ARCH=s390 967else 968ifeq ($(DESTCPU),s390x) 969ARCH=s390x 970else 971ifeq ($(DESTCPU),riscv64) 972ARCH=riscv64 973else 974ARCH=x86 975endif 976endif 977endif 978endif 979endif 980endif 981endif 982endif 983 984# node and v8 use different arch names (e.g. node 'x86' vs v8 'ia32'). 985# pass the proper v8 arch name to $V8_ARCH based on user-specified $DESTCPU. 986ifeq ($(DESTCPU),x86) 987V8_ARCH=ia32 988else 989V8_ARCH ?= $(DESTCPU) 990 991endif 992 993# enforce "x86" over "ia32" as the generally accepted way of referring to 32-bit intel 994ifeq ($(ARCH),ia32) 995override ARCH=x86 996endif 997ifeq ($(DESTCPU),ia32) 998override DESTCPU=x86 999endif 1000 1001TARNAME=node-$(FULLVERSION) 1002TARBALL=$(TARNAME).tar 1003# Custom user-specified variation, use it directly 1004ifdef VARIATION 1005BINARYNAME=$(TARNAME)-$(PLATFORM)-$(ARCH)-$(VARIATION) 1006else 1007BINARYNAME=$(TARNAME)-$(PLATFORM)-$(ARCH) 1008endif 1009BINARYTAR=$(BINARYNAME).tar 1010# OSX doesn't have xz installed by default, http://macpkg.sourceforge.net/ 1011HAS_XZ ?= $(shell command -v xz > /dev/null 2>&1; [ $$? -eq 0 ] && echo 1 || echo 0) 1012# Supply SKIP_XZ=1 to explicitly skip .tar.xz creation 1013SKIP_XZ ?= 0 1014XZ = $(shell [ $(HAS_XZ) -eq 1 ] && [ $(SKIP_XZ) -eq 0 ] && echo 1 || echo 0) 1015XZ_COMPRESSION ?= 9e 1016PKG=$(TARNAME).pkg 1017MACOSOUTDIR=out/macos 1018 1019.PHONY: check-xz 1020ifeq ($(SKIP_XZ), 1) 1021check-xz: 1022 $(info SKIP_XZ=1 supplied, skipping .tar.xz creation) 1023else 1024ifeq ($(HAS_XZ), 1) 1025check-xz: 1026else 1027check-xz: 1028 $(error No xz command, cannot continue) 1029endif 1030endif 1031 1032.PHONY: release-only 1033release-only: check-xz 1034 @if [ "$(DISTTYPE)" = "release" ] && `grep -q REPLACEME doc/api/*.md`; then \ 1035 echo 'Please update REPLACEME tags in the following doc/api/*.md files (See doc/contributing/releases.md):\n' ; \ 1036 REPLACEMES="$(shell grep -l REPLACEME doc/api/*.md)" ; \ 1037 echo "$$REPLACEMES\n" | tr " " "\n" ; \ 1038 exit 1 ; \ 1039 fi 1040 @if [ "$(DISTTYPE)" = "release" ] && \ 1041 `grep -q DEP...X doc/api/deprecations.md`; then \ 1042 echo 'Please update DEP...X in doc/api/deprecations.md (See doc/contributing/releases.md)' ; \ 1043 exit 1 ; \ 1044 fi 1045 @if [ "$(shell git status --porcelain | egrep -v '^\?\? ')" = "" ]; then \ 1046 exit 0 ; \ 1047 else \ 1048 echo "" >&2 ; \ 1049 echo "The git repository is not clean." >&2 ; \ 1050 echo "Please commit changes before building release tarball." >&2 ; \ 1051 echo "" >&2 ; \ 1052 git status --porcelain | egrep -v '^\?\?' >&2 ; \ 1053 echo "" >&2 ; \ 1054 exit 1 ; \ 1055 fi 1056 @if [ "$(DISTTYPE)" != "release" ] || [ "$(RELEASE)" = "1" ]; then \ 1057 exit 0; \ 1058 else \ 1059 echo "" >&2 ; \ 1060 echo "#NODE_VERSION_IS_RELEASE is set to $(RELEASE)." >&2 ; \ 1061 echo "Did you remember to update src/node_version.h?" >&2 ; \ 1062 echo "" >&2 ; \ 1063 exit 1 ; \ 1064 fi 1065 @if [ "$(RELEASE)" = "0" ] || [ -f "$(CHANGELOG)" ]; then \ 1066 exit 0; \ 1067 else \ 1068 echo "" >&2 ; \ 1069 echo "#NODE_VERSION_IS_RELEASE is set to $(RELEASE) but " >&2 ; \ 1070 echo "$(CHANGELOG) does not exist." >&2 ; \ 1071 echo "" >&2 ; \ 1072 exit 1 ; \ 1073 fi 1074 1075$(PKG): release-only 1076# pkg building is currently only supported on an ARM64 macOS host for 1077# ease of compiling fat-binaries for both macOS architectures. 1078ifneq ($(OSTYPE),darwin) 1079 $(warning Invalid OSTYPE) 1080 $(error OSTYPE should be `darwin` currently is $(OSTYPE)) 1081endif 1082ifneq ($(ARCHTYPE),arm64) 1083 $(warning Invalid ARCHTYPE) 1084 $(error ARCHTYPE should be `arm64` currently is $(ARCHTYPE)) 1085endif 1086 $(RM) -r $(MACOSOUTDIR) 1087 mkdir -p $(MACOSOUTDIR)/installer/productbuild 1088 cat tools/macos-installer/productbuild/distribution.xml.tmpl \ 1089 | sed -E "s/\\{nodeversion\\}/$(FULLVERSION)/g" \ 1090 | sed -E "s/\\{npmversion\\}/$(NPMVERSION)/g" \ 1091 >$(MACOSOUTDIR)/installer/productbuild/distribution.xml ; \ 1092 1093 @for dirname in tools/macos-installer/productbuild/Resources/*/; do \ 1094 lang=$$(basename $$dirname) ; \ 1095 mkdir -p $(MACOSOUTDIR)/installer/productbuild/Resources/$$lang ; \ 1096 printf "Found localization directory $$dirname\n" ; \ 1097 cat $$dirname/welcome.html.tmpl \ 1098 | sed -E "s/\\{nodeversion\\}/$(FULLVERSION)/g" \ 1099 | sed -E "s/\\{npmversion\\}/$(NPMVERSION)/g" \ 1100 >$(MACOSOUTDIR)/installer/productbuild/Resources/$$lang/welcome.html ; \ 1101 cat $$dirname/conclusion.html.tmpl \ 1102 | sed -E "s/\\{nodeversion\\}/$(FULLVERSION)/g" \ 1103 | sed -E "s/\\{npmversion\\}/$(NPMVERSION)/g" \ 1104 >$(MACOSOUTDIR)/installer/productbuild/Resources/$$lang/conclusion.html ; \ 1105 done 1106 CC_host="cc -arch x86_64" CXX_host="c++ -arch x86_64" \ 1107 CC_target="cc -arch x86_64" CXX_target="c++ -arch x86_64" \ 1108 CC="cc -arch x86_64" CXX="c++ -arch x86_64" $(PYTHON) ./configure \ 1109 --dest-cpu=x86_64 \ 1110 --tag=$(TAG) \ 1111 --release-urlbase=$(RELEASE_URLBASE) \ 1112 $(CONFIG_FLAGS) $(BUILD_RELEASE_FLAGS) 1113 arch -x86_64 $(MAKE) install V=$(V) DESTDIR=$(MACOSOUTDIR)/dist/x64/node 1114 SIGN="$(CODESIGN_CERT)" PKGDIR="$(MACOSOUTDIR)/dist/x64/node/usr/local" sh \ 1115 tools/osx-codesign.sh 1116 $(PYTHON) ./configure \ 1117 --dest-cpu=arm64 \ 1118 --tag=$(TAG) \ 1119 --release-urlbase=$(RELEASE_URLBASE) \ 1120 $(CONFIG_FLAGS) $(BUILD_RELEASE_FLAGS) 1121 $(MAKE) install V=$(V) DESTDIR=$(MACOSOUTDIR)/dist/node 1122 SIGN="$(CODESIGN_CERT)" PKGDIR="$(MACOSOUTDIR)/dist/node/usr/local" sh \ 1123 tools/osx-codesign.sh 1124 lipo $(MACOSOUTDIR)/dist/x64/node/usr/local/bin/node \ 1125 $(MACOSOUTDIR)/dist/node/usr/local/bin/node \ 1126 -output $(MACOSOUTDIR)/dist/node/usr/local/bin/node \ 1127 -create 1128 mkdir -p $(MACOSOUTDIR)/dist/npm/usr/local/lib/node_modules 1129 mkdir -p $(MACOSOUTDIR)/pkgs 1130 mv $(MACOSOUTDIR)/dist/node/usr/local/lib/node_modules/npm \ 1131 $(MACOSOUTDIR)/dist/npm/usr/local/lib/node_modules 1132 unlink $(MACOSOUTDIR)/dist/node/usr/local/bin/npm 1133 unlink $(MACOSOUTDIR)/dist/node/usr/local/bin/npx 1134 $(NODE) tools/license2rtf.mjs < LICENSE > \ 1135 $(MACOSOUTDIR)/installer/productbuild/Resources/license.rtf 1136 cp doc/osx_installer_logo.png $(MACOSOUTDIR)/installer/productbuild/Resources 1137 pkgbuild --version $(FULLVERSION) \ 1138 --identifier org.nodejs.node.pkg \ 1139 --root $(MACOSOUTDIR)/dist/node $(MACOSOUTDIR)/pkgs/node-$(FULLVERSION).pkg 1140 pkgbuild --version $(NPMVERSION) \ 1141 --identifier org.nodejs.npm.pkg \ 1142 --root $(MACOSOUTDIR)/dist/npm \ 1143 --scripts ./tools/macos-installer/pkgbuild/npm/scripts \ 1144 $(MACOSOUTDIR)/pkgs/npm-$(NPMVERSION).pkg 1145 productbuild --distribution $(MACOSOUTDIR)/installer/productbuild/distribution.xml \ 1146 --resources $(MACOSOUTDIR)/installer/productbuild/Resources \ 1147 --package-path $(MACOSOUTDIR)/pkgs ./$(PKG) 1148 SIGN="$(PRODUCTSIGN_CERT)" PKG="$(PKG)" sh tools/osx-productsign.sh 1149 sh tools/osx-notarize.sh $(FULLVERSION) 1150 1151.PHONY: pkg 1152# Builds the macOS installer for releases. 1153pkg: $(PKG) 1154 1155.PHONY: corepack-update 1156corepack-update: 1157 mkdir -p /tmp/node-corepack 1158 curl -qLo /tmp/node-corepack/package.tgz "$$(npm view corepack dist.tarball)" 1159 1160 rm -rf deps/corepack && mkdir deps/corepack 1161 cd deps/corepack && tar xf /tmp/node-corepack/package.tgz --strip-components=1 1162 chmod +x deps/corepack/shims/* 1163 1164 node deps/corepack/dist/corepack.js --version 1165 1166.PHONY: pkg-upload 1167# Note: this is strictly for release builds on release machines only. 1168pkg-upload: pkg 1169 ssh $(STAGINGSERVER) "mkdir -p nodejs/$(DISTTYPEDIR)/$(FULLVERSION)" 1170 chmod 664 $(TARNAME).pkg 1171 scp -p $(TARNAME).pkg $(STAGINGSERVER):nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME).pkg 1172 ssh $(STAGINGSERVER) "touch nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME).pkg.done" 1173 1174$(TARBALL): release-only doc-only 1175 git checkout-index -a -f --prefix=$(TARNAME)/ 1176 mkdir -p $(TARNAME)/doc/api 1177 cp doc/node.1 $(TARNAME)/doc/node.1 1178 cp -r out/doc/api/* $(TARNAME)/doc/api/ 1179 $(RM) -r $(TARNAME)/.editorconfig 1180 $(RM) -r $(TARNAME)/.git* 1181 $(RM) -r $(TARNAME)/.mailmap 1182 $(RM) -r $(TARNAME)/deps/openssl/openssl/demos 1183 $(RM) -r $(TARNAME)/deps/openssl/openssl/doc 1184 $(RM) -r $(TARNAME)/deps/openssl/openssl/test 1185 $(RM) -r $(TARNAME)/deps/uv/docs 1186 $(RM) -r $(TARNAME)/deps/uv/samples 1187 $(RM) -r $(TARNAME)/deps/uv/test 1188 $(RM) -r $(TARNAME)/deps/v8/samples 1189 $(RM) -r $(TARNAME)/deps/v8/tools/profviz 1190 $(RM) -r $(TARNAME)/deps/v8/tools/run-tests.py 1191 $(RM) -r $(TARNAME)/doc/images # too big 1192 $(RM) -r $(TARNAME)/test*.tap 1193 $(RM) -r $(TARNAME)/tools/cpplint.py 1194 $(RM) -r $(TARNAME)/tools/eslint-rules 1195 $(RM) -r $(TARNAME)/tools/license-builder.sh 1196 $(RM) -r $(TARNAME)/tools/node_modules 1197 $(RM) -r $(TARNAME)/tools/osx-* 1198 $(RM) -r $(TARNAME)/tools/osx-pkg.pmdoc 1199 find $(TARNAME)/deps/v8/test/* -type d ! -regex '.*/test/torque$$' | xargs $(RM) -r 1200 find $(TARNAME)/deps/v8/test -type f ! -regex '.*/test/torque/.*' | xargs $(RM) 1201 find $(TARNAME)/deps/zlib/contrib/* -type d ! -regex '.*/contrib/optimizations$$' | xargs $(RM) -r 1202 find $(TARNAME)/ -name ".eslint*" -maxdepth 2 | xargs $(RM) 1203 find $(TARNAME)/ -type l | xargs $(RM) 1204 tar -cf $(TARNAME).tar $(TARNAME) 1205 $(RM) -r $(TARNAME) 1206 gzip -c -f -9 $(TARNAME).tar > $(TARNAME).tar.gz 1207ifeq ($(XZ), 1) 1208 xz -c -f -$(XZ_COMPRESSION) $(TARNAME).tar > $(TARNAME).tar.xz 1209endif 1210 $(RM) $(TARNAME).tar 1211 1212.PHONY: tar 1213tar: $(TARBALL) ## Create a source tarball. 1214 1215.PHONY: tar-upload 1216# Note: this is strictly for release builds on release machines only. 1217tar-upload: tar 1218 ssh $(STAGINGSERVER) "mkdir -p nodejs/$(DISTTYPEDIR)/$(FULLVERSION)" 1219 chmod 664 $(TARNAME).tar.gz 1220 scp -p $(TARNAME).tar.gz $(STAGINGSERVER):nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME).tar.gz 1221 ssh $(STAGINGSERVER) "touch nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME).tar.gz.done" 1222ifeq ($(XZ), 1) 1223 chmod 664 $(TARNAME).tar.xz 1224 scp -p $(TARNAME).tar.xz $(STAGINGSERVER):nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME).tar.xz 1225 ssh $(STAGINGSERVER) "touch nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME).tar.xz.done" 1226endif 1227 1228.PHONY: doc-upload 1229# Note: this is strictly for release builds on release machines only. 1230doc-upload: doc 1231 ssh $(STAGINGSERVER) "mkdir -p nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/docs/" 1232 chmod -R ug=rw-x+X,o=r+X out/doc/ 1233 scp -pr out/doc/* $(STAGINGSERVER):nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/docs/ 1234 ssh $(STAGINGSERVER) "touch nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/docs.done" 1235 1236.PHONY: $(TARBALL)-headers 1237$(TARBALL)-headers: release-only 1238 $(PYTHON) ./configure \ 1239 --prefix=/ \ 1240 --dest-cpu=$(DESTCPU) \ 1241 --tag=$(TAG) \ 1242 --release-urlbase=$(RELEASE_URLBASE) \ 1243 $(CONFIG_FLAGS) $(BUILD_RELEASE_FLAGS) 1244 HEADERS_ONLY=1 $(PYTHON) tools/install.py install '$(TARNAME)' '/' 1245 find $(TARNAME)/ -type l | xargs $(RM) 1246 tar -cf $(TARNAME)-headers.tar $(TARNAME) 1247 $(RM) -r $(TARNAME) 1248 gzip -c -f -9 $(TARNAME)-headers.tar > $(TARNAME)-headers.tar.gz 1249ifeq ($(XZ), 1) 1250 xz -c -f -$(XZ_COMPRESSION) $(TARNAME)-headers.tar > $(TARNAME)-headers.tar.xz 1251endif 1252 $(RM) $(TARNAME)-headers.tar 1253 1254.PHONY: tar-headers 1255tar-headers: $(TARBALL)-headers ## Build the node header tarball. 1256 1257.PHONY: tar-headers-upload 1258tar-headers-upload: tar-headers 1259 ssh $(STAGINGSERVER) "mkdir -p nodejs/$(DISTTYPEDIR)/$(FULLVERSION)" 1260 chmod 664 $(TARNAME)-headers.tar.gz 1261 scp -p $(TARNAME)-headers.tar.gz $(STAGINGSERVER):nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME)-headers.tar.gz 1262 ssh $(STAGINGSERVER) "touch nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME)-headers.tar.gz.done" 1263ifeq ($(XZ), 1) 1264 chmod 664 $(TARNAME)-headers.tar.xz 1265 scp -p $(TARNAME)-headers.tar.xz $(STAGINGSERVER):nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME)-headers.tar.xz 1266 ssh $(STAGINGSERVER) "touch nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME)-headers.tar.xz.done" 1267endif 1268 1269$(BINARYTAR): release-only 1270 $(RM) -r $(BINARYNAME) 1271 $(RM) -r out/deps out/Release 1272 $(PYTHON) ./configure \ 1273 --prefix=/ \ 1274 --dest-cpu=$(DESTCPU) \ 1275 --tag=$(TAG) \ 1276 --release-urlbase=$(RELEASE_URLBASE) \ 1277 $(CONFIG_FLAGS) $(BUILD_RELEASE_FLAGS) 1278 $(MAKE) install DESTDIR=$(BINARYNAME) V=$(V) PORTABLE=1 1279 cp README.md $(BINARYNAME) 1280 cp LICENSE $(BINARYNAME) 1281ifeq ("$(wildcard $(CHANGELOG))","") 1282 cp CHANGELOG.md $(BINARYNAME) 1283else 1284 cp $(CHANGELOG) $(BINARYNAME)/CHANGELOG.md 1285endif 1286ifeq ($(OSTYPE),darwin) 1287 SIGN="$(CODESIGN_CERT)" PKGDIR="$(BINARYNAME)" sh tools/osx-codesign.sh 1288endif 1289 tar -cf $(BINARYNAME).tar $(BINARYNAME) 1290 $(RM) -r $(BINARYNAME) 1291 gzip -c -f -9 $(BINARYNAME).tar > $(BINARYNAME).tar.gz 1292ifeq ($(XZ), 1) 1293 xz -c -f -$(XZ_COMPRESSION) $(BINARYNAME).tar > $(BINARYNAME).tar.xz 1294endif 1295 $(RM) $(BINARYNAME).tar 1296 1297.PHONY: binary 1298# This requires NODE_VERSION_IS_RELEASE defined as 1 in src/node_version.h. 1299binary: $(BINARYTAR) ## Build release binary tarballs. 1300 1301.PHONY: binary-upload 1302# Note: this is strictly for release builds on release machines only. 1303binary-upload: binary 1304 ssh $(STAGINGSERVER) "mkdir -p nodejs/$(DISTTYPEDIR)/$(FULLVERSION)" 1305 chmod 664 $(TARNAME)-$(OSTYPE)-$(ARCH).tar.gz 1306 scp -p $(TARNAME)-$(OSTYPE)-$(ARCH).tar.gz $(STAGINGSERVER):nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME)-$(OSTYPE)-$(ARCH).tar.gz 1307 ssh $(STAGINGSERVER) "touch nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME)-$(OSTYPE)-$(ARCH).tar.gz.done" 1308ifeq ($(XZ), 1) 1309 chmod 664 $(TARNAME)-$(OSTYPE)-$(ARCH).tar.xz 1310 scp -p $(TARNAME)-$(OSTYPE)-$(ARCH).tar.xz $(STAGINGSERVER):nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME)-$(OSTYPE)-$(ARCH).tar.xz 1311 ssh $(STAGINGSERVER) "touch nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME)-$(OSTYPE)-$(ARCH).tar.xz.done" 1312endif 1313 1314.PHONY: bench-all 1315.PHONY: bench 1316bench bench-all: bench-addons-build 1317 $(warning Please use benchmark/run.js or benchmark/compare.js to run the benchmarks.) 1318 1319# Build required addons for benchmark before running it. 1320.PHONY: bench-addons-build 1321bench-addons-build: | $(NODE_EXE) benchmark/napi/.buildstamp 1322 1323.PHONY: bench-addons-clean 1324.NOTPARALLEL: bench-addons-clean 1325bench-addons-clean: 1326 $(RM) -r benchmark/napi/*/build 1327 $(RM) benchmark/napi/.buildstamp 1328 1329.PHONY: lint-md-rollup 1330lint-md-rollup: 1331 $(RM) tools/.*mdlintstamp 1332 cd tools/lint-md && npm ci && npm run build 1333 1334.PHONY: lint-md-clean 1335.NOTPARALLEL: lint-md-clean 1336lint-md-clean: 1337 $(RM) -r tools/lint-md/node_modules 1338 $(RM) tools/.*mdlintstamp 1339 1340.PHONY: lint-md-build 1341lint-md-build: 1342 $(warning Deprecated no-op target 'lint-md-build') 1343 1344ifeq ("$(wildcard tools/.mdlintstamp)","") 1345LINT_MD_NEWER = 1346else 1347LINT_MD_NEWER = -newer tools/.mdlintstamp 1348endif 1349 1350LINT_MD_TARGETS = doc src lib benchmark test tools/doc tools/icu $(wildcard *.md) 1351LINT_MD_FILES = $(shell $(FIND) $(LINT_MD_TARGETS) -type f \ 1352 ! -path '*node_modules*' ! -path 'test/fixtures/*' -name '*.md' \ 1353 $(LINT_MD_NEWER)) 1354run-lint-md = tools/lint-md/lint-md.mjs $(LINT_MD_FILES) 1355# Lint all changed markdown files maintained by us 1356tools/.mdlintstamp: $(LINT_MD_FILES) 1357 $(info Running Markdown linter...) 1358 @$(call available-node,$(run-lint-md)) 1359 @touch $@ 1360 1361.PHONY: lint-md 1362# Lints the markdown documents maintained by us in the codebase. 1363lint-md: lint-js-doc | tools/.mdlintstamp 1364 1365run-format-md = tools/lint-md/lint-md.mjs --format $(LINT_MD_FILES) 1366.PHONY: format-md 1367# Formats the markdown documents maintained by us in the codebase. 1368format-md: 1369 @$(call available-node,$(run-format-md)) 1370 1371 1372 1373LINT_JS_TARGETS = .eslintrc.js benchmark doc lib test tools 1374 1375run-lint-js = tools/node_modules/eslint/bin/eslint.js --cache \ 1376 --max-warnings=0 --report-unused-disable-directives $(LINT_JS_TARGETS) 1377run-lint-js-fix = $(run-lint-js) --fix 1378 1379.PHONY: lint-js-fix 1380lint-js-fix: 1381 @$(call available-node,$(run-lint-js-fix)) 1382 1383.PHONY: lint-js 1384.PHONY: lint-js-doc 1385# Note that on the CI `lint-js-ci` is run instead. 1386# Lints the JavaScript code with eslint. 1387lint-js-doc: LINT_JS_TARGETS=doc 1388lint-js lint-js-doc: 1389 @if [ "$(shell $(node_use_openssl))" != "true" ]; then \ 1390 echo "Skipping $@ (no crypto)"; \ 1391 else \ 1392 echo "Running JS linter..."; \ 1393 $(call available-node,$(run-lint-js)) \ 1394 fi 1395 1396jslint: lint-js 1397 $(warning Please use lint-js instead of jslint) 1398 1399run-lint-js-ci = tools/node_modules/eslint/bin/eslint.js \ 1400 --max-warnings=0 --report-unused-disable-directives -f tap \ 1401 -o test-eslint.tap $(LINT_JS_TARGETS) 1402 1403.PHONY: lint-js-ci 1404# On the CI the output is emitted in the TAP format. 1405lint-js-ci: 1406 $(info Running JS linter...) 1407 @$(call available-node,$(run-lint-js-ci)) 1408 1409jslint-ci: lint-js-ci 1410 $(warning Please use lint-js-ci instead of jslint-ci) 1411 1412LINT_CPP_ADDON_DOC_FILES_GLOB = test/addons/??_*/*.cc test/addons/??_*/*.h 1413LINT_CPP_ADDON_DOC_FILES = $(wildcard $(LINT_CPP_ADDON_DOC_FILES_GLOB)) 1414LINT_CPP_EXCLUDE ?= 1415LINT_CPP_EXCLUDE += src/node_root_certs.h 1416LINT_CPP_EXCLUDE += $(LINT_CPP_ADDON_DOC_FILES) 1417# These files were copied more or less verbatim from V8. 1418LINT_CPP_EXCLUDE += src/tracing/trace_event.h src/tracing/trace_event_common.h 1419 1420LINT_CPP_FILES = $(filter-out $(LINT_CPP_EXCLUDE), $(wildcard \ 1421 benchmark/napi/*/*.cc \ 1422 src/*.c \ 1423 src/*.cc \ 1424 src/*.h \ 1425 src/*/*.c \ 1426 src/*/*.cc \ 1427 src/*/*.h \ 1428 test/addons/*/*.cc \ 1429 test/addons/*/*.h \ 1430 test/cctest/*.cc \ 1431 test/cctest/*.h \ 1432 test/embedding/*.cc \ 1433 test/embedding/*.h \ 1434 test/fixtures/*.c \ 1435 test/js-native-api/*/*.cc \ 1436 test/node-api/*/*.cc \ 1437 tools/icu/*.cc \ 1438 tools/icu/*.h \ 1439 tools/code_cache/*.cc \ 1440 tools/code_cache/*.h \ 1441 tools/snapshot/*.cc \ 1442 tools/snapshot/*.h \ 1443 )) 1444 1445FORMAT_CPP_FILES ?= 1446FORMAT_CPP_FILES += $(LINT_CPP_FILES) 1447# C source codes. 1448FORMAT_CPP_FILES += $(wildcard \ 1449 benchmark/napi/*/*.c \ 1450 test/js-native-api/*.h \ 1451 test/js-native-api/*/*.c \ 1452 test/js-native-api/*/*.h \ 1453 test/node-api/*/*.c \ 1454 test/node-api/*/*.h \ 1455 ) 1456 1457# Code blocks don't have newline at the end, 1458# and the actual filename is generated so it won't match header guards 1459ADDON_DOC_LINT_FLAGS=-whitespace/ending_newline,-build/header_guard 1460 1461.PHONY: format-cpp-build 1462format-cpp-build: 1463 cd tools/clang-format && $(call available-node,$(run-npm-ci)) 1464 1465.PHONY: format-cpp-clean 1466.NOTPARALLEL: format-cpp-clean 1467format-cpp-clean: 1468 $(RM) -r tools/clang-format/node_modules 1469 1470CLANG_FORMAT_START ?= HEAD 1471.PHONY: format-cpp 1472# To format staged changes: 1473# $ make format-cpp 1474# To format HEAD~1...HEAD (latest commit): 1475# $ CLANG_FORMAT_START=`git rev-parse HEAD~1` make format-cpp 1476# To format diff between main and current branch head (main...HEAD): 1477# $ CLANG_FORMAT_START=main make format-cpp 1478format-cpp: ## Format C++ diff from $CLANG_FORMAT_START to current changes 1479ifneq ("","$(wildcard tools/clang-format/node_modules/)") 1480 $(info Formatting C++ diff from $(CLANG_FORMAT_START)..) 1481 @$(PYTHON) tools/clang-format/node_modules/.bin/git-clang-format \ 1482 --binary=tools/clang-format/node_modules/.bin/clang-format \ 1483 --style=file \ 1484 $(CLANG_FORMAT_START) -- \ 1485 $(FORMAT_CPP_FILES) 1486else 1487 $(info Required tooling for C++ code formatting is not installed.) 1488 $(info To install (requires internet access) run: $$ make format-cpp-build) 1489endif 1490 1491ifeq ($(V),1) 1492CPPLINT_QUIET = 1493else 1494CPPLINT_QUIET = --quiet 1495endif 1496.PHONY: lint-cpp 1497# Lints the C++ code with cpplint.py and checkimports.py. 1498lint-cpp: tools/.cpplintstamp 1499 1500tools/.cpplintstamp: $(LINT_CPP_FILES) 1501 $(info Running C++ linter...) 1502 @$(PYTHON) tools/cpplint.py $(CPPLINT_QUIET) $? 1503 @$(PYTHON) tools/checkimports.py $? 1504 @touch $@ 1505 1506.PHONY: lint-addon-docs 1507lint-addon-docs: tools/.doclintstamp 1508 1509tools/.doclintstamp: test/addons/.docbuildstamp 1510 $(info Running C++ linter on addon docs...) 1511 @$(PYTHON) tools/cpplint.py $(CPPLINT_QUIET) --filter=$(ADDON_DOC_LINT_FLAGS) \ 1512 $(LINT_CPP_ADDON_DOC_FILES_GLOB) 1513 @touch $@ 1514 1515cpplint: lint-cpp 1516 $(warning Please use lint-cpp instead of cpplint) 1517 1518.PHONY: lint-py-build 1519# python -m pip install ruff 1520# Try with '--system' if it fails without; the system may have set '--user' 1521lint-py-build: 1522 $(info Pip installing ruff on $(shell $(PYTHON) --version)...) 1523 $(PYTHON) -m pip install --upgrade --target tools/pip/site-packages ruff==0.0.272 || \ 1524 $(PYTHON) -m pip install --upgrade --system --target tools/pip/site-packages ruff==0.0.272 1525 1526.PHONY: lint-py 1527ifneq ("","$(wildcard tools/pip/site-packages/ruff)") 1528# Lint the Python code with ruff. 1529lint-py: 1530 tools/pip/site-packages/bin/ruff --version 1531 tools/pip/site-packages/bin/ruff . 1532else 1533lint-py: 1534 $(warning Python linting with ruff is not available) 1535 $(warning Run 'make lint-py-build') 1536endif 1537 1538.PHONY: lint-yaml-build 1539# python -m pip install yamllint 1540# Try with '--system' if it fails without; the system may have set '--user' 1541lint-yaml-build: 1542 $(info Pip installing yamllint on $(shell $(PYTHON) --version)...) 1543 $(PYTHON) -m pip install --upgrade -t tools/pip/site-packages yamllint || \ 1544 $(PYTHON) -m pip install --upgrade --system -t tools/pip/site-packages yamllint 1545 1546.PHONY: lint-yaml 1547# Lints the YAML files with yamllint. 1548lint-yaml: 1549 @if [ -d "tools/pip/site-packages/yamllint" ]; then \ 1550 PYTHONPATH=tools/pip $(PYTHON) -m yamllint .; \ 1551 else \ 1552 echo 'YAML linting with yamllint is not available'; \ 1553 echo "Run 'make lint-yaml-build'"; \ 1554 fi 1555 1556.PHONY: lint 1557.PHONY: lint-ci 1558ifneq ("","$(wildcard tools/node_modules/eslint/)") 1559lint: ## Run JS, C++, MD and doc linters. 1560 @EXIT_STATUS=0 ; \ 1561 $(MAKE) lint-js || EXIT_STATUS=$$? ; \ 1562 $(MAKE) lint-cpp || EXIT_STATUS=$$? ; \ 1563 $(MAKE) lint-addon-docs || EXIT_STATUS=$$? ; \ 1564 $(MAKE) lint-md || EXIT_STATUS=$$? ; \ 1565 $(MAKE) lint-yaml || EXIT_STATUS=$$? ; \ 1566 exit $$EXIT_STATUS 1567CONFLICT_RE=^>>>>>>> [[:xdigit:]]+|^<<<<<<< [[:alpha:]]+ 1568 1569# Related CI job: node-test-linter 1570lint-ci: lint-js-ci lint-cpp lint-py lint-md lint-addon-docs lint-yaml-build lint-yaml 1571 @if ! ( grep -IEqrs "$(CONFLICT_RE)" --exclude="error-message.js" --exclude="merge-conflict.json" benchmark deps doc lib src test tools ) \ 1572 && ! ( $(FIND) . -maxdepth 1 -type f | xargs grep -IEqs "$(CONFLICT_RE)" ); then \ 1573 exit 0 ; \ 1574 else \ 1575 echo "" >&2 ; \ 1576 echo "Conflict marker detected in one or more files. Please fix them first." >&2 ; \ 1577 exit 1 ; \ 1578 fi 1579else 1580lint lint-ci: 1581 $(info Linting is not available through the source tarball.) 1582 $(info Use the git repo instead: $$ git clone https://github.com/nodejs/node.git) 1583endif 1584 1585.PHONY: lint-clean 1586lint-clean: 1587 $(RM) tools/.*lintstamp 1588 $(RM) .eslintcache 1589 1590HAS_DOCKER ?= $(shell command -v docker > /dev/null 2>&1; [ $$? -eq 0 ] && echo 1 || echo 0) 1591 1592.PHONY: gen-openssl 1593ifeq ($(HAS_DOCKER), 1) 1594DOCKER_COMMAND ?= docker run -it -v $(PWD):/node 1595IS_IN_WORKTREE = $(shell grep '^gitdir: ' $(PWD)/.git 2>/dev/null) 1596GIT_WORKTREE_COMMON = $(shell git rev-parse --git-common-dir) 1597DOCKER_COMMAND += $(if $(IS_IN_WORKTREE), -v $(GIT_WORKTREE_COMMON):$(GIT_WORKTREE_COMMON)) 1598gen-openssl: ## Generate platform dependent openssl files (requires docker) 1599 docker build -t node-openssl-builder deps/openssl/config/ 1600 $(DOCKER_COMMAND) node-openssl-builder make -C deps/openssl/config 1601else 1602gen-openssl: 1603 $(error No docker command, cannot continue) 1604endif 1605