&& java_version_cache[3] == '\0')
|| (java_version_cache[0] == '9'
&& java_version_cache[1] == '\0')
- || (java_version_cache[0] == '1'
+ || ((java_version_cache[0] >= '1'
+ && java_version_cache[0] <= '9')
&& (java_version_cache[1] >= '0'
- && java_version_cache[1] <= '1')
+ && java_version_cache[1] <= '9')
&& java_version_cache[2] == '\0'))
- /* It's one of the valid target version values. */
+ /* Here we could choose any target_version between source_version and
+ the java_version_cache. (If it is too small, it will be incremented
+ below until it works.) Since we documented in javacomp.h that it is
+ determined from the JVM, we do that. */
;
- else if (java_version_cache[0] == '1'
- && (java_version_cache[1] >= '2'
- && java_version_cache[1] <= '7')
- && java_version_cache[2] == '\0')
- /* Assume that these (not yet released) Java versions will behave
- like the preceding ones. */
- java_version_cache = "11";
else
java_version_cache = "1.6";
}
/* ======================= Source version dependent ======================= */
/* Convert a source version to an index. */
-#define SOURCE_VERSION_BOUND 6 /* exclusive upper bound */
+#define SOURCE_VERSION_BOUND 94 /* exclusive upper bound */
static unsigned int
source_version_index (const char *source_version)
{
}
else if (source_version[0] == '9' && source_version[1] == '\0')
return 3;
- else if (source_version[0] == '1'
- && (source_version[1] >= '0' && source_version[1] <= '1')
+ else if ((source_version[0] >= '1' && source_version[0] <= '9')
+ && (source_version[1] >= '0' && source_version[1] <= '9')
&& source_version[2] == '\0')
- return source_version[1] - '0' + 4;
+ return (source_version[0] - '1') * 10 + source_version[1] - '0' + 4;
error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
return 0;
}
-/* Return a snippet of code that should compile in the given source version. */
-static const char *
-get_goodcode_snippet (const char *source_version)
-{
- if (strcmp (source_version, "1.6") == 0)
- return "class conftest<T> { T foo() { return null; } }\n";
- if (strcmp (source_version, "1.7") == 0)
- return "class conftest { void foo () { switch (\"A\") {} } }\n";
- if (strcmp (source_version, "1.8") == 0)
- return "class conftest { void foo () { Runnable r = () -> {}; } }\n";
- if (strcmp (source_version, "9") == 0)
- return "interface conftest { private void foo () {} }\n";
- if (strcmp (source_version, "10") == 0)
- return "class conftest { public void m() { var i = new Integer(0); } }\n";
- if (strcmp (source_version, "11") == 0)
- return "class conftest { Readable r = (var b) -> 0; }\n";
- error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
- return NULL;
-}
-
-/* Return a snippet of code that should fail to compile in the given source
- version, or NULL (standing for a snippet that would fail to compile with
- any compiler). */
-static const char *
-get_failcode_snippet (const char *source_version)
-{
- if (strcmp (source_version, "1.6") == 0)
- return "class conftestfail { void foo () { switch (\"A\") {} } }\n";
- if (strcmp (source_version, "1.7") == 0)
- return "class conftestfail { void foo () { Runnable r = () -> {}; } }\n";
- if (strcmp (source_version, "1.8") == 0)
- return "interface conftestfail { private void foo () {} }\n";
- if (strcmp (source_version, "9") == 0)
- return "class conftestfail { public void m() { var i = new Integer(0); } }\n";
- if (strcmp (source_version, "10") == 0)
- return "class conftestfail { Readable r = (var b) -> 0; }\n";
- if (strcmp (source_version, "11") == 0)
- return NULL;
- error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
- return NULL;
-}
-
/* ======================= Target version dependent ======================= */
/* Convert a target version to an index. */
-#define TARGET_VERSION_BOUND 6 /* exclusive upper bound */
+#define TARGET_VERSION_BOUND 94 /* exclusive upper bound */
static unsigned int
target_version_index (const char *target_version)
{
return target_version[2] - '6';
else if (target_version[0] == '9' && target_version[1] == '\0')
return 3;
- else if (target_version[0] == '1'
- && (target_version[1] >= '0' && target_version[1] <= '1')
+ else if ((target_version[0] >= '1' && target_version[0] <= '9')
+ && (target_version[1] >= '0' && target_version[1] <= '9')
&& target_version[2] == '\0')
- return target_version[1] - '0' + 4;
- error (EXIT_FAILURE, 0, _("invalid target_version argument to compile_java_class"));
- return 0;
-}
-
-/* Return the class file version number corresponding to a given target
- version. */
-static int
-corresponding_classfile_version (const char *target_version)
-{
- if (strcmp (target_version, "1.6") == 0)
- return 50;
- if (strcmp (target_version, "1.7") == 0)
- return 51;
- if (strcmp (target_version, "1.8") == 0)
- return 52;
- if (strcmp (target_version, "9") == 0)
- return 53;
- if (strcmp (target_version, "10") == 0)
- return 54;
- if (strcmp (target_version, "11") == 0)
- return 55;
+ return (target_version[0] - '1') * 10 + target_version[1] - '0' + 4;
error (EXIT_FAILURE, 0, _("invalid target_version argument to compile_java_class"));
return 0;
}
/* ====================== Usability test subroutines ====================== */
+/* Executes a program.
+ Returns the first line of its output, as a freshly allocated string, or
+ NULL. */
+static char *
+execute_and_read_line (const char *progname,
+ const char *prog_path, const char * const *prog_argv)
+{
+ pid_t child;
+ int fd[1];
+ FILE *fp;
+ char *line;
+ size_t linesize;
+ size_t linelen;
+ int exitstatus;
+
+ /* Open a pipe to the program. */
+ child = create_pipe_in (progname, prog_path, prog_argv, NULL,
+ DEV_NULL, false, true, false, fd);
+
+ if (child == -1)
+ return NULL;
+
+ /* Retrieve its result. */
+ fp = fdopen (fd[0], "r");
+ if (fp == NULL)
+ {
+ error (0, errno, _("fdopen() failed"));
+ return NULL;
+ }
+
+ line = NULL; linesize = 0;
+ linelen = getline (&line, &linesize, fp);
+ if (linelen == (size_t)(-1))
+ {
+ error (0, 0, _("%s subprocess I/O error"), progname);
+ return NULL;
+ }
+ if (linelen > 0 && line[linelen - 1] == '\n')
+ line[linelen - 1] = '\0';
+
+ /* Read until EOF (otherwise the child process may get a SIGPIPE signal). */
+ while (getc (fp) != EOF)
+ ;
+
+ fclose (fp);
+
+ /* Remove zombie process from process list, and retrieve exit status. */
+ exitstatus =
+ wait_subprocess (child, progname, true, false, true, false, NULL);
+ if (exitstatus != 0)
+ {
+ free (line);
+ return NULL;
+ }
+
+ return line;
+}
+
+/* Executes a program, assumed to be a Java compiler with '-version' option.
+ Returns the version number. */
+static unsigned int
+get_compiler_version (const char *progname,
+ const char *prog_path, const char * const *prog_argv)
+{
+ char *line = execute_and_read_line (progname, prog_path, prog_argv);
+ if (line == NULL)
+ return 0;
+
+ /* Search the first digit in line. */
+ char *version_start = line;
+ for (version_start = line; ; version_start++)
+ {
+ if (*version_start == '\0')
+ {
+ /* No digits found. */
+ free (line);
+ return 0;
+ }
+ if (*version_start >= '0' && *version_start <= '9')
+ break;
+ }
+
+ /* Search the end of the version string. */
+ char *version_end = version_start;
+ while ((*version_end >= '0' && *version_end <= '9') || *version_end == '.')
+ version_end++;
+ *version_end = '\0';
+
+ /* Map 1.6.0_85 to 6, 1.8.0_151 to 8. Map 9.0.4 to 9, 10.0.2 to 10, etc. */
+ if (version_start[0] == '1' && version_start[1] == '.')
+ version_start += 2;
+ version_end = strchr (version_start, '.');
+ if (version_end != NULL)
+ *version_end = '\0';
+
+ /* Convert number to 'unsigned int'. */
+ unsigned int result;
+ switch (strlen (version_start))
+ {
+ case 1:
+ result = version_start[0] - '0';
+ break;
+
+ case 2:
+ result = (version_start[0] - '0') * 10 + (version_start[1] - '0');
+ break;
+
+ default:
+ result = 0;
+ }
+
+ free (line);
+ return result;
+}
+
/* Write a given contents to a temporary file.
FILE_NAME is the name of a file inside TMPDIR that is known not to exist
yet.
is_envjavac_usable (const char *javac,
const char *source_version, const char *target_version,
bool *usablep,
- bool *source_option_p, bool *target_option_p)
+ char source_option_out[30], char target_option_out[30])
{
/* The cache depends on the source_version and target_version. */
struct result_t
{
- bool tested;
- bool usable;
- bool source_option;
- bool target_option;
+ /*bool*/ unsigned int tested : 1;
+ /*bool*/ unsigned int usable : 1;
+ unsigned int source_option : 7;
+ unsigned int target_option : 7;
};
static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
struct result_t *resultp;
[target_version_index (target_version)];
if (!resultp->tested)
{
- /* Try $JAVAC. */
- struct temp_dir *tmpdir;
- char *conftest_file_name;
- char *compiled_file_name;
- const char *java_sources[1];
- struct stat statbuf;
-
- tmpdir = create_temp_dir ("java", NULL, false);
- if (tmpdir == NULL)
- return true;
-
- conftest_file_name =
- xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
- if (write_temp_file (tmpdir, conftest_file_name,
- get_goodcode_snippet (source_version)))
- {
- free (conftest_file_name);
- cleanup_temp_dir (tmpdir);
- return true;
- }
-
- compiled_file_name =
- xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
- register_temp_file (tmpdir, compiled_file_name);
-
- java_sources[0] = conftest_file_name;
- if (!compile_using_envjavac (javac,
- java_sources, 1, tmpdir->dir_name,
- false, false, false, true)
- && stat (compiled_file_name, &statbuf) >= 0
- && get_classfile_version (compiled_file_name)
- <= corresponding_classfile_version (target_version))
+ /* Canonicalize source_version and target_version, for easier
+ arithmetic. */
+ int try_source_version = 6 + source_version_index (source_version);
+ int try_target_version = 6 + target_version_index (target_version);
+ /* Sanity check. */
+ if (try_source_version <= try_target_version)
{
- /* $JAVAC compiled conftest.java successfully. */
- /* Try adding -source option if it is useful. */
- char *javac_source =
- xasprintf ("%s -source %s", javac, source_version);
- assume (javac_source != NULL);
+ /* Try $JAVAC. */
+ struct temp_dir *tmpdir;
+ char *conftest_file_name;
+ char *compiled_file_name;
+ const char *java_sources[1];
+ struct stat statbuf;
+
+ tmpdir = create_temp_dir ("java", NULL, false);
+ if (tmpdir == NULL)
+ return true;
+
+ conftest_file_name =
+ xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
+ if (write_temp_file (tmpdir, conftest_file_name, "class conftest {}"))
+ {
+ free (conftest_file_name);
+ cleanup_temp_dir (tmpdir);
+ return true;
+ }
- unlink (compiled_file_name);
+ compiled_file_name =
+ xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
+ register_temp_file (tmpdir, compiled_file_name);
java_sources[0] = conftest_file_name;
- if (!compile_using_envjavac (javac_source,
+ if (!compile_using_envjavac (javac,
java_sources, 1, tmpdir->dir_name,
false, false, false, true)
- && stat (compiled_file_name, &statbuf) >= 0
- && get_classfile_version (compiled_file_name)
- <= corresponding_classfile_version (target_version))
+ && stat (compiled_file_name, &statbuf) >= 0)
{
- const char *failcode = get_failcode_snippet (source_version);
-
- if (failcode != NULL)
+ /* $JAVAC compiled conftest.java successfully. */
+ int compiler_cfversion =
+ get_classfile_version (compiled_file_name);
+ int compiler_target_version = compiler_cfversion - 44;
+
+ /* It is hard to determine the compiler_source_version. This
+ would require a list of code snippets that can be compiled only
+ with a specific '-source' option and up, and this list would
+ need to grow every 6 months.
+ Also, $JAVAC may already include a '-source' option.
+ Therefore, pass a '-source' option always. */
+ char source_option[30];
+ sprintf (source_option, " -source %s%d",
+ try_source_version <= 8 ? "1." : "",
+ try_source_version);
+
+ /* And pass a '-target' option as well, if needed.
+ (All supported javac versions support both, see the table in
+ javacomp.m4.) */
+ char target_option[30];
+ if (try_target_version == compiler_target_version)
+ target_option[0] = '\0';
+ else
+ sprintf (target_option, " -target %s%d",
+ try_target_version <= 8 ? "1." : "",
+ try_target_version);
+
+ char *javac_source_target =
+ xasprintf ("%s%s%s", javac, source_option, target_option);
+ assume (javac_source_target != NULL);
+
+ unlink (compiled_file_name);
+
+ java_sources[0] = conftest_file_name;
+ if (!compile_using_envjavac (javac_source_target,
+ java_sources, 1, tmpdir->dir_name,
+ false, false, false, true)
+ && stat (compiled_file_name, &statbuf) >= 0)
{
- free (compiled_file_name);
- free (conftest_file_name);
-
- conftest_file_name =
- xconcatenated_filename (tmpdir->dir_name,
- "conftestfail.java",
- NULL);
- if (write_temp_file (tmpdir, conftest_file_name, failcode))
+ /* The compiler directly supports the desired source_version
+ and target_version. Perfect. */
+ free (javac_source_target);
+
+ resultp->source_option = try_source_version;
+ resultp->target_option =
+ (try_target_version == compiler_target_version ? 0 :
+ try_target_version);
+ resultp->usable = true;
+ }
+ else
+ {
+ /* If the desired source_version or target_version were too
+ large for the compiler, there's nothing else we can do. */
+ unsigned int compiler_version;
+
+ free (javac_source_target);
+
+ {
+ size_t command_length;
+ char *command;
+ const char *argv[4];
+
+ command_length = strlen (javac) + 9 + 1;
+
+ command = (char *) xmalloca (command_length);
{
- free (conftest_file_name);
- free (javac_source);
- cleanup_temp_dir (tmpdir);
- return true;
+ char *p = command;
+ p = stpcpy (p, javac);
+ p = stpcpy (p, " -version");
+ *p++ = '\0';
+ /* Ensure command_length was correctly calculated. */
+ if (p - command > command_length)
+ abort ();
}
- compiled_file_name =
- xconcatenated_filename (tmpdir->dir_name,
- "conftestfail.class",
- NULL);
- register_temp_file (tmpdir, compiled_file_name);
-
- java_sources[0] = conftest_file_name;
- if (!compile_using_envjavac (javac,
- java_sources, 1,
- tmpdir->dir_name,
- false, false, false, true)
- && stat (compiled_file_name, &statbuf) >= 0)
+ argv[0] = BOURNE_SHELL;
+ argv[1] = "-c";
+ argv[2] = command;
+ argv[3] = NULL;
+ compiler_version =
+ get_compiler_version (javac, BOURNE_SHELL, argv);
+
+ freea (command);
+ }
+
+ if (try_source_version <= compiler_version
+ && try_target_version <= compiler_version)
{
- unlink (compiled_file_name);
-
- java_sources[0] = conftest_file_name;
- if (compile_using_envjavac (javac_source,
- java_sources, 1,
- tmpdir->dir_name,
- false, false, false, true))
- /* $JAVAC compiled conftestfail.java successfully, and
- "$JAVAC -source $source_version" rejects it.
- So the -source option is useful. */
- resultp->source_option = true;
+ /* Increase try_source_version and compiler_version until
+ the compiler accepts these values. This is necessary
+ to make e.g. try_source_version = 6 work with Java 12
+ or newer, or try_source_version = 7 work with Java 20
+ or newer. */
+ for (;;)
+ {
+ /* Invariant:
+ try_source_version <= try_target_version. */
+ if (try_source_version == try_target_version)
+ try_target_version++;
+ try_source_version++;
+ if (try_source_version > compiler_version)
+ break;
+
+ sprintf (source_option, " -source %s%d",
+ try_source_version <= 8 ? "1." : "",
+ try_source_version);
+
+ if (try_target_version == compiler_target_version)
+ target_option[0] = '\0';
+ else
+ sprintf (target_option, " -target %s%d",
+ try_target_version <= 8 ? "1." : "",
+ try_target_version);
+
+ javac_source_target =
+ xasprintf ("%s%s%s", javac,
+ source_option, target_option);
+ assume (javac_source_target != NULL);
+
+ unlink (compiled_file_name);
+
+ java_sources[0] = conftest_file_name;
+ if (!compile_using_envjavac (javac_source_target,
+ java_sources, 1,
+ tmpdir->dir_name,
+ false, false,
+ false, true)
+ && stat (compiled_file_name, &statbuf) >= 0)
+ {
+ /* The compiler supports the try_source_version
+ and try_target_version. It's better than
+ nothing. */
+ free (javac_source_target);
+
+ resultp->source_option = try_source_version;
+ resultp->target_option =
+ (try_target_version == compiler_target_version ? 0 :
+ try_target_version);
+ resultp->usable = true;
+ break;
+ }
+
+ free (javac_source_target);
+ }
}
}
}
- free (javac_source);
-
- resultp->usable = true;
- }
- else
- {
- /* Try with -target and -source options. (All supported javac
- versions support both, see the table in javacomp.m4.) */
- char *javac_target_source =
- xasprintf ("%s -target %s -source %s", javac,
- target_version, source_version);
- assume (javac_target_source != NULL);
-
- unlink (compiled_file_name);
-
- java_sources[0] = conftest_file_name;
- if (!compile_using_envjavac (javac_target_source,
- java_sources, 1, tmpdir->dir_name,
- false, false, false, true)
- && stat (compiled_file_name, &statbuf) >= 0
- && get_classfile_version (compiled_file_name)
- <= corresponding_classfile_version (target_version))
- {
- /* "$JAVAC -target $target_version -source $source_version"
- compiled conftest.java successfully. */
- resultp->source_option = true;
- resultp->target_option = true;
- resultp->usable = true;
- }
+ cleanup_temp_dir (tmpdir);
- free (javac_target_source);
+ free (compiled_file_name);
+ free (conftest_file_name);
}
- free (compiled_file_name);
- free (conftest_file_name);
-
resultp->tested = true;
}
*usablep = resultp->usable;
- *source_option_p = resultp->source_option;
- *target_option_p = resultp->target_option;
+ sprintf (source_option_out, " -source %s%d",
+ resultp->source_option <= 8 ? "1." : "",
+ resultp->source_option);
+ if (resultp->target_option == 0)
+ target_option_out[0] = '\0';
+ else
+ sprintf (target_option_out, " -target %s%d",
+ resultp->target_option <= 8 ? "1." : "",
+ resultp->target_option);
return false;
}
Return a failure indicator (true upon error). */
static bool
is_javac_usable (const char *source_version, const char *target_version,
- bool *usablep, bool *source_option_p, bool *target_option_p)
+ bool *usablep,
+ char source_option_out[20], char target_option_out[20])
{
/* The cache depends on the source_version and target_version. */
struct result_t
{
- bool tested;
- bool usable;
- bool source_option;
- bool target_option;
+ /*bool*/ unsigned int tested : 1;
+ /*bool*/ unsigned int usable : 1;
+ unsigned int source_option : 7;
+ unsigned int target_option : 7;
};
static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
struct result_t *resultp;
[target_version_index (target_version)];
if (!resultp->tested)
{
- /* Try javac. */
- struct temp_dir *tmpdir;
- char *conftest_file_name;
- char *compiled_file_name;
- const char *java_sources[1];
- struct stat statbuf;
-
- tmpdir = create_temp_dir ("java", NULL, false);
- if (tmpdir == NULL)
- return true;
-
- conftest_file_name =
- xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
- if (write_temp_file (tmpdir, conftest_file_name,
- get_goodcode_snippet (source_version)))
+ /* Canonicalize source_version and target_version, for easier
+ arithmetic. */
+ int try_source_version = 6 + source_version_index (source_version);
+ int try_target_version = 6 + target_version_index (target_version);
+ /* Sanity check. */
+ if (try_source_version <= try_target_version)
{
- free (conftest_file_name);
- cleanup_temp_dir (tmpdir);
- return true;
- }
+ /* Try javac. */
+ struct temp_dir *tmpdir;
+ char *conftest_file_name;
+ char *compiled_file_name;
+ const char *java_sources[1];
+ struct stat statbuf;
+
+ tmpdir = create_temp_dir ("java", NULL, false);
+ if (tmpdir == NULL)
+ return true;
+
+ conftest_file_name =
+ xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
+ if (write_temp_file (tmpdir, conftest_file_name, "class conftest {}"))
+ {
+ free (conftest_file_name);
+ cleanup_temp_dir (tmpdir);
+ return true;
+ }
- compiled_file_name =
- xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
- register_temp_file (tmpdir, compiled_file_name);
-
- java_sources[0] = conftest_file_name;
- if (!compile_using_javac (java_sources, 1,
- false, source_version,
- false, target_version,
- tmpdir->dir_name, false, false, false, true)
- && stat (compiled_file_name, &statbuf) >= 0
- && get_classfile_version (compiled_file_name)
- <= corresponding_classfile_version (target_version))
- {
- /* javac compiled conftest.java successfully. */
- /* Try adding -source option if it is useful. */
- unlink (compiled_file_name);
+ compiled_file_name =
+ xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
+ register_temp_file (tmpdir, compiled_file_name);
java_sources[0] = conftest_file_name;
if (!compile_using_javac (java_sources, 1,
- true, source_version,
+ false, source_version,
false, target_version,
- tmpdir->dir_name, false, false, false, true)
- && stat (compiled_file_name, &statbuf) >= 0
- && get_classfile_version (compiled_file_name)
- <= corresponding_classfile_version (target_version))
+ tmpdir->dir_name,
+ false, false, false, true)
+ && stat (compiled_file_name, &statbuf) >= 0)
{
- const char *failcode = get_failcode_snippet (source_version);
-
- if (failcode != NULL)
+ /* javac compiled conftest.java successfully. */
+ int compiler_cfversion =
+ get_classfile_version (compiled_file_name);
+ int compiler_target_version = compiler_cfversion - 44;
+
+ /* It is hard to determine the compiler_source_version. This
+ would require a list of code snippets that can be compiled only
+ with a specific '-source' option and up, and this list would
+ need to grow every 6 months.
+ Also, javac may point to a shell script that already includes a
+ '-source' option.
+ Therefore, pass a '-source' option always. */
+ char source_option[20];
+ sprintf (source_option, "%s%d",
+ try_source_version <= 8 ? "1." : "",
+ try_source_version);
+
+ /* And pass a '-target' option as well, if needed.
+ (All supported javac versions support both, see the table in
+ javacomp.m4.) */
+ char target_option[20];
+ sprintf (target_option, "%s%d",
+ try_target_version <= 8 ? "1." : "",
+ try_target_version);
+
+ unlink (compiled_file_name);
+
+ java_sources[0] = conftest_file_name;
+ if (!compile_using_javac (java_sources, 1,
+ true,
+ source_option,
+ try_target_version != compiler_target_version,
+ target_option,
+ tmpdir->dir_name,
+ false, false, false, true)
+ && stat (compiled_file_name, &statbuf) >= 0)
{
- free (compiled_file_name);
- free (conftest_file_name);
-
- conftest_file_name =
- xconcatenated_filename (tmpdir->dir_name,
- "conftestfail.java",
- NULL);
- if (write_temp_file (tmpdir, conftest_file_name, failcode))
- {
- free (conftest_file_name);
- cleanup_temp_dir (tmpdir);
- return true;
- }
-
- compiled_file_name =
- xconcatenated_filename (tmpdir->dir_name,
- "conftestfail.class",
- NULL);
- register_temp_file (tmpdir, compiled_file_name);
-
- java_sources[0] = conftest_file_name;
- if (!compile_using_javac (java_sources, 1,
- false, source_version,
- false, target_version,
- tmpdir->dir_name,
- false, false, false, true)
- && stat (compiled_file_name, &statbuf) >= 0)
+ /* The compiler directly supports the desired source_version
+ and target_version. Perfect. */
+ resultp->source_option = try_source_version;
+ resultp->target_option =
+ (try_target_version == compiler_target_version ? 0 :
+ try_target_version);
+ resultp->usable = true;
+ }
+ else
+ {
+ /* If the desired source_version or target_version were too
+ large for the compiler, there's nothing else we can do. */
+ unsigned int compiler_version;
+
+ {
+ const char *argv[3];
+
+ argv[0] = "javac";
+ argv[1] = "-version";
+ argv[2] = NULL;
+ compiler_version =
+ get_compiler_version ("javac", argv[0], argv);
+ }
+
+ if (try_source_version <= compiler_version
+ && try_target_version <= compiler_version)
{
- unlink (compiled_file_name);
-
- java_sources[0] = conftest_file_name;
- if (compile_using_javac (java_sources, 1,
- true, source_version,
- false, target_version,
- tmpdir->dir_name,
- false, false, false, true))
- /* javac compiled conftestfail.java successfully, and
- "javac -source $source_version" rejects it.
- So the -source option is useful. */
- resultp->source_option = true;
+ /* Increase try_source_version and compiler_version until
+ the compiler accepts these values. This is necessary
+ to make e.g. try_source_version = 6 work with Java 12
+ or newer, or try_source_version = 7 work with Java 20
+ or newer. */
+ for (;;)
+ {
+ /* Invariant:
+ try_source_version <= try_target_version. */
+ if (try_source_version == try_target_version)
+ try_target_version++;
+ try_source_version++;
+ if (try_source_version > compiler_version)
+ break;
+
+ sprintf (source_option, "%s%d",
+ try_source_version <= 8 ? "1." : "",
+ try_source_version);
+
+ sprintf (target_option, "%s%d",
+ try_target_version <= 8 ? "1." : "",
+ try_target_version);
+
+ unlink (compiled_file_name);
+
+ java_sources[0] = conftest_file_name;
+ if (!compile_using_javac (java_sources, 1,
+ true,
+ source_option,
+ try_target_version != compiler_target_version,
+ target_option,
+ tmpdir->dir_name,
+ false, false, false, true)
+ && stat (compiled_file_name, &statbuf) >= 0)
+ {
+ /* The compiler supports the try_source_version
+ and try_target_version. It's better than
+ nothing. */
+ resultp->source_option = try_source_version;
+ resultp->target_option =
+ (try_target_version == compiler_target_version ? 0 :
+ try_target_version);
+ resultp->usable = true;
+ break;
+ }
+ }
}
}
}
- resultp->usable = true;
- }
- else
- {
- /* Try with -target and -source options. (All supported javac
- versions support both, see the table in javacomp.m4.) */
- unlink (compiled_file_name);
+ cleanup_temp_dir (tmpdir);
- java_sources[0] = conftest_file_name;
- if (!compile_using_javac (java_sources, 1,
- true, source_version,
- true, target_version,
- tmpdir->dir_name,
- false, false, false, true)
- && stat (compiled_file_name, &statbuf) >= 0
- && get_classfile_version (compiled_file_name)
- <= corresponding_classfile_version (target_version))
- {
- /* "javac -target $target_version -source $source_version"
- compiled conftest.java successfully. */
- resultp->source_option = true;
- resultp->target_option = true;
- resultp->usable = true;
- }
+ free (compiled_file_name);
+ free (conftest_file_name);
}
- free (compiled_file_name);
- free (conftest_file_name);
-
resultp->tested = true;
}
*usablep = resultp->usable;
- *source_option_p = resultp->source_option;
- *target_option_p = resultp->target_option;
+ sprintf (source_option_out, "%s%d",
+ resultp->source_option <= 8 ? "1." : "",
+ resultp->source_option);
+ if (resultp->target_option == 0)
+ target_option_out[0] = '\0';
+ else
+ sprintf (target_option_out, "%s%d",
+ resultp->target_option <= 8 ? "1." : "",
+ resultp->target_option);
return false;
}
if (javac != NULL && javac[0] != '\0')
{
bool usable = false;
- bool source_option = false;
- bool target_option = false;
+ char source_option[30];
+ char target_option[30];
if (target_version == NULL)
target_version = default_target_version ();
if (is_envjavac_usable (javac,
source_version, target_version,
&usable,
- &source_option, &target_option))
+ source_option, target_option))
{
err = true;
goto done1;
set_classpath (classpaths, classpaths_count, false, verbose);
javac_with_options =
- xasprintf ("%s%s%s%s%s",
- javac,
- source_option ? " -source " : "",
- source_option ? source_version : "",
- target_option ? " -target " : "",
- target_option ? target_version : "");
+ xasprintf ("%s%s%s", javac, source_option, target_option);
assume (javac_with_options != NULL);
err = compile_using_envjavac (javac_with_options,
if (is_javac_present ())
{
bool usable = false;
- bool source_option = false;
- bool target_option = false;
+ char source_option[20];
+ char target_option[20];
if (target_version == NULL)
target_version = default_target_version ();
if (is_javac_usable (source_version, target_version,
- &usable, &source_option, &target_option))
+ &usable,
+ source_option, target_option))
{
err = true;
goto done1;
verbose);
err = compile_using_javac (java_sources, java_sources_count,
- source_option, source_version,
- target_option, target_version,
+ true, source_option,
+ target_option[0] != '\0', target_option,
directory, optimize, debug, verbose,
false);
-# javacomp.m4 serial 24
+# javacomp.m4 serial 25
dnl Copyright (C) 2001-2003, 2006-2007, 2009-2023 Free Software Foundation,
dnl Inc.
dnl This file is free software; the Free Software Foundation
# 9 private interface methods
# 10 type inference for local variables
# 11 'var' in parameters of lambda expressions
+# ...
+# (For reference, see <https://en.wikipedia.org/wiki/Java_version_history>.)
# If source-version 1.3 or 1.4 or 1.5 is requested, it gets mapped to 1.6, for
# backward compatibility. (Currently the minimum Java and javac version we need
# to support is Java 1.6, since that's the default Java version on Solaris 10.)
# 9 53.0
# 10 54.0
# 11 55.0
+# ... ...
# The classfile version of a .class file can be determined through the "file"
# command. More portably, the classfile major version can be determined through
# "od -A n -t d1 -j 7 -N 1 classfile".
# 9 JDK/JRE 9
# 10 JDK/JRE 10
# 11 JDK/JRE 11
+# ... ...
#
# Specifying target-version is useful when building a library (.jar) that is
# useful outside the given package. Omitting target-version is useful when
| tr -d '\012\015' \
| tr '!"#$%&()*+,./0123456789:;<=>?@ABCDEFGHJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyzI' '\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\040\041\046\050\051\052\056\057\073\074\076\103\106\114\116\117\120\123\124\126\133\141\142\143\144\145\146\147\151\152\154\155\156\157\160\162\163\164\165\166\171\261\262\266\267\270\272\276\312\376\055' \
> conftestver.class
- target_version=`{
+ java_exec_version=`{
unset JAVA_HOME
echo "$as_me:__oline__: CLASSPATH=.${CLASSPATH:+$CLASSPATH_SEPARATOR$CLASSPATH} $CONF_JAVA conftestver" >&AS_MESSAGE_LOG_FD
CLASSPATH=.${CLASSPATH:+$CLASSPATH_SEPARATOR$CLASSPATH} $CONF_JAVA conftestver 2>&AS_MESSAGE_LOG_FD
}`
- case "$target_version" in
+ case "$java_exec_version" in
null)
dnl JDK 1.1.X returns null.
- target_version=1.1 ;;
+ java_exec_version=1.1 ;;
esac
- case "$target_version" in
+ case "$java_exec_version" in
1.1 | 1.2 | 1.3 | 1.4 | 1.5)
AC_MSG_WARN([$CONF_JAVA is too old, cannot compile Java code for this old version any more])
target_version=1.6 ;;
- 1.6 | 1.7 | 1.8 | 9 | 10 | 11) ;;
- 12 | 13 | 14 | 15 | 16 | 17)
- dnl Assume that these (not yet released) Java versions will behave
- dnl like the preceding ones.
- target_version=11 ;;
+changequote(,)dnl
+ 1.6 | 1.7 | 1.8 | 9 | [1-9][0-9])
+changequote([,])dnl
+ dnl Here we could choose any target_version between $source_version
+ dnl and the $java_exec_version. (If it is too small, it will be
+ dnl incremented below until it works.) Since we documented above that
+ dnl it is determined from the JVM, we do that:
+ target_version="$java_exec_version" ;;
*) AC_MSG_WARN([unknown target-version $target_version, please update gt_@&t@JAVACOMP macro])
target_version=1.6 ;;
esac
esac
])
case "$source_version" in
- 1.6) goodcode='class conftest<T> { T foo() { return null; } }'
- failcode='class conftestfail { void foo () { switch ("A") {} } }' ;;
- 1.7) goodcode='class conftest { void foo () { switch ("A") {} } }'
- failcode='class conftestfail { void foo () { Runnable r = () -> {}; } }' ;;
- 1.8) goodcode='class conftest { void foo () { Runnable r = () -> {}; } }'
- failcode='interface conftestfail { private void foo () {} }' ;;
- 9) goodcode='interface conftest { private void foo () {} }'
- failcode='class conftestfail { public void m() { var i = new Integer(0); } }' ;;
- 10) goodcode='class conftest { public void m() { var i = new Integer(0); } }'
- failcode='class conftestfail { Readable r = (var b) -> 0; }' ;;
- 11) goodcode='class conftest { Readable r = (var b) -> 0; }'
- failcode='class conftestfail syntax error' ;;
+changequote(,)dnl
+ 1.6 | 1.7 | 1.8 | 9 | [1-9][0-9]) ;;
+changequote([,])dnl
*) AC_MSG_ERROR([invalid source-version argument to gt_@&t@JAVACOMP: $source_version]) ;;
esac
case "$target_version" in
- 1.6) cfversion=50 ;;
- 1.7) cfversion=51 ;;
- 1.8) cfversion=52 ;;
- 9) cfversion=53 ;;
- 10) cfversion=54 ;;
- 11) cfversion=55 ;;
+changequote(,)dnl
+ 1.6 | 1.7 | 1.8 | 9 | [1-9][0-9]) ;;
+changequote([,])dnl
*) AC_MSG_ERROR([invalid target-version argument to gt_@&t@JAVACOMP: $target_version]) ;;
esac
# Function to output the classfile version of a file (8th byte) in decimal.
dnl -target 1.8 only possible with -source 1.6/1.7/1.8
dnl -target 9 only possible with -source 1.6/1.7/1.8/9
dnl
- dnl javac 11: -target 1.6 1.7 1.8 9 10 11 default: 11
- dnl -source 1.6 1.7 1.8 9 10 11 default: 11
- dnl -target 1.6 only possible with -source 1.6
- dnl -target 1.7 only possible with -source 1.6/1.7
- dnl -target 1.8 only possible with -source 1.6/1.7/1.8
- dnl -target 9 only possible with -source 1.6/1.7/1.8/9
- dnl -target 10 only possible with -source 1.6/1.7/1.8/9/10
+ dnl and so on.
+ dnl This can be summarized in this table:
dnl
+ dnl javac classfile valid -source and obsolete -source
+ dnl version default version -target values and -target values
+ dnl ------- --------------- ----------------- ------------------
+ dnl 1.6 50.0 1.3 .. 1.6
+ dnl 1.7 51.0 1.3 .. 1.7
+ dnl 1.8 52.0 1.3 .. 1.8 1.3 .. 1.5
+ dnl 9 53.0 1.6 .. 9 1.6
+ dnl 10 54.0 1.6 .. 10 1.6
+ dnl 11 55.0 1.6 .. 11 1.6
+ dnl 12 56.0 1.7 .. 12 1.7
+ dnl 13 57.0 1.7 .. 13 1.7
+ dnl 14 58.0 1.7 .. 14 1.7
+ dnl 15 59.0 1.7 .. 15 1.7
+ dnl 16 60.0 1.7 .. 16 1.7
+ dnl 17 61.0 1.7 .. 17 1.7
+ dnl 18 62.0 1.7 .. 18 1.7
+ dnl 19 63.0 1.7 .. 19 1.7
+ dnl 20 64.0 1.8 .. 20 1.8
+ dnl
+ dnl The -source option value must be <= the -target option value.
+ dnl The minimal -source and -target option value produces an "is obsolete"
+ dnl warning.
+ dnl
+ dnl Canonicalize source_version and target_version, for easier arithmetic.
+ case "$source_version" in
+ 1.*) source_version=`echo "$source_version" | sed -e 's/^1\.//'` ;;
+ esac
+ case "$target_version" in
+ 1.*) target_version=`echo "$target_version" | sed -e 's/^1\.//'` ;;
+ esac
CONF_JAVAC=
HAVE_JAVAC_ENVVAR=
HAVE_JAVAC=
HAVE_JAVACOMP=
- echo "$goodcode" > conftest.java
- echo "$failcode" > conftestfail.java
- dnl If the user has set the JAVAC environment variable, use that, if it
- dnl satisfies the constraints (possibly after adding -target and -source
- dnl options).
- if test -n "$JAVAC"; then
- dnl Try $JAVAC.
- rm -f conftest.class
- if { echo "$as_me:__oline__: $JAVAC -d . conftest.java" >&AS_MESSAGE_LOG_FD
- $JAVAC -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
- } \
- && test -f conftest.class \
- && expr `func_classfile_version conftest.class` '<=' $cfversion >/dev/null 2>&AS_MESSAGE_LOG_FD; then
- dnl Try adding -source option if it is useful.
- rm -f conftest.class
- rm -f conftestfail.class
- if { echo "$as_me:__oline__: $JAVAC -source $source_version -d . conftest.java" >&AS_MESSAGE_LOG_FD
- $JAVAC -source "$source_version" -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
- } \
- && test -f conftest.class \
- && expr `func_classfile_version conftest.class` '<=' $cfversion >/dev/null 2>&AS_MESSAGE_LOG_FD \
- && { echo "$as_me:__oline__: $JAVAC -d . conftestfail.java" >&AS_MESSAGE_LOG_FD
- $JAVAC -d . conftestfail.java >&AS_MESSAGE_LOG_FD 2>&1
- } \
- && test -f conftestfail.class \
- && ! { echo "$as_me:__oline__: $JAVAC -source $source_version -d . conftestfail.java" >&AS_MESSAGE_LOG_FD
- $JAVAC -source "$source_version" -d . conftestfail.java >&AS_MESSAGE_LOG_FD 2>&1
- }; then
- CONF_JAVAC="$JAVAC -source $source_version"
- HAVE_JAVAC_ENVVAR=1
- HAVE_JAVACOMP=1
- else
- CONF_JAVAC="$JAVAC"
- HAVE_JAVAC_ENVVAR=1
- HAVE_JAVACOMP=1
- fi
- else
- dnl Try with -target and -source options. (All supported javac
- dnl versions support both, see the table above.)
+ dnl Sanity check.
+ if expr $source_version '<=' $target_version >/dev/null; then
+ echo 'class conftest {}' > conftest.java
+ dnl If the user has set the JAVAC environment variable, use that, if it
+ dnl satisfies the constraints (possibly after adding -target and -source
+ dnl options).
+ if test -n "$JAVAC"; then
+ dnl Test whether $JAVAC is usable.
rm -f conftest.class
- if { echo "$as_me:__oline__: $JAVAC -target $target_version -source $source_version -d . conftest.java" >&AS_MESSAGE_LOG_FD
- $JAVAC -target "$target_version" -source "$source_version" -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
+ if { echo "$as_me:__oline__: $JAVAC -d . conftest.java" >&AS_MESSAGE_LOG_FD
+ $JAVAC -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
} \
- && test -f conftest.class \
- && expr `func_classfile_version conftest.class` '<=' $cfversion >/dev/null 2>&AS_MESSAGE_LOG_FD; then
- CONF_JAVAC="$JAVAC -target $target_version -source $source_version"
- HAVE_JAVAC_ENVVAR=1
- HAVE_JAVACOMP=1
+ && test -f conftest.class; then
+ compiler_cfversion=`func_classfile_version conftest.class`
+ compiler_target_version=`expr $compiler_cfversion - 44`
+ dnl It is hard to determine the compiler_source_version. This would
+ dnl require a list of code snippets that can be compiled only with a
+ dnl specific '-source' option and up, and this list would need to grow
+ dnl every 6 months.
+ dnl Also, $JAVAC may already include a '-source' option.
+ dnl Therefore, pass a '-source' option always.
+ source_option=' -source '`case "$source_version" in 6|7|8) echo 1. ;; esac`"$source_version"
+ dnl And pass a '-target' option as well, if needed.
+ dnl (All supported javac versions support both, see the table above.)
+ if expr $target_version = $compiler_target_version >/dev/null; then
+ target_option=
+ else
+ target_option=' -target '`case "$target_version" in 6|7|8) echo 1. ;; esac`"$target_version"
+ fi
+ if { echo "$as_me:__oline__: $JAVAC$source_option$target_option -d . conftest.java" >&AS_MESSAGE_LOG_FD
+ $JAVAC$source_option$target_option -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
+ } \
+ && test -f conftest.class; then
+ dnl The compiler directly supports the desired source_version and
+ dnl target_version. Perfect.
+ CONF_JAVAC="$JAVAC$source_option$target_option"
+ HAVE_JAVAC_ENVVAR=1
+ HAVE_JAVACOMP=1
+ else
+ dnl If the desired source_version or target_version were too large
+ dnl for the compiler, there's nothing else we can do.
+ compiler_version=`echo "$as_me:__oline__: $JAVAC -version | sed -e 1q" >&AS_MESSAGE_LOG_FD
+ $JAVAC -version | sed -e 1q`
+changequote(,)dnl
+ compiler_version=`echo "$compiler_version" | sed -e 's/^[^0-9]*\([0-9][0-9.]*\).*/\1/'`
+changequote([,])dnl
+ case "$compiler_version" in
+ 1.*) dnl Map 1.6.0_85 to 6, 1.8.0_151 to 8.
+ compiler_version=`echo "$compiler_version" | sed -e 's/^1\.//' -e 's/\..*//'`
+ ;;
+ *) dnl Map 9.0.4 to 9, 10.0.2 to 10, etc.
+ compiler_version=`echo "$compiler_version" | sed -e 's/\..*//'`
+ ;;
+ esac
+ if expr $source_version '<=' "$compiler_version" >/dev/null \
+ && expr $target_version '<=' "$compiler_version" >/dev/null; then
+ dnl Increase $source_version and $compiler_version until the
+ dnl compiler accepts these values. This is necessary to make
+ dnl e.g. $source_version = 6 work with Java 12 or newer, or
+ dnl $source_version = 7 work with Java 20 or newer.
+ try_source_version="$source_version"
+ try_target_version="$target_version"
+ while true; do
+ dnl Invariant: $try_source_version <= $try_target_version.
+ if expr $try_source_version = $try_target_version >/dev/null; then
+ try_target_version=`expr $try_target_version + 1`
+ fi
+ try_source_version=`expr $try_source_version + 1`
+ expr $try_source_version '<=' $compiler_version >/dev/null || break
+ source_option=' -source '`case "$try_source_version" in 6|7|8) echo 1. ;; esac`"$try_source_version"
+ if expr $try_target_version = $compiler_target_version >/dev/null; then
+ target_option=
+ else
+ target_option=' -target '`case "$try_target_version" in 6|7|8) echo 1. ;; esac`"$try_target_version"
+ fi
+ if { echo "$as_me:__oline__: $JAVAC$source_option$target_option -d . conftest.java" >&AS_MESSAGE_LOG_FD
+ $JAVAC$source_option$target_option -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
+ } \
+ && test -f conftest.class; then
+ dnl The compiler supports the try_source_version and
+ dnl try_target_version. It's better than nothing.
+ CONF_JAVAC="$JAVAC$source_option$target_option"
+ HAVE_JAVAC_ENVVAR=1
+ HAVE_JAVACOMP=1
+ break
+ fi
+ done
+ fi
+ fi
fi
fi
- fi
- if test -z "$HAVE_JAVACOMP"; then
- pushdef([AC_MSG_CHECKING],[:])dnl
- pushdef([AC_CHECKING],[:])dnl
- pushdef([AC_MSG_RESULT],[:])dnl
- AC_CHECK_PROG([HAVE_JAVAC_IN_PATH], [javac], [yes])
- popdef([AC_MSG_RESULT])dnl
- popdef([AC_CHECKING])dnl
- popdef([AC_MSG_CHECKING])dnl
- if test -z "$HAVE_JAVACOMP" && test -n "$HAVE_JAVAC_IN_PATH"; then
- dnl Test whether javac is usable.
- if { javac -version >/dev/null 2>/dev/null || test $? -le 2; } \
- && ( if javac -help 2>&1 >/dev/null | grep at.dms.kjc.Main >/dev/null && javac -help 2>/dev/null | grep 'released.*2000' >/dev/null ; then exit 1; else exit 0; fi ); then
- dnl OK, javac works.
- dnl Now test whether it supports the desired target-version and
- dnl source-version.
+ if test -z "$HAVE_JAVACOMP"; then
+ pushdef([AC_MSG_CHECKING],[:])dnl
+ pushdef([AC_CHECKING],[:])dnl
+ pushdef([AC_MSG_RESULT],[:])dnl
+ AC_CHECK_PROG([HAVE_JAVAC_IN_PATH], [javac], [yes])
+ popdef([AC_MSG_RESULT])dnl
+ popdef([AC_CHECKING])dnl
+ popdef([AC_MSG_CHECKING])dnl
+ if test -z "$HAVE_JAVACOMP" && test -n "$HAVE_JAVAC_IN_PATH"; then
+ dnl Test whether javac is usable.
rm -f conftest.class
if { echo "$as_me:__oline__: javac -d . conftest.java" >&AS_MESSAGE_LOG_FD
javac -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
} \
- && test -f conftest.class \
- && expr `func_classfile_version conftest.class` '<=' $cfversion >/dev/null 2>&AS_MESSAGE_LOG_FD; then
- dnl Try adding -source option if it is useful.
- rm -f conftest.class
- rm -f conftestfail.class
- if { echo "$as_me:__oline__: javac -source $source_version -d . conftest.java" >&AS_MESSAGE_LOG_FD
- javac -source "$source_version" -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
- } \
- && test -f conftest.class \
- && expr `func_classfile_version conftest.class` '<=' $cfversion >/dev/null 2>&AS_MESSAGE_LOG_FD \
- && { echo "$as_me:__oline__: javac -d . conftestfail.java" >&AS_MESSAGE_LOG_FD
- javac -d . conftestfail.java >&AS_MESSAGE_LOG_FD 2>&1
- } \
- && test -f conftestfail.class \
- && ! { echo "$as_me:__oline__: javac -source $source_version -d . conftestfail.java" >&AS_MESSAGE_LOG_FD
- javac -source "$source_version" -d . conftestfail.java >&AS_MESSAGE_LOG_FD 2>&1
- }; then
- CONF_JAVAC="javac -source $source_version"
- HAVE_JAVAC=1
- HAVE_JAVACOMP=1
+ && test -f conftest.class; then
+ compiler_cfversion=`func_classfile_version conftest.class`
+ compiler_target_version=`expr $compiler_cfversion - 44`
+ dnl It is hard to determine the compiler_source_version. This would
+ dnl require a list of code snippets that can be compiled only with a
+ dnl specific '-source' option and up, and this list would need to grow
+ dnl every 6 months.
+ dnl Also, javac may point to a shell script that already includes a
+ dnl '-source' option.
+ dnl Therefore, pass a '-source' option always.
+ source_option=' -source '`case "$source_version" in 6|7|8) echo 1. ;; esac`"$source_version"
+ dnl And pass a '-target' option as well, if needed.
+ dnl (All supported javac versions support both, see the table above.)
+ if expr $target_version = $compiler_target_version >/dev/null; then
+ target_option=
else
- CONF_JAVAC="javac"
- HAVE_JAVAC=1
- HAVE_JAVACOMP=1
+ target_option=' -target '`case "$target_version" in 6|7|8) echo 1. ;; esac`"$target_version"
fi
- else
- dnl Try with -target and -source options. (All supported javac
- dnl versions support both, see the table above.)
- rm -f conftest.class
- if { echo "$as_me:__oline__: javac -target $target_version -source $source_version -d . conftest.java" >&AS_MESSAGE_LOG_FD
- javac -target "$target_version" -source "$source_version" -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
+ if { echo "$as_me:__oline__: javac$source_option$target_option -d . conftest.java" >&AS_MESSAGE_LOG_FD
+ javac$source_option$target_option -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
} \
- && test -f conftest.class \
- && expr `func_classfile_version conftest.class` '<=' $cfversion >/dev/null 2>&AS_MESSAGE_LOG_FD; then
- CONF_JAVAC="javac -target $target_version -source $source_version"
+ && test -f conftest.class; then
+ dnl The compiler directly supports the desired source_version and
+ dnl target_version. Perfect.
+ CONF_JAVAC="javac$source_option$target_option"
HAVE_JAVAC=1
HAVE_JAVACOMP=1
+ else
+ dnl If the desired source_version or target_version were too large
+ dnl for the compiler, there's nothing else we can do.
+ compiler_version=`echo "$as_me:__oline__: javac -version | sed -e 1q" >&AS_MESSAGE_LOG_FD
+ javac -version | sed -e 1q`
+changequote(,)dnl
+ compiler_version=`echo "$compiler_version" | sed -e 's/^[^0-9]*\([0-9][0-9.]*\).*/\1/'`
+changequote([,])dnl
+ case "$compiler_version" in
+ 1.*) dnl Map 1.6.0_85 to 6, 1.8.0_151 to 8.
+ compiler_version=`echo "$compiler_version" | sed -e 's/^1\.//' -e 's/\..*//'`
+ ;;
+ *) dnl Map 9.0.4 to 9, 10.0.2 to 10, etc.
+ compiler_version=`echo "$compiler_version" | sed -e 's/\..*//'`
+ ;;
+ esac
+ if expr $source_version '<=' "$compiler_version" >/dev/null \
+ && expr $target_version '<=' "$compiler_version" >/dev/null; then
+ dnl Increase $source_version and $compiler_version until the
+ dnl compiler accepts these values. This is necessary to make
+ dnl e.g. $source_version = 6 work with Java 12 or newer, or
+ dnl $source_version = 7 work with Java 20 or newer.
+ try_source_version="$source_version"
+ try_target_version="$target_version"
+ while true; do
+ dnl Invariant: $try_source_version <= $try_target_version.
+ if expr $try_source_version = $try_target_version >/dev/null; then
+ try_target_version=`expr $try_target_version + 1`
+ fi
+ try_source_version=`expr $try_source_version + 1`
+ expr $try_source_version '<=' $compiler_version >/dev/null || break
+ source_option=' -source '`case "$try_source_version" in 6|7|8) echo 1. ;; esac`"$try_source_version"
+ if expr $try_target_version = $compiler_target_version >/dev/null; then
+ target_option=
+ else
+ target_option=' -target '`case "$try_target_version" in 6|7|8) echo 1. ;; esac`"$try_target_version"
+ fi
+ if { echo "$as_me:__oline__: javac$source_option$target_option -d . conftest.java" >&AS_MESSAGE_LOG_FD
+ javac$source_option$target_option -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1
+ } \
+ && test -f conftest.class; then
+ dnl The compiler supports the try_source_version and
+ dnl try_target_version. It's better than nothing.
+ CONF_JAVAC="javac$source_option$target_option"
+ HAVE_JAVAC=1
+ HAVE_JAVACOMP=1
+ break
+ fi
+ done
+ fi
fi
fi
fi
fi
+ rm -f conftest*.java conftest*.class
fi
- rm -f conftest*.java conftest*.class
if test -n "$HAVE_JAVACOMP"; then
ac_result="$CONF_JAVAC"
else