From: Bruno Haible Date: Sat, 22 Jul 2006 16:03:47 +0000 (+0000) Subject: Update from GNU gettext 0.15. Accept source and target versions. X-Git-Tag: cvs-readonly~2164 X-Git-Url: http://erislabs.net/gitweb/?a=commitdiff_plain;h=18eedd96914ce2143792d1c98879ebbf8a369361;p=gnulib.git Update from GNU gettext 0.15. Accept source and target versions. --- diff --git a/ChangeLog b/ChangeLog index 1cf6c0a00..3c70a356a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2006-05-01 Bruno Haible + + * build-aux/javacomp.sh.in: Update for changed javacomp.m4. + 2006-07-22 Bruno Haible * modules/javaversion: New file. diff --git a/build-aux/javacomp.sh.in b/build-aux/javacomp.sh.in index e0c560c1e..8c707cb4a 100644 --- a/build-aux/javacomp.sh.in +++ b/build-aux/javacomp.sh.in @@ -1,7 +1,7 @@ #!/bin/sh # Compile a Java program. -# Copyright (C) 2001-2002 Free Software Foundation, Inc. +# Copyright (C) 2001-2002, 2006 Free Software Foundation, Inc. # Written by Bruno Haible , 2001. # # This program is free software; you can redistribute it and/or modify @@ -16,7 +16,7 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # This uses the same choices as javacomp.c, but instead of relying on the # environment settings at run time, it uses the environment variables @@ -28,9 +28,9 @@ # The extra CLASSPATH must have been set prior to calling this script. # Options that can be passed are -O, -g and "-d DIRECTORY". -CONF_JAVAC='@JAVAC@' +CONF_JAVAC='@CONF_JAVAC@' CONF_CLASSPATH='@CLASSPATH@' -if test -n "$CONF_JAVAC"; then +if test -n "@HAVE_JAVAC_ENVVAR@"; then # Combine given CLASSPATH and configured CLASSPATH. if test -n "$CLASSPATH"; then CLASSPATH="$CLASSPATH${CONF_CLASSPATH:+@CLASSPATH_SEPARATOR@$CONF_CLASSPATH}" @@ -43,18 +43,21 @@ if test -n "$CONF_JAVAC"; then else unset JAVA_HOME if test -n "@HAVE_GCJ_C@"; then + # In this case, $CONF_JAVAC starts with "gcj -C". CLASSPATH="$CLASSPATH" export CLASSPATH - test -z "$JAVA_VERBOSE" || echo gcj -C "$@" - exec gcj -C "$@" + test -z "$JAVA_VERBOSE" || echo "$CONF_JAVAC $@" + exec $CONF_JAVAC "$@" else if test -n "@HAVE_JAVAC@"; then + # In this case, $CONF_JAVAC starts with "javac". CLASSPATH="$CLASSPATH" export CLASSPATH - test -z "$JAVA_VERBOSE" || echo javac "$@" - exec javac "$@" + test -z "$JAVA_VERBOSE" || echo "$CONF_JAVAC $@" + exec $CONF_JAVAC "$@" else if test -n "@HAVE_JIKES@"; then + # In this case, $CONF_JAVAC starts with "jikes". # Combine given CLASSPATH and configured CLASSPATH. if test -n "$CLASSPATH"; then CLASSPATH="$CLASSPATH${CONF_CLASSPATH:+@CLASSPATH_SEPARATOR@$CONF_CLASSPATH}" @@ -62,8 +65,8 @@ else CLASSPATH="$CONF_CLASSPATH" fi export CLASSPATH - test -z "$JAVA_VERBOSE" || echo jikes "$@" - exec jikes "$@" + test -z "$JAVA_VERBOSE" || echo "$CONF_JAVAC $@" + exec $CONF_JAVAC "$@" else echo 'Java compiler not found, try installing gcj or set $JAVAC, then reconfigure' 1>&2 exit 1 diff --git a/lib/ChangeLog b/lib/ChangeLog index 9454299d7..9779a66d5 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,3 +1,15 @@ +2006-07-11 Bruno Haible + + * javacomp.c: Fix a comment. + Reported by Jim Meyering. + +2006-04-30 Bruno Haible + + * javacomp.h (compile_java_class): Add source_version, target_version + arguments. + * javacomp.c: Rewritten to choose only a compiler that respects the + specified source_version and target_version. + 2006-06-27 Bruno Haible Assume correct S_ISDIR macro. diff --git a/lib/javacomp.c b/lib/javacomp.c index ba47b6e7c..859d0725b 100644 --- a/lib/javacomp.c +++ b/lib/javacomp.c @@ -24,20 +24,33 @@ /* Specification. */ #include "javacomp.h" +#include +#include #include #include #include +#include +#include +#include +#include "javaversion.h" #include "execute.h" #include "pipe.h" #include "wait-process.h" #include "classpath.h" #include "xsetenv.h" #include "sh-quote.h" +#include "binary-io.h" #include "safe-read.h" #include "xalloc.h" #include "xallocsa.h" +#include "getline.h" +#include "pathname.h" +#include "fwriteerror.h" +#include "clean-temp.h" #include "error.h" +#include "xvasprintf.h" +#include "strstr.h" #include "gettext.h" #define _(str) gettext (str) @@ -78,391 +91,1708 @@ this variable can confuse the JDK's javac. */ -bool -compile_java_class (const char * const *java_sources, - unsigned int java_sources_count, - const char * const *classpaths, - unsigned int classpaths_count, - const char *directory, - bool optimize, bool debug, - bool use_minimal_classpath, - bool verbose) +/* Return the default target_version. */ +static const char * +default_target_version (void) { - bool err = false; - char *old_JAVA_HOME; + /* Use a cache. Assumes that the PATH environment variable doesn't change + during the lifetime of the program. */ + static const char *java_version_cache; + if (java_version_cache == NULL) + { + /* Determine the version from the found JVM. */ + java_version_cache = javaexec_version (); + if (java_version_cache == NULL + || !(java_version_cache[0] == '1' && java_version_cache[1] == '.' + && (java_version_cache[2] >= '1' && java_version_cache[2] <= '6') + && java_version_cache[3] == '\0')) + java_version_cache = "1.1"; + } + return java_version_cache; +} - { - const char *javac = getenv ("JAVAC"); - if (javac != NULL && javac[0] != '\0') - { - /* Because $JAVAC may consist of a command and options, we use the - shell. Because $JAVAC has been set by the user, we leave all - environment variables in place, including JAVA_HOME, and - we don't erase the user's CLASSPATH. */ - char *old_classpath; - unsigned int command_length; - char *command; - char *argv[4]; - int exitstatus; - unsigned int i; - char *p; - - /* Set CLASSPATH. */ - old_classpath = - set_classpath (classpaths, classpaths_count, false, - verbose); - - command_length = strlen (javac); - if (optimize) - command_length += 3; - if (debug) - command_length += 3; - if (directory != NULL) - command_length += 4 + shell_quote_length (directory); - for (i = 0; i < java_sources_count; i++) - command_length += 1 + shell_quote_length (java_sources[i]); - command_length += 1; - - command = (char *) xallocsa (command_length); - p = command; - /* Don't shell_quote $JAVAC, because it may consist of a command - and options. */ - memcpy (p, javac, strlen (javac)); - p += strlen (javac); - if (optimize) - { - memcpy (p, " -O", 3); - p += 3; - } - if (debug) - { - memcpy (p, " -g", 3); - p += 3; - } - if (directory != NULL) - { - memcpy (p, " -d ", 4); - p += 4; - p = shell_quote_copy (p, directory); - } - for (i = 0; i < java_sources_count; i++) - { - *p++ = ' '; - p = shell_quote_copy (p, java_sources[i]); - } - *p++ = '\0'; - /* Ensure command_length was correctly calculated. */ - if (p - command > command_length) - abort (); +/* ======================= Source version dependent ======================= */ - if (verbose) - printf ("%s\n", command); +/* Convert a source version to an index. */ +#define SOURCE_VERSION_BOUND 3 /* exclusive upper bound */ +static unsigned int +source_version_index (const char *source_version) +{ + if (source_version[0] == '1' && source_version[1] == '.' + && (source_version[2] >= '3' && source_version[2] <= '5') + && source_version[3] == '\0') + return source_version[2] - '3'; + 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.3") == 0) + return "class conftest {}\n"; + if (strcmp (source_version, "1.4") == 0) + return "class conftest { static { assert(true); } }\n"; + if (strcmp (source_version, "1.5") == 0) + return "class conftest { T foo() { return null; } }\n"; + error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class")); + return NULL; +} - argv[0] = "/bin/sh"; - argv[1] = "-c"; - argv[2] = command; - argv[3] = NULL; - exitstatus = execute (javac, "/bin/sh", argv, false, false, false, - false, true, true); - err = (exitstatus != 0); +/* 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.3") == 0) + return "class conftestfail { static { assert(true); } }\n"; + if (strcmp (source_version, "1.4") == 0) + return "class conftestfail { T foo() { return null; } }\n"; + if (strcmp (source_version, "1.5") == 0) + return NULL; + error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class")); + return NULL; +} - freesa (command); +/* ======================= Target version dependent ======================= */ - /* Reset CLASSPATH. */ - reset_classpath (old_classpath); +/* Convert a target version to an index. */ +#define TARGET_VERSION_BOUND 6 /* exclusive upper bound */ +static unsigned int +target_version_index (const char *target_version) +{ + if (target_version[0] == '1' && target_version[1] == '.' + && (target_version[2] >= '1' && target_version[2] <= '6') + && target_version[3] == '\0') + return target_version[2] - '1'; + error (EXIT_FAILURE, 0, _("invalid target_version argument to compile_java_class")); + return 0; +} - goto done1; - } - } +/* 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.1") == 0) + return 45; + if (strcmp (target_version, "1.2") == 0) + return 46; + if (strcmp (target_version, "1.3") == 0) + return 47; + if (strcmp (target_version, "1.4") == 0) + return 48; + if (strcmp (target_version, "1.5") == 0) + return 49; + if (strcmp (target_version, "1.6") == 0) + return 50; + error (EXIT_FAILURE, 0, _("invalid target_version argument to compile_java_class")); + return 0; +} - /* Unset the JAVA_HOME environment variable. */ - old_JAVA_HOME = getenv ("JAVA_HOME"); - if (old_JAVA_HOME != NULL) +/* ======================== Compilation subroutines ======================== */ + +/* Try to compile a set of Java sources with $JAVAC. + Return a failure indicator (true upon error). */ +static bool +compile_using_envjavac (const char *javac, + const char * const *java_sources, + unsigned int java_sources_count, + const char *directory, + bool optimize, bool debug, + bool verbose, bool null_stderr) +{ + /* Because $JAVAC may consist of a command and options, we use the + shell. Because $JAVAC has been set by the user, we leave all + environment variables in place, including JAVA_HOME, and we don't + erase the user's CLASSPATH. */ + bool err; + unsigned int command_length; + char *command; + char *argv[4]; + int exitstatus; + unsigned int i; + char *p; + + command_length = strlen (javac); + if (optimize) + command_length += 3; + if (debug) + command_length += 3; + if (directory != NULL) + command_length += 4 + shell_quote_length (directory); + for (i = 0; i < java_sources_count; i++) + command_length += 1 + shell_quote_length (java_sources[i]); + command_length += 1; + + command = (char *) xallocsa (command_length); + p = command; + /* Don't shell_quote $JAVAC, because it may consist of a command + and options. */ + memcpy (p, javac, strlen (javac)); + p += strlen (javac); + if (optimize) { - old_JAVA_HOME = xstrdup (old_JAVA_HOME); - unsetenv ("JAVA_HOME"); + memcpy (p, " -O", 3); + p += 3; + } + if (debug) + { + memcpy (p, " -g", 3); + p += 3; + } + if (directory != NULL) + { + memcpy (p, " -d ", 4); + p += 4; + p = shell_quote_copy (p, directory); + } + for (i = 0; i < java_sources_count; i++) + { + *p++ = ' '; + p = shell_quote_copy (p, java_sources[i]); + } + *p++ = '\0'; + /* Ensure command_length was correctly calculated. */ + if (p - command > command_length) + abort (); + + if (verbose) + printf ("%s\n", command); + + argv[0] = "/bin/sh"; + argv[1] = "-c"; + argv[2] = command; + argv[3] = NULL; + exitstatus = execute (javac, "/bin/sh", argv, false, false, false, + null_stderr, true, true); + err = (exitstatus != 0); + + freesa (command); + + return err; +} + +/* Try to compile a set of Java sources with gcj. + Return a failure indicator (true upon error). */ +static bool +compile_using_gcj (const char * const *java_sources, + unsigned int java_sources_count, + bool no_assert_option, + const char *directory, + bool optimize, bool debug, + bool verbose, bool null_stderr) +{ + bool err; + unsigned int argc; + char **argv; + char **argp; + int exitstatus; + unsigned int i; + + argc = + 2 + (no_assert_option ? 1 : 0) + (optimize ? 1 : 0) + (debug ? 1 : 0) + + (directory != NULL ? 2 : 0) + java_sources_count; + argv = (char **) xallocsa ((argc + 1) * sizeof (char *)); + + argp = argv; + *argp++ = "gcj"; + *argp++ = "-C"; + if (no_assert_option) + *argp++ = "-fno-assert"; + if (optimize) + *argp++ = "-O"; + if (debug) + *argp++ = "-g"; + if (directory != NULL) + { + *argp++ = "-d"; + *argp++ = (char *) directory; + } + for (i = 0; i < java_sources_count; i++) + *argp++ = (char *) java_sources[i]; + *argp = NULL; + /* Ensure argv length was correctly calculated. */ + if (argp - argv != argc) + abort (); + + if (verbose) + { + char *command = shell_quote_argv (argv); + printf ("%s\n", command); + free (command); + } + + exitstatus = execute ("gcj", "gcj", argv, false, false, false, null_stderr, + true, true); + err = (exitstatus != 0); + + freesa (argv); + + return err; +} + +/* Try to compile a set of Java sources with javac. + Return a failure indicator (true upon error). */ +static bool +compile_using_javac (const char * const *java_sources, + unsigned int java_sources_count, + bool source_option, const char *source_version, + bool target_option, const char *target_version, + const char *directory, + bool optimize, bool debug, + bool verbose, bool null_stderr) +{ + bool err; + unsigned int argc; + char **argv; + char **argp; + int exitstatus; + unsigned int i; + + argc = + 1 + (source_option ? 2 : 0) + (target_option ? 2 : 0) + (optimize ? 1 : 0) + + (debug ? 1 : 0) + (directory != NULL ? 2 : 0) + java_sources_count; + argv = (char **) xallocsa ((argc + 1) * sizeof (char *)); + + argp = argv; + *argp++ = "javac"; + if (source_option) + { + *argp++ = "-source"; + *argp++ = (char *) source_version; + } + if (target_option) + { + *argp++ = "-target"; + *argp++ = (char *) target_version; + } + if (optimize) + *argp++ = "-O"; + if (debug) + *argp++ = "-g"; + if (directory != NULL) + { + *argp++ = "-d"; + *argp++ = (char *) directory; + } + for (i = 0; i < java_sources_count; i++) + *argp++ = (char *) java_sources[i]; + *argp = NULL; + /* Ensure argv length was correctly calculated. */ + if (argp - argv != argc) + abort (); + + if (verbose) + { + char *command = shell_quote_argv (argv); + printf ("%s\n", command); + free (command); + } + + exitstatus = execute ("javac", "javac", argv, false, false, false, + null_stderr, true, true); + err = (exitstatus != 0); + + freesa (argv); + + return err; +} + +/* Try to compile a set of Java sources with jikes. + Return a failure indicator (true upon error). */ +static bool +compile_using_jikes (const char * const *java_sources, + unsigned int java_sources_count, + const char *directory, + bool optimize, bool debug, + bool verbose, bool null_stderr) +{ + bool err; + unsigned int argc; + char **argv; + char **argp; + int exitstatus; + unsigned int i; + + argc = + 1 + (optimize ? 1 : 0) + (debug ? 1 : 0) + (directory != NULL ? 2 : 0) + + java_sources_count; + argv = (char **) xallocsa ((argc + 1) * sizeof (char *)); + + argp = argv; + *argp++ = "jikes"; + if (optimize) + *argp++ = "-O"; + if (debug) + *argp++ = "-g"; + if (directory != NULL) + { + *argp++ = "-d"; + *argp++ = (char *) directory; + } + for (i = 0; i < java_sources_count; i++) + *argp++ = (char *) java_sources[i]; + *argp = NULL; + /* Ensure argv length was correctly calculated. */ + if (argp - argv != argc) + abort (); + + if (verbose) + { + char *command = shell_quote_argv (argv); + printf ("%s\n", command); + free (command); + } + + exitstatus = execute ("jikes", "jikes", argv, false, false, false, + null_stderr, true, true); + err = (exitstatus != 0); + + freesa (argv); + + return err; +} + +/* ====================== Usability test subroutines ====================== */ + +/* 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. + Return a failure indicator (true upon error). */ +static bool +write_temp_file (struct temp_dir *tmpdir, const char *file_name, + const char *contents) +{ + FILE *fp; + + register_temp_file (tmpdir, file_name); + fp = fopen (file_name, "w"); + if (fp == NULL) + { + error (0, errno, _("failed to create \"%s\""), file_name); + unregister_temp_file (tmpdir, file_name); + return true; + } + fputs (contents, fp); + if (fwriteerror (fp)) + { + error (0, errno, _("error while writing \"%s\" file"), file_name); + return true; + } + return false; +} + +/* Return the class file version number of a class file on disk. */ +static int +get_classfile_version (const char *compiled_file_name) +{ + unsigned char header[8]; + int fd; + + /* Open the class file. */ + fd = open (compiled_file_name, O_RDONLY | O_BINARY, 0); + if (fd >= 0) + { + /* Read its first 8 bytes. */ + if (safe_read (fd, header, 8) == 8) + { + /* Verify the class file signature. */ + if (header[0] == 0xCA && header[1] == 0xFE + && header[2] == 0xBA && header[3] == 0xBE) + return header[7]; + } + close (fd); + } + + /* Could not get the class file version. Return a very large one. */ + return INT_MAX; +} + +/* Return true if $JAVAC is a version of gcj. */ +static bool +is_envjavac_gcj (const char *javac) +{ + static bool envjavac_tested; + static bool envjavac_gcj; + + if (!envjavac_tested) + { + /* Test whether $JAVAC is gcj: + "$JAVAC --version 2>/dev/null | sed -e 1q | grep gcj > /dev/null" */ + unsigned int command_length; + char *command; + char *argv[4]; + pid_t child; + int fd[1]; + FILE *fp; + char *line; + size_t linesize; + size_t linelen; + int exitstatus; + char *p; + + /* Setup the command "$JAVAC --version". */ + command_length = strlen (javac) + 1 + 9 + 1; + command = (char *) xallocsa (command_length); + p = command; + /* Don't shell_quote $JAVAC, because it may consist of a command + and options. */ + memcpy (p, javac, strlen (javac)); + p += strlen (javac); + memcpy (p, " --version", 1 + 9 + 1); + p += 1 + 9 + 1; + /* Ensure command_length was correctly calculated. */ + if (p - command > command_length) + abort (); + + /* Call $JAVAC --version 2>/dev/null. */ + argv[0] = "/bin/sh"; + argv[1] = "-c"; + argv[2] = command; + argv[3] = NULL; + child = create_pipe_in (javac, "/bin/sh", argv, DEV_NULL, true, true, + false, fd); + if (child == -1) + goto failed; + + /* Retrieve its result. */ + fp = fdopen (fd[0], "r"); + if (fp == NULL) + goto failed; + + line = NULL; linesize = 0; + linelen = getline (&line, &linesize, fp); + if (linelen == (size_t)(-1)) + { + fclose (fp); + goto failed; + } + envjavac_gcj = (strstr (line, "gcj") != NULL); + + fclose (fp); + + /* Remove zombie process from process list, and retrieve exit status. */ + exitstatus = wait_subprocess (child, javac, true, true, true, false); + if (exitstatus != 0) + envjavac_gcj = false; + + failed: + freesa (command); + + envjavac_tested = true; + } + + return envjavac_gcj; +} + +/* Test whether $JAVAC, known to be a version of gcj, can be used for + compiling with target_version = 1.4 and source_version = 1.4. + Return a failure indicator (true upon error). */ +static bool +is_envjavac_gcj_14_14_usable (const char *javac, bool *usablep) +{ + static bool envjavac_tested; + static bool envjavac_usable; + + if (!envjavac_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 = + concatenated_pathname (tmpdir->dir_name, "conftest.java", NULL); + if (write_temp_file (tmpdir, conftest_file_name, + get_goodcode_snippet ("1.4"))) + { + free (conftest_file_name); + cleanup_temp_dir (tmpdir); + return true; + } + + compiled_file_name = + concatenated_pathname (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) + /* Compilation succeeded. */ + envjavac_usable = true; + + free (compiled_file_name); + free (conftest_file_name); + + cleanup_temp_dir (tmpdir); + + envjavac_tested = true; } + *usablep = envjavac_usable; + return false; +} + +/* Test whether $JAVAC, known to be a version of gcj, can be used for + compiling with target_version = 1.4 and source_version = 1.3. + Return a failure indicator (true upon error). */ +static bool +is_envjavac_gcj_14_13_usable (const char *javac, + bool *usablep, bool *need_no_assert_option_p) +{ + static bool envjavac_tested; + static bool envjavac_usable; + static bool envjavac_need_no_assert_option; + + if (!envjavac_tested) + { + /* Try $JAVAC and "$JAVAC -fno-assert". But add -fno-assert only if + it makes a difference. (It could already be part of $JAVAC.) */ + struct temp_dir *tmpdir; + char *conftest_file_name; + char *compiled_file_name; + const char *java_sources[1]; + struct stat statbuf; + bool javac_works; + char *javac_noassert; + bool javac_noassert_works; + + tmpdir = create_temp_dir ("java", NULL, false); + if (tmpdir == NULL) + return true; + + conftest_file_name = + concatenated_pathname (tmpdir->dir_name, "conftest.java", NULL); + if (write_temp_file (tmpdir, conftest_file_name, + get_goodcode_snippet ("1.3"))) + { + free (conftest_file_name); + cleanup_temp_dir (tmpdir); + return true; + } + + compiled_file_name = + concatenated_pathname (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) + /* Compilation succeeded. */ + javac_works = true; + else + javac_works = false; + + unlink (compiled_file_name); + + javac_noassert = xasprintf ("%s -fno-assert", javac); + + java_sources[0] = conftest_file_name; + if (!compile_using_envjavac (javac_noassert, + java_sources, 1, tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0) + /* Compilation succeeded. */ + javac_noassert_works = true; + else + javac_noassert_works = false; + + free (compiled_file_name); + free (conftest_file_name); + + if (javac_works && javac_noassert_works) + { + conftest_file_name = + concatenated_pathname (tmpdir->dir_name, "conftestfail.java", + NULL); + if (write_temp_file (tmpdir, conftest_file_name, + get_failcode_snippet ("1.3"))) + { + free (conftest_file_name); + free (javac_noassert); + cleanup_temp_dir (tmpdir); + return true; + } + + compiled_file_name = + concatenated_pathname (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) + { + /* Compilation succeeded. */ + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!(!compile_using_envjavac (javac_noassert, + java_sources, 1, tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0)) + /* Compilation failed. */ + /* "$JAVAC -fno-assert" works better than $JAVAC. */ + javac_works = true; + } + + free (compiled_file_name); + free (conftest_file_name); + } + + cleanup_temp_dir (tmpdir); + + if (javac_works) + { + envjavac_usable = true; + envjavac_need_no_assert_option = false; + } + else if (javac_noassert_works) + { + envjavac_usable = true; + envjavac_need_no_assert_option = true; + } + + envjavac_tested = true; + } + + *usablep = envjavac_usable; + *need_no_assert_option_p = envjavac_need_no_assert_option; + return false; +} + +/* Test whether $JAVAC, known to be not a version of gcj, can be used, and + whether it needs a -source and/or -target option. + Return a failure indicator (true upon error). */ +static bool +is_envjavac_nongcj_usable (const char *javac, + const char *source_version, + const char *target_version, + bool *usablep, + bool *source_option_p, bool *target_option_p) +{ + /* The cache depends on the source_version and target_version. */ + struct result_t { - static bool gcj_tested; - static bool gcj_present; + bool tested; + bool usable; + bool source_option; + bool target_option; + }; + static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND]; + struct result_t *resultp; + + resultp = &result_cache[source_version_index (source_version)] + [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 = + concatenated_pathname (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 = + concatenated_pathname (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)) + { + /* $JAVAC compiled conftest.java successfully. */ + /* Try adding -source option if it is useful. */ + char *javac_source = + xasprintf ("%s -source %s", javac, source_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) + && stat (compiled_file_name, &statbuf) >= 0 + && get_classfile_version (compiled_file_name) + <= corresponding_classfile_version (target_version)) + { + const char *failcode = get_failcode_snippet (source_version); + + if (failcode != NULL) + { + free (compiled_file_name); + free (conftest_file_name); + + conftest_file_name = + concatenated_pathname (tmpdir->dir_name, + "conftestfail.java", + NULL); + if (write_temp_file (tmpdir, conftest_file_name, failcode)) + { + free (conftest_file_name); + free (javac_source); + cleanup_temp_dir (tmpdir); + return true; + } + + compiled_file_name = + concatenated_pathname (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) + { + 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; + } + } + } + + free (javac_source); + + resultp->usable = true; + } + else + { + /* Try with -target option alone. (Sun javac 1.3.1 has the -target + option but no -source option.) */ + char *javac_target = + xasprintf ("%s -target %s", javac, target_version); + + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_envjavac (javac_target, + 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" compiled conftest.java + successfully. */ + /* Try adding -source option if it is useful. */ + char *javac_target_source = + xasprintf ("%s -source %s", javac_target, source_version); + + 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)) + { + const char *failcode = get_failcode_snippet (source_version); + + if (failcode != NULL) + { + free (compiled_file_name); + free (conftest_file_name); + + conftest_file_name = + concatenated_pathname (tmpdir->dir_name, + "conftestfail.java", + NULL); + if (write_temp_file (tmpdir, conftest_file_name, + failcode)) + { + free (conftest_file_name); + free (javac_target_source); + free (javac_target); + cleanup_temp_dir (tmpdir); + return true; + } + + compiled_file_name = + concatenated_pathname (tmpdir->dir_name, + "conftestfail.class", + NULL); + register_temp_file (tmpdir, compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_envjavac (javac_target, + java_sources, 1, + tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0) + { + 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)) + /* "$JAVAC -target $target_version" compiled + conftestfail.java successfully, and + "$JAVAC -target $target_version -source $source_version" + rejects it. So the -source option is useful. */ + resultp->source_option = true; + } + } + } + + free (javac_target_source); + + resultp->target_option = true; + resultp->usable = true; + } + else + { + /* Maybe this -target option requires a -source option? Try with + -target and -source options. (Supported by Sun javac 1.4 and + higher.) */ + char *javac_target_source = + xasprintf ("%s -source %s", javac_target, source_version); + + 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; + } + + free (javac_target_source); + } + + free (javac_target); + } + + free (compiled_file_name); + free (conftest_file_name); + + resultp->tested = true; + } - if (!gcj_tested) - { - /* Test for presence of gcj: - "gcj --version 2> /dev/null | \ - sed -e 's,^[^0-9]*,,' -e 1q | \ - sed -e '/^3\.[01]/d' | grep '^[3-9]' > /dev/null" */ - char *argv[3]; - pid_t child; - int fd[1]; - int exitstatus; - - argv[0] = "gcj"; - argv[1] = "--version"; - argv[2] = NULL; - child = create_pipe_in ("gcj", "gcj", argv, DEV_NULL, true, true, - false, fd); - gcj_present = false; - if (child != -1) - { - /* Read the subprocess output, drop all lines except the first, - drop all characters before the first digit, and test whether - the remaining string starts with a digit >= 3, but not with - "3.0" or "3.1". */ - char c[3]; - size_t count = 0; - - while (safe_read (fd[0], &c[count], 1) > 0) - { - if (c[count] == '\n') + *usablep = resultp->usable; + *source_option_p = resultp->source_option; + *target_option_p = resultp->target_option; + return false; +} + +static bool +is_gcj_present (void) +{ + static bool gcj_tested; + static bool gcj_present; + + if (!gcj_tested) + { + /* Test for presence of gcj: + "gcj --version 2> /dev/null | \ + sed -e 's,^[^0-9]*,,' -e 1q | \ + sed -e '/^3\.[01]/d' | grep '^[3-9]' > /dev/null" */ + char *argv[3]; + pid_t child; + int fd[1]; + int exitstatus; + + argv[0] = "gcj"; + argv[1] = "--version"; + argv[2] = NULL; + child = create_pipe_in ("gcj", "gcj", argv, DEV_NULL, true, true, + false, fd); + gcj_present = false; + if (child != -1) + { + /* Read the subprocess output, drop all lines except the first, + drop all characters before the first digit, and test whether + the remaining string starts with a digit >= 3, but not with + "3.0" or "3.1". */ + char c[3]; + size_t count = 0; + + while (safe_read (fd[0], &c[count], 1) > 0) + { + if (c[count] == '\n') + break; + if (count == 0) + { + if (!(c[0] >= '0' && c[0] <= '9')) + continue; + gcj_present = (c[0] >= '3'); + } + count++; + if (count == 3) + { + if (c[0] == '3' && c[1] == '.' + && (c[2] == '0' || c[2] == '1')) + gcj_present = false; break; - if (count == 0) - { - if (!(c[0] >= '0' && c[0] <= '9')) - continue; - gcj_present = (c[0] >= '3'); - } - count++; - if (count == 3) - { - if (c[0] == '3' && c[1] == '.' - && (c[2] == '0' || c[2] == '1')) - gcj_present = false; - break; - } - } - while (safe_read (fd[0], &c[0], 1) > 0) - ; + } + } + while (safe_read (fd[0], &c[0], 1) > 0) + ; + + close (fd[0]); + + /* Remove zombie process from process list, and retrieve exit + status. */ + exitstatus = + wait_subprocess (child, "gcj", false, true, true, false); + if (exitstatus != 0) + gcj_present = false; + } + + if (gcj_present) + { + /* See if libgcj.jar is well installed. */ + struct temp_dir *tmpdir; + + tmpdir = create_temp_dir ("java", NULL, false); + if (tmpdir == NULL) + gcj_present = false; + else + { + char *conftest_file_name; + + conftest_file_name = + concatenated_pathname (tmpdir->dir_name, "conftestlib.java", + NULL); + if (write_temp_file (tmpdir, conftest_file_name, +"public class conftestlib {\n" +" public static void main (String[] args) {\n" +" }\n" +"}\n")) + gcj_present = false; + else + { + char *compiled_file_name; + const char *java_sources[1]; + + compiled_file_name = + concatenated_pathname (tmpdir->dir_name, + "conftestlib.class", + NULL); + register_temp_file (tmpdir, compiled_file_name); + + java_sources[0] = conftest_file_name; + if (compile_using_gcj (java_sources, 1, false, + tmpdir->dir_name, + false, false, false, true)) + gcj_present = false; + + free (compiled_file_name); + } + free (conftest_file_name); + } + cleanup_temp_dir (tmpdir); + } + + gcj_tested = true; + } + + return gcj_present; +} - close (fd[0]); +/* Test gcj can be used for compiling with target_version = 1.4 and + source_version = 1.4. + Return a failure indicator (true upon error). */ +static bool +is_gcj_14_14_usable (bool *usablep) +{ + static bool gcj_tested; + static bool gcj_usable; - /* Remove zombie process from process list, and retrieve exit - status. */ - exitstatus = - wait_subprocess (child, "gcj", false, true, true, false); - if (exitstatus != 0) - gcj_present = false; - } - gcj_tested = true; - } + if (!gcj_tested) + { + /* Try gcj. */ + 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 = + concatenated_pathname (tmpdir->dir_name, "conftest.java", NULL); + if (write_temp_file (tmpdir, conftest_file_name, + get_goodcode_snippet ("1.4"))) + { + free (conftest_file_name); + cleanup_temp_dir (tmpdir); + return true; + } + + compiled_file_name = + concatenated_pathname (tmpdir->dir_name, "conftest.class", NULL); + register_temp_file (tmpdir, compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_gcj (java_sources, 1, false, tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0) + /* Compilation succeeded. */ + gcj_usable = true; + + free (compiled_file_name); + free (conftest_file_name); + + cleanup_temp_dir (tmpdir); + + gcj_tested = true; + } - if (gcj_present) - { - char *old_classpath; - unsigned int argc; - char **argv; - char **argp; - int exitstatus; - unsigned int i; - - /* Set CLASSPATH. We could also use the --CLASSPATH=... option - of gcj. Note that --classpath=... option is different: its - argument should also contain gcj's libgcj.jar, but we don't - know its location. */ - old_classpath = - set_classpath (classpaths, classpaths_count, use_minimal_classpath, - verbose); - - argc = - 2 + (optimize ? 1 : 0) + (debug ? 1 : 0) + (directory != NULL ? 2 : 0) - + java_sources_count; - argv = (char **) xallocsa ((argc + 1) * sizeof (char *)); - - argp = argv; - *argp++ = "gcj"; - *argp++ = "-C"; - if (optimize) - *argp++ = "-O"; - if (debug) - *argp++ = "-g"; - if (directory != NULL) - { - *argp++ = "-d"; - *argp++ = (char *) directory; - } - for (i = 0; i < java_sources_count; i++) - *argp++ = (char *) java_sources[i]; - *argp = NULL; - /* Ensure argv length was correctly calculated. */ - if (argp - argv != argc) - abort (); - - if (verbose) - { - char *command = shell_quote_argv (argv); - printf ("%s\n", command); - free (command); - } + *usablep = gcj_usable; + return false; +} + +/* Test whether gcj can be used for compiling with target_version = 1.4 and + source_version = 1.3. + Return a failure indicator (true upon error). */ +static bool +is_gcj_14_13_usable (bool *usablep, bool *need_no_assert_option_p) +{ + static bool gcj_tested; + static bool gcj_usable; + static bool gcj_need_no_assert_option; + + if (!gcj_tested) + { + /* Try gcj and "gcj -fno-assert". But add -fno-assert only if + it works (not gcj < 3.3). */ + 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 = + concatenated_pathname (tmpdir->dir_name, "conftest.java", NULL); + if (write_temp_file (tmpdir, conftest_file_name, + get_goodcode_snippet ("1.3"))) + { + free (conftest_file_name); + cleanup_temp_dir (tmpdir); + return true; + } + + compiled_file_name = + concatenated_pathname (tmpdir->dir_name, "conftest.class", NULL); + register_temp_file (tmpdir, compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_gcj (java_sources, 1, true, tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0) + /* Compilation succeeded. */ + { + gcj_usable = true; + gcj_need_no_assert_option = true; + } + else + { + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_gcj (java_sources, 1, false, tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0) + /* Compilation succeeded. */ + { + gcj_usable = true; + gcj_need_no_assert_option = false; + } + } + + free (compiled_file_name); + free (conftest_file_name); + + cleanup_temp_dir (tmpdir); + + gcj_tested = true; + } - exitstatus = execute ("gcj", "gcj", argv, false, false, false, false, - true, true); - err = (exitstatus != 0); + *usablep = gcj_usable; + *need_no_assert_option_p = gcj_need_no_assert_option; + return false; +} - freesa (argv); +static bool +is_javac_present (void) +{ + static bool javac_tested; + static bool javac_present; - /* Reset CLASSPATH. */ - reset_classpath (old_classpath); + if (!javac_tested) + { + /* Test for presence of javac: "javac 2> /dev/null ; test $? -le 2" */ + char *argv[2]; + int exitstatus; + + argv[0] = "javac"; + argv[1] = NULL; + exitstatus = execute ("javac", "javac", argv, false, false, true, true, + true, false); + javac_present = (exitstatus == 0 || exitstatus == 1 || exitstatus == 2); + javac_tested = true; + } - goto done2; - } - } + return javac_present; +} +/* Test whether javac can be used and whether it needs a -source and/or + -target option. + 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) +{ + /* The cache depends on the source_version and target_version. */ + struct result_t { - static bool javac_tested; - static bool javac_present; + bool tested; + bool usable; + bool source_option; + bool target_option; + }; + static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND]; + struct result_t *resultp; + + resultp = &result_cache[source_version_index (source_version)] + [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 = + concatenated_pathname (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 = + concatenated_pathname (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); + + 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) + && stat (compiled_file_name, &statbuf) >= 0 + && get_classfile_version (compiled_file_name) + <= corresponding_classfile_version (target_version)) + { + const char *failcode = get_failcode_snippet (source_version); + + if (failcode != NULL) + { + free (compiled_file_name); + free (conftest_file_name); + + conftest_file_name = + concatenated_pathname (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 = + concatenated_pathname (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) + { + 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; + } + } + } + + resultp->usable = true; + } + else + { + /* Try with -target option alone. (Sun javac 1.3.1 has the -target + option but no -source option.) */ + unlink (compiled_file_name); + + java_sources[0] = conftest_file_name; + if (!compile_using_javac (java_sources, 1, + false, 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" compiled conftest.java + successfully. */ + /* Try adding -source option if it is useful. */ + unlink (compiled_file_name); + + 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)) + { + const char *failcode = get_failcode_snippet (source_version); + + if (failcode != NULL) + { + free (compiled_file_name); + free (conftest_file_name); + + conftest_file_name = + concatenated_pathname (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 = + concatenated_pathname (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, + true, target_version, + tmpdir->dir_name, + false, false, false, true) + && stat (compiled_file_name, &statbuf) >= 0) + { + unlink (compiled_file_name); + + 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)) + /* "javac -target $target_version" compiled + conftestfail.java successfully, and + "javac -target $target_version -source $source_version" + rejects it. So the -source option is useful. */ + resultp->source_option = true; + } + } + } + + resultp->target_option = true; + resultp->usable = true; + } + else + { + /* Maybe this -target option requires a -source option? Try with + -target and -source options. (Supported by Sun javac 1.4 and + higher.) */ + unlink (compiled_file_name); + + 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); + + resultp->tested = true; + } - if (!javac_tested) - { - /* Test for presence of javac: "javac 2> /dev/null ; test $? -le 2" */ - char *argv[2]; - int exitstatus; - - argv[0] = "javac"; - argv[1] = NULL; - exitstatus = execute ("javac", "javac", argv, false, false, true, true, - true, false); - javac_present = (exitstatus == 0 || exitstatus == 1 || exitstatus == 2); - javac_tested = true; - } + *usablep = resultp->usable; + *source_option_p = resultp->source_option; + *target_option_p = resultp->target_option; + return false; +} - if (javac_present) - { - char *old_classpath; - unsigned int argc; - char **argv; - char **argp; - int exitstatus; - unsigned int i; - - /* Set CLASSPATH. We don't use the "-classpath ..." option because - in JDK 1.1.x its argument should also contain the JDK's classes.zip, - but we don't know its location. (In JDK 1.3.0 it would work.) */ - old_classpath = - set_classpath (classpaths, classpaths_count, use_minimal_classpath, - verbose); - - argc = - 1 + (optimize ? 1 : 0) + (debug ? 1 : 0) + (directory != NULL ? 2 : 0) - + java_sources_count; - argv = (char **) xallocsa ((argc + 1) * sizeof (char *)); - - argp = argv; - *argp++ = "javac"; - if (optimize) - *argp++ = "-O"; - if (debug) - *argp++ = "-g"; - if (directory != NULL) - { - *argp++ = "-d"; - *argp++ = (char *) directory; - } - for (i = 0; i < java_sources_count; i++) - *argp++ = (char *) java_sources[i]; - *argp = NULL; - /* Ensure argv length was correctly calculated. */ - if (argp - argv != argc) - abort (); - - if (verbose) - { - char *command = shell_quote_argv (argv); - printf ("%s\n", command); - free (command); - } +static bool +is_jikes_present (void) +{ + static bool jikes_tested; + static bool jikes_present; - exitstatus = execute ("javac", "javac", argv, false, false, false, - false, true, true); - err = (exitstatus != 0); + if (!jikes_tested) + { + /* Test for presence of jikes: "jikes 2> /dev/null ; test $? = 1" */ + char *argv[2]; + int exitstatus; + + argv[0] = "jikes"; + argv[1] = NULL; + exitstatus = execute ("jikes", "jikes", argv, false, false, true, true, + true, false); + jikes_present = (exitstatus == 0 || exitstatus == 1); + jikes_tested = true; + } - freesa (argv); + return jikes_present; +} - /* Reset CLASSPATH. */ - reset_classpath (old_classpath); +/* ============================= Main function ============================= */ - goto done2; - } - } +bool +compile_java_class (const char * const *java_sources, + unsigned int java_sources_count, + const char * const *classpaths, + unsigned int classpaths_count, + const char *source_version, + const char *target_version, + const char *directory, + bool optimize, bool debug, + bool use_minimal_classpath, + bool verbose) +{ + bool err = false; + char *old_JAVA_HOME; { - static bool jikes_tested; - static bool jikes_present; - - if (!jikes_tested) + const char *javac = getenv ("JAVAC"); + if (javac != NULL && javac[0] != '\0') { - /* Test for presence of jikes: "jikes 2> /dev/null ; test $? = 1" */ - char *argv[2]; - int exitstatus; - - argv[0] = "jikes"; - argv[1] = NULL; - exitstatus = execute ("jikes", "jikes", argv, false, false, true, true, - true, false); - jikes_present = (exitstatus == 0 || exitstatus == 1); - jikes_tested = true; - } + bool usable = false; + bool no_assert_option = false; + bool source_option = false; + bool target_option = false; - if (jikes_present) - { - char *old_classpath; - unsigned int argc; - char **argv; - char **argp; - int exitstatus; - unsigned int i; - - /* Set CLASSPATH. We could also use the "-classpath ..." option. - Since jikes doesn't come with its own standard library, it - needs a classes.zip or rt.jar or libgcj.jar in the CLASSPATH. - To increase the chance of success, we reuse the current CLASSPATH - if the user has set it. */ - old_classpath = - set_classpath (classpaths, classpaths_count, false, - verbose); - - argc = - 1 + (optimize ? 1 : 0) + (debug ? 1 : 0) + (directory != NULL ? 2 : 0) - + java_sources_count; - argv = (char **) xallocsa ((argc + 1) * sizeof (char *)); - - argp = argv; - *argp++ = "jikes"; - if (optimize) - *argp++ = "-O"; - if (debug) - *argp++ = "-g"; - if (directory != NULL) + if (target_version == NULL) + target_version = default_target_version (); + + if (is_envjavac_gcj (javac)) { - *argp++ = "-d"; - *argp++ = (char *) directory; + /* It's a version of gcj. Ignore the version of the class files + that it creates. */ + if (strcmp (target_version, "1.4") == 0 + && strcmp (source_version, "1.4") == 0) + { + if (is_envjavac_gcj_14_14_usable (javac, &usable)) + { + err = true; + goto done1; + } + } + else if (strcmp (target_version, "1.4") == 0 + && strcmp (source_version, "1.3") == 0) + { + if (is_envjavac_gcj_14_13_usable (javac, + &usable, &no_assert_option)) + { + err = true; + goto done1; + } + } } - for (i = 0; i < java_sources_count; i++) - *argp++ = (char *) java_sources[i]; - *argp = NULL; - /* Ensure argv length was correctly calculated. */ - if (argp - argv != argc) - abort (); - - if (verbose) + else { - char *command = shell_quote_argv (argv); - printf ("%s\n", command); - free (command); + /* It's not gcj. Assume the classfile versions are correct. */ + if (is_envjavac_nongcj_usable (javac, + source_version, target_version, + &usable, + &source_option, &target_option)) + { + err = true; + goto done1; + } } - exitstatus = execute ("jikes", "jikes", argv, false, false, false, - false, true, true); - err = (exitstatus != 0); + if (usable) + { + char *old_classpath; + char *javac_with_options; + + /* Set CLASSPATH. */ + old_classpath = + set_classpath (classpaths, classpaths_count, false, verbose); + + javac_with_options = + (no_assert_option + ? xasprintf ("%s -fno-assert", javac) + : xasprintf ("%s%s%s%s%s", + javac, + source_option ? " -source " : "", + source_option ? source_version : "", + target_option ? " -target " : "", + target_option ? target_version : "")); + + err = compile_using_envjavac (javac_with_options, + java_sources, java_sources_count, + directory, optimize, debug, verbose, + false); + + free (javac_with_options); + + /* Reset CLASSPATH. */ + reset_classpath (old_classpath); + + goto done1; + } + } + } - freesa (argv); + /* Unset the JAVA_HOME environment variable. */ + old_JAVA_HOME = getenv ("JAVA_HOME"); + if (old_JAVA_HOME != NULL) + { + old_JAVA_HOME = xstrdup (old_JAVA_HOME); + unsetenv ("JAVA_HOME"); + } + + if (is_gcj_present ()) + { + /* Test whether it supports the desired target-version and + source-version. But ignore the version of the class files that + it creates. */ + bool usable = false; + bool no_assert_option = false; + + if (target_version == NULL) + target_version = default_target_version (); + + if (strcmp (target_version, "1.4") == 0 + && strcmp (source_version, "1.4") == 0) + { + if (is_gcj_14_14_usable (&usable)) + { + err = true; + goto done1; + } + } + else if (strcmp (target_version, "1.4") == 0 + && strcmp (source_version, "1.3") == 0) + { + if (is_gcj_14_13_usable (&usable, &no_assert_option)) + { + err = true; + goto done1; + } + } + + if (usable) + { + char *old_classpath; + + /* Set CLASSPATH. We could also use the --CLASSPATH=... option + of gcj. Note that --classpath=... option is different: its + argument should also contain gcj's libgcj.jar, but we don't + know its location. */ + old_classpath = + set_classpath (classpaths, classpaths_count, use_minimal_classpath, + verbose); + + err = compile_using_gcj (java_sources, java_sources_count, + no_assert_option, + directory, optimize, debug, verbose, false); + + /* Reset CLASSPATH. */ + reset_classpath (old_classpath); + + goto done2; + } + } - /* Reset CLASSPATH. */ - reset_classpath (old_classpath); + if (is_javac_present ()) + { + bool usable = false; + bool source_option = false; + bool target_option = false; + + if (target_version == NULL) + target_version = default_target_version (); + + if (is_javac_usable (source_version, target_version, + &usable, &source_option, &target_option)) + { + err = true; + goto done1; + } + + if (usable) + { + char *old_classpath; + + /* Set CLASSPATH. We don't use the "-classpath ..." option because + in JDK 1.1.x its argument should also contain the JDK's + classes.zip, but we don't know its location. (In JDK 1.3.0 it + would work.) */ + old_classpath = + set_classpath (classpaths, classpaths_count, use_minimal_classpath, + verbose); + + err = compile_using_javac (java_sources, java_sources_count, + source_option, source_version, + target_option, target_version, + directory, optimize, debug, verbose, + false); + + /* Reset CLASSPATH. */ + reset_classpath (old_classpath); + + goto done2; + } + } - goto done2; - } - } + if (is_jikes_present ()) + { + /* Test whether it supports the desired target-version and + source-version. */ + bool usable = (strcmp (source_version, "1.3") == 0); + + if (usable) + { + char *old_classpath; + + /* Set CLASSPATH. We could also use the "-classpath ..." option. + Since jikes doesn't come with its own standard library, it + needs a classes.zip or rt.jar or libgcj.jar in the CLASSPATH. + To increase the chance of success, we reuse the current CLASSPATH + if the user has set it. */ + old_classpath = + set_classpath (classpaths, classpaths_count, false, verbose); + + err = compile_using_jikes (java_sources, java_sources_count, + directory, optimize, debug, verbose, + false); + + /* Reset CLASSPATH. */ + reset_classpath (old_classpath); + + goto done2; + } + } error (0, 0, _("Java compiler not found, try installing gcj or set $JAVAC")); err = true; diff --git a/lib/javacomp.h b/lib/javacomp.h index 4b979699d..df4547059 100644 --- a/lib/javacomp.h +++ b/lib/javacomp.h @@ -1,5 +1,5 @@ /* Compile a Java program. - Copyright (C) 2001-2002 Free Software Foundation, Inc. + Copyright (C) 2001-2002, 2006 Free Software Foundation, Inc. Written by Bruno Haible , 2001. This program is free software; you can redistribute it and/or modify @@ -24,6 +24,35 @@ /* Compile a Java source file to bytecode. java_sources is an array of source file names. classpaths is a list of pathnames to be prepended to the CLASSPATH. + + source_version can be: support for + 1.3 inner classes + 1.4 assert keyword + 1.5 generic classes and methods + 1.6 (not yet supported) + target_version can be: classfile version: + 1.1 45.3 + 1.2 46.0 + 1.3 47.0 + 1.4 48.0 + 1.5 49.0 + 1.6 50.0 + target_version can also be given as NULL. In this case, the required + target_version is determined from the found JVM (see javaversion.h). + Specifying target_version is useful when building a library (.jar) that is + useful outside the given package. Passing target_version = NULL is useful + when building an application. + It is unreasonable to ask for: + - target_version < 1.4 with source_version >= 1.4, or + - target_version < 1.5 with source_version >= 1.5, or + - target_version < 1.6 with source_version >= 1.6, + because even Sun's javac doesn't support these combinations. + It is redundant to ask for a target_version > source_version, since the + smaller target_version = source_version will also always work and newer JVMs + support the older target_versions too. Except for the case + target_version = 1.4, source_version = 1.3, which allows gcj versions 3.0 + to 3.2 to be used. + directory is the target directory. The .class file for class X.Y.Z is written at directory/X/Y/Z.class. If directory is NULL, the .class file is written in the source's directory. @@ -37,6 +66,8 @@ extern bool compile_java_class (const char * const *java_sources, unsigned int java_sources_count, const char * const *classpaths, unsigned int classpaths_count, + const char *source_version, + const char *target_version, const char *directory, bool optimize, bool debug, bool use_minimal_classpath, diff --git a/m4/ChangeLog b/m4/ChangeLog index 0b9319ba4..9edb3f88a 100644 --- a/m4/ChangeLog +++ b/m4/ChangeLog @@ -1,3 +1,26 @@ +2006-07-21 Bruno Haible + + * javacomp.m4 (gt_JAVACOMP): Convert target_version "null" to "1.1". + +2006-05-09 Bruno Haible + + * javacomp.m4 (gt_JAVACOMP): On Cygwin, set CLASSPATH_SEPARATOR to + a semicolon. Use CLASSPATH_SEPARATOR for the conftestver execution. + +2006-05-01 Bruno Haible + + * javacomp.m4 (gt_JAVACOMP): Accept a source-version and an optional + target-version argument. Verify that the compiler groks source of the + specified source-version, or add -source option as necessary. Verify + that the compiler produces bytecode in the specified target-version, + or add -target and -source options as necessary. Make the result of + the test available as variable CONF_JAVAC. Also log error output in + config.log. + +2006-03-11 Bruno Haible + + * javacomp.m4 (gt_JAVACOMP): Treat gcj-4.x like gcj-3.x. + 2006-05-09 Bruno Haible * javaexec.m4 (gt_JAVAEXEC): On Cygwin, set CLASSPATH_SEPARATOR to a diff --git a/m4/javacomp.m4 b/m4/javacomp.m4 index a180647a5..1cc7a1ca2 100644 --- a/m4/javacomp.m4 +++ b/m4/javacomp.m4 @@ -1,24 +1,352 @@ -# javacomp.m4 serial 6 (gettext-0.13) -dnl Copyright (C) 2001-2003 Free Software Foundation, Inc. +# javacomp.m4 serial 8 (gettext-0.15) +dnl Copyright (C) 2001-2003, 2006 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. # Prerequisites of javacomp.sh. -# Sets HAVE_JAVACOMP to nonempty if javacomp.sh will work. +# gt_JAVACOMP([source-version], [target-version]) +# Sets HAVE_JAVACOMP to nonempty if javacomp.sh will allow Java source code +# according to source-version to be compiled to Java bytecode classes in the +# target-version format. +# +# source-version can be: support for +# 1.3 inner classes +# 1.4 assert keyword +# 1.5 generic classes and methods +# 1.6 (not yet supported) +# +# target-version can be: classfile version: +# 1.1 45.3 +# 1.2 46.0 +# 1.3 47.0 +# 1.4 48.0 +# 1.5 49.0 +# 1.6 50.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". +# target-version can also be omitted. In this case, the required target-version +# is determined from the found JVM (see macro gt_JAVAEXEC): +# target-version for JVM +# 1.1 JDK 1.1, jview +# 1.2 JDK/JRE 1.2 +# 1.3 JDK/JRE 1.3, gij 3.3, 3.4 +# 1.4 JDK/JRE 1.4, gij 4.0, 4.1 +# 1.5 JDK/JRE 1.5 +# 1.6 JDK/JRE 1.6 +# Note: gij >= 3.3 can in some cases handle classes compiled with -target 1.4, +# and gij >= 4.1 can in some cases partially handle classes compiled with +# -target 1.5, but I have no idea how complete this support is. +# +# Specifying target-version is useful when building a library (.jar) that is +# useful outside the given package. Omitting target-version is useful when +# building an application. +# +# It is unreasonable to ask for: +# - target-version < 1.4 with source-version >= 1.4, or +# - target-version < 1.5 with source-version >= 1.5, or +# - target-version < 1.6 with source-version >= 1.6, +# because even Sun's javac doesn't support these combinations. +# +# It is redundant to ask for a target-version > source-version, since the +# smaller target-version = source-version will also always work and newer JVMs +# support the older target-versions too. Except for the case +# target-version = 1.4, source-version = 1.3, which allows gcj versions 3.0 +# to 3.2 to be used. AC_DEFUN([gt_JAVACOMP], [ - AC_MSG_CHECKING([for Java compiler]) + ifelse([$2], [], [AC_REQUIRE([gt_JAVAEXEC])], []) AC_EGREP_CPP(yes, [ -#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ +#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ yes #endif ], CLASSPATH_SEPARATOR=';', CLASSPATH_SEPARATOR=':') - HAVE_JAVACOMP=1 - if test -n "$JAVAC"; then - ac_result="$JAVAC" + source_version=$1 + test -n "$source_version" || { + AC_MSG_ERROR([missing source-version argument to gt_@&t@JAVACOMP]) + } + ifelse([$2], [], + [if test -n "$HAVE_JAVAEXEC"; then + dnl Use $CONF_JAVA to determine the JVM's version. +changequote(,)dnl + cat > conftestver.java <?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz' '\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\055\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' \ + > conftestver.class + target_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 + 1.1 | 1.2 | 1.3 | 1.4 | 1.5 | 1.6) ;; + null) + dnl JDK 1.1.X returns null. + target_version=1.1 ;; + *) AC_MSG_WARN([unknown target-version $target_version, please update gt_@&t@JAVACOMP macro]) + target_version=1.1 ;; + esac + else + target_version="1.1" + fi + ], + [target_version=$2]) + case "$source_version" in + 1.3) goodcode='class conftest {}' + failcode='class conftestfail { static { assert(true); } }' ;; + 1.4) goodcode='class conftest { static { assert(true); } }' + failcode='class conftestfail { T foo() { return null; } }' ;; + 1.5) goodcode='class conftest { T foo() { return null; } }' + failcode='class conftestfail syntax error' ;; + *) AC_MSG_ERROR([invalid source-version argument to gt_@&t@JAVACOMP: $source_version]) ;; + esac + case "$target_version" in + 1.1) cfversion=45 ;; + 1.2) cfversion=46 ;; + 1.3) cfversion=47 ;; + 1.4) cfversion=48 ;; + 1.5) cfversion=49 ;; + 1.6) cfversion=50 ;; + *) 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. + if od -A x < /dev/null >/dev/null 2>/dev/null; then + # Use POSIX od. + func_classfile_version () + { + od -A n -t d1 -j 7 -N 1 "[$]1" + } else + # Use BSD hexdump. + func_classfile_version () + { + dd if="[$]1" bs=1 count=1 skip=7 2>/dev/null | hexdump -e '1/1 "%3d "' + echo + } + fi + AC_MSG_CHECKING([for Java compiler]) + dnl + dnl The support of GNU gcj for target-version and source-version: + dnl + dnl gcj 3.0.4 to 4.1 does not have a way to specify the target-version. + dnl It always assumes target-version=1.4 but labels the class files as 1.1. + dnl One consequence of this is that gcj compiles GetURL.java to invalid + dnl bytecode, which crashes with a VerifyError when executed by Sun Java + dnl 1.3.1. The bug is registered as java/7066, see + dnl http://gcc.gnu.org/bugzilla/show_bug.cgi?id=7066 + dnl FIXME: Check new versions of gcj as they come out. + dnl + dnl For gcj < 3.3, the source-version always is 1.3. + dnl For gcj >= 3.3, the source-version defaults to 1.4; option + dnl "-fno-assert" switches to source-version 1.3. + dnl + dnl The support of Sun javac for target-version and source-version: + dnl + dnl javac 1.3: -target 1.1 1.2 1.3 default: 1.1 + dnl source always: 1.3 + dnl + dnl javac 1.4: -target 1.1 1.2 1.3 1.4 default: 1.2 + dnl -source 1.3 1.4 default: 1.3 + dnl -target 1.1/1.2/1.3 only possible with -source 1.3 or no -source + dnl + dnl javac 1.5: -target 1.1 1.2 1.3 1.4 1.5 default: 1.5 + dnl -source 1.3 1.4 1.5 default: 1.5 + dnl -target 1.1/1.2/1.3 only possible with -source 1.3 + dnl -target 1.4 only possible with -source 1.3/1.4 + dnl + dnl javac 1.6: -target 1.1 1.2 1.3 1.4 1.5 1.6 default: 1.6 + dnl -source 1.3 1.4 1.5 1.6 default: 1.5 + dnl -target 1.1/1.2/1.3 only possible with -source 1.3 + dnl -target 1.4 only possible with -source 1.3/1.4 + dnl -target 1.5 only possible with -source 1.3/1.4/1.5 or no -source + dnl + dnl The support of jikes for target-version and source-version: + dnl + dnl jikes 1.14 does not have a way to specify the target-version. It + dnl always assumes target-version=1.1. + dnl + dnl For jikes 1.14, the source-version always is 1.3. + dnl + CONF_JAVAC= + HAVE_JAVAC_ENVVAR= + HAVE_GCJ_C= + HAVE_JAVAC= + HAVE_JIKES= + HAVE_JAVACOMP= +changequote(,)dnl + cat > conftestlib.java < 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 the original $JAVAC. + if $JAVAC --version 2>/dev/null | sed -e 1q | grep gcj > /dev/null; then + dnl It's a version of gcj. Ignore the version of conftest.class. + if test "$target_version" = 1.4 && test "$source_version" = 1.4; 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; then + CONF_JAVAC="$JAVAC" + HAVE_JAVAC_ENVVAR=1 + HAVE_JAVACOMP=1 + fi + else + if test "$target_version" = 1.4 && test "$source_version" = 1.3; then + dnl Try $JAVAC and "$JAVAC -fno-assert". But add -fno-assert only if + dnl it makes a difference. (It could already be part of $JAVAC.) + javac_works= + 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; then + javac_works=1 + fi + javac_noassert_works= + rm -f conftest.class + if { echo "$as_me:__oline__: $JAVAC -fno-assert -d . conftest.java" >&AS_MESSAGE_LOG_FD + $JAVAC -fno-assert -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1 + } \ + && test -f conftest.class; then + javac_noassert_works=1 + fi + if test -n "$javac_works" && test -n "$javac_noassert_works"; then + rm -f conftestfail.class + if { 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 -fno-assert -d . conftestfail.java" >&AS_MESSAGE_LOG_FD + $JAVAC -fno-assert -d . conftestfail.java >&AS_MESSAGE_LOG_FD 2>&1 + }; then + dnl "$JAVAC -fno-assert" works better than $JAVAC. + javac_works= + fi + fi + if test -n "$javac_works"; then + CONF_JAVAC="$JAVAC" + HAVE_JAVAC_ENVVAR=1 + HAVE_JAVACOMP=1 + else + if test -n "$javac_noassert_works"; then + CONF_JAVAC="$JAVAC -fno-assert" + HAVE_JAVAC_ENVVAR=1 + HAVE_JAVACOMP=1 + fi + fi + fi + fi + else + dnl It's not gcj. Assume the classfile versions are correct. + 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 option alone. (Sun javac 1.3.1 has the -target + dnl option but no -source option.) + rm -f conftest.class + if { echo "$as_me:__oline__: $JAVAC -target $target_version -d . conftest.java" >&AS_MESSAGE_LOG_FD + $JAVAC -target "$target_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; then + dnl Try adding -source option if it is useful. + rm -f conftest.class + rm -f conftestfail.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 + } \ + && test -f conftest.class \ + && expr `func_classfile_version conftest.class` '<=' $cfversion >/dev/null 2>&AS_MESSAGE_LOG_FD \ + && { echo "$as_me:__oline__: $JAVAC -target $target_version -d . conftestfail.java" >&AS_MESSAGE_LOG_FD + $JAVAC -target "$target_version" -d . conftestfail.java >&AS_MESSAGE_LOG_FD 2>&1 + } \ + && test -f conftestfail.class \ + && ! { echo "$as_me:__oline__: $JAVAC -target $target_version -source $source_version -d . conftestfail.java" >&AS_MESSAGE_LOG_FD + $JAVAC -target "$target_version" -source "$source_version" -d . conftestfail.java >&AS_MESSAGE_LOG_FD 2>&1 + }; then + CONF_JAVAC="$JAVAC -target $target_version -source $source_version" + HAVE_JAVAC_ENVVAR=1 + HAVE_JAVACOMP=1 + else + CONF_JAVAC="$JAVAC -target $target_version" + HAVE_JAVAC_ENVVAR=1 + HAVE_JAVACOMP=1 + fi + else + dnl Maybe this -target option requires a -source option? Try with + dnl -target and -source options. (Supported by Sun javac 1.4 and + dnl higher.) + 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 + } \ + && 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 + 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 @@ -28,70 +356,175 @@ AC_DEFUN([gt_JAVACOMP], popdef([AC_MSG_RESULT])dnl popdef([AC_CHECKING])dnl popdef([AC_MSG_CHECKING])dnl + if test -z "$HAVE_JAVACOMP" && test -n "$HAVE_GCJ_IN_PATH"; then + dnl Test for a good gcj version (>= 3.0). changequote(,)dnl - # Test for a good gcj version (>= 3.0). - # Exclude some versions of gcj: gcj 3.0.4 compiles GetURL.java to invalid - # bytecode, that crashes with an IllegalAccessError when executed by - # gij 3.0.4 or with a VerifyError when executed by Sun Java. Likewise for - # gcj 3.1. - # I also exclude gcj 3.2, 3.3 etc. because I have no idea when this bug - # will be fixed. The bug is registered as java/7066, see - # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=7066 - # FIXME: Check new versions of gcj as they come out. - if test -n "$HAVE_GCJ_IN_PATH" \ - && gcj --version 2>/dev/null | sed -e 's,^[^0-9]*,,' -e 1q | sed -e '/^3\.[0123456789]/d' | grep '^[3-9]' >/dev/null \ - && ( - # See if libgcj.jar is well installed. - cat > conftest.java </dev/null - error=$? - rm -f conftest.java conftest.class - exit $error - ); then - HAVE_GCJ_C=1 - ac_result="gcj -C" - else - if test -n "$HAVE_JAVAC_IN_PATH" \ - && (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 - HAVE_JAVAC=1 - ac_result="javac" - else - if test -n "$HAVE_JIKES_IN_PATH" \ - && (jikes >/dev/null 2>/dev/null || test $? = 1) \ - && ( - # See if the existing CLASSPATH is sufficient to make jikes work. - cat > conftest.java </dev/null - error=$? - rm -f conftest.java conftest.class - exit $error - ); then - HAVE_JIKES=1 - ac_result="jikes" + if gcj --version 2>/dev/null | sed -e 's,^[^0-9]*,,' -e 1q | sed -e '/^3\.[01]/d' | grep '^[3-9]' >/dev/null; then +changequote([,])dnl + dnl See if libgcj.jar is well installed. + if { echo "$as_me:__oline__: gcj -C -d . conftestlib.java" >&AS_MESSAGE_LOG_FD + gcj -C -d . conftestlib.java >&AS_MESSAGE_LOG_FD 2>&1 + }; then + dnl OK, gcj works. + dnl Now test whether it supports the desired target-version and + dnl source-version. But ignore the version of conftest.class. + if test "$target_version" = 1.4 && test "$source_version" = 1.4; then + rm -f conftest.class + if { echo "$as_me:__oline__: gcj -C -d . conftest.java" >&AS_MESSAGE_LOG_FD + gcj -C -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1 + } \ + && test -f conftest.class; then + CONF_JAVAC="gcj -C" + HAVE_GCJ_C=1 + HAVE_JAVACOMP=1 + fi + else + if test "$target_version" = 1.4 && test "$source_version" = 1.3; then + dnl Try gcj and "gcj -fno-assert". But add -fno-assert only if + dnl it works (not gcj < 3.3). + rm -f conftest.class + if { echo "$as_me:__oline__: gcj -C -fno-assert -d . conftest.java" >&AS_MESSAGE_LOG_FD + gcj -C -fno-assert -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1 + } \ + && test -f conftest.class; then + CONF_JAVAC="gcj -C -fno-assert" + HAVE_GCJ_C=1 + HAVE_JAVACOMP=1 + else + rm -f conftest.class + if { echo "$as_me:__oline__: gcj -C -d . conftest.java" >&AS_MESSAGE_LOG_FD + gcj -C -d . conftest.java >&AS_MESSAGE_LOG_FD 2>&1 + } \ + && test -f conftest.class; then + CONF_JAVAC="gcj -C" + HAVE_GCJ_C=1 + HAVE_JAVACOMP=1 + fi + fi + fi + fi + fi + fi + fi + 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. + 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 + else + CONF_JAVAC="javac" + HAVE_JAVAC=1 + HAVE_JAVACOMP=1 + fi else - HAVE_JAVACOMP= - ac_result="no" + dnl Try with -target option alone. (Sun javac 1.3.1 has the -target + dnl option but no -source option.) + rm -f conftest.class + if { echo "$as_me:__oline__: javac -target $target_version -d . conftest.java" >&AS_MESSAGE_LOG_FD + javac -target "$target_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; then + dnl Try adding -source option if it is useful. + rm -f conftest.class + rm -f conftestfail.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 + } \ + && test -f conftest.class \ + && expr `func_classfile_version conftest.class` '<=' $cfversion >/dev/null 2>&AS_MESSAGE_LOG_FD \ + && { echo "$as_me:__oline__: javac -target $target_version -d . conftestfail.java" >&AS_MESSAGE_LOG_FD + javac -target "$target_version" -d . conftestfail.java >&AS_MESSAGE_LOG_FD 2>&1 + } \ + && test -f conftestfail.class \ + && ! { echo "$as_me:__oline__: javac -target $target_version -source $source_version -d . conftestfail.java" >&AS_MESSAGE_LOG_FD + javac -target "$target_version" -source "$source_version" -d . conftestfail.java >&AS_MESSAGE_LOG_FD 2>&1 + }; then + CONF_JAVAC="javac -target $target_version -source $source_version" + HAVE_JAVAC=1 + HAVE_JAVACOMP=1 + else + CONF_JAVAC="javac -target $target_version" + HAVE_JAVAC=1 + HAVE_JAVACOMP=1 + fi + else + dnl Maybe this -target option requires a -source option? Try with + dnl -target and -source options. (Supported by Sun javac 1.4 and + dnl higher.) + 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 + } \ + && 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=1 + HAVE_JAVACOMP=1 + fi + fi fi fi fi -changequote([,])dnl + if test -z "$HAVE_JAVACOMP" && test -n "$HAVE_JIKES_IN_PATH"; then + dnl Test whether jikes is usable. + if { jikes >/dev/null 2>/dev/null || test $? = 1; } \ + && ( + # See if the existing CLASSPATH is sufficient to make jikes work. + unset JAVA_HOME + jikes conftestlib.java >&AS_MESSAGE_LOG_FD 2>&1 + error=$? + rm -f conftestlib.class + exit $error + ); then + dnl OK, jikes works. + dnl Now test whether it supports the desired target-version and + dnl source-version. + if test "$source_version" = 1.3; then + CONF_JAVAC="jikes" + HAVE_JIKES=1 + HAVE_JAVACOMP=1 + fi + fi + fi + fi + rm -f conftest*.java conftest*.class + if test -n "$HAVE_JAVACOMP"; then + ac_result="$CONF_JAVAC" + else + ac_result="no" fi AC_MSG_RESULT([$ac_result]) - AC_SUBST(JAVAC) + AC_SUBST(CONF_JAVAC) AC_SUBST(CLASSPATH) AC_SUBST(CLASSPATH_SEPARATOR) + AC_SUBST(HAVE_JAVAC_ENVVAR) AC_SUBST(HAVE_GCJ_C) AC_SUBST(HAVE_JAVAC) AC_SUBST(HAVE_JIKES)