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