changeset 39287:aa7bb6bee927

javacomp-script, javacomp: Fix support for Java 7, 8, 9. * lib/javaversion.h: Update comments. * lib/javacomp.h: Likewise. * lib/javacomp.c (default_target_version, source_version_index, get_goodcode_snippet, get_failcode_snippet): Recognize "9" instead of "1.9". (TARGET_VERSION_BOUND): Bump to 9. (target_version_index, corresponding_classfile_version): Recognize "9" instead of "1.9". (get_source_version_for_javac): New function. (is_envjavac_nongcj_usable, is_javac_usable): Add source_version_for_javac argument. (compile_java_class): Determine and pass source_version_for_javac. * m4/javacomp.m4: Recognize version '9' instead of '1.9'. When invoking $JAVAC or javac, pass '-source 1.6' instead of '-source 1.5' when appropriate.
author Bruno Haible <bruno@clisp.org>
date Sat, 24 Mar 2018 12:54:42 +0100
parents 40f32a4011b4
children f4ca00710ecf
files ChangeLog lib/javacomp.c lib/javacomp.h lib/javaversion.h m4/javacomp.m4
diffstat 5 files changed, 129 insertions(+), 52 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Fri Mar 23 16:46:13 2018 -0700
+++ b/ChangeLog	Sat Mar 24 12:54:42 2018 +0100
@@ -1,3 +1,22 @@
+2018-03-24  Bruno Haible  <bruno@clisp.org>
+
+	javacomp-script, javacomp: Fix support for Java 7, 8, 9.
+	* lib/javaversion.h: Update comments.
+	* lib/javacomp.h: Likewise.
+	* lib/javacomp.c (default_target_version, source_version_index,
+	get_goodcode_snippet, get_failcode_snippet): Recognize "9" instead of
+	"1.9".
+	(TARGET_VERSION_BOUND): Bump to 9.
+	(target_version_index, corresponding_classfile_version): Recognize "9"
+	instead of "1.9".
+	(get_source_version_for_javac): New function.
+	(is_envjavac_nongcj_usable, is_javac_usable): Add
+	source_version_for_javac argument.
+	(compile_java_class): Determine and pass source_version_for_javac.
+	* m4/javacomp.m4: Recognize version '9' instead of '1.9'. When invoking
+	$JAVAC or javac, pass '-source 1.6' instead of '-source 1.5' when
+	appropriate.
+
 2018-03-23  Jim Meyering  <meyering@fb.com>
 
 	test-version-etc.sh: port to diff without -c
--- a/lib/javacomp.c	Fri Mar 23 16:46:13 2018 -0700
+++ b/lib/javacomp.c	Sat Mar 24 12:54:42 2018 +0100
@@ -99,9 +99,12 @@
       /* 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] <= '9')
-               && java_version_cache[3] == '\0'))
+          || !((java_version_cache[0] == '1'
+                && java_version_cache[1] == '.'
+                && java_version_cache[2] >= '1' && java_version_cache[2] <= '8'
+                && java_version_cache[3] == '\0')
+               || (java_version_cache[0] == '9'
+                   && java_version_cache[1] == '\0')))
         java_version_cache = "1.1";
     }
   return java_version_cache;
@@ -119,10 +122,12 @@
       if ((source_version[2] >= '3' && source_version[2] <= '5')
           && source_version[3] == '\0')
         return source_version[2] - '3';
-      if ((source_version[2] >= '7' && source_version[2] <= '9')
+      if ((source_version[2] >= '7' && source_version[2] <= '8')
           && source_version[3] == '\0')
         return source_version[2] - '4';
     }
+  else if (source_version[0] == '9' && source_version[1] == '\0')
+    return 5;
   error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
   return 0;
 }
@@ -141,7 +146,7 @@
     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, "1.9") == 0)
+  if (strcmp (source_version, "9") == 0)
     return "interface conftest { private void foo () {} }\n";
   error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
   return NULL;
@@ -163,7 +168,7 @@
     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, "1.9") == 0)
+  if (strcmp (source_version, "9") == 0)
     return NULL;
   error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
   return NULL;
@@ -172,14 +177,16 @@
 /* ======================= Target version dependent ======================= */
 
 /* Convert a target version to an index.  */
