From 44014fa1cdd2b39eaa4e1ef1ee6e2287870ad9fb Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Sat, 10 Oct 2026 12:02:45 -0700 Subject: [PATCH 1/4] Factor JAVA_HOME detection into scripts/java-home.mak Use ":=" so the shell commands run once, not on every expansion. --- Makefile | 2 +- java/Makefile | 12 +----------- scripts/java-home.mak | 16 ++++++++++++++++ tests/Makefile.common | 12 +----------- tests/daikon-tests/junit/Makefile.user | 12 +----------- tests/daikon-tests/junit5/Makefile.user | 12 +----------- 6 files changed, 21 insertions(+), 45 deletions(-) create mode 100644 scripts/java-home.mak diff --git a/Makefile b/Makefile index 3783aa641d..36e6cfe1a3 100644 --- a/Makefile +++ b/Makefile @@ -59,7 +59,7 @@ DIST_VERSION_FILES := ${README_PATHS} doc/daikon.texinfo doc/developer.texinfo \ # Need to include the Dockerfiles as they are referenced from 'Requirements for # compiling Daikon' in the Daikon Developer manual; which is in turn referenced # from the 'Installation' section of the Daikon manual. -SCRIPT_FILES := Makefile \ +SCRIPT_FILES := Makefile java-home.mak \ daikon.bashrc \ dfepl dtrace-perl dtype-perl \ java-cpp \ diff --git a/java/Makefile b/java/Makefile index ce436e5d69..4f152f2186 100644 --- a/java/Makefile +++ b/java/Makefile @@ -25,17 +25,7 @@ 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 -endif +include ${DAIKONDIR}/scripts/java-home.mak # The "JAVANN" variables mean "at least version NN", except JAVA8. JAVA_VERSION_STRING_WITH_EA := $(shell javac -version 2>&1 | head -1 | cut "-d " -f2) diff --git a/scripts/java-home.mak b/scripts/java-home.mak new file mode 100644 index 0000000000..3d614faee8 --- /dev/null +++ b/scripts/java-home.mak @@ -0,0 +1,16 @@ +# Sets JAVA_HOME, if it is not already set. +# Uses ":=" so that the shell commands run only once. + +ifndef JAVA_HOME +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 +endif diff --git a/tests/Makefile.common b/tests/Makefile.common index 38dde8e8cb..661bab293e 100644 --- a/tests/Makefile.common +++ b/tests/Makefile.common @@ -186,17 +186,7 @@ ECLAT_SCRATCH = $(SCRATCH_FOR_DAIKON_BASE)/$(PROJECT)_eclat # CP_PARENTS := cp -pf --parents CP_PARENTS := rsync -aR -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 +include ${DAIKONDIR}/scripts/java-home.mak 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 9c2889b925..487fe63617 100644 --- a/tests/daikon-tests/junit/Makefile.user +++ b/tests/daikon-tests/junit/Makefile.user @@ -1,16 +1,6 @@ ########################################################################### -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 +include ${DAIKONDIR}/scripts/java-home.mak # 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 d10d1f57d7..08ccc10c01 100644 --- a/tests/daikon-tests/junit5/Makefile.user +++ b/tests/daikon-tests/junit5/Makefile.user @@ -1,16 +1,6 @@ ########################################################################### -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 +include ${DAIKONDIR}/scripts/java-home.mak # need junit.jar on classpath to compile all junit references # explicit order is necessary to get versions built with JDK 8 not 5 From 3a24a837ff67a15c714472c822679bf5c09b1423 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Sat, 10 Oct 2026 12:33:35 -0700 Subject: [PATCH 2/4] Address code review of java-home.mak Check that javac is on the PATH even when JAVA_HOME is set, report a failure of /usr/libexec/java_home, warn when JAVA_HOME disagrees with the javac on the PATH, compute JAVA_HOME with Make built-ins, and export it. Include the fragment once in tests/Makefile.common, relative to that file rather than DAIKONDIR, and after the Makefile.user includes. Co-Authored-By: Claude --- Makefile | 2 +- scripts/java-home.mak | 36 ++++++++++++++++--------- tests/Makefile.common | 8 ++++-- tests/daikon-tests/junit/Makefile.user | 5 ++-- tests/daikon-tests/junit5/Makefile.user | 5 ++-- 5 files changed, 35 insertions(+), 21 deletions(-) diff --git a/Makefile b/Makefile index 36e6cfe1a3..0449aa2ec7 100644 --- a/Makefile +++ b/Makefile @@ -454,7 +454,7 @@ staging: @echo "]2;Building Javadoc" mkdir ${STAGING_DIR}/download/api # Javadoc is skipped on Java 8. Hard-coded JAVA_HOME path is a hack. - (export PATH=/usr/lib/jvm/java-11/bin:${PATH}; cd java; ${MAKE} SKIP_JAVADOC=0 'JAVADOC_DEST=${STAGING_DIR}/download/api' javadoc) + (export JAVA_HOME=/usr/lib/jvm/java-11 PATH=/usr/lib/jvm/java-11/bin:${PATH}; cd java; ${MAKE} SKIP_JAVADOC=0 'JAVADOC_DEST=${STAGING_DIR}/download/api' javadoc) # Copy the documentation @echo "]2;Copying documentation" mkdir ${STAGING_DIR}/download/doc diff --git a/scripts/java-home.mak b/scripts/java-home.mak index 3d614faee8..f43d1527b5 100644 --- a/scripts/java-home.mak +++ b/scripts/java-home.mak @@ -1,16 +1,28 @@ -# Sets JAVA_HOME, if it is not already set. -# Uses ":=" so that the shell commands run only once. +# Sets JAVA_HOME, if it is not already set, and exports it so that sub-makes +# do not recompute it. Requires javac to be on the PATH. + +JAVAC_ON_PATH := $(shell command -v javac 2>/dev/null) +ifeq (,$(JAVAC_ON_PATH)) + $(error javac is not on the PATH) +endif -ifndef JAVA_HOME 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::") + # On macOS, /usr/bin/javac is a stub that uses JAVA_HOME, so JAVA_HOME and + # the javac on the PATH always agree. + ifndef 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 + endif else - $(info Failure: Here is the output of: which javac) - $(info $(shell which javac)) - $(error 'which javac' had exit status 1) -endif -endif + # Resolve symbolic links such as /usr/bin/javac -> /etc/alternatives/javac. + JAVAC_ON_PATH_REALPATH := $(realpath $(JAVAC_ON_PATH)) + ifndef JAVA_HOME + JAVA_HOME := $(patsubst %/bin/javac,%,$(JAVAC_ON_PATH_REALPATH)) + else ifneq ($(realpath $(JAVA_HOME)/bin/javac),$(JAVAC_ON_PATH_REALPATH)) + $(warning JAVA_HOME is $(JAVA_HOME), but the javac on the PATH is $(JAVAC_ON_PATH_REALPATH)) + endif endif + +export JAVA_HOME diff --git a/tests/Makefile.common b/tests/Makefile.common index 661bab293e..84c35bee1d 100644 --- a/tests/Makefile.common +++ b/tests/Makefile.common @@ -133,12 +133,15 @@ ifdef ESC_ON endif +# MAKEFILE_COMMON_DIR is the directory containing this file, even if the user set DAIKONDIR. +MAKEFILE_COMMON_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))) + # DAIKONDIR is the clone of the 'daikon' project. # Would like to use simple '?=' but this is recursively expanded while ':=' is simply expanded. # The include of Makefile.user (if it exists) will change the value of MAKEFILE_LIST and thus # '?=' will not evaluate as we desire. ifeq ($(origin DAIKONDIR), undefined) - DAIKONDIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))..) + DAIKONDIR := $(realpath ${MAKEFILE_COMMON_DIR}/..) endif # COMMON_HERE is where the Makefile.common is located. @@ -186,7 +189,8 @@ ECLAT_SCRATCH = $(SCRATCH_FOR_DAIKON_BASE)/$(PROJECT)_eclat # CP_PARENTS := cp -pf --parents CP_PARENTS := rsync -aR -include ${DAIKONDIR}/scripts/java-home.mak +# This follows the Makefile.user includes, so that a JAVA_HOME set there takes precedence. +include ${MAKEFILE_COMMON_DIR}/../scripts/java-home.mak 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 487fe63617..7e277bae7a 100644 --- a/tests/daikon-tests/junit/Makefile.user +++ b/tests/daikon-tests/junit/Makefile.user @@ -1,7 +1,6 @@ ########################################################################### -include ${DAIKONDIR}/scripts/java-home.mak - # need junit.jar on classpath to compile all junit references JUNIT_CLASSPATH := ${DAIKONDIR}/java/lib/* -JAVAC := $(JAVA_HOME)/bin/javac -cp .:$(JUNIT_CLASSPATH) +# "=" because Makefile.common sets JAVA_HOME after including this file. +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 08ccc10c01..a15d1be4ff 100644 --- a/tests/daikon-tests/junit5/Makefile.user +++ b/tests/daikon-tests/junit5/Makefile.user @@ -1,8 +1,7 @@ ########################################################################### -include ${DAIKONDIR}/scripts/java-home.mak - # 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) +# "=" because Makefile.common sets JAVA_HOME after including this file. +JAVAC = $(JAVA_HOME)/bin/javac -cp .:$(JUNIT_CLASSPATH) From 4ccfbbc341cad16036f5ed055ad636e6d1fce996 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Sat, 10 Oct 2026 12:47:02 -0700 Subject: [PATCH 3/4] Make java-home.mak stricter and simplify its clients On macOS, use /usr/libexec/java_home only when the javac on the PATH is the /usr/bin/javac stub; otherwise derive JAVA_HOME from the javac on the PATH. Check that the derived JAVA_HOME contains bin/javac. Make a mismatch between JAVA_HOME and the javac on the PATH an error. Do not export JAVA_HOME. Simplify DAIKONDIR in tests/Makefile.common, and let Makefile.common add JUNIT_CLASSPATH to JAVAC rather than redefining JAVAC in Makefile.user files. --- scripts/java-home.mak | 44 ++++++++++++++++--------- tests/Makefile.common | 10 ++---- tests/daikon-tests/junit/Makefile.user | 2 -- tests/daikon-tests/junit5/Makefile.user | 2 -- 4 files changed, 30 insertions(+), 28 deletions(-) diff --git a/scripts/java-home.mak b/scripts/java-home.mak index f43d1527b5..ef9e0a554f 100644 --- a/scripts/java-home.mak +++ b/scripts/java-home.mak @@ -1,28 +1,40 @@ -# Sets JAVA_HOME, if it is not already set, and exports it so that sub-makes -# do not recompute it. Requires javac to be on the PATH. +# Sets JAVA_HOME, if it is not already set, to the JDK that contains the javac +# on the PATH. If JAVA_HOME is already set, checks that it agrees with the +# javac on the PATH. Requires javac to be on the PATH. JAVAC_ON_PATH := $(shell command -v javac 2>/dev/null) ifeq (,$(JAVAC_ON_PATH)) $(error javac is not on the PATH) endif +# Resolve symbolic links such as /usr/bin/javac -> /etc/alternatives/javac. +JAVAC_ON_PATH_REALPATH := $(realpath $(JAVAC_ON_PATH)) +# On macOS, /usr/bin/javac is a stub that runs the javac of JAVA_HOME if it is +# set, or else of the JDK that /usr/libexec/java_home reports. +JAVAC_ON_PATH_IS_MACOS_STUB := ifeq ($(shell uname), Darwin) - # On macOS, /usr/bin/javac is a stub that uses JAVA_HOME, so JAVA_HOME and - # the javac on the PATH always agree. - ifndef JAVA_HOME - JAVA_HOME := $(shell /usr/libexec/java_home) + ifeq ($(JAVAC_ON_PATH_REALPATH), /usr/bin/javac) + JAVAC_ON_PATH_IS_MACOS_STUB := 1 + endif +endif + +ifndef JAVA_HOME + ifdef JAVAC_ON_PATH_IS_MACOS_STUB + JAVA_HOME := $(shell /usr/libexec/java_home 2>/dev/null) ifeq (,$(JAVA_HOME)) - $(error /usr/libexec/java_home did not find a JDK; set JAVA_HOME) + $(error /usr/libexec/java_home did not find a JDK; set JAVA_HOME or put a JDK's bin directory on the PATH) endif - endif -else - # Resolve symbolic links such as /usr/bin/javac -> /etc/alternatives/javac. - JAVAC_ON_PATH_REALPATH := $(realpath $(JAVAC_ON_PATH)) - ifndef JAVA_HOME + else JAVA_HOME := $(patsubst %/bin/javac,%,$(JAVAC_ON_PATH_REALPATH)) - else ifneq ($(realpath $(JAVA_HOME)/bin/javac),$(JAVAC_ON_PATH_REALPATH)) - $(warning JAVA_HOME is $(JAVA_HOME), but the javac on the PATH is $(JAVAC_ON_PATH_REALPATH)) + endif + ifeq (,$(wildcard $(JAVA_HOME)/bin/javac)) + $(error Cannot determine JAVA_HOME from $(JAVAC_ON_PATH) (which resolves to $(JAVAC_ON_PATH_REALPATH)); set JAVA_HOME) + endif +else ifndef JAVAC_ON_PATH_IS_MACOS_STUB + # A javac that is not within a JDK, such as a jenv shim script, is not checked. + ifneq ($(filter %/bin/javac,$(JAVAC_ON_PATH_REALPATH)),) + ifneq ($(realpath $(JAVA_HOME)/bin/javac),$(JAVAC_ON_PATH_REALPATH)) + $(error JAVA_HOME is $(JAVA_HOME), but the javac on the PATH is $(JAVAC_ON_PATH_REALPATH); make them agree) + endif endif endif - -export JAVA_HOME diff --git a/tests/Makefile.common b/tests/Makefile.common index 84c35bee1d..e8bdab9098 100644 --- a/tests/Makefile.common +++ b/tests/Makefile.common @@ -137,12 +137,7 @@ endif MAKEFILE_COMMON_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))) # DAIKONDIR is the clone of the 'daikon' project. -# Would like to use simple '?=' but this is recursively expanded while ':=' is simply expanded. -# The include of Makefile.user (if it exists) will change the value of MAKEFILE_LIST and thus -# '?=' will not evaluate as we desire. -ifeq ($(origin DAIKONDIR), undefined) - DAIKONDIR := $(realpath ${MAKEFILE_COMMON_DIR}/..) -endif +DAIKONDIR ?= $(realpath ${MAKEFILE_COMMON_DIR}/..) # COMMON_HERE is where the Makefile.common is located. COMMON_HERE?=${DAIKONDIR}/tests @@ -192,9 +187,8 @@ CP_PARENTS := rsync -aR # This follows the Makefile.user includes, so that a JAVA_HOME set there takes precedence. include ${MAKEFILE_COMMON_DIR}/../scripts/java-home.mak JAVA := ${JAVA_HOME}/bin/java -JAVAC ?= ${JAVA_HOME}/bin/javac - JUNIT_CLASSPATH ?= +JAVAC ?= ${JAVA_HOME}/bin/javac$(if ${JUNIT_CLASSPATH}, -cp .:${JUNIT_CLASSPATH}) JAVALIB_CLASSPATH := ${JAVA_HOME}/jre/lib/rt.jar:${JAVA_HOME}/lib/tools.jar diff --git a/tests/daikon-tests/junit/Makefile.user b/tests/daikon-tests/junit/Makefile.user index 7e277bae7a..c0917ab212 100644 --- a/tests/daikon-tests/junit/Makefile.user +++ b/tests/daikon-tests/junit/Makefile.user @@ -2,5 +2,3 @@ # need junit.jar on classpath to compile all junit references JUNIT_CLASSPATH := ${DAIKONDIR}/java/lib/* -# "=" because Makefile.common sets JAVA_HOME after including this file. -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 a15d1be4ff..8a61e160f6 100644 --- a/tests/daikon-tests/junit5/Makefile.user +++ b/tests/daikon-tests/junit5/Makefile.user @@ -3,5 +3,3 @@ # 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/* -# "=" because Makefile.common sets JAVA_HOME after including this file. -JAVAC = $(JAVA_HOME)/bin/javac -cp .:$(JUNIT_CLASSPATH) From f0dd11dd9dad1ca8cdddfb1b83e2b70bbc6397c0 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Sat, 10 Oct 2026 13:24:30 -0700 Subject: [PATCH 4/4] Address code review of PR 896 - daikon.bashrc uses the same PATH-first JAVA_HOME logic as java-home.mak. - java-home.mak recognizes a JDK by its release file, so a javac wrapper is neither used to infer JAVA_HOME nor checked against it. - java-home.mak reports a nonexistent JAVA_HOME and paths with whitespace. - The staging target sets JAVA_HOME only if /usr/lib/jvm/java-11 exists. - JUnit tests use JUNIT_CLASSPATH even if JAVAC is set in the environment. - tests/Makefile.common includes java-home.mak via DAIKONDIR. --- Makefile | 2 +- scripts/daikon.bashrc | 16 ++++++++++++---- scripts/java-home.mak | 37 +++++++++++++++++++++++++++++-------- tests/Makefile.common | 9 +++++++-- 4 files changed, 49 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index 0449aa2ec7..1e7a12d0b4 100644 --- a/Makefile +++ b/Makefile @@ -454,7 +454,7 @@ staging: @echo "]2;Building Javadoc" mkdir ${STAGING_DIR}/download/api # Javadoc is skipped on Java 8. Hard-coded JAVA_HOME path is a hack. - (export JAVA_HOME=/usr/lib/jvm/java-11 PATH=/usr/lib/jvm/java-11/bin:${PATH}; cd java; ${MAKE} SKIP_JAVADOC=0 'JAVADOC_DEST=${STAGING_DIR}/download/api' javadoc) + (if [ -d /usr/lib/jvm/java-11 ]; then export JAVA_HOME=/usr/lib/jvm/java-11 PATH=/usr/lib/jvm/java-11/bin:$${PATH}; fi; cd java; ${MAKE} SKIP_JAVADOC=0 'JAVADOC_DEST=${STAGING_DIR}/download/api' javadoc) # Copy the documentation @echo "]2;Copying documentation" mkdir ${STAGING_DIR}/download/doc diff --git a/scripts/daikon.bashrc b/scripts/daikon.bashrc index 9949bdde44..6ef2d27bed 100644 --- a/scripts/daikon.bashrc +++ b/scripts/daikon.bashrc @@ -8,10 +8,18 @@ ## files to .class files but have not re-made the daikon.jar file. ## You should not need to edit this file. -if [ "$(uname)" = "Darwin" ] ; then - export JAVA_HOME=${JAVA_HOME:-$(/usr/libexec/java_home)} -else - export JAVA_HOME=${JAVA_HOME:-$(dirname $(dirname $(readlink -f $(which javac))))} +# This logic is the same as in java-home.mak: use the JDK that contains the +# javac on the PATH. On macOS, /usr/bin/javac is a stub; then use the JDK that +# /usr/libexec/java_home reports. +if [ -z "$JAVA_HOME" ] ; then + DAIKON_JAVAC_REALPATH=$(type -P javac > /dev/null && readlink -f "$(type -P javac)") + if [ "$(uname)" = "Darwin" ] && [ "$DAIKON_JAVAC_REALPATH" = "/usr/bin/javac" ] ; then + JAVA_HOME=$(/usr/libexec/java_home) + elif [ -n "$DAIKON_JAVAC_REALPATH" ] ; then + JAVA_HOME=$(dirname "$(dirname "$DAIKON_JAVAC_REALPATH")") + fi + unset DAIKON_JAVAC_REALPATH + export JAVA_HOME fi if [ ! -d "$JAVA_HOME" ]; then echo "Cannot infer JAVA_HOME; please set it. Aborting daikon.bashrc ." diff --git a/scripts/java-home.mak b/scripts/java-home.mak index ef9e0a554f..a6aeb1af98 100644 --- a/scripts/java-home.mak +++ b/scripts/java-home.mak @@ -1,11 +1,16 @@ # Sets JAVA_HOME, if it is not already set, to the JDK that contains the javac # on the PATH. If JAVA_HOME is already set, checks that it agrees with the # javac on the PATH. Requires javac to be on the PATH. +# A JDK is recognized by its "release" file. +# Paths that contain whitespace are not supported, because Make splits on it. JAVAC_ON_PATH := $(shell command -v javac 2>/dev/null) ifeq (,$(JAVAC_ON_PATH)) $(error javac is not on the PATH) endif +ifneq (1,$(words $(JAVAC_ON_PATH))) + $(error The javac on the PATH, "$(JAVAC_ON_PATH)", contains whitespace, which is not supported) +endif # Resolve symbolic links such as /usr/bin/javac -> /etc/alternatives/javac. JAVAC_ON_PATH_REALPATH := $(realpath $(JAVAC_ON_PATH)) @@ -18,23 +23,39 @@ ifeq ($(shell uname), Darwin) endif endif +# The JDK that contains the javac on the PATH, or empty if that javac is not +# within a JDK (for example, it is a wrapper script or a jenv shim). +JAVAC_ON_PATH_JDK := +ifndef JAVAC_ON_PATH_IS_MACOS_STUB + ifneq (,$(filter %/bin/javac,$(JAVAC_ON_PATH_REALPATH))) + ifneq (,$(wildcard $(patsubst %/bin/javac,%,$(JAVAC_ON_PATH_REALPATH))/release)) + JAVAC_ON_PATH_JDK := $(patsubst %/bin/javac,%,$(JAVAC_ON_PATH_REALPATH)) + endif + endif +endif + ifndef JAVA_HOME ifdef JAVAC_ON_PATH_IS_MACOS_STUB JAVA_HOME := $(shell /usr/libexec/java_home 2>/dev/null) ifeq (,$(JAVA_HOME)) $(error /usr/libexec/java_home did not find a JDK; set JAVA_HOME or put a JDK's bin directory on the PATH) endif + else ifdef JAVAC_ON_PATH_JDK + JAVA_HOME := $(JAVAC_ON_PATH_JDK) else - JAVA_HOME := $(patsubst %/bin/javac,%,$(JAVAC_ON_PATH_REALPATH)) + $(error Cannot determine JAVA_HOME: $(JAVAC_ON_PATH) (which resolves to $(JAVAC_ON_PATH_REALPATH)) is not within a JDK; set JAVA_HOME) endif - ifeq (,$(wildcard $(JAVA_HOME)/bin/javac)) - $(error Cannot determine JAVA_HOME from $(JAVAC_ON_PATH) (which resolves to $(JAVAC_ON_PATH_REALPATH)); set JAVA_HOME) +else + ifneq (1,$(words $(JAVA_HOME))) + $(error JAVA_HOME, "$(JAVA_HOME)", contains whitespace, which is not supported) endif -else ifndef JAVAC_ON_PATH_IS_MACOS_STUB - # A javac that is not within a JDK, such as a jenv shim script, is not checked. - ifneq ($(filter %/bin/javac,$(JAVAC_ON_PATH_REALPATH)),) - ifneq ($(realpath $(JAVA_HOME)/bin/javac),$(JAVAC_ON_PATH_REALPATH)) - $(error JAVA_HOME is $(JAVA_HOME), but the javac on the PATH is $(JAVAC_ON_PATH_REALPATH); make them agree) + ifeq (,$(wildcard $(JAVA_HOME)/bin/javac)) + $(error JAVA_HOME is $(JAVA_HOME), but $(JAVA_HOME)/bin/javac does not exist) endif + # A javac that is not within a JDK is not checked. + ifdef JAVAC_ON_PATH_JDK + ifneq ($(realpath $(JAVA_HOME)/bin/javac),$(JAVAC_ON_PATH_REALPATH)) + $(error JAVA_HOME is $(JAVA_HOME), but the javac on the PATH is $(JAVAC_ON_PATH_REALPATH); make them agree) + endif endif endif diff --git a/tests/Makefile.common b/tests/Makefile.common index e8bdab9098..ba9216ad45 100644 --- a/tests/Makefile.common +++ b/tests/Makefile.common @@ -185,10 +185,15 @@ ECLAT_SCRATCH = $(SCRATCH_FOR_DAIKON_BASE)/$(PROJECT)_eclat CP_PARENTS := rsync -aR # This follows the Makefile.user includes, so that a JAVA_HOME set there takes precedence. -include ${MAKEFILE_COMMON_DIR}/../scripts/java-home.mak +include ${DAIKONDIR}/scripts/java-home.mak JAVA := ${JAVA_HOME}/bin/java JUNIT_CLASSPATH ?= -JAVAC ?= ${JAVA_HOME}/bin/javac$(if ${JUNIT_CLASSPATH}, -cp .:${JUNIT_CLASSPATH}) +ifneq (,${JUNIT_CLASSPATH}) + # The JUnit tests require JUNIT_CLASSPATH, even if the environment sets JAVAC. + JAVAC := ${JAVA_HOME}/bin/javac -cp .:${JUNIT_CLASSPATH} +else + JAVAC ?= ${JAVA_HOME}/bin/javac +endif JAVALIB_CLASSPATH := ${JAVA_HOME}/jre/lib/rt.jar:${JAVA_HOME}/lib/tools.jar