mirror of
https://github.com/compiler-explorer/compiler-explorer.git
synced 2026-07-16 17:26:58 -04:00
## What Reworks the bespoke `etc/scripts/find-node` and its `Makefile` interaction so node discovery works out of the box on Linux and macOS, is optionally friendly to version managers, and stays sympathetic to people who just use system node. ### Before - Only ever looked at `PATH`, plus a vestigial `/opt/compiler-explorer/node` hardcode (an affordance for one dev's local setup, unused by the live site). - Duplicated the required node version in three places (`find-node` had `22` twice; `.node-version`; `package.json` `engines`). - Silently fell back *past* an unusable `NODE_DIR` to whatever else it found. - nvm users got whatever default was active, not the version this repo pins. - Nagged on any version that wasn't exactly `22.x`, even newer ones. ### After — clear, permissive resolution order 1. **`$NODE_DIR/bin/node`** — explicit override, now authoritative. If it's set but missing/too old you get a clear error instead of a silent fallback. 2. **`node`/`nodejs` on `PATH`** — covers system node *and* any version manager with shell integration (fnm, asdf, nodenv, volta, an active nvm). Zero extra steps on a well-configured machine. 3. **Manager rescue** — only when PATH node is absent or below the minimum: source `nvm` and ask for the pinned version (the one manager that's a shell function rather than a PATH binary), then try `fnm`/`nodenv`/`asdf`. Each branch is inert unless that tool is installed, so nobody is pushed onto a manager. Other changes: - **Single source of truth**: the minimum major now comes solely from `.node-version` (the same file the managers read). Newer majors are always fine — the "only tested against v22.x" warning is dropped. - **`Makefile`**: `.node-bin` now also depends on `.node-version`, so bumping the pin re-resolves node instead of serving a stale cache. The lazy-dotfile pattern (so failures abort `make` and `make help` pays nothing) is kept. - **`README`**: documents the PATH-first + manager-rescue behaviour. ## Testing - `shellcheck` clean. - Verified: PATH discovery, valid/bogus `NODE_DIR`, nvm rescue (shadowed `node`+`nodejs` with v18 shims → skipped them and resolved v22.22 via nvm), too-old fallthrough, no-node/no-manager failure message, and `make info` end-to-end. - `fnm` branch is logically straightforward but was not exercised (no fnm on the test box) — worth a smoke test if you have one. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: mattgodbolt-molty <mattgodbolt-molty@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Matt Godbolt <matt@godbolt.org> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
127 lines
4.7 KiB
Makefile
127 lines
4.7 KiB
Makefile
default: run
|
|
|
|
help: # with thanks to Ben Rady
|
|
@grep -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
|
|
|
|
# If you see "node-not-found" then you need to depend on node-installed.
|
|
NODE:=node-not-found
|
|
NPM:=npm-not-found
|
|
NODE_MODULES:=./node_modules/.npm-updated
|
|
NODE_ARGS?=
|
|
TS_NODE_ARGS:=--no-warnings=ExperimentalWarning --import=tsx
|
|
|
|
# All file paths that are not .ts files that should be watched for changes if launched with watch.
|
|
FILEWATCHER_ARGS:=--watch --include "etc/config/*"
|
|
|
|
# find-node caches its result in .node-bin.
|
|
# Doing it this way instead of NODE:=$(shell etc/scripts/find-node) means
|
|
# if it fails, it stops the make process. As best I can tell there's no
|
|
# way to get make to fail if a sub-shell command fails.
|
|
# Depending on .node-version means bumping the pinned version re-resolves node;
|
|
# if you switch node behind make's back, `rm .node-bin` (or `make clean`).
|
|
.node-bin: etc/scripts/find-node .node-version
|
|
@etc/scripts/find-node .node-bin
|
|
|
|
# All targets that need node must depend on this to ensure the NODE variable
|
|
# is appropriately set, and that PATH is updated.
|
|
.PHONY: node-installed
|
|
node-installed: .node-bin
|
|
@$(eval NODE:=$(shell cat .node-bin))
|
|
@$(eval NPM:=$(shell dirname $(shell cat .node-bin))/npm)
|
|
@$(eval PATH=$(shell dirname $(realpath $(NODE))):$(PATH))
|
|
|
|
.PHONY: info
|
|
info: node-installed ## print out some useful variables
|
|
@echo Using node from $(NODE)
|
|
@echo Using npm from $(NPM)
|
|
@echo PATH is $(PATH)
|
|
|
|
# disassemblers are needed for local deploys: #4225
|
|
.PHONY: scripts
|
|
scripts:
|
|
mkdir -p out/dist/etc/scripts/disasms
|
|
rsync -r -u etc/scripts/disasms/* out/dist/etc/scripts/disasms
|
|
|
|
.PHONY: prereqs
|
|
prereqs: $(NODE_MODULES)
|
|
|
|
$(NODE_MODULES): package.json package-lock.json | node-installed
|
|
$(NPM) clean-install $(NPM_FLAGS)
|
|
@rm -rf node_modules/.cache/esm/*
|
|
@touch $@
|
|
|
|
.PHONY: lint
|
|
lint: $(NODE_MODULES) ## Checks if the source currently matches code conventions
|
|
$(NPM) run ts-check
|
|
$(NPM) run lint-check
|
|
|
|
.PHONY: lint-fix
|
|
lint-fix: $(NODE_MODULES) ## Checks if everything matches code conventions & fixes those which are trivial to do so
|
|
$(NPM) run lint
|
|
|
|
.PHONY: test
|
|
test: $(NODE_MODULES) ## Runs the tests
|
|
$(NPM) run test
|
|
@echo Tests pass
|
|
|
|
.PHONY: test-min
|
|
test-min: $(NODE_MODULES) ## Runs the minimal tests
|
|
$(NPM) run test-min
|
|
@echo Tests pass
|
|
|
|
.PHONY: check
|
|
check: $(NODE_MODULES) lint test ## Runs all checks required before committing (fixing trivial things automatically)
|
|
|
|
.PHONY: check-frontend-imports
|
|
check-frontend-imports: node-installed ## Check that frontend doesn't import from backend
|
|
@$(NODE) ./etc/scripts/check-frontend-imports.js
|
|
|
|
.PHONY: check-license-headers
|
|
check-license-headers: node-installed ## Check that every source file has the license banner
|
|
@$(NODE) ./etc/scripts/check-license-headers.js
|
|
|
|
.PHONY: pre-commit
|
|
pre-commit: $(NODE_MODULES) test-min lint check-frontend-imports check-license-headers
|
|
|
|
.PHONY: clean
|
|
clean: ## Cleans up everything
|
|
rm -rf node_modules .*-updated .*-bin out
|
|
|
|
.PHONY: prebuild
|
|
prebuild: prereqs scripts
|
|
$(NPM) run webpack
|
|
$(NPM) run ts-compile
|
|
|
|
.PHONY: run-only
|
|
run-only: node-installed ## Runs the site like it runs in production without building it
|
|
env NODE_ENV=production $(NODE) $(NODE_ARGS) ./out/dist/app.js --static ./out/webpack/static $(EXTRA_ARGS)
|
|
|
|
.PHONY: run
|
|
run: ## Runs the site like it runs in production
|
|
$(MAKE) prebuild
|
|
$(MAKE) run-only
|
|
|
|
.PHONY: dev
|
|
dev: prereqs ## Runs the site as a developer; including live reload support and installation of git hooks
|
|
NODE_OPTIONS="$(TS_NODE_ARGS) $(NODE_ARGS)" ./node_modules/.bin/tsx watch $(FILEWATCHER_ARGS) ./app.ts $(EXTRA_ARGS)
|
|
|
|
.PHONY: gpu-dev
|
|
gpu-dev: prereqs ## Runs the site as a developer; including live reload support and installation of git hooks
|
|
NODE_OPTIONS="$(TS_NODE_ARGS) $(NODE_ARGS)" ./node_modules/.bin/tsx watch $(FILEWATCHER_ARGS) ./app.ts --env gpu $(EXTRA_ARGS)
|
|
|
|
.PHONY: debug
|
|
debug: prereqs ## Runs the site as a developer with full debugging; including live reload support and installation of git hooks
|
|
NODE_OPTIONS="$(TS_NODE_ARGS) $(NODE_ARGS) --inspect 9229" ./node_modules/.bin/tsx watch $(FILEWATCHER_ARGS) ./app.ts --debug $(EXTRA_ARGS)
|
|
|
|
.PHONY:
|
|
asm-docs:
|
|
$(MAKE) -C etc/scripts/docenizers || ( \
|
|
echo "==============================================================================="; \
|
|
echo "One of the docenizers failed to run. The dependencies are managed by uv and"; \
|
|
echo "should be automatically installed. If you see this error, please check that:"; \
|
|
echo " 1. uv is available (it will be auto-installed if not)"; \
|
|
echo " 2. npm install has been run for the TypeScript docenizers"; \
|
|
echo "==============================================================================="; \
|
|
exit 1 \
|
|
)
|