-#define TARGET_VERSION_BOUND 6 /* exclusive upper bound */
+#define TARGET_VERSION_BOUND 9 /* 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[2] >= '1' && target_version[2] <= '8')
       && target_version[3] == '\0')
     return target_version[2] - '1';
+  else if (target_version[0] == '9' && target_version[1] == '\0')
+    return 8;
   error (EXIT_FAILURE, 0, _("invalid target_version argument to compile_java_class"));
   return 0;
 }
@@ -205,12 +212,28 @@
     return 51;
   if (strcmp (target_version, "1.8") == 0)
     return 52;
-  if (strcmp (target_version, "1.9") == 0)
+  if (strcmp (target_version, "9") == 0)
     return 53;
   error (EXIT_FAILURE, 0, _("invalid target_version argument to compile_java_class"));
   return 0;
 }
 
+/* Return the source version to pass to javac.  */
+static const char *
+get_source_version_for_javac (const char *source_version,
+                              const char *target_version)
+{
+  /* The javac option '-source 1.5' has the same meaning as '-source 1.6',
+     but since Java 9 supports only the latter, prefer the latter if a
+     target_version >= 1.6 is requested.  */
+  if (strcmp (source_version, "1.5") == 0
+      && !(target_version[0] == '1' && target_version[1] == '.'
+           && (target_version[2] >= '1' && target_version[2] <= '5')
+           && target_version[3] == '\0'))
+    return "1.6";
+  return source_version;
+}
+
 /* ======================== Compilation subroutines ======================== */
 
 /* Try to compile a set of Java sources with $JAVAC.
@@ -1081,6 +1104,7 @@
 static bool
 is_envjavac_nongcj_usable (const char *javac,
                            const char *source_version,
+                           const char *source_version_for_javac,
                            const char *target_version,
                            bool *usablep,
                            bool *source_option_p, bool *target_option_p)
@@ -1136,7 +1160,7 @@
           /* $JAVAC compiled conftest.java successfully.  */
           /* Try adding -source option if it is useful.  */
           char *javac_source =
-            xasprintf ("%s -source %s", javac, source_version);
+            xasprintf ("%s -source %s", javac, source_version_for_javac);
 
           unlink (compiled_file_name);
 
@@ -1188,8 +1212,8 @@
                                                   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.  */
+                           "$JAVAC -source $source_version_for_javac" rejects it.
+                           So the -source option is useful.  */
                         resultp->source_option = true;
                     }
                 }
@@ -1220,7 +1244,7 @@
                  successfully.  */
               /* Try adding -source option if it is useful.  */
               char *javac_target_source =
-                xasprintf ("%s -source %s", javac_target, source_version);
+                xasprintf ("%s -source %s", javac_target, source_version_for_javac);
 
               unlink (compiled_file_name);
 
@@ -1276,7 +1300,7 @@
                                                       true))
                             /* "$JAVAC -target $target_version" compiled
                                conftestfail.java successfully, and
-                               "$JAVAC -target $target_version -source $source_version"
+                               "$JAVAC -target $target_version -source $source_version_for_javac"
                                rejects it.  So the -source option is useful.  */
                             resultp->source_option = true;
                         }
@@ -1294,7 +1318,7 @@
                  -target and -source options. (Supported by Sun javac 1.4 and
                  higher.)  */
               char *javac_target_source =
-                xasprintf ("%s -source %s", javac_target, source_version);
+                xasprintf ("%s -source %s", javac_target, source_version_for_javac);
 
               unlink (compiled_file_name);
 
