INTERNAL = Makefile.internal ARGS = with_llvm=no ifdef DEBUG ARGS+=DEBUG=1 endif UNAME := $(shell uname) ifeq ($(UNAME), Darwin) PAGER ?= less else PAGER ?= pager endif # Parallelism for the instrumented coverage rebuild (portable nproc). NPROC ?= $(shell nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 1) # --------------------------------------------------------------------------- # This is a thin "porcelain" wrapper. The real build (the PGXS targets: all, # install, clean, installcheck, tdkc, ...) lives in Makefile.internal; the # catch-all `%:` rule below forwards any target not defined here down to it. # Targets defined here (test, docs, website, deploy, the studio/playground/ # wasm helpers) override that forward. Run `make help` for the menu. # # Note: because of the `%:` forward, a mistyped target (e.g. `make instal`) # is silently passed to Makefile.internal, which then errors -- not the # wrapper. Check `make help` if a target behaves unexpectedly. # --------------------------------------------------------------------------- .PHONY: default default: $(MAKE) -f $(INTERNAL) $(ARGS) %: $(MAKE) -f $(INTERNAL) $@ $(ARGS) ## =========================================================================== ## Build (delegated to Makefile.internal / PGXS) ## =========================================================================== ## make Build the extension (default) ## install Install into the local PostgreSQL (PGXS) ## clean Remove build artefacts (PGXS + EXTRA_CLEAN) ## tdkc Build the tree-decomposition knowledge-compiler binary ## provsql_migrate_mmap Build the mmap circuit-store migration helper .PHONY: tdkc provsql_migrate_mmap tdkc provsql_migrate_mmap: $(MAKE) -f $(INTERNAL) $@ $(ARGS) ## =========================================================================== ## Test & QA ## =========================================================================== ## test Run the SQL/C regression suite (pg_regress, via tdkc) .PHONY: test test: tdkc bash -c "set -o pipefail && bash test/kcmcp/with-tdkc.sh make installcheck 2>&1 | tee test.log" || $(PAGER) `grep regression.diffs test.log | perl -pe 's/.*?"//;s/".*//'` # Test coverage: rebuild the C/C++ extension instrumented, then run the full # suite against a throwaway PostgreSQL cluster owned by the invoking user (see # test/coverage/run-coverage.sh). Produces a gcovr line+branch report under # coverage/ plus coverage/zero_call.txt, the provsql functions the suite never # calls. The cluster loads the instrumented build from a private staging prefix, # so NOTHING is installed into the system PostgreSQL and no sudo is needed; this # requires PostgreSQL >= 18. See test/coverage/README.md. Needs gcovr # (pipx install gcovr). tdkc is (re)built uninstrumented so the kcmcp client # tests run instead of skipping. # # make coverage # make coverage PROVSQL_COVERAGE_PORT=55000 GCOVR=~/.local/bin/gcovr ## coverage Instrumented rebuild + gcovr line/branch report GCOVR ?= gcovr .PHONY: coverage coverage: $(MAKE) -f $(INTERNAL) clean $(ARGS) $(MAKE) -f $(INTERNAL) -j $(NPROC) COVERAGE=1 $(ARGS) $(MAKE) -f $(INTERNAL) tdkc $(ARGS) GCOVR="$(GCOVR)" bash test/coverage/run-coverage.sh @echo "The system PostgreSQL was untouched; restore the normal local build with: make" # Upgrade-chain parity: a database upgraded from 1.0.0 must be # catalog-identical to a fresh install (the strong form of the # extension_upgrade canary; run before every release). Pass psql # options via PSQL_ARGS, e.g. make test-upgrade-parity PSQL_ARGS=--port=5434 ## test-upgrade-parity Prove an upgraded DB == a fresh install (catalog parity) .PHONY: test-upgrade-parity test-upgrade-parity: test/upgrade_parity.sh $(PSQL_ARGS) ## lint-studio ruff check over the Studio Python .PHONY: lint-studio lint-studio: cd studio && ruff check . ## test-studio Studio unit tests (ruff first, then pytest; no e2e) .PHONY: test-studio test-studio: lint-studio # tests/web (browser/PGlite e2e) needs the assembled doc-root + headless # Chromium; run it separately with `make test-playground`. cd studio && python3 -m pytest tests --ignore=tests/web ## =========================================================================== ## Docs & website ## =========================================================================== # Regenerate the Studio example notebooks (tutorial + case studies) # from the annotated user-guide .rst sources. Also a prerequisite of # `make docs`, so editing an annotated .rst cannot leave the committed # .ipynb files under studio/provsql_studio/notebooks/ stale. Skipped # with a warning where pandoc is missing (e.g. the docs CI runner): # regeneration is a repo-maintenance step, not a docs artifact. ## notebooks Regenerate the Studio example notebooks from .rst .PHONY: notebooks notebooks: @if command -v pandoc >/dev/null; then \ python3 studio/scripts/rst2nb.py; \ else \ echo "WARNING: pandoc not found; skipping example-notebook regeneration"; \ fi ## docs Build the Sphinx HTML documentation .PHONY: docs docs: notebooks # Regenerate the concatenated sql/provsql.sql (the Doxygen SQL input, built # from sql/provsql.common.sql + sql/provsql.14.sql) via Makefile.internal, # whose rule tracks those sources. Delegating is required: listing # sql/provsql.sql as a bare prerequisite here resolves it through the # catch-all `%:' rule, which carries no prerequisites, so an existing but # stale file is treated as up-to-date and SQL docstring edits never reach # the generated API reference. $(MAKE) -f $(INTERNAL) sql/provsql.sql $(ARGS) cd doc/source && make html ## website Build docs + assemble the Jekyll site .PHONY: website website: docs # Copy branding assets into website source cp -r branding/fonts/. website/assets/fonts cp branding/logo.png website/assets/images/logo.png cp branding/favicon.ico website/assets/images/favicon.ico cp branding/favicon.ico website/favicon.ico # Generate SCSS partial for fonts (adjust path from fonts/ to ../fonts/) sed "s|url('fonts/|url('../fonts/|g" branding/fonts-face.css > website/assets/css/_fonts-face.scss # Copy generated docs into Jekyll source tree so jekyll serve also sees them. # rsync --delete so files removed upstream (e.g. retired sql/index.rst) # don't linger as stale, half-styled artifacts under website/docs/. # --omit-dir-times: setting a directory's mtime needs ownership, not just # write access, so it fails when the staging dirs are owned by another user # sharing the repo (group-writable); file times are still preserved. mkdir -p website/docs website/doxygen-sql/html website/doxygen-c/html rsync -a --omit-dir-times --delete doc/source/_build/html/ website/docs/ rsync -a --omit-dir-times --delete doc/doxygen-sql/html/ website/doxygen-sql/html/ rsync -a --omit-dir-times --delete doc/doxygen-c/html/ website/doxygen-c/html/ cd website && bundle exec jekyll build ## deploy Build the website and rsync it to provsql.org .PHONY: deploy deploy: website # -c hashes content so Jekyll's fresh mtimes don't trigger spurious transfers rsync -avzcP website/_site/ provsql:/var/www/provsql/ ## =========================================================================== ## Playground & WASM (in-browser build; heavy, local-only) ## =========================================================================== # Reproduce the GitHub `wasm` workflow's build locally: build the PGlite WASM # core + the ProvSQL extension against the Emscripten builder image. Needs a # container runtime (podman or docker), Node/corepack, and Boost headers; it is # heavy (pulls the multi-GB builder image and compiles the PG tree). # See wasm/build-wasm.sh. ## wasm Build the PGlite + ProvSQL WASM core (container build) .PHONY: wasm wasm: wasm/build-wasm.sh # Assemble the ProvSQL Playground doc-root (the in-browser build). The heavy # WASM artifacts (the matched PGlite dist + provsql.tar.gz, from wasm/; see # studio/web/README.md) are needed only the first time, then reused in place: # # make playground PGLITE_DIST=