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 arm,$(UNAME_M)),arm) 829DESTCPU ?= arm 830else 831ifeq ($(findstring aarch64,$(UNAME_M)),aarch64) 832DESTCPU ?= arm64 833else 834ifeq ($(findstring powerpc,$(shell uname -p)),powerpc) 835DESTCPU ?= ppc64 836else 837DESTCPU ?= x86 838endif 839endif 840endif 841endif 842endif 843endif 844endif 845endif 846endif 847ifeq ($(DESTCPU),x64) 848ARCH=x64 849else 850ifeq ($(DESTCPU),arm) 851ARCH=arm 852else 853ifeq ($(DESTCPU),arm64) 854ARCH=arm64 855else 856ifeq ($(DESTCPU),ppc64) 857ARCH=ppc64 858else 859ifeq ($(DESTCPU),ppc) 860ARCH=ppc 861else 862ifeq ($(DESTCPU),s390) 863ARCH=s390 864else 865ifeq ($(DESTCPU),s390x) 866ARCH=s390x 867else 868ARCH=x86 869endif 870endif 871endif 872endif 873endif 874endif 875endif 876 877# node and v8 use different arch names (e.g. node 'x86' vs v8 'ia32'). 878# pass the proper v8 arch name to $V8_ARCH based on user-specified $DESTCPU. 879ifeq ($(DESTCPU),x86) 880V8_ARCH=ia32 881else 882V8_ARCH ?= $(DESTCPU) 883 884endif 885 886# enforce "x86" over "ia32" as the generally accepted way of referring to 32-bit intel 887ifeq ($(ARCH),ia32) 888override ARCH=x86 889endif 890ifeq ($(DESTCPU),ia32) 891override DESTCPU=x86 892endif 893 894TARNAME=node-$(FULLVERSION) 895TARBALL=$(TARNAME).tar 896# Custom user-specified variation, use it directly 897ifdef VARIATION 898BINARYNAME=$(TARNAME)-$(PLATFORM)-$(ARCH)-$(VARIATION) 899else 900BINARYNAME=$(TARNAME)-$(PLATFORM)-$(ARCH) 901endif 902BINARYTAR=$(BINARYNAME).tar 903# OSX doesn't have xz installed by default, http://macpkg.sourceforge.net/ 904HAS_XZ ?= $(shell command -v xz > /dev/null 2>&1; [ $$? -eq 0 ] && echo 1 || echo 0) 905# Supply SKIP_XZ=1 to explicitly skip .tar.xz creation 906SKIP_XZ ?= 0 907XZ = $(shell [ $(HAS_XZ) -eq 1 ] && [ $(SKIP_XZ) -eq 0 ] && echo 1 || echo 0) 908XZ_COMPRESSION ?= 9e 909PKG=$(TARNAME).pkg 910MACOSOUTDIR=out/macos 911 912ifeq ($(SKIP_XZ), 1) 913check-xz: 914 $(info SKIP_XZ=1 supplied, skipping .tar.xz creation) 915else 916ifeq ($(HAS_XZ), 1) 917check-xz: 918else 919check-xz: 920 $(error No xz command, cannot continue) 921endif 922endif 923 924.PHONY: release-only 925release-only: check-xz 926 @if [ "$(DISTTYPE)" = "release" ] && `grep -q REPLACEME doc/api/*.md`; then \ 927 echo 'Please update REPLACEME tags in the following doc/api/*.md files (See doc/guides/releases.md):\n' ; \ 928 REPLACEMES="$(shell grep -l REPLACEME doc/api/*.md)" ; \ 929 echo "$$REPLACEMES\n" | tr " " "\n" ; \ 930 exit 1 ; \ 931 fi 932 @if [ "$(DISTTYPE)" = "release" ] && \ 933 `grep -q DEP...X doc/api/deprecations.md`; then \ 934 echo 'Please update DEP...X in doc/api/deprecations.md (See doc/guides/releases.md)' ; \ 935 exit 1 ; \ 936 fi 937 @if [ "$(shell git status --porcelain | egrep -v '^\?\? ')" = "" ]; then \ 938 exit 0 ; \ 939 else \ 940 echo "" >&2 ; \ 941 echo "The git repository is not clean." >&2 ; \ 942 echo "Please commit changes before building release tarball." >&2 ; \ 943 echo "" >&2 ; \ 944 git status --porcelain | egrep -v '^\?\?' >&2 ; \ 945 echo "" >&2 ; \ 946 exit 1 ; \ 947 fi 948 @if [ "$(DISTTYPE)" != "release" ] || [ "$(RELEASE)" = "1" ]; then \ 949 exit 0; \ 950 else \ 951 echo "" >&2 ; \ 952 echo "#NODE_VERSION_IS_RELEASE is set to $(RELEASE)." >&2 ; \ 953 echo "Did you remember to update src/node_version.h?" >&2 ; \ 954 echo "" >&2 ; \ 955 exit 1 ; \ 956 fi 957 @if [ "$(RELEASE)" = "0" ] || [ -f "$(CHANGELOG)" ]; then \ 958 exit 0; \ 959 else \ 960 echo "" >&2 ; \ 961 echo "#NODE_VERSION_IS_RELEASE is set to $(RELEASE) but " >&2 ; \ 962 echo "$(CHANGELOG) does not exist." >&2 ; \ 963 echo "" >&2 ; \ 964 exit 1 ; \ 965 fi 966 967$(PKG): release-only 968 $(RM) -r $(MACOSOUTDIR) 969 mkdir -p $(MACOSOUTDIR)/installer/productbuild 970 cat tools/macos-installer/productbuild/distribution.xml.tmpl \ 971 | sed -E "s/\\{nodeversion\\}/$(FULLVERSION)/g" \ 972 | sed -E "s/\\{npmversion\\}/$(NPMVERSION)/g" \ 973 >$(MACOSOUTDIR)/installer/productbuild/distribution.xml ; \ 974 975 @for dirname in tools/macos-installer/productbuild/Resources/*/; do \ 976 lang=$$(basename $$dirname) ; \ 977 mkdir -p $(MACOSOUTDIR)/installer/productbuild/Resources/$$lang ; \ 978 printf "Found localization directory $$dirname\n" ; \ 979 cat $$dirname/welcome.html.tmpl \ 980 | sed -E "s/\\{nodeversion\\}/$(FULLVERSION)/g" \ 981 | sed -E "s/\\{npmversion\\}/$(NPMVERSION)/g" \ 982 >$(MACOSOUTDIR)/installer/productbuild/Resources/$$lang/welcome.html ; \ 983 cat $$dirname/conclusion.html.tmpl \ 984 | sed -E "s/\\{nodeversion\\}/$(FULLVERSION)/g" \ 985 | sed -E "s/\\{npmversion\\}/$(NPMVERSION)/g" \ 986 >$(MACOSOUTDIR)/installer/productbuild/Resources/$$lang/conclusion.html ; \ 987 done 988 $(PYTHON) ./configure \ 989 --dest-cpu=x64 \ 990 --tag=$(TAG) \ 991 --release-urlbase=$(RELEASE_URLBASE) \ 992 $(CONFIG_FLAGS) $(BUILD_RELEASE_FLAGS) 993 $(MAKE) install V=$(V) DESTDIR=$(MACOSOUTDIR)/dist/node 994 SIGN="$(CODESIGN_CERT)" PKGDIR="$(MACOSOUTDIR)/dist/node/usr/local" sh \ 995 tools/osx-codesign.sh 996 mkdir -p $(MACOSOUTDIR)/dist/npm/usr/local/lib/node_modules 997 mkdir -p $(MACOSOUTDIR)/pkgs 998 mv $(MACOSOUTDIR)/dist/node/usr/local/lib/node_modules/npm \ 999 $(MACOSOUTDIR)/dist/npm/usr/local/lib/node_modules 1000 unlink $(MACOSOUTDIR)/dist/node/usr/local/bin/npm 1001 unlink $(MACOSOUTDIR)/dist/node/usr/local/bin/npx 1002 $(NODE) tools/license2rtf.js < LICENSE > \ 1003 $(MACOSOUTDIR)/installer/productbuild/Resources/license.rtf 1004 cp doc/osx_installer_logo.png $(MACOSOUTDIR)/installer/productbuild/Resources 1005 pkgbuild --version $(FULLVERSION) \ 1006 --identifier org.nodejs.node.pkg \ 1007 --root $(MACOSOUTDIR)/dist/node $(MACOSOUTDIR)/pkgs/node-$(FULLVERSION).pkg 1008 pkgbuild --version $(NPMVERSION) \ 1009 --identifier org.nodejs.npm.pkg \ 1010 --root $(MACOSOUTDIR)/dist/npm \ 1011 --scripts ./tools/macos-installer/pkgbuild/npm/scripts \ 1012 $(MACOSOUTDIR)/pkgs/npm-$(NPMVERSION).pkg 1013 productbuild --distribution $(MACOSOUTDIR)/installer/productbuild/distribution.xml \ 1014 --resources $(MACOSOUTDIR)/installer/productbuild/Resources \ 1015 --package-path $(MACOSOUTDIR)/pkgs ./$(PKG) 1016 SIGN="$(PRODUCTSIGN_CERT)" PKG="$(PKG)" sh tools/osx-productsign.sh 1017 sh tools/osx-notarize.sh $(FULLVERSION) 1018 1019.PHONY: pkg 1020# Builds the macOS installer for releases. 1021pkg: $(PKG) 1022 1023corepack-update: 1024 rm -rf /tmp/node-corepack-clone 1025 git clone 'https://github.com/nodejs/corepack.git' /tmp/node-corepack-clone 1026 cd /tmp/node-corepack-clone && yarn pack 1027 rm -rf deps/corepack && mkdir -p deps/corepack 1028 cd deps/corepack && tar xf /tmp/node-corepack-clone/package.tgz --strip-components=1 1029 chmod +x deps/corepack/shims/* 1030 1031# Note: this is strictly for release builds on release machines only. 1032pkg-upload: pkg 1033 ssh $(STAGINGSERVER) "mkdir -p nodejs/$(DISTTYPEDIR)/$(FULLVERSION)" 1034 chmod 664 $(TARNAME).pkg 1035 scp -p $(TARNAME).pkg $(STAGINGSERVER):nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME).pkg 1036 ssh $(STAGINGSERVER) "touch nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME).pkg.done" 1037 1038$(TARBALL): release-only doc-only 1039 git checkout-index -a -f --prefix=$(TARNAME)/ 1040 mkdir -p $(TARNAME)/doc/api 1041 cp doc/node.1 $(TARNAME)/doc/node.1 1042 cp -r out/doc/api/* $(TARNAME)/doc/api/ 1043 $(RM) -r $(TARNAME)/.editorconfig 1044 $(RM) -r $(TARNAME)/.git* 1045 $(RM) -r $(TARNAME)/.mailmap 1046 $(RM) -r $(TARNAME)/deps/openssl/openssl/demos 1047 $(RM) -r $(TARNAME)/deps/openssl/openssl/doc 1048 $(RM) -r $(TARNAME)/deps/openssl/openssl/test 1049 $(RM) -r $(TARNAME)/deps/uv/docs 1050 $(RM) -r $(TARNAME)/deps/uv/samples 1051 $(RM) -r $(TARNAME)/deps/uv/test 1052 $(RM) -r $(TARNAME)/deps/v8/samples 1053 $(RM) -r $(TARNAME)/deps/v8/tools/profviz 1054 $(RM) -r $(TARNAME)/deps/v8/tools/run-tests.py 1055 $(RM) -r $(TARNAME)/doc/images # too big 1056 $(RM) -r $(TARNAME)/test*.tap 1057 $(RM) -r $(TARNAME)/tools/cpplint.py 1058 $(RM) -r $(TARNAME)/tools/eslint-rules 1059 $(RM) -r $(TARNAME)/tools/license-builder.sh 1060 $(RM) -r $(TARNAME)/tools/node_modules 1061 $(RM) -r $(TARNAME)/tools/osx-* 1062 $(RM) -r $(TARNAME)/tools/osx-pkg.pmdoc 1063 find $(TARNAME)/deps/v8/test/* -type d ! -regex '.*/test/torque$$' | xargs $(RM) -r 1064 find $(TARNAME)/deps/v8/test -type f ! -regex '.*/test/torque/.*' | xargs $(RM) 1065 find $(TARNAME)/deps/zlib/contrib/* -type d ! -regex '.*/contrib/optimizations$$' | xargs $(RM) -r 1066 find $(TARNAME)/ -name ".eslint*" -maxdepth 2 | xargs $(RM) 1067 find $(TARNAME)/ -type l | xargs $(RM) 1068 tar -cf $(TARNAME).tar $(TARNAME) 1069 $(RM) -r $(TARNAME) 1070 gzip -c -f -9 $(TARNAME).tar > $(TARNAME).tar.gz 1071ifeq ($(XZ), 1) 1072 xz -c -f -$(XZ_COMPRESSION) $(TARNAME).tar > $(TARNAME).tar.xz 1073endif 1074 $(RM) $(TARNAME).tar 1075 1076.PHONY: tar 1077tar: $(TARBALL) ## Create a source tarball. 1078 1079# Note: this is strictly for release builds on release machines only. 1080tar-upload: tar 1081 ssh $(STAGINGSERVER) "mkdir -p nodejs/$(DISTTYPEDIR)/$(FULLVERSION)" 1082 chmod 664 $(TARNAME).tar.gz 1083 scp -p $(TARNAME).tar.gz $(STAGINGSERVER):nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME).tar.gz 1084 ssh $(STAGINGSERVER) "touch nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME).tar.gz.done" 1085ifeq ($(XZ), 1) 1086 chmod 664 $(TARNAME).tar.xz 1087 scp -p $(TARNAME).tar.xz $(STAGINGSERVER):nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME).tar.xz 1088 ssh $(STAGINGSERVER) "touch nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME).tar.xz.done" 1089endif 1090 1091# Note: this is strictly for release builds on release machines only. 1092doc-upload: doc 1093 ssh $(STAGINGSERVER) "mkdir -p nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/docs/" 1094 chmod -R ug=rw-x+X,o=r+X out/doc/ 1095 scp -pr out/doc/* $(STAGINGSERVER):nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/docs/ 1096 ssh $(STAGINGSERVER) "touch nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/docs.done" 1097 1098.PHONY: $(TARBALL)-headers 1099$(TARBALL)-headers: release-only 1100 $(PYTHON) ./configure \ 1101 --prefix=/ \ 1102 --dest-cpu=$(DESTCPU) \ 1103 --tag=$(TAG) \ 1104 --release-urlbase=$(RELEASE_URLBASE) \ 1105 $(CONFIG_FLAGS) $(BUILD_RELEASE_FLAGS) 1106 HEADERS_ONLY=1 $(PYTHON) tools/install.py install '$(TARNAME)' '/' 1107 find $(TARNAME)/ -type l | xargs $(RM) 1108 tar -cf $(TARNAME)-headers.tar $(TARNAME) 1109 $(RM) -r $(TARNAME) 1110 gzip -c -f -9 $(TARNAME)-headers.tar > $(TARNAME)-headers.tar.gz 1111ifeq ($(XZ), 1) 1112 xz -c -f -$(XZ_COMPRESSION) $(TARNAME)-headers.tar > $(TARNAME)-headers.tar.xz 1113endif 1114 $(RM) $(TARNAME)-headers.tar 1115 1116tar-headers: $(TARBALL)-headers ## Build the node header tarball. 1117 1118tar-headers-upload: tar-headers 1119 ssh $(STAGINGSERVER) "mkdir -p nodejs/$(DISTTYPEDIR)/$(FULLVERSION)" 1120 chmod 664 $(TARNAME)-headers.tar.gz 1121 scp -p $(TARNAME)-headers.tar.gz $(STAGINGSERVER):nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME)-headers.tar.gz 1122 ssh $(STAGINGSERVER) "touch nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME)-headers.tar.gz.done" 1123ifeq ($(XZ), 1) 1124 chmod 664 $(TARNAME)-headers.tar.xz 1125 scp -p $(TARNAME)-headers.tar.xz $(STAGINGSERVER):nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME)-headers.tar.xz 1126 ssh $(STAGINGSERVER) "touch nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME)-headers.tar.xz.done" 1127endif 1128 1129$(BINARYTAR): release-only 1130 $(RM) -r $(BINARYNAME) 1131 $(RM) -r out/deps out/Release 1132 $(PYTHON) ./configure \ 1133 --prefix=/ \ 1134 --dest-cpu=$(DESTCPU) \ 1135 --tag=$(TAG) \ 1136 --release-urlbase=$(RELEASE_URLBASE) \ 1137 $(CONFIG_FLAGS) $(BUILD_RELEASE_FLAGS) 1138 $(MAKE) install DESTDIR=$(BINARYNAME) V=$(V) PORTABLE=1 1139 cp README.md $(BINARYNAME) 1140 cp LICENSE $(BINARYNAME) 1141ifeq ("$(wildcard $(CHANGELOG))","") 1142 cp CHANGELOG.md $(BINARYNAME) 1143else 1144 cp $(CHANGELOG) $(BINARYNAME)/CHANGELOG.md 1145endif 1146ifeq ($(OSTYPE),darwin) 1147 SIGN="$(CODESIGN_CERT)" PKGDIR="$(BINARYNAME)" sh tools/osx-codesign.sh 1148endif 1149 tar -cf $(BINARYNAME).tar $(BINARYNAME) 1150 $(RM) -r $(BINARYNAME) 1151 gzip -c -f -9 $(BINARYNAME).tar > $(BINARYNAME).tar.gz 1152ifeq ($(XZ), 1) 1153 xz -c -f -$(XZ_COMPRESSION) $(BINARYNAME).tar > $(BINARYNAME).tar.xz 1154endif 1155 $(RM) $(BINARYNAME).tar 1156 1157.PHONY: binary 1158# This requires NODE_VERSION_IS_RELEASE defined as 1 in src/node_version.h. 1159binary: $(BINARYTAR) ## Build release binary tarballs. 1160 1161# Note: this is strictly for release builds on release machines only. 1162binary-upload: binary 1163 ssh $(STAGINGSERVER) "mkdir -p nodejs/$(DISTTYPEDIR)/$(FULLVERSION)" 1164 chmod 664 $(TARNAME)-$(OSTYPE)-$(ARCH).tar.gz 1165 scp -p $(TARNAME)-$(OSTYPE)-$(ARCH).tar.gz $(STAGINGSERVER):nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME)-$(OSTYPE)-$(ARCH).tar.gz 1166 ssh $(STAGINGSERVER) "touch nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME)-$(OSTYPE)-$(ARCH).tar.gz.done" 1167ifeq ($(XZ), 1) 1168 chmod 664 $(TARNAME)-$(OSTYPE)-$(ARCH).tar.xz 1169 scp -p $(TARNAME)-$(OSTYPE)-$(ARCH).tar.xz $(STAGINGSERVER):nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME)-$(OSTYPE)-$(ARCH).tar.xz 1170 ssh $(STAGINGSERVER) "touch nodejs/$(DISTTYPEDIR)/$(FULLVERSION)/$(TARNAME)-$(OSTYPE)-$(ARCH).tar.xz.done" 1171endif 1172 1173.PHONY: bench-all 1174.PHONY: bench 1175bench bench-all: bench-addons-build 1176 $(warning Please use benchmark/run.js or benchmark/compare.js to run the benchmarks.) 1177 1178# Build required addons for benchmark before running it. 1179.PHONY: bench-addons-build 1180bench-addons-build: | $(NODE_EXE) benchmark/napi/.buildstamp 1181 1182.PHONY: bench-addons-clean 1183bench-addons-clean: 1184 $(RM) -r benchmark/napi/*/build 1185 $(RM) benchmark/napi/.buildstamp 1186 1187.PHONY: lint-md-rollup 1188lint-md-rollup: 1189 $(RM) tools/.*mdlintstamp 1190 cd tools/node-lint-md-cli-rollup && npm install 1191 cd tools/node-lint-md-cli-rollup && npm run build-node 1192 1193.PHONY: lint-md-clean 1194lint-md-clean: 1195 $(RM) -r tools/node-lint-md-cli-rollup/node_modules 1196 $(RM) tools/.*mdlintstamp 1197 1198.PHONY: lint-md-build 1199lint-md-build: 1200 $(warning Deprecated no-op target 'lint-md-build') 1201 1202ifeq ("$(wildcard tools/.mdlintstamp)","") 1203LINT_MD_NEWER = 1204else 1205LINT_MD_NEWER = -newer tools/.mdlintstamp 1206endif 1207 1208LINT_MD_TARGETS = doc src lib benchmark test tools/doc tools/icu $(wildcard *.md) 1209LINT_MD_FILES = $(shell $(FIND) $(LINT_MD_TARGETS) -type f \ 1210 ! -path '*node_modules*' ! -path 'test/fixtures/*' -name '*.md' \ 1211 $(LINT_MD_NEWER)) 1212run-lint-md = tools/lint-md.mjs -q -f --no-stdout $(LINT_MD_FILES) 1213# Lint all changed markdown files maintained by us 1214tools/.mdlintstamp: $(LINT_MD_FILES) 1215 $(info Running Markdown linter...) 1216 @$(call available-node,$(run-lint-md)) 1217 @touch $@ 1218 1219.PHONY: lint-md 1220# Lints the markdown documents maintained by us in the codebase. 1221lint-md: lint-js-doc | tools/.mdlintstamp 1222 1223 1224LINT_JS_TARGETS = .eslintrc.js benchmark doc lib test tools 1225 1226run-lint-js = tools/node_modules/eslint/bin/eslint.js --cache \ 1227 --report-unused-disable-directives $(LINT_JS_TARGETS) 1228run-lint-js-fix = $(run-lint-js) --fix 1229 1230.PHONY: lint-js-fix 1231lint-js-fix: 1232 @$(call available-node,$(run-lint-js-fix)) 1233 1234.PHONY: lint-js 1235.PHONY: lint-js-doc 1236# Note that on the CI `lint-js-ci` is run instead. 1237# Lints the JavaScript code with eslint. 1238lint-js-doc: LINT_JS_TARGETS=doc 1239lint-js lint-js-doc: 1240 @if [ "$(shell $(node_use_openssl))" != "true" ]; then \ 1241 echo "Skipping $@ (no crypto)"; \ 1242 else \ 1243 echo "Running JS linter..."; \ 1244 $(call available-node,$(run-lint-js)) \ 1245 fi 1246 1247jslint: lint-js 1248 $(warning Please use lint-js instead of jslint) 1249 1250run-lint-js-ci = tools/node_modules/eslint/bin/eslint.js \ 1251 --report-unused-disable-directives -f tap \ 1252 -o test-eslint.tap $(LINT_JS_TARGETS) 1253 1254.PHONY: lint-js-ci 1255# On the CI the output is emitted in the TAP format. 1256lint-js-ci: 1257 $(info Running JS linter...) 1258 @$(call available-node,$(run-lint-js-ci)) 1259 1260jslint-ci: lint-js-ci 1261 $(warning Please use lint-js-ci instead of jslint-ci) 1262 1263LINT_CPP_ADDON_DOC_FILES_GLOB = test/addons/??_*/*.cc test/addons/??_*/*.h 1264LINT_CPP_ADDON_DOC_FILES = $(wildcard $(LINT_CPP_ADDON_DOC_FILES_GLOB)) 1265LINT_CPP_EXCLUDE ?= 1266LINT_CPP_EXCLUDE += src/node_root_certs.h 1267LINT_CPP_EXCLUDE += $(LINT_CPP_ADDON_DOC_FILES) 1268LINT_CPP_EXCLUDE += $(wildcard test/js-native-api/??_*/*.cc test/js-native-api/??_*/*.h test/node-api/??_*/*.cc test/node-api/??_*/*.h) 1269# These files were copied more or less verbatim from V8. 1270LINT_CPP_EXCLUDE += src/tracing/trace_event.h src/tracing/trace_event_common.h 1271 1272LINT_CPP_FILES = $(filter-out $(LINT_CPP_EXCLUDE), $(wildcard \ 1273 benchmark/napi/*/*.cc \ 1274 src/*.c \ 1275 src/*.cc \ 1276 src/*.h \ 1277 src/*/*.c \ 1278 src/*/*.cc \ 1279 src/*/*.h \ 1280 test/addons/*/*.cc \ 1281 test/addons/*/*.h \ 1282 test/cctest/*.cc \ 1283 test/cctest/*.h \ 1284 test/embedding/*.cc \ 1285 test/embedding/*.h \ 1286 test/js-native-api/*/*.cc \ 1287 test/js-native-api/*/*.h \ 1288 test/node-api/*/*.cc \ 1289 test/node-api/*/*.h \ 1290 tools/icu/*.cc \ 1291 tools/icu/*.h \ 1292 tools/code_cache/*.cc \ 1293 tools/code_cache/*.h \ 1294 tools/snapshot/*.cc \ 1295 tools/snapshot/*.h \ 1296 )) 1297 1298# Code blocks don't have newline at the end, 1299# and the actual filename is generated so it won't match header guards 1300ADDON_DOC_LINT_FLAGS=-whitespace/ending_newline,-build/header_guard 1301 1302format-cpp-build: 1303 cd tools/clang-format && $(call available-node,$(run-npm-ci)) 1304 1305format-cpp-clean: 1306 $(RM) -r tools/clang-format/node_modules 1307 1308CLANG_FORMAT_START ?= HEAD 1309.PHONY: format-cpp 1310# To format staged changes: 1311# $ make format-cpp 1312# To format HEAD~1...HEAD (latest commit): 1313# $ CLANG_FORMAT_START=`git rev-parse HEAD~1` make format-cpp 1314# To format diff between master and current branch head (master...HEAD): 1315# $ CLANG_FORMAT_START=master make format-cpp 1316format-cpp: ## Format C++ diff from $CLANG_FORMAT_START to current changes 1317ifneq ("","$(wildcard tools/clang-format/node_modules/)") 1318 $(info Formatting C++ diff from $(CLANG_FORMAT_START)..) 1319 @$(PYTHON) tools/clang-format/node_modules/.bin/git-clang-format \ 1320 --binary=tools/clang-format/node_modules/.bin/clang-format \ 1321 --style=file \ 1322 $(CLANG_FORMAT_START) -- \ 1323 $(LINT_CPP_FILES) 1324else 1325 $(info clang-format is not installed.) 1326 $(info To install (requires internet access) run: $$ make format-cpp-build) 1327endif 1328 1329ifeq ($(V),1) 1330CPPLINT_QUIET = 1331else 1332CPPLINT_QUIET = --quiet 1333endif 1334.PHONY: lint-cpp 1335# Lints the C++ code with cpplint.py and checkimports.py. 1336lint-cpp: tools/.cpplintstamp 1337 1338tools/.cpplintstamp: $(LINT_CPP_FILES) 1339 $(info Running C++ linter...) 1340 @$(PYTHON) tools/cpplint.py $(CPPLINT_QUIET) $? 1341 @$(PYTHON) tools/checkimports.py $? 1342 @touch $@ 1343 1344.PHONY: lint-addon-docs 1345lint-addon-docs: tools/.doclintstamp 1346 1347tools/.doclintstamp: test/addons/.docbuildstamp 1348 $(info Running C++ linter on addon docs...) 1349 @$(PYTHON) tools/cpplint.py $(CPPLINT_QUIET) --filter=$(ADDON_DOC_LINT_FLAGS) \ 1350 $(LINT_CPP_ADDON_DOC_FILES_GLOB) 1351 @touch $@ 1352 1353cpplint: lint-cpp 1354 $(warning Please use lint-cpp instead of cpplint) 1355 1356.PHONY: lint-py-build 1357# python -m pip install flake8 1358# Try with '--system' is to overcome systems that blindly set '--user' 1359lint-py-build: 1360 $(info Pip installing flake8 linter on $(shell $(PYTHON) --version)...) 1361 $(PYTHON) -m pip install --upgrade -t tools/pip/site-packages flake8 || \ 1362 $(PYTHON) -m pip install --upgrade --system -t tools/pip/site-packages flake8 1363 1364ifneq ("","$(wildcard tools/pip/site-packages)") 1365.PHONY: lint-py 1366# Lints the Python code with flake8. 1367# Flag the build if there are Python syntax errors or undefined names 1368lint-py: 1369 PYTHONPATH=tools/pip $(PYTHON) -m flake8 --count --show-source --statistics . 1370else 1371lint-py: 1372 $(warning Python linting with flake8 is not available) 1373 $(warning Run 'make lint-py-build') 1374endif 1375 1376.PHONY: lint 1377.PHONY: lint-ci 1378ifneq ("","$(wildcard tools/node_modules/eslint/)") 1379lint: ## Run JS, C++, MD and doc linters. 1380 @EXIT_STATUS=0 ; \ 1381 $(MAKE) lint-js || EXIT_STATUS=$$? ; \ 1382 $(MAKE) lint-cpp || EXIT_STATUS=$$? ; \ 1383 $(MAKE) lint-addon-docs || EXIT_STATUS=$$? ; \ 1384 $(MAKE) lint-md || EXIT_STATUS=$$? ; \ 1385 exit $$EXIT_STATUS 1386CONFLICT_RE=^>>>>>>> [[:xdigit:]]+|^<<<<<<< [[:alpha:]]+ 1387 1388# Related CI job: node-test-linter 1389lint-ci: lint-js-ci lint-cpp lint-py lint-md lint-addon-docs 1390 @if ! ( grep -IEqrs "$(CONFLICT_RE)" benchmark deps doc lib src test tools ) \ 1391 && ! ( $(FIND) . -maxdepth 1 -type f | xargs grep -IEqs "$(CONFLICT_RE)" ); then \ 1392 exit 0 ; \ 1393 else \ 1394 echo "" >&2 ; \ 1395 echo "Conflict marker detected in one or more files. Please fix them first." >&2 ; \ 1396 exit 1 ; \ 1397 fi 1398else 1399lint lint-ci: 1400 $(info Linting is not available through the source tarball.) 1401 $(info Use the git repo instead: $$ git clone https://github.com/nodejs/node.git) 1402endif 1403 1404.PHONY: lint-clean 1405lint-clean: 1406 $(RM) tools/.*lintstamp 1407 $(RM) .eslintcache 1408 1409HAS_DOCKER ?= $(shell command -v docker > /dev/null 2>&1; [ $$? -eq 0 ] && echo 1 || echo 0) 1410 1411ifeq ($(HAS_DOCKER), 1) 1412DOCKER_COMMAND ?= docker run -it -v $(PWD):/node 1413IS_IN_WORKTREE = $(shell grep '^gitdir: ' $(PWD)/.git 2>/dev/null) 1414GIT_WORKTREE_COMMON = $(shell git rev-parse --git-common-dir) 1415DOCKER_COMMAND += $(if $(IS_IN_WORKTREE), -v $(GIT_WORKTREE_COMMON):$(GIT_WORKTREE_COMMON)) 1416gen-openssl: ## Generate platform dependent openssl files (requires docker) 1417 docker build -t node-openssl-builder deps/openssl/config/ 1418 $(DOCKER_COMMAND) node-openssl-builder make -C deps/openssl/config 1419else 1420gen-openssl: 1421 $(error No docker command, cannot continue) 1422endif 1423