@@ -1306,7 +1330,7 @@
                   && get_classfile_version (compiled_file_name)
                      <= corresponding_classfile_version (target_version))
                 {
-                  /* "$JAVAC -target $target_version -source $source_version"
+                  /* "$JAVAC -target $target_version -source $source_version_for_javac"
                      compiled conftest.java successfully.  */
                   resultp->source_option = true;
                   resultp->target_option = true;
@@ -1826,7 +1850,9 @@
    -target option.
    Return a failure indicator (true upon error).  */
 static bool
-is_javac_usable (const char *source_version, const char *target_version,
+is_javac_usable (const char *source_version,
+                 const char *source_version_for_javac,
+                 const char *target_version,
                  bool *usablep, bool *source_option_p, bool *target_option_p)
 {
   /* The cache depends on the source_version and target_version.  */
@@ -1871,7 +1897,7 @@
 
       java_sources[0] = conftest_file_name;
       if (!compile_using_javac (java_sources, 1,
-                                false, source_version,
+                                false, source_version_for_javac,
                                 false, target_version,
                                 tmpdir->dir_name, false, false, false, true)
           && stat (compiled_file_name, &statbuf) >= 0
@@ -1884,7 +1910,7 @@
 
           java_sources[0] = conftest_file_name;
           if (!compile_using_javac (java_sources, 1,
-                                    true, source_version,
+                                    true, source_version_for_javac,
                                     false, target_version,
                                     tmpdir->dir_name, false, false, false, true)
               && stat (compiled_file_name, &statbuf) >= 0
@@ -1917,7 +1943,7 @@
 
                   java_sources[0] = conftest_file_name;
                   if (!compile_using_javac (java_sources, 1,
-                                            false, source_version,
+                                            false, source_version_for_javac,
                                             false, target_version,
                                             tmpdir->dir_name,
                                             false, false, false, true)
@@ -1927,13 +1953,13 @@
 
                       java_sources[0] = conftest_file_name;
                       if (compile_using_javac (java_sources, 1,
-                                               true, source_version,
+                                               true, source_version_for_javac,
                                                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.  */
+                           "javac -source $source_version_for_javac" rejects it.
+                           So the -source option is useful.  */
                         resultp->source_option = true;
                     }
                 }
@@ -1949,7 +1975,7 @@
 
           java_sources[0] = conftest_file_name;
           if (!compile_using_javac (java_sources, 1,
-                                    false, source_version,
+                                    false, source_version_for_javac,
                                     true, target_version,
                                     tmpdir->dir_name,
                                     false, false, false, true)
@@ -1964,7 +1990,7 @@
 
               java_sources[0] = conftest_file_name;
               if (!compile_using_javac (java_sources, 1,
-                                        true, source_version,
+                                        true, source_version_for_javac,
                                         true, target_version,
                                         tmpdir->dir_name,
                                         false, false, false, true)
@@ -1999,7 +2025,7 @@
 
                       java_sources[0] = conftest_file_name;
                       if (!compile_using_javac (java_sources, 1,
-                                                false, source_version,
+                                                false, source_version_for_javac,
                                                 true, target_version,
                                                 tmpdir->dir_name,
                                                 false, false, false, true)
@@ -2009,13 +2035,13 @@
 
                           java_sources[0] = conftest_file_name;
                           if (compile_using_javac (java_sources, 1,
-                                                   true, source_version,
+                                                   true, source_version_for_javac,
                                                    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"
+                               "javac -target $target_version -source $source_version_for_javac"
                                rejects it.  So the -source option is useful.  */
                             resultp->source_option = true;
                         }
@@ -2034,7 +2060,7 @@
 
               java_sources[0] = conftest_file_name;
               if (!compile_using_javac (java_sources, 1,
-                                        true, source_version,
+                                        true, source_version_for_javac,
                                         true, target_version,
                                         tmpdir->dir_name,
                                         false, false, false, true)
@@ -2042,7 +2068,7 @@
                   && get_classfile_version (compiled_file_name)
                      <= corresponding_classfile_version (target_version))
                 {
-                  /* "javac -target $target_version -source $source_version"
+                  /* "javac -target $target_version -source $source_version_for_javac"
                      compiled conftest.java successfully.  */
                   resultp->source_option = true;
                   resultp->target_option = true;
@@ -2113,10 +2139,14 @@
         bool target_option = false;
         bool fsource_option = false;
         bool ftarget_option = false;
+        const char *source_version_for_javac;
 
         if (target_version == NULL)
           target_version = default_target_version ();
 
+        source_version_for_javac =
+          get_source_version_for_javac (source_version, target_version);
+
         if (is_envjavac_gcj (javac))
           {
             /* It's a version of gcj.  */
@@ -2163,7 +2193,9 @@
           {
             /* It's not gcj.  Assume the classfile versions are correct.  */
             if (is_envjavac_nongcj_usable (javac,
-                                           source_version, target_version,
+                                           source_version,
+                                           source_version_for_javac,
+                                           target_version,
                                            &usable,
                                            &source_option, &target_option))
               {
@@ -2187,7 +2219,7 @@
                : xasprintf ("%s%s%s%s%s%s%s%s%s",
                             javac,
                             source_option ? " -source " : "",
-                            source_option ? source_version : "",
+                            source_option ? source_version_for_javac : "",
                             target_option ? " -target " : "",
                             target_option ? target_version : "",
                             fsource_option ? " -fsource=" : "",
@@ -2296,11 +2328,16 @@
       bool usable = false;
       bool source_option = false;
       bool target_option = false;
+      const char *source_version_for_javac;
 
       if (target_version == NULL)
         target_version = default_target_version ();
 
-      if (is_javac_usable (source_version, target_version,
+      source_version_for_javac =
+        get_source_version_for_javac (source_version, target_version);
+
+      if (is_javac_usable (source_version, source_version_for_javac,
+                           target_version,
                            &usable, &source_option, &target_option))
         {
           err = true;
@@ -2320,7 +2357,7 @@
                            verbose);
 
           err = compile_using_javac (java_sources, java_sources_count,
-                                     source_option, source_version,
+                                     source_option, source_version_for_javac,
                                      target_option, target_version,
                                      directory, optimize, debug, verbose,
                                      false);
--- a/lib/javacomp.h	Fri Mar 23 16:46:13 2018 -0700
+++ b/lib/javacomp.h	Sat Mar 24 12:54:42 2018 +0100
@@ -31,7 +31,7 @@
              1.6             (not supported)
              1.7             switch(string)
              1.8             lambdas
-             1.9             private interface methods
+             9               private interface methods
    target_version can be:  classfile version:
              1.1                 45.3
              1.2                 46.0
@@ -41,7 +41,7 @@
              1.6                 50.0
              1.7                 51.0
              1.8                 52.0
-             1.9                 53.0
+             9                   53.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
@@ -53,7 +53,7 @@
      - target_version < 1.6 with source_version >= 1.6, or
      - target_version < 1.7 with source_version >= 1.7, or
      - target_version < 1.8 with source_version >= 1.8, or
-     - target_version < 1.9 with source_version >= 1.9,
+     - target_version < 9 with source_version >= 9,
    because even Sun's/Oracle'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
--- a/lib/javaversion.h	Fri Mar 23 16:46:13 2018 -0700
+++ b/lib/javaversion.h	Sat Mar 24 12:54:42 2018 +0100
@@ -26,8 +26,8 @@
 
 /* Return information about the Java version used by execute_java_class().
    This is the value of System.getProperty("java.specification.version").
-   Some possible values are: 1.1, 1.2, 1.3, 1.4, 1.5, 1.6.  Return NULL if
-   the Java version cannot be determined.  */
+   Some possible values are: 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 9.
+   Return NULL if the Java version cannot be determined.  */
 extern char * javaexec_version (void);
 
 
--- a/m4/javacomp.m4	Fri Mar 23 16:46:13 2018 -0700
+++ b/m4/javacomp.m4	Sat Mar 24 12:54:42 2018 +0100
@@ -18,7 +18,7 @@
 #           1.6             (not supported)
 #           1.7             switch(string)
 #           1.8             lambdas
-#           1.9             private interface methods
+#           9               private interface methods
 # Instead of source-version 1.6, use 1.5, since Java 6 did not introduce any
 # language changes. See
 # https://docs.oracle.com/javase/8/docs/technotes/guides/language/enhancements.html
@@ -32,7 +32,7 @@
 #           1.6                 50.0
 #           1.7                 51.0
 #           1.8                 52.0
-#           1.9                 53.0
+#           9                   53.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".
@@ -43,11 +43,11 @@
 #           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
-#           1.7         JDK/JRE 1.7
-#           1.8         JDK/JRE 1.8
-#           1.9         JDK/JRE 1.9
+#           1.5         JDK/JRE 5
+#           1.6         JDK/JRE 6
+#           1.7         JDK/JRE 7
+#           1.8         JDK/JRE 8
+#           9           JDK/JRE 9
 # 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.
@@ -59,7 +59,10 @@
 # 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,
+#   - target_version < 1.6 with source_version >= 1.6, or
+#   - target_version < 1.7 with source_version >= 1.7, or
+#   - target_version < 1.8 with source_version >= 1.8, or
+#   - target_version < 9 with source_version >= 9,
 # because even Sun's/Oracle's javac doesn't support these combinations.
 #
 # It is redundant to ask for a target-version > source-version, since the
@@ -111,7 +114,7 @@
          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 | 1.7 | 1.8 | 1.9) ;;
+         1.1 | 1.2 | 1.3 | 1.4 | 1.5 | 1.6 | 1.7 | 1.8 | 9) ;;
          null)
            dnl JDK 1.1.X returns null.
            target_version=1.1 ;;
@@ -134,7 +137,7 @@
          failcode='class conftestfail { void foo () { Runnable r = () -> {}; } }' ;;
     1.8) goodcode='class conftest     { void foo () { Runnable r = () -> {}; } }'
          failcode='interface conftestfail { private void foo () {} }' ;;
-    1.9) goodcode='interface conftest     { private void foo () {} }'
+    9)   goodcode='interface conftest     { private void foo () {} }'
          failcode='class conftestfail syntax error' ;;
     *) AC_MSG_ERROR([invalid source-version argument to gt_@&t@JAVACOMP: $source_version]) ;;
   esac
@@ -147,7 +150,7 @@
     1.6) cfversion=50 ;;
     1.7) cfversion=51 ;;
     1.8) cfversion=52 ;;
-    1.9) cfversion=53 ;;
+    9)   cfversion=53 ;;
     *) 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.
@@ -217,8 +220,8 @@
   dnl                -target 1.6 only possible with -source 1.3/1.4/1.5/1.6
   dnl                -target 1.7 only possible with -source 1.3/1.4/1.5/1.6/1.7
   dnl
-  dnl   javac 1.9:   -target 1.6 1.7 1.8 1.9  default: 1.9
-  dnl                -source 1.6 1.7 1.8 1.9  default: 1.9
+  dnl   javac 9:     -target 1.6 1.7 1.8 9  default: 9
+  dnl                -source 1.6 1.7 1.8 9  default: 9
   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
@@ -364,6 +367,15 @@
     else
       dnl It's not gcj. Assume the classfile versions are correct.
       dnl Try $JAVAC.
+      dnl The javac option '-source 1.5' has the same meaning as '-source 1.6',
+      dnl but since Java 9 supports only the latter, prefer the latter if a
+      dnl target_version >= 1.6 is requested.
+      if test "$source_version" = 1.5; then
+        case "$target_version" in
+          1.1 | 1.2 | 1.3 | 1.4 | 1.5) ;;
+          *) source_version='1.6' ;;
+        esac
+      fi
       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
@@ -559,6 +571,15 @@
       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 The javac option '-source 1.5' has the same meaning as '-source 1.6',
+        dnl but since Java 9 supports only the latter, prefer the latter if a
+        dnl target_version >= 1.6 is requested.
+        if test "$source_version" = 1.5; then
+          case "$target_version" in
+            1.1 | 1.2 | 1.3 | 1.4 | 1.5) ;;
+            *) source_version='1.6' ;;
+          esac
+        fi
         dnl Now test whether it supports the desired target-version and
         dnl source-version.
         rm -f conftest.class