From c42f5f98ab5986cf6db7bd12411057969d3ed2f4 Mon Sep 17 00:00:00 2001 From: Jan Lindemann Date: Sun, 16 Aug 2026 18:56:59 +0200 Subject: [PATCH] test-guard.mk: Add file Running "make clean" in some directories can break "make test" in others. That notably happens by running clean somewhere in or below $(TOPDIR)/src/python, which removes __init__.py files potentially needed by unit and integration tests in $(TOPDIR)/test. This commit makes the failure easily visible by introducing the notion of "testabiltity" - if the tree is not testable, "make test" logs exactly that in a clear error message and gives up. Makefiles which need to check "testability" can use it as a prerequisite. This commit does that with py-run.mk and jw-py-test.mk. Testability is asserted by running "make", "make all" or "make test" from $(TOPDIR). A successful toplevel build coincides with testability, and leaves a $(TOPDIR)/dirs-all.done behind, which is why that file is the perfect testability marker. It is automatically created by a toplevel build and cleared by using the "invalidate-testability" prerequisite. This commit makes target "clean" depend on it in py-mod.mk. To be extended to other use cases / makefile snippets as needed. Signed-off-by: Jan Lindemann --- make/py-mod.mk | 3 ++- make/py-run.mk | 3 ++- make/test-guard.mk | 21 +++++++++++++++++++++ make/test-jw-pkg.mk | 4 +++- 4 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 make/test-guard.mk diff --git a/make/py-mod.mk b/make/py-mod.mk index cf8ae627..54ac1bf6 100644 --- a/make/py-mod.mk +++ b/make/py-mod.mk @@ -2,6 +2,7 @@ include $(JWBDIR)/make/defs.mk include $(JWBDIR)/make/py-defs.mk include $(JWBDIR)/make/dirs.mk include $(JWBDIR)/make/dev-utils.mk +include $(JWBDIR)/make/test-guard.mk PY_INIT_TMPL = $(wildcard __init__.py.tmpl) PY_SED_EXTRACT_EXPORT_DEF := /\(\(class\|def\)\s\+[a-zA-Z_].*\|^ *\S\+\s*=.*\|^\s\+\"\S\+\",\)\s*\#\s*export/!d; @@ -24,7 +25,7 @@ endif all: $(PY_PYC) install: install-dirs.done install-reg.done -clean: py.clean +clean: invalidate-testability py.clean distclean: include $(JWBDIR)/make/py-rules.mk diff --git a/make/py-run.mk b/make/py-run.mk index 85ebeba1..c2c8f80f 100644 --- a/make/py-run.mk +++ b/make/py-run.mk @@ -1,5 +1,6 @@ include $(JWBDIR)/make/defs.mk include $(JWBDIR)/make/py-defs.mk +include $(JWBDIR)/make/test-guard.mk EXE ?= $(firstword $(wildcard main.py runme.py test.py *.py)) EXE_ARGS ?= @@ -9,7 +10,7 @@ all: install: clean: distclean: -test: all +test: all testability run: $(PYTHON_RUNNER) $(EXE) $(EXE_ARGS) diff --git a/make/test-guard.mk b/make/test-guard.mk new file mode 100644 index 00000000..db91a623 --- /dev/null +++ b/make/test-guard.mk @@ -0,0 +1,21 @@ +# Testability guard +# +# Tree testability is a single top-level property tracked by +# $(TOPDIR)/dirs-all.done: created by a full `make all` from the topdir, +# removed by `make clean`. A per-dir `make test` only makes sense when the tree +# is importable, i.e. testable. So `test` requires testability, and a `make +# clean` that drops artifacts crucial for testing (a Python module's +# __init__.py, ...) invalidates it. + +.PHONY: testability invalidate-testability + +TEST_GUARD = $(TOPDIR)/dirs-all.done + +all: + +testability: + @test -f "$(TEST_GUARD)" || \ + { echo 'Error: Tree not testable -- run "make all" (or "make test") from project root to fix that!' >&2; exit 1; } + +invalidate-testability: + $(RM) -f "$(TEST_GUARD)" diff --git a/make/test-jw-pkg.mk b/make/test-jw-pkg.mk index 32f1d651..d9718863 100644 --- a/make/test-jw-pkg.mk +++ b/make/test-jw-pkg.mk @@ -14,6 +14,8 @@ all: include $(JWBDIR)/make/defs.mk include $(JWBDIR)/make/py-defs.mk include $(JWBDIR)/make/dev-utils.mk +include $(JWBDIR)/make/test-guard.mk -test-default: +test: testability +test-default: testability $(TEST_CMD_LINE) -- 2.55.0