From 493e8a3a52bcdc1f7ccd2d4edf9cc221856373c4 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Sat, 10 Oct 2026 11:01:15 -0700 Subject: [PATCH 1/6] Use shell command substitution correctly in Makefiles In a make recipe, $(cmd) is a make variable reference, not shell command substitution; it must be written $$(cmd). Outside a recipe, use $(shell cmd). --- tests/Makefile | 2 +- tests/Makefile.common | 2 +- tests/daikon-tests/junit/Makefile.user | 2 +- tests/daikon-tests/junit5/Makefile.user | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index e238ef2bd2..f10e7c3beb 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -52,7 +52,7 @@ txt-chicory-diff everything-txt-diff stats dyncomp-diff txt-jaif-diff txt-jaif: ${MAKE} pat-daikon-tests-$@ pat-daikon-tests-%: # Under CI, there are two CPUs, but limit to 1 to avoid out-of-memory error. - if [ -n "$("${PLUME_SCRIPTS}"/is-ci.sh)" ]; then \ + if [ -n "$$("${PLUME_SCRIPTS}"/is-ci.sh)" ]; then \ ${MAKE} -C daikon-tests --jobs=1 ${MPARG} $*; \ else \ ${MAKE} -C daikon-tests --jobs=4 ${MPARG} $*; \ diff --git a/tests/Makefile.common b/tests/Makefile.common index 38dde8e8cb..c151d000b3 100644 --- a/tests/Makefile.common +++ b/tests/Makefile.common @@ -187,7 +187,7 @@ ECLAT_SCRATCH = $(SCRATCH_FOR_DAIKON_BASE)/$(PROJECT)_eclat CP_PARENTS := rsync -aR ifeq ($(shell uname), Darwin) - JAVA_HOME ?= $(/usr/libexec/java_home) + JAVA_HOME ?= $(shell /usr/libexec/java_home) else ifeq ($(shell which javac > /dev/null 2>&1 && echo found || echo nonexistent), found) JAVA_HOME ?= $(shell readlink -f $(shell which javac) | sed "s:/bin/javac::") diff --git a/tests/daikon-tests/junit/Makefile.user b/tests/daikon-tests/junit/Makefile.user index 9c2889b925..20a6da71d7 100644 --- a/tests/daikon-tests/junit/Makefile.user +++ b/tests/daikon-tests/junit/Makefile.user @@ -1,7 +1,7 @@ ########################################################################### ifeq ($(shell uname), Darwin) - JAVA_HOME ?= $(/usr/libexec/java_home) + JAVA_HOME ?= $(shell /usr/libexec/java_home) else ifeq ($(shell which javac > /dev/null 2>&1 && echo found || echo nonexistent), found) JAVA_HOME ?= $(shell readlink -f $(shell which javac) | sed "s:/bin/javac::") diff --git a/tests/daikon-tests/junit5/Makefile.user b/tests/daikon-tests/junit5/Makefile.user index d10d1f57d7..b820d37665 100644 --- a/tests/daikon-tests/junit5/Makefile.user +++ b/tests/daikon-tests/junit5/Makefile.user @@ -1,7 +1,7 @@ ########################################################################### ifeq ($(shell uname), Darwin) - JAVA_HOME ?= $(/usr/libexec/java_home) + JAVA_HOME ?= $(shell /usr/libexec/java_home) else ifeq ($(shell which javac > /dev/null 2>&1 && echo found || echo nonexistent), found) JAVA_HOME ?= $(shell readlink -f $(shell which javac) | sed "s:/bin/javac::") From 2164fed85c91c2fa9a45875549cc6cef0331ff51 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Sat, 10 Oct 2026 12:01:48 -0700 Subject: [PATCH 2/6] Fix remaining is-ci.sh substitutions; fail clearly if is-ci.sh is missing --- tests/Makefile | 4 ++++ tests/dyncomp-tests/Makefile | 6 +++++- tests/kvasir-tests/Makefile | 9 +++++++-- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index f10e7c3beb..b8450521fc 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -34,6 +34,9 @@ else MPARG ?= endif +ifeq ($(origin DAIKONDIR), undefined) + DAIKONDIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))..) +endif PLUME_SCRIPTS ?= ${DAIKONDIR}/.utils/plume-scripts all diffs: txt-diff non-txt-diff dyncomp-tests results @@ -52,6 +55,7 @@ txt-chicory-diff everything-txt-diff stats dyncomp-diff txt-jaif-diff txt-jaif: ${MAKE} pat-daikon-tests-$@ pat-daikon-tests-%: # Under CI, there are two CPUs, but limit to 1 to avoid out-of-memory error. + @test -x "${PLUME_SCRIPTS}"/is-ci.sh || { echo "Not found: ${PLUME_SCRIPTS}/is-ci.sh ; running 'make' in ${DAIKONDIR} clones it" >&2; exit 1; } if [ -n "$$("${PLUME_SCRIPTS}"/is-ci.sh)" ]; then \ ${MAKE} -C daikon-tests --jobs=1 ${MPARG} $*; \ else \ diff --git a/tests/dyncomp-tests/Makefile b/tests/dyncomp-tests/Makefile index f3452923af..b2eaa8e885 100644 --- a/tests/dyncomp-tests/Makefile +++ b/tests/dyncomp-tests/Makefile @@ -18,6 +18,9 @@ # Forked from $DAIKONDIR/tests/kvasir-tests/Makefile +ifeq ($(origin DAIKONDIR), undefined) + DAIKONDIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))../..) +endif PLUME_SCRIPTS ?= ${DAIKONDIR}/.utils/plume-scripts default: summary @@ -64,7 +67,8 @@ update-all: .PHONY: clean-all clean-all: - if [ -n "$("${PLUME_SCRIPTS}"/is-ci.sh)" ]; then \ + @test -x "${PLUME_SCRIPTS}"/is-ci.sh || { echo "Not found: ${PLUME_SCRIPTS}/is-ci.sh ; running 'make' in ${DAIKONDIR} clones it" >&2; exit 1; } + if [ -n "$$("${PLUME_SCRIPTS}"/is-ci.sh)" ]; then \ ${MAKE} --jobs=1 ${MPARG} nightly-tests__clean; \ else \ ${MAKE} --jobs=4 ${MPARG} nightly-tests__clean; \ diff --git a/tests/kvasir-tests/Makefile b/tests/kvasir-tests/Makefile index bff779dccc..7067317980 100644 --- a/tests/kvasir-tests/Makefile +++ b/tests/kvasir-tests/Makefile @@ -20,13 +20,17 @@ else MPARG ?= endif +ifeq ($(origin DAIKONDIR), undefined) + DAIKONDIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))../..) +endif PLUME_SCRIPTS ?= ${DAIKONDIR}/.utils/plume-scripts default: summary-w-daikon .PHONY: regression-tests regression-tests: - if [ -n "$("${PLUME_SCRIPTS}"/is-ci.sh)" ]; then \ + @test -x "${PLUME_SCRIPTS}"/is-ci.sh || { echo "Not found: ${PLUME_SCRIPTS}/is-ci.sh ; running 'make' in ${DAIKONDIR} clones it" >&2; exit 1; } + if [ -n "$$("${PLUME_SCRIPTS}"/is-ci.sh)" ]; then \ ${MAKE} --jobs=1 ${MPARG} nightly-tests__diffs-w-daikon-if-working; \ else \ ${MAKE} --jobs=4 ${MPARG} nightly-tests__diffs-w-daikon-if-working; \ @@ -80,7 +84,8 @@ update-all: .PHONY: clean-all clean-all: - if [ -n "$("${PLUME_SCRIPTS}"/is-ci.sh)" ]; then \ + @test -x "${PLUME_SCRIPTS}"/is-ci.sh || { echo "Not found: ${PLUME_SCRIPTS}/is-ci.sh ; running 'make' in ${DAIKONDIR} clones it" >&2; exit 1; } + if [ -n "$$("${PLUME_SCRIPTS}"/is-ci.sh)" ]; then \ ${MAKE} --jobs=1 ${MPARG} nightly-tests__clean; \ else \ ${MAKE} --jobs=4 ${MPARG} nightly-tests__clean; \ From c86dd6e4cd7306f1c945ff4613618cecdd9e4af7 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Sat, 10 Oct 2026 12:41:49 -0700 Subject: [PATCH 3/6] Compute test job count once; robust JAVA_HOME; consistent DAIKONDIR; define MPARG - Choose --jobs once at parse time (TEST_JOBS); a missing is-ci.sh means not under CI. - Evaluate JAVA_HOME once, and fail clearly on macOS if no JDK is found. - Use the same DAIKONDIR idiom in the kvasir-tests and dyncomp-tests Makefile.common. - Define MPARG in tests/dyncomp-tests/Makefile. --- tests/Makefile | 11 ++++------- tests/Makefile.common | 10 ++++++++-- tests/daikon-tests/junit/Makefile.user | 10 ++++++++-- tests/daikon-tests/junit5/Makefile.user | 10 ++++++++-- tests/dyncomp-tests/Makefile | 17 +++++++++++------ tests/dyncomp-tests/Makefile.common | 4 +++- tests/kvasir-tests/Makefile | 17 +++++------------ tests/kvasir-tests/Makefile.common | 4 +++- 8 files changed, 50 insertions(+), 33 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index b8450521fc..cd00967c70 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -38,6 +38,9 @@ ifeq ($(origin DAIKONDIR), undefined) DAIKONDIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))..) endif PLUME_SCRIPTS ?= ${DAIKONDIR}/.utils/plume-scripts +# Under CI, there are two CPUs, but limit to 1 to avoid out-of-memory error. +# If is-ci.sh is absent, assume the run is not under CI. +TEST_JOBS := $(if $(shell "${PLUME_SCRIPTS}/is-ci.sh" 2>/dev/null),1,4) all diffs: txt-diff non-txt-diff dyncomp-tests results @@ -54,13 +57,7 @@ esc jml inv txt-daikon-diff txt-esc-diff txt-jml-diff txt-csharpcontract-diff tx txt-chicory-diff everything-txt-diff stats dyncomp-diff txt-jaif-diff txt-jaif: ${MAKE} pat-daikon-tests-$@ pat-daikon-tests-%: -# Under CI, there are two CPUs, but limit to 1 to avoid out-of-memory error. - @test -x "${PLUME_SCRIPTS}"/is-ci.sh || { echo "Not found: ${PLUME_SCRIPTS}/is-ci.sh ; running 'make' in ${DAIKONDIR} clones it" >&2; exit 1; } - if [ -n "$$("${PLUME_SCRIPTS}"/is-ci.sh)" ]; then \ - ${MAKE} -C daikon-tests --jobs=1 ${MPARG} $*; \ - else \ - ${MAKE} -C daikon-tests --jobs=4 ${MPARG} $*; \ - fi + ${MAKE} -C daikon-tests --jobs=${TEST_JOBS} ${MPARG} $* list-targets: ${MAKE} -C daikon-tests list-targets diff --git a/tests/Makefile.common b/tests/Makefile.common index c151d000b3..95e6c75d96 100644 --- a/tests/Makefile.common +++ b/tests/Makefile.common @@ -186,17 +186,23 @@ ECLAT_SCRATCH = $(SCRATCH_FOR_DAIKON_BASE)/$(PROJECT)_eclat # CP_PARENTS := cp -pf --parents CP_PARENTS := rsync -aR +# Use ":=" so that the shell commands run only once. +ifeq ($(origin JAVA_HOME), undefined) ifeq ($(shell uname), Darwin) - JAVA_HOME ?= $(shell /usr/libexec/java_home) + JAVA_HOME := $(shell /usr/libexec/java_home) + ifeq (${JAVA_HOME},) + $(error /usr/libexec/java_home did not find a JDK; set JAVA_HOME) + endif else ifeq ($(shell which javac > /dev/null 2>&1 && echo found || echo nonexistent), found) - JAVA_HOME ?= $(shell readlink -f $(shell which javac) | sed "s:/bin/javac::") + JAVA_HOME := $(shell readlink -f $(shell which javac) | sed "s:/bin/javac::") else $(info Failure: Here is the output of: which javac) $(info $(shell which javac)) $(error 'which javac' had exit status 1) endif endif +endif JAVA := ${JAVA_HOME}/bin/java JAVAC ?= ${JAVA_HOME}/bin/javac diff --git a/tests/daikon-tests/junit/Makefile.user b/tests/daikon-tests/junit/Makefile.user index 20a6da71d7..032cf37886 100644 --- a/tests/daikon-tests/junit/Makefile.user +++ b/tests/daikon-tests/junit/Makefile.user @@ -1,16 +1,22 @@ ########################################################################### +# Use ":=" so that the shell commands run only once. +ifeq ($(origin JAVA_HOME), undefined) ifeq ($(shell uname), Darwin) - JAVA_HOME ?= $(shell /usr/libexec/java_home) + JAVA_HOME := $(shell /usr/libexec/java_home) + ifeq (${JAVA_HOME},) + $(error /usr/libexec/java_home did not find a JDK; set JAVA_HOME) + endif else ifeq ($(shell which javac > /dev/null 2>&1 && echo found || echo nonexistent), found) - JAVA_HOME ?= $(shell readlink -f $(shell which javac) | sed "s:/bin/javac::") + JAVA_HOME := $(shell readlink -f $(shell which javac) | sed "s:/bin/javac::") else $(info Failure: Here is the output of: which javac) $(info $(shell which javac)) $(error 'which javac' had exit status 1) endif endif +endif # need junit.jar on classpath to compile all junit references JUNIT_CLASSPATH := ${DAIKONDIR}/java/lib/* diff --git a/tests/daikon-tests/junit5/Makefile.user b/tests/daikon-tests/junit5/Makefile.user index b820d37665..5a03c11f02 100644 --- a/tests/daikon-tests/junit5/Makefile.user +++ b/tests/daikon-tests/junit5/Makefile.user @@ -1,16 +1,22 @@ ########################################################################### +# Use ":=" so that the shell commands run only once. +ifeq ($(origin JAVA_HOME), undefined) ifeq ($(shell uname), Darwin) - JAVA_HOME ?= $(shell /usr/libexec/java_home) + JAVA_HOME := $(shell /usr/libexec/java_home) + ifeq (${JAVA_HOME},) + $(error /usr/libexec/java_home did not find a JDK; set JAVA_HOME) + endif else ifeq ($(shell which javac > /dev/null 2>&1 && echo found || echo nonexistent), found) - JAVA_HOME ?= $(shell readlink -f $(shell which javac) | sed "s:/bin/javac::") + JAVA_HOME := $(shell readlink -f $(shell which javac) | sed "s:/bin/javac::") else $(info Failure: Here is the output of: which javac) $(info $(shell which javac)) $(error 'which javac' had exit status 1) endif endif +endif # need junit.jar on classpath to compile all junit references # explicit order is necessary to get versions built with JDK 8 not 5 diff --git a/tests/dyncomp-tests/Makefile b/tests/dyncomp-tests/Makefile index b2eaa8e885..a4915c56fb 100644 --- a/tests/dyncomp-tests/Makefile +++ b/tests/dyncomp-tests/Makefile @@ -18,10 +18,20 @@ # Forked from $DAIKONDIR/tests/kvasir-tests/Makefile +ifeq (4.0,$(firstword $(sort ${MAKE_VERSION} 4.0))) + # Version 4.0 or higher + MPARG ?= -Orecurse +else + MPARG ?= +endif + ifeq ($(origin DAIKONDIR), undefined) DAIKONDIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))../..) endif PLUME_SCRIPTS ?= ${DAIKONDIR}/.utils/plume-scripts +# Under CI, there are two CPUs, but limit to 1 to avoid out-of-memory error. +# If is-ci.sh is absent, assume the run is not under CI. +TEST_JOBS := $(if $(shell "${PLUME_SCRIPTS}/is-ci.sh" 2>/dev/null),1,4) default: summary @@ -67,12 +77,7 @@ update-all: .PHONY: clean-all clean-all: - @test -x "${PLUME_SCRIPTS}"/is-ci.sh || { echo "Not found: ${PLUME_SCRIPTS}/is-ci.sh ; running 'make' in ${DAIKONDIR} clones it" >&2; exit 1; } - if [ -n "$$("${PLUME_SCRIPTS}"/is-ci.sh)" ]; then \ - ${MAKE} --jobs=1 ${MPARG} nightly-tests__clean; \ - else \ - ${MAKE} --jobs=4 ${MPARG} nightly-tests__clean; \ - fi + ${MAKE} --jobs=${TEST_JOBS} ${MPARG} nightly-tests__clean default-projects__%: pgbovine-tests__% diff --git a/tests/dyncomp-tests/Makefile.common b/tests/dyncomp-tests/Makefile.common index 173bce853b..261b7946d0 100644 --- a/tests/dyncomp-tests/Makefile.common +++ b/tests/dyncomp-tests/Makefile.common @@ -3,7 +3,9 @@ # Forked from $DAIKONDIR/tests/kvasir-tests/Makefile.common # DAIKONDIR is the clone of the 'daikon' project. -DAIKONDIR ?= $(realpath $(dir $(lastword $(MAKEFILE_LIST)))../..) +ifeq ($(origin DAIKONDIR), undefined) + DAIKONDIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))../..) +endif ifeq ($(shell uname -m),x86_64) VALGRIND_ARCH := amd64 diff --git a/tests/kvasir-tests/Makefile b/tests/kvasir-tests/Makefile index 7067317980..7e89a2de9b 100644 --- a/tests/kvasir-tests/Makefile +++ b/tests/kvasir-tests/Makefile @@ -24,17 +24,15 @@ ifeq ($(origin DAIKONDIR), undefined) DAIKONDIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))../..) endif PLUME_SCRIPTS ?= ${DAIKONDIR}/.utils/plume-scripts +# Under CI, there are two CPUs, but limit to 1 to avoid out-of-memory error. +# If is-ci.sh is absent, assume the run is not under CI. +TEST_JOBS := $(if $(shell "${PLUME_SCRIPTS}/is-ci.sh" 2>/dev/null),1,4) default: summary-w-daikon .PHONY: regression-tests regression-tests: - @test -x "${PLUME_SCRIPTS}"/is-ci.sh || { echo "Not found: ${PLUME_SCRIPTS}/is-ci.sh ; running 'make' in ${DAIKONDIR} clones it" >&2; exit 1; } - if [ -n "$$("${PLUME_SCRIPTS}"/is-ci.sh)" ]; then \ - ${MAKE} --jobs=1 ${MPARG} nightly-tests__diffs-w-daikon-if-working; \ - else \ - ${MAKE} --jobs=4 ${MPARG} nightly-tests__diffs-w-daikon-if-working; \ - fi + ${MAKE} --jobs=${TEST_JOBS} ${MPARG} nightly-tests__diffs-w-daikon-if-working ${MAKE} nightly-summary-only-w-daikon @${MAKE} --no-print-directory results @@ -84,12 +82,7 @@ update-all: .PHONY: clean-all clean-all: - @test -x "${PLUME_SCRIPTS}"/is-ci.sh || { echo "Not found: ${PLUME_SCRIPTS}/is-ci.sh ; running 'make' in ${DAIKONDIR} clones it" >&2; exit 1; } - if [ -n "$$("${PLUME_SCRIPTS}"/is-ci.sh)" ]; then \ - ${MAKE} --jobs=1 ${MPARG} nightly-tests__clean; \ - else \ - ${MAKE} --jobs=4 ${MPARG} nightly-tests__clean; \ - fi + ${MAKE} --jobs=${TEST_JOBS} ${MPARG} nightly-tests__clean default-projects__%: pgbovine-tests__% smcc-tests__% tiny-real-tests__% tws-tests__% @ diff --git a/tests/kvasir-tests/Makefile.common b/tests/kvasir-tests/Makefile.common index c1fc9bd33b..aeab77975a 100644 --- a/tests/kvasir-tests/Makefile.common +++ b/tests/kvasir-tests/Makefile.common @@ -1,7 +1,9 @@ # This is a -*- makefile -*-, Emacs # DAIKONDIR is the clone of the 'daikon' project. -DAIKONDIR ?= $(realpath $(dir $(lastword $(MAKEFILE_LIST)))../..) +ifeq ($(origin DAIKONDIR), undefined) + DAIKONDIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))../..) +endif DAIKON_JAR := ${DAIKONDIR}/daikon.jar # Fails when running "clean". # $(if $(wildcard ${DAIKON_JAR}),,$(error daikon.jar not found at ${DAIKON_JAR})) From 9c658a1a2d89d26e400edee1f9a32a05b899b6c7 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Sat, 10 Oct 2026 12:58:37 -0700 Subject: [PATCH 4/6] Address code review: shared Makefile.jobs, deferred JDK check, consistent DAIKONDIR * New tests/Makefile.jobs holds MPARG, DAIKONDIR, PLUME_SCRIPTS and TEST_JOBS for the three test-driver Makefiles. It fails clearly if is-ci.sh is missing, computes TEST_JOBS once and exports it, and honors a TEST_JOBS value from the command line or environment. * tests/Makefile.common sets JAVA_HOME before including Makefile.user, so the junit and junit5 Makefile.user files no longer duplicate the detection. Locate javac with a single shell command. Check for a missing JDK only when JAVA or JAVAC is expanded, so targets such as "clean" work without a JDK. * java/Makefile: compute JAVA_HOME once and fail clearly if no JDK is found. * Define DAIKONDIR with ":=" in the remaining test Makefiles; fix its depth in tests/daikon-tests/Makefile. --- java/Makefile | 20 ++++----- tests/Makefile | 17 +------- tests/Makefile.common | 41 +++++++++---------- tests/Makefile.jobs | 32 +++++++++++++++ tests/daikon-tests/Makefile | 4 +- tests/daikon-tests/junit/Makefile.user | 20 +-------- tests/daikon-tests/junit5/Makefile.user | 20 +-------- tests/diff-tests/Makefile.common | 4 +- tests/dyncomp-tests/Makefile | 15 +------ tests/kvasir-tests/Makefile | 15 +------ tests/merge-invariants-tests/drawlet/Makefile | 4 +- tests/parser-tests/Makefile | 4 +- 12 files changed, 78 insertions(+), 118 deletions(-) create mode 100644 tests/Makefile.jobs diff --git a/java/Makefile b/java/Makefile index ce436e5d69..65dab35496 100644 --- a/java/Makefile +++ b/java/Makefile @@ -25,16 +25,16 @@ JAR ?= jar BuildJDKTool = BuildJDK -ifeq ($(shell uname), Darwin) - JAVA_HOME ?= $(shell /usr/libexec/java_home) -else -ifeq ($(shell which javac > /dev/null 2>&1 && echo found || echo nonexistent), found) - JAVA_HOME ?= $(shell readlink -f $(shell which javac) | sed "s:/bin/javac::") -else - $(info Failure: Here is the output of: which javac) - $(info $(shell which javac)) - $(error 'which javac' had exit status 1) -endif +# Use ":=" so that the shell commands run only once. +ifeq ($(origin JAVA_HOME), undefined) + ifeq ($(shell uname), Darwin) + JAVA_HOME := $(shell /usr/libexec/java_home) + else + JAVA_HOME := $(shell javac=$$(command -v javac) && readlink -f "$$javac" | sed 's:/bin/javac$$::') + endif + ifeq (${JAVA_HOME},) + $(error No JDK found; set JAVA_HOME or put javac on the PATH) + endif endif # The "JAVANN" variables mean "at least version NN", except JAVA8. diff --git a/tests/Makefile b/tests/Makefile index cd00967c70..7ae1ffebe6 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -25,22 +25,7 @@ help-recurse-list: @echo " which are ones that have been selected as useful tests.)" @echo "" -# To produce incremental output, invoke make as: make MPARG=-Otarget ... -# To not run in parallel, invoke make as: make MPARG=-j1 ... -ifeq (4.0,$(firstword $(sort ${MAKE_VERSION} 4.0))) - # Version 4.0 or higher - MPARG ?= -Orecurse -else - MPARG ?= -endif - -ifeq ($(origin DAIKONDIR), undefined) - DAIKONDIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))..) -endif -PLUME_SCRIPTS ?= ${DAIKONDIR}/.utils/plume-scripts -# Under CI, there are two CPUs, but limit to 1 to avoid out-of-memory error. -# If is-ci.sh is absent, assume the run is not under CI. -TEST_JOBS := $(if $(shell "${PLUME_SCRIPTS}/is-ci.sh" 2>/dev/null),1,4) +include $(dir $(lastword $(MAKEFILE_LIST)))Makefile.jobs all diffs: txt-diff non-txt-diff dyncomp-tests results diff --git a/tests/Makefile.common b/tests/Makefile.common index 95e6c75d96..7013f200a2 100644 --- a/tests/Makefile.common +++ b/tests/Makefile.common @@ -149,6 +149,20 @@ ifndef COMMON_HERE $(error Test directory ${DAIKONDIR}/tests does not exist) endif +# JAVA_HOME is set before Makefile.user is included, so that Makefile.user can use or override it. +# Use ":=" so that the shell commands run only once. +ifeq ($(origin JAVA_HOME), undefined) + ifeq ($(shell uname), Darwin) + JAVA_HOME := $(shell /usr/libexec/java_home) + else + JAVA_HOME := $(shell javac=$$(command -v javac) && readlink -f "$$javac" | sed 's:/bin/javac$$::') + endif +endif +# CHECKED_JAVA_HOME is JAVA_HOME, but expanding it fails if no JDK was found. +# The check happens only when a variable that uses it is expanded, so targets +# that do not run Java (such as "clean") work without a JDK. +CHECKED_JAVA_HOME = $(or ${JAVA_HOME},$(error No JDK found; set JAVA_HOME)) + # Put user-specific changes in your own Makefile.user # (such as changes to PLUME_DIR or JAVAC or PATH). # Make will silently continue if the file does not exist. @@ -186,25 +200,8 @@ ECLAT_SCRATCH = $(SCRATCH_FOR_DAIKON_BASE)/$(PROJECT)_eclat # CP_PARENTS := cp -pf --parents CP_PARENTS := rsync -aR -# Use ":=" so that the shell commands run only once. -ifeq ($(origin JAVA_HOME), undefined) -ifeq ($(shell uname), Darwin) - JAVA_HOME := $(shell /usr/libexec/java_home) - ifeq (${JAVA_HOME},) - $(error /usr/libexec/java_home did not find a JDK; set JAVA_HOME) - endif -else -ifeq ($(shell which javac > /dev/null 2>&1 && echo found || echo nonexistent), found) - JAVA_HOME := $(shell readlink -f $(shell which javac) | sed "s:/bin/javac::") -else - $(info Failure: Here is the output of: which javac) - $(info $(shell which javac)) - $(error 'which javac' had exit status 1) -endif -endif -endif -JAVA := ${JAVA_HOME}/bin/java -JAVAC ?= ${JAVA_HOME}/bin/javac +JAVA = ${CHECKED_JAVA_HOME}/bin/java +JAVAC ?= ${CHECKED_JAVA_HOME}/bin/javac JUNIT_CLASSPATH ?= @@ -215,7 +212,7 @@ DAIKON_CLASSPATH := ${DAIKONDIR}/java:${DAIKONDIR}/java/lib/*:${DAIKONDIR}/daiko export DAIKON_TESTS_CLASSPATH := .:$(JAVALIB_CLASSPATH):$(SCRATCH_FOR_DAIKON):$(JUNIT_CLASSPATH):$(DAIKON_CLASSPATH) # Dynamic instrumentation based java front end command. -CHICORY := $(JAVA) -ea -cp "$(DAIKON_TESTS_CLASSPATH)" daikon.Chicory +CHICORY = $(JAVA) -ea -cp "$(DAIKON_TESTS_CLASSPATH)" daikon.Chicory CHICORY_EXEC := ${DAIKONDIR}/java/daikon/Chicory.class # As of JDK 1.3 (and 1.4, I think), don't use "-server" here. @@ -308,12 +305,12 @@ endif # If specified, setup for the old declaration format ifeq (old,${DECL_FORMAT}) - CHICORY := $(CHICORY) --new_decl_format=false + CHICORY += --new_decl_format=false endif # "make PROFILE_JAVA=1 " to get profile information ifdef PROFILE_JAVA -RUN_JAVA:=$(RUN_JAVA) -Xrunhprof:cpu=samples,file=${PROJECT_FILE}.profile.txt,depth=3 +RUN_JAVA += -Xrunhprof:cpu=samples,file=${PROJECT_FILE}.profile.txt,depth=3 endif # To turn off Simplify, put this in the project's own Makefile, after diff --git a/tests/Makefile.jobs b/tests/Makefile.jobs new file mode 100644 index 0000000000..e3736b3ca6 --- /dev/null +++ b/tests/Makefile.jobs @@ -0,0 +1,32 @@ +# This is a -*- makefile -*-, Emacs +# +# Settings shared by the Makefiles that drive a whole test suite: +# tests/Makefile, tests/kvasir-tests/Makefile, and tests/dyncomp-tests/Makefile. +# Include it before any other include, so that MAKEFILE_LIST ends with this file. + +# To produce incremental output, invoke make as: make MPARG=-Otarget ... +# To not run in parallel, invoke make as: make MPARG=-j1 ... +ifeq (4.0,$(firstword $(sort ${MAKE_VERSION} 4.0))) + # Version 4.0 or higher + MPARG ?= -Orecurse +else + MPARG ?= +endif + +# DAIKONDIR is the clone of the 'daikon' project. +ifeq ($(origin DAIKONDIR), undefined) + DAIKONDIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))..) +endif +PLUME_SCRIPTS ?= ${DAIKONDIR}/.utils/plume-scripts + +# TEST_JOBS is the number of tests to run in parallel. +# Under CI, there are two CPUs, but limit to 1 to avoid out-of-memory error. +# The value is exported, so recursive invocations of make do not recompute it. +# To override it, set TEST_JOBS on the command line or in the environment. +ifeq ($(origin TEST_JOBS), undefined) + ifeq ($(wildcard ${PLUME_SCRIPTS}/is-ci.sh),) + $(error ${PLUME_SCRIPTS}/is-ci.sh not found; run "make" in ${DAIKONDIR} to clone plume-scripts, or set TEST_JOBS) + endif + TEST_JOBS := $(if $(shell sh "${PLUME_SCRIPTS}/is-ci.sh"),1,4) +endif +export TEST_JOBS diff --git a/tests/daikon-tests/Makefile b/tests/daikon-tests/Makefile index 3342685d68..aa5b656531 100644 --- a/tests/daikon-tests/Makefile +++ b/tests/daikon-tests/Makefile @@ -2,7 +2,9 @@ # Read Makefile in parent directory to see what this all means # DAIKONDIR is the clone of the 'daikon' project. -DAIKONDIR ?= $(realpath $(dir $(lastword ${MAKEFILE_LIST}))..) +ifeq ($(origin DAIKONDIR), undefined) + DAIKONDIR := $(realpath $(dir $(lastword ${MAKEFILE_LIST}))../..) +endif SCRIPTS=${DAIKONDIR}/scripts # Help system diff --git a/tests/daikon-tests/junit/Makefile.user b/tests/daikon-tests/junit/Makefile.user index 032cf37886..169d40bfae 100644 --- a/tests/daikon-tests/junit/Makefile.user +++ b/tests/daikon-tests/junit/Makefile.user @@ -1,23 +1,5 @@ ########################################################################### -# Use ":=" so that the shell commands run only once. -ifeq ($(origin JAVA_HOME), undefined) -ifeq ($(shell uname), Darwin) - JAVA_HOME := $(shell /usr/libexec/java_home) - ifeq (${JAVA_HOME},) - $(error /usr/libexec/java_home did not find a JDK; set JAVA_HOME) - endif -else -ifeq ($(shell which javac > /dev/null 2>&1 && echo found || echo nonexistent), found) - JAVA_HOME := $(shell readlink -f $(shell which javac) | sed "s:/bin/javac::") -else - $(info Failure: Here is the output of: which javac) - $(info $(shell which javac)) - $(error 'which javac' had exit status 1) -endif -endif -endif - # need junit.jar on classpath to compile all junit references JUNIT_CLASSPATH := ${DAIKONDIR}/java/lib/* -JAVAC := $(JAVA_HOME)/bin/javac -cp .:$(JUNIT_CLASSPATH) +JAVAC = ${CHECKED_JAVA_HOME}/bin/javac -cp .:$(JUNIT_CLASSPATH) diff --git a/tests/daikon-tests/junit5/Makefile.user b/tests/daikon-tests/junit5/Makefile.user index 5a03c11f02..90c4b5cdad 100644 --- a/tests/daikon-tests/junit5/Makefile.user +++ b/tests/daikon-tests/junit5/Makefile.user @@ -1,24 +1,6 @@ ########################################################################### -# Use ":=" so that the shell commands run only once. -ifeq ($(origin JAVA_HOME), undefined) -ifeq ($(shell uname), Darwin) - JAVA_HOME := $(shell /usr/libexec/java_home) - ifeq (${JAVA_HOME},) - $(error /usr/libexec/java_home did not find a JDK; set JAVA_HOME) - endif -else -ifeq ($(shell which javac > /dev/null 2>&1 && echo found || echo nonexistent), found) - JAVA_HOME := $(shell readlink -f $(shell which javac) | sed "s:/bin/javac::") -else - $(info Failure: Here is the output of: which javac) - $(info $(shell which javac)) - $(error 'which javac' had exit status 1) -endif -endif -endif - # need junit.jar on classpath to compile all junit references # explicit order is necessary to get versions built with JDK 8 not 5 JUNIT_CLASSPATH := ${DAIKONDIR}/java/lib/junit-4.13.2-Daikon.jar:${DAIKONDIR}/java/lib/hamcrest-core-1.3-Daikon.jar:${DAIKONDIR}/java/lib/* -JAVAC := $(JAVA_HOME)/bin/javac -cp .:$(JUNIT_CLASSPATH) +JAVAC = ${CHECKED_JAVA_HOME}/bin/javac -cp .:$(JUNIT_CLASSPATH) diff --git a/tests/diff-tests/Makefile.common b/tests/diff-tests/Makefile.common index 7a22461dfd..c0edcaf4ab 100644 --- a/tests/diff-tests/Makefile.common +++ b/tests/diff-tests/Makefile.common @@ -6,7 +6,9 @@ # of Diff. # DAIKONDIR is the clone of the 'daikon' project. -DAIKONDIR ?= $(realpath $(dir $(lastword $(MAKEFILE_LIST)))../..) +ifeq ($(origin DAIKONDIR), undefined) + DAIKONDIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))../..) +endif DAIKON_CLASSPATH := ${DAIKONDIR}/java:${DAIKONDIR}/java/lib/*:${DAIKONDIR}/daikon.jar diff --git a/tests/dyncomp-tests/Makefile b/tests/dyncomp-tests/Makefile index a4915c56fb..e69a8eb91a 100644 --- a/tests/dyncomp-tests/Makefile +++ b/tests/dyncomp-tests/Makefile @@ -18,20 +18,7 @@ # Forked from $DAIKONDIR/tests/kvasir-tests/Makefile -ifeq (4.0,$(firstword $(sort ${MAKE_VERSION} 4.0))) - # Version 4.0 or higher - MPARG ?= -Orecurse -else - MPARG ?= -endif - -ifeq ($(origin DAIKONDIR), undefined) - DAIKONDIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))../..) -endif -PLUME_SCRIPTS ?= ${DAIKONDIR}/.utils/plume-scripts -# Under CI, there are two CPUs, but limit to 1 to avoid out-of-memory error. -# If is-ci.sh is absent, assume the run is not under CI. -TEST_JOBS := $(if $(shell "${PLUME_SCRIPTS}/is-ci.sh" 2>/dev/null),1,4) +include $(dir $(lastword $(MAKEFILE_LIST)))../Makefile.jobs default: summary diff --git a/tests/kvasir-tests/Makefile b/tests/kvasir-tests/Makefile index 7e89a2de9b..9e86fee177 100644 --- a/tests/kvasir-tests/Makefile +++ b/tests/kvasir-tests/Makefile @@ -13,20 +13,7 @@ # category to contain it. # -ifeq (4.0,$(firstword $(sort ${MAKE_VERSION} 4.0))) - # Version 4.0 or higher - MPARG ?= -Orecurse -else - MPARG ?= -endif - -ifeq ($(origin DAIKONDIR), undefined) - DAIKONDIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))../..) -endif -PLUME_SCRIPTS ?= ${DAIKONDIR}/.utils/plume-scripts -# Under CI, there are two CPUs, but limit to 1 to avoid out-of-memory error. -# If is-ci.sh is absent, assume the run is not under CI. -TEST_JOBS := $(if $(shell "${PLUME_SCRIPTS}/is-ci.sh" 2>/dev/null),1,4) +include $(dir $(lastword $(MAKEFILE_LIST)))../Makefile.jobs default: summary-w-daikon diff --git a/tests/merge-invariants-tests/drawlet/Makefile b/tests/merge-invariants-tests/drawlet/Makefile index da2a137a0f..332447d42a 100644 --- a/tests/merge-invariants-tests/drawlet/Makefile +++ b/tests/merge-invariants-tests/drawlet/Makefile @@ -9,7 +9,9 @@ # files are in drawlet_src.zip in this directory # DAIKONDIR is the clone of the 'daikon' project. -DAIKONDIR ?= $(realpath $(dir $(lastword ${MAKEFILE_LIST}))../../..) +ifeq ($(origin DAIKONDIR), undefined) + DAIKONDIR := $(realpath $(dir $(lastword ${MAKEFILE_LIST}))../../..) +endif DAIKON_ARGS = '--ppt-omit-pattern=^org\.' --no_text_output --no_show_progress --config_option daikon.Debug.show_stack_trace=true DAIKON = ${DAIKONDIR}/java/daikon/Daikon.class diff --git a/tests/parser-tests/Makefile b/tests/parser-tests/Makefile index 6a1755c3ea..4adb545dde 100644 --- a/tests/parser-tests/Makefile +++ b/tests/parser-tests/Makefile @@ -1,5 +1,7 @@ # DAIKONDIR is the clone of the 'daikon' project. -DAIKONDIR ?= $(realpath $(dir $(lastword ${MAKEFILE_LIST}))../..) +ifeq ($(origin DAIKONDIR), undefined) + DAIKONDIR := $(realpath $(dir $(lastword ${MAKEFILE_LIST}))../..) +endif DAIKON_CLASSPATH := ${DAIKONDIR}/java:${DAIKONDIR}/java/lib/*:${DAIKONDIR}/daikon.jar From b31b497c9c327b9e807756c30bddce56b0980692 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Sat, 10 Oct 2026 13:04:08 -0700 Subject: [PATCH 5/6] Move the JAVA_HOME and DAIKONDIR changes to separate pull requests --- java/Makefile | 20 +++++------ tests/Makefile.common | 35 +++++++++---------- tests/daikon-tests/Makefile | 4 +-- tests/daikon-tests/junit/Makefile.user | 14 +++++++- tests/daikon-tests/junit5/Makefile.user | 14 +++++++- tests/diff-tests/Makefile.common | 4 +-- tests/dyncomp-tests/Makefile.common | 4 +-- tests/kvasir-tests/Makefile.common | 4 +-- tests/merge-invariants-tests/drawlet/Makefile | 4 +-- tests/parser-tests/Makefile | 4 +-- 10 files changed, 58 insertions(+), 49 deletions(-) diff --git a/java/Makefile b/java/Makefile index 65dab35496..ce436e5d69 100644 --- a/java/Makefile +++ b/java/Makefile @@ -25,16 +25,16 @@ JAR ?= jar BuildJDKTool = BuildJDK -# Use ":=" so that the shell commands run only once. -ifeq ($(origin JAVA_HOME), undefined) - ifeq ($(shell uname), Darwin) - JAVA_HOME := $(shell /usr/libexec/java_home) - else - JAVA_HOME := $(shell javac=$$(command -v javac) && readlink -f "$$javac" | sed 's:/bin/javac$$::') - endif - ifeq (${JAVA_HOME},) - $(error No JDK found; set JAVA_HOME or put javac on the PATH) - endif +ifeq ($(shell uname), Darwin) + JAVA_HOME ?= $(shell /usr/libexec/java_home) +else +ifeq ($(shell which javac > /dev/null 2>&1 && echo found || echo nonexistent), found) + JAVA_HOME ?= $(shell readlink -f $(shell which javac) | sed "s:/bin/javac::") +else + $(info Failure: Here is the output of: which javac) + $(info $(shell which javac)) + $(error 'which javac' had exit status 1) +endif endif # The "JAVANN" variables mean "at least version NN", except JAVA8. diff --git a/tests/Makefile.common b/tests/Makefile.common index 7013f200a2..38dde8e8cb 100644 --- a/tests/Makefile.common +++ b/tests/Makefile.common @@ -149,20 +149,6 @@ ifndef COMMON_HERE $(error Test directory ${DAIKONDIR}/tests does not exist) endif -# JAVA_HOME is set before Makefile.user is included, so that Makefile.user can use or override it. -# Use ":=" so that the shell commands run only once. -ifeq ($(origin JAVA_HOME), undefined) - ifeq ($(shell uname), Darwin) - JAVA_HOME := $(shell /usr/libexec/java_home) - else - JAVA_HOME := $(shell javac=$$(command -v javac) && readlink -f "$$javac" | sed 's:/bin/javac$$::') - endif -endif -# CHECKED_JAVA_HOME is JAVA_HOME, but expanding it fails if no JDK was found. -# The check happens only when a variable that uses it is expanded, so targets -# that do not run Java (such as "clean") work without a JDK. -CHECKED_JAVA_HOME = $(or ${JAVA_HOME},$(error No JDK found; set JAVA_HOME)) - # Put user-specific changes in your own Makefile.user # (such as changes to PLUME_DIR or JAVAC or PATH). # Make will silently continue if the file does not exist. @@ -200,8 +186,19 @@ ECLAT_SCRATCH = $(SCRATCH_FOR_DAIKON_BASE)/$(PROJECT)_eclat # CP_PARENTS := cp -pf --parents CP_PARENTS := rsync -aR -JAVA = ${CHECKED_JAVA_HOME}/bin/java -JAVAC ?= ${CHECKED_JAVA_HOME}/bin/javac +ifeq ($(shell uname), Darwin) + JAVA_HOME ?= $(/usr/libexec/java_home) +else +ifeq ($(shell which javac > /dev/null 2>&1 && echo found || echo nonexistent), found) + JAVA_HOME ?= $(shell readlink -f $(shell which javac) | sed "s:/bin/javac::") +else + $(info Failure: Here is the output of: which javac) + $(info $(shell which javac)) + $(error 'which javac' had exit status 1) +endif +endif +JAVA := ${JAVA_HOME}/bin/java +JAVAC ?= ${JAVA_HOME}/bin/javac JUNIT_CLASSPATH ?= @@ -212,7 +209,7 @@ DAIKON_CLASSPATH := ${DAIKONDIR}/java:${DAIKONDIR}/java/lib/*:${DAIKONDIR}/daiko export DAIKON_TESTS_CLASSPATH := .:$(JAVALIB_CLASSPATH):$(SCRATCH_FOR_DAIKON):$(JUNIT_CLASSPATH):$(DAIKON_CLASSPATH) # Dynamic instrumentation based java front end command. -CHICORY = $(JAVA) -ea -cp "$(DAIKON_TESTS_CLASSPATH)" daikon.Chicory +CHICORY := $(JAVA) -ea -cp "$(DAIKON_TESTS_CLASSPATH)" daikon.Chicory CHICORY_EXEC := ${DAIKONDIR}/java/daikon/Chicory.class # As of JDK 1.3 (and 1.4, I think), don't use "-server" here. @@ -305,12 +302,12 @@ endif # If specified, setup for the old declaration format ifeq (old,${DECL_FORMAT}) - CHICORY += --new_decl_format=false + CHICORY := $(CHICORY) --new_decl_format=false endif # "make PROFILE_JAVA=1 " to get profile information ifdef PROFILE_JAVA -RUN_JAVA += -Xrunhprof:cpu=samples,file=${PROJECT_FILE}.profile.txt,depth=3 +RUN_JAVA:=$(RUN_JAVA) -Xrunhprof:cpu=samples,file=${PROJECT_FILE}.profile.txt,depth=3 endif # To turn off Simplify, put this in the project's own Makefile, after diff --git a/tests/daikon-tests/Makefile b/tests/daikon-tests/Makefile index aa5b656531..3342685d68 100644 --- a/tests/daikon-tests/Makefile +++ b/tests/daikon-tests/Makefile @@ -2,9 +2,7 @@ # Read Makefile in parent directory to see what this all means # DAIKONDIR is the clone of the 'daikon' project. -ifeq ($(origin DAIKONDIR), undefined) - DAIKONDIR := $(realpath $(dir $(lastword ${MAKEFILE_LIST}))../..) -endif +DAIKONDIR ?= $(realpath $(dir $(lastword ${MAKEFILE_LIST}))..) SCRIPTS=${DAIKONDIR}/scripts # Help system diff --git a/tests/daikon-tests/junit/Makefile.user b/tests/daikon-tests/junit/Makefile.user index 169d40bfae..9c2889b925 100644 --- a/tests/daikon-tests/junit/Makefile.user +++ b/tests/daikon-tests/junit/Makefile.user @@ -1,5 +1,17 @@ ########################################################################### +ifeq ($(shell uname), Darwin) + JAVA_HOME ?= $(/usr/libexec/java_home) +else +ifeq ($(shell which javac > /dev/null 2>&1 && echo found || echo nonexistent), found) + JAVA_HOME ?= $(shell readlink -f $(shell which javac) | sed "s:/bin/javac::") +else + $(info Failure: Here is the output of: which javac) + $(info $(shell which javac)) + $(error 'which javac' had exit status 1) +endif +endif + # need junit.jar on classpath to compile all junit references JUNIT_CLASSPATH := ${DAIKONDIR}/java/lib/* -JAVAC = ${CHECKED_JAVA_HOME}/bin/javac -cp .:$(JUNIT_CLASSPATH) +JAVAC := $(JAVA_HOME)/bin/javac -cp .:$(JUNIT_CLASSPATH) diff --git a/tests/daikon-tests/junit5/Makefile.user b/tests/daikon-tests/junit5/Makefile.user index 90c4b5cdad..d10d1f57d7 100644 --- a/tests/daikon-tests/junit5/Makefile.user +++ b/tests/daikon-tests/junit5/Makefile.user @@ -1,6 +1,18 @@ ########################################################################### +ifeq ($(shell uname), Darwin) + JAVA_HOME ?= $(/usr/libexec/java_home) +else +ifeq ($(shell which javac > /dev/null 2>&1 && echo found || echo nonexistent), found) + JAVA_HOME ?= $(shell readlink -f $(shell which javac) | sed "s:/bin/javac::") +else + $(info Failure: Here is the output of: which javac) + $(info $(shell which javac)) + $(error 'which javac' had exit status 1) +endif +endif + # need junit.jar on classpath to compile all junit references # explicit order is necessary to get versions built with JDK 8 not 5 JUNIT_CLASSPATH := ${DAIKONDIR}/java/lib/junit-4.13.2-Daikon.jar:${DAIKONDIR}/java/lib/hamcrest-core-1.3-Daikon.jar:${DAIKONDIR}/java/lib/* -JAVAC = ${CHECKED_JAVA_HOME}/bin/javac -cp .:$(JUNIT_CLASSPATH) +JAVAC := $(JAVA_HOME)/bin/javac -cp .:$(JUNIT_CLASSPATH) diff --git a/tests/diff-tests/Makefile.common b/tests/diff-tests/Makefile.common index c0edcaf4ab..7a22461dfd 100644 --- a/tests/diff-tests/Makefile.common +++ b/tests/diff-tests/Makefile.common @@ -6,9 +6,7 @@ # of Diff. # DAIKONDIR is the clone of the 'daikon' project. -ifeq ($(origin DAIKONDIR), undefined) - DAIKONDIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))../..) -endif +DAIKONDIR ?= $(realpath $(dir $(lastword $(MAKEFILE_LIST)))../..) DAIKON_CLASSPATH := ${DAIKONDIR}/java:${DAIKONDIR}/java/lib/*:${DAIKONDIR}/daikon.jar diff --git a/tests/dyncomp-tests/Makefile.common b/tests/dyncomp-tests/Makefile.common index 261b7946d0..173bce853b 100644 --- a/tests/dyncomp-tests/Makefile.common +++ b/tests/dyncomp-tests/Makefile.common @@ -3,9 +3,7 @@ # Forked from $DAIKONDIR/tests/kvasir-tests/Makefile.common # DAIKONDIR is the clone of the 'daikon' project. -ifeq ($(origin DAIKONDIR), undefined) - DAIKONDIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))../..) -endif +DAIKONDIR ?= $(realpath $(dir $(lastword $(MAKEFILE_LIST)))../..) ifeq ($(shell uname -m),x86_64) VALGRIND_ARCH := amd64 diff --git a/tests/kvasir-tests/Makefile.common b/tests/kvasir-tests/Makefile.common index aeab77975a..c1fc9bd33b 100644 --- a/tests/kvasir-tests/Makefile.common +++ b/tests/kvasir-tests/Makefile.common @@ -1,9 +1,7 @@ # This is a -*- makefile -*-, Emacs # DAIKONDIR is the clone of the 'daikon' project. -ifeq ($(origin DAIKONDIR), undefined) - DAIKONDIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))../..) -endif +DAIKONDIR ?= $(realpath $(dir $(lastword $(MAKEFILE_LIST)))../..) DAIKON_JAR := ${DAIKONDIR}/daikon.jar # Fails when running "clean". # $(if $(wildcard ${DAIKON_JAR}),,$(error daikon.jar not found at ${DAIKON_JAR})) diff --git a/tests/merge-invariants-tests/drawlet/Makefile b/tests/merge-invariants-tests/drawlet/Makefile index 332447d42a..da2a137a0f 100644 --- a/tests/merge-invariants-tests/drawlet/Makefile +++ b/tests/merge-invariants-tests/drawlet/Makefile @@ -9,9 +9,7 @@ # files are in drawlet_src.zip in this directory # DAIKONDIR is the clone of the 'daikon' project. -ifeq ($(origin DAIKONDIR), undefined) - DAIKONDIR := $(realpath $(dir $(lastword ${MAKEFILE_LIST}))../../..) -endif +DAIKONDIR ?= $(realpath $(dir $(lastword ${MAKEFILE_LIST}))../../..) DAIKON_ARGS = '--ppt-omit-pattern=^org\.' --no_text_output --no_show_progress --config_option daikon.Debug.show_stack_trace=true DAIKON = ${DAIKONDIR}/java/daikon/Daikon.class diff --git a/tests/parser-tests/Makefile b/tests/parser-tests/Makefile index 4adb545dde..6a1755c3ea 100644 --- a/tests/parser-tests/Makefile +++ b/tests/parser-tests/Makefile @@ -1,7 +1,5 @@ # DAIKONDIR is the clone of the 'daikon' project. -ifeq ($(origin DAIKONDIR), undefined) - DAIKONDIR := $(realpath $(dir $(lastword ${MAKEFILE_LIST}))../..) -endif +DAIKONDIR ?= $(realpath $(dir $(lastword ${MAKEFILE_LIST}))../..) DAIKON_CLASSPATH := ${DAIKONDIR}/java:${DAIKONDIR}/java/lib/*:${DAIKONDIR}/daikon.jar From 562057df71bc5bb9176811b0501c8f30af321d5a Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Sat, 10 Oct 2026 13:28:10 -0700 Subject: [PATCH 6/6] Address code review: compute DAIKON_TEST_JOBS lazily, rename it, and do not set DAIKONDIR Computing the job count only when a recipe uses it lets targets such as clean and help work when plume-scripts is absent. An empty value is treated as unset. The variable is no longer exported. --- tests/Makefile | 2 +- tests/Makefile.jobs | 26 +++++++++++--------------- tests/dyncomp-tests/Makefile | 2 +- tests/kvasir-tests/Makefile | 4 ++-- 4 files changed, 15 insertions(+), 19 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 7ae1ffebe6..aa5b7c2fdd 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -42,7 +42,7 @@ esc jml inv txt-daikon-diff txt-esc-diff txt-jml-diff txt-csharpcontract-diff tx txt-chicory-diff everything-txt-diff stats dyncomp-diff txt-jaif-diff txt-jaif: ${MAKE} pat-daikon-tests-$@ pat-daikon-tests-%: - ${MAKE} -C daikon-tests --jobs=${TEST_JOBS} ${MPARG} $* + ${MAKE} -C daikon-tests --jobs=${DAIKON_TEST_JOBS} ${MPARG} $* list-targets: ${MAKE} -C daikon-tests list-targets diff --git a/tests/Makefile.jobs b/tests/Makefile.jobs index e3736b3ca6..16e741d962 100644 --- a/tests/Makefile.jobs +++ b/tests/Makefile.jobs @@ -2,7 +2,8 @@ # # Settings shared by the Makefiles that drive a whole test suite: # tests/Makefile, tests/kvasir-tests/Makefile, and tests/dyncomp-tests/Makefile. -# Include it before any other include, so that MAKEFILE_LIST ends with this file. +# The including Makefile locates this file via $(lastword $(MAKEFILE_LIST)), +# so its include line must precede any other include in that Makefile. # To produce incremental output, invoke make as: make MPARG=-Otarget ... # To not run in parallel, invoke make as: make MPARG=-j1 ... @@ -13,20 +14,15 @@ else MPARG ?= endif -# DAIKONDIR is the clone of the 'daikon' project. -ifeq ($(origin DAIKONDIR), undefined) - DAIKONDIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))..) +ifndef PLUME_SCRIPTS + PLUME_SCRIPTS := $(or ${DAIKONDIR},$(realpath $(dir $(lastword $(MAKEFILE_LIST)))..))/.utils/plume-scripts endif -PLUME_SCRIPTS ?= ${DAIKONDIR}/.utils/plume-scripts -# TEST_JOBS is the number of tests to run in parallel. -# Under CI, there are two CPUs, but limit to 1 to avoid out-of-memory error. -# The value is exported, so recursive invocations of make do not recompute it. -# To override it, set TEST_JOBS on the command line or in the environment. -ifeq ($(origin TEST_JOBS), undefined) - ifeq ($(wildcard ${PLUME_SCRIPTS}/is-ci.sh),) - $(error ${PLUME_SCRIPTS}/is-ci.sh not found; run "make" in ${DAIKONDIR} to clone plume-scripts, or set TEST_JOBS) - endif - TEST_JOBS := $(if $(shell sh "${PLUME_SCRIPTS}/is-ci.sh"),1,4) +# DAIKON_TEST_JOBS is the number of tests to run in parallel. +# Under CI, limit to 1 to avoid out-of-memory errors. +# To override it, set DAIKON_TEST_JOBS on the command line or in the environment. +# The default is computed only when a recipe uses it, so targets such as +# "clean" and "help" work even if plume-scripts has not been cloned. +ifeq ($(strip ${DAIKON_TEST_JOBS}),) + override DAIKON_TEST_JOBS = $(if $(wildcard ${PLUME_SCRIPTS}/is-ci.sh),$(if $(shell sh "${PLUME_SCRIPTS}/is-ci.sh"),1,4),$(error ${PLUME_SCRIPTS}/is-ci.sh not found; clone plume-scripts there, or set DAIKON_TEST_JOBS)) endif -export TEST_JOBS diff --git a/tests/dyncomp-tests/Makefile b/tests/dyncomp-tests/Makefile index e69a8eb91a..3838027735 100644 --- a/tests/dyncomp-tests/Makefile +++ b/tests/dyncomp-tests/Makefile @@ -64,7 +64,7 @@ update-all: .PHONY: clean-all clean-all: - ${MAKE} --jobs=${TEST_JOBS} ${MPARG} nightly-tests__clean + ${MAKE} --jobs=${DAIKON_TEST_JOBS} ${MPARG} nightly-tests__clean default-projects__%: pgbovine-tests__% diff --git a/tests/kvasir-tests/Makefile b/tests/kvasir-tests/Makefile index 9e86fee177..6774e5bb39 100644 --- a/tests/kvasir-tests/Makefile +++ b/tests/kvasir-tests/Makefile @@ -19,7 +19,7 @@ default: summary-w-daikon .PHONY: regression-tests regression-tests: - ${MAKE} --jobs=${TEST_JOBS} ${MPARG} nightly-tests__diffs-w-daikon-if-working + ${MAKE} --jobs=${DAIKON_TEST_JOBS} ${MPARG} nightly-tests__diffs-w-daikon-if-working ${MAKE} nightly-summary-only-w-daikon @${MAKE} --no-print-directory results @@ -69,7 +69,7 @@ update-all: .PHONY: clean-all clean-all: - ${MAKE} --jobs=${TEST_JOBS} ${MPARG} nightly-tests__clean + ${MAKE} --jobs=${DAIKON_TEST_JOBS} ${MPARG} nightly-tests__clean default-projects__%: pgbovine-tests__% smcc-tests__% tiny-real-tests__% tws-tests__% @