1 /* Compile a Java program.
2 Copyright (C) 2001-2003, 2006-2016 Free Software Foundation, Inc.
3 Written by Bruno Haible <haible@clisp.cons.org>, 2001.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
30 #include <sys/types.h>
33 #include "javaversion.h"
35 #include "spawn-pipe.h"
36 #include "wait-process.h"
37 #include "classpath.h"
40 #include "binary-io.h"
41 #include "safe-read.h"
44 #include "concat-filename.h"
45 #include "fwriteerror.h"
46 #include "clean-temp.h"
48 #include "xvasprintf.h"
52 #define _(str) gettext (str)
55 /* Survey of Java compilers.
57 A = does it work without CLASSPATH being set
58 C = option to set CLASSPATH, other than setting it in the environment
59 O = option for optimizing
60 g = option for debugging
63 Program from A C O g T
65 $JAVAC unknown N n/a -O -g true
66 gcj -C GCC 3.2 Y --classpath=P -O -g gcj --version | sed -e 's,^[^0-9]*,,' -e 1q | sed -e '/^3\.[01]/d' | grep '^[3-9]' >/dev/null
67 javac JDK 1.1.8 Y -classpath P -O -g javac 2>/dev/null; test $? = 1
68 javac JDK 1.3.0 Y -classpath P -O -g javac 2>/dev/null; test $? -le 2
69 jikes Jikes 1.14 N -classpath P -O -g jikes 2>/dev/null; test $? = 1
71 All compilers support the option "-d DIRECTORY" for the base directory
72 of the classes to be written.
74 The CLASSPATH is a colon separated list of pathnames. (On Windows: a
75 semicolon separated list of pathnames.)
77 We try the Java compilers in the following order:
78 1. getenv ("JAVAC"), because the user must be able to override our
80 2. "gcj -C", because it is a completely free compiler,
81 3. "javac", because it is a standard compiler,
82 4. "jikes", comes last because it has some deviating interpretation
83 of the Java Language Specification and because it requires a
84 CLASSPATH environment variable.
86 We unset the JAVA_HOME environment variable, because a wrong setting of
87 this variable can confuse the JDK's javac.
90 /* Return the default target_version. */
92 default_target_version (void)
94 /* Use a cache. Assumes that the PATH environment variable doesn't change
95 during the lifetime of the program. */
96 static const char *java_version_cache;
97 if (java_version_cache == NULL)
99 /* Determine the version from the found JVM. */
100 java_version_cache = javaexec_version ();
101 if (java_version_cache == NULL
102 || !(java_version_cache[0] == '1' && java_version_cache[1] == '.'
103 && (java_version_cache[2] >= '1' && java_version_cache[2] <= '6')
104 && java_version_cache[3] == '\0'))
105 java_version_cache = "1.1";
107 return java_version_cache;
110 /* ======================= Source version dependent ======================= */
112 /* Convert a source version to an index. */
113 #define SOURCE_VERSION_BOUND 3 /* exclusive upper bound */
115 source_version_index (const char *source_version)
117 if (source_version[0] == '1' && source_version[1] == '.'
118 && (source_version[2] >= '3' && source_version[2] <= '5')
119 && source_version[3] == '\0')
120 return source_version[2] - '3';
121 error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
125 /* Return a snippet of code that should compile in the given source version. */
127 get_goodcode_snippet (const char *source_version)
129 if (strcmp (source_version, "1.3") == 0)
130 return "class conftest {}\n";
131 if (strcmp (source_version, "1.4") == 0)
132 return "class conftest { static { assert(true); } }\n";
133 if (strcmp (source_version, "1.5") == 0)
134 return "class conftest<T> { T foo() { return null; } }\n";
135 error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
139 /* Return a snippet of code that should fail to compile in the given source
140 version, or NULL (standing for a snippet that would fail to compile with
143 get_failcode_snippet (const char *source_version)
145 if (strcmp (source_version, "1.3") == 0)
146 return "class conftestfail { static { assert(true); } }\n";
147 if (strcmp (source_version, "1.4") == 0)
148 return "class conftestfail<T> { T foo() { return null; } }\n";
149 if (strcmp (source_version, "1.5") == 0)
151 error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
155 /* ======================= Target version dependent ======================= */
157 /* Convert a target version to an index. */
158 #define TARGET_VERSION_BOUND 6 /* exclusive upper bound */
160 target_version_index (const char *target_version)
162 if (target_version[0] == '1' && target_version[1] == '.'
163 && (target_version[2] >= '1' && target_version[2] <= '6')
164 && target_version[3] == '\0')
165 return target_version[2] - '1';
166 error (EXIT_FAILURE, 0, _("invalid target_version argument to compile_java_class"));
170 /* Return the class file version number corresponding to a given target
173 corresponding_classfile_version (const char *target_version)
175 if (strcmp (target_version, "1.1") == 0)
177 if (strcmp (target_version, "1.2") == 0)
179 if (strcmp (target_version, "1.3") == 0)
181 if (strcmp (target_version, "1.4") == 0)
183 if (strcmp (target_version, "1.5") == 0)
185 if (strcmp (target_version, "1.6") == 0)
187 error (EXIT_FAILURE, 0, _("invalid target_version argument to compile_java_class"));
191 /* ======================== Compilation subroutines ======================== */
193 /* Try to compile a set of Java sources with $JAVAC.
194 Return a failure indicator (true upon error). */
196 compile_using_envjavac (const char *javac,
197 const char * const *java_sources,
198 unsigned int java_sources_count,
199 const char *directory,
200 bool optimize, bool debug,
201 bool verbose, bool null_stderr)
203 /* Because $JAVAC may consist of a command and options, we use the
204 shell. Because $JAVAC has been set by the user, we leave all
205 environment variables in place, including JAVA_HOME, and we don't
206 erase the user's CLASSPATH. */
208 unsigned int command_length;
215 command_length = strlen (javac);
220 if (directory != NULL)
221 command_length += 4 + shell_quote_length (directory);
222 for (i = 0; i < java_sources_count; i++)
223 command_length += 1 + shell_quote_length (java_sources[i]);
226 command = (char *) xmalloca (command_length);
228 /* Don't shell_quote $JAVAC, because it may consist of a command
230 memcpy (p, javac, strlen (javac));
234 memcpy (p, " -O", 3);
239 memcpy (p, " -g", 3);
242 if (directory != NULL)
244 memcpy (p, " -d ", 4);
246 p = shell_quote_copy (p, directory);
248 for (i = 0; i < java_sources_count; i++)
251 p = shell_quote_copy (p, java_sources[i]);
254 /* Ensure command_length was correctly calculated. */
255 if (p - command > command_length)
259 printf ("%s\n", command);
265 exitstatus = execute (javac, "/bin/sh", argv, false, false, false,
266 null_stderr, true, true, NULL);
267 err = (exitstatus != 0);
274 /* Try to compile a set of Java sources with gcj.
275 Return a failure indicator (true upon error). */
277 compile_using_gcj (const char * const *java_sources,
278 unsigned int java_sources_count,
279 bool no_assert_option,
280 bool fsource_option, const char *source_version,
281 bool ftarget_option, const char *target_version,
282 const char *directory,
283 bool optimize, bool debug,
284 bool verbose, bool null_stderr)
296 2 + (no_assert_option ? 1 : 0) + (fsource_option ? 1 : 0)
297 + (ftarget_option ? 1 : 0) + (optimize ? 1 : 0) + (debug ? 1 : 0)
298 + (directory != NULL ? 2 : 0) + java_sources_count;
299 argv = (char **) xmalloca ((argc + 1) * sizeof (char *));
304 if (no_assert_option)
305 *argp++ = "-fno-assert";
308 fsource_arg = (char *) xmalloca (9 + strlen (source_version) + 1);
309 memcpy (fsource_arg, "-fsource=", 9);
310 strcpy (fsource_arg + 9, source_version);
311 *argp++ = fsource_arg;
317 ftarget_arg = (char *) xmalloca (9 + strlen (target_version) + 1);
318 memcpy (ftarget_arg, "-ftarget=", 9);
319 strcpy (ftarget_arg + 9, target_version);
320 *argp++ = ftarget_arg;
328 if (directory != NULL)
331 *argp++ = (char *) directory;
333 for (i = 0; i < java_sources_count; i++)
334 *argp++ = (char *) java_sources[i];
336 /* Ensure argv length was correctly calculated. */
337 if (argp - argv != argc)
342 char *command = shell_quote_argv (argv);
343 printf ("%s\n", command);
347 exitstatus = execute ("gcj", "gcj", argv, false, false, false, null_stderr,
349 err = (exitstatus != 0);
351 if (ftarget_arg != NULL)
353 if (fsource_arg != NULL)
360 /* Try to compile a set of Java sources with javac.
361 Return a failure indicator (true upon error). */
363 compile_using_javac (const char * const *java_sources,
364 unsigned int java_sources_count,
365 bool source_option, const char *source_version,
366 bool target_option, const char *target_version,
367 const char *directory,
368 bool optimize, bool debug,
369 bool verbose, bool null_stderr)
379 1 + (source_option ? 2 : 0) + (target_option ? 2 : 0) + (optimize ? 1 : 0)
380 + (debug ? 1 : 0) + (directory != NULL ? 2 : 0) + java_sources_count;
381 argv = (char **) xmalloca ((argc + 1) * sizeof (char *));
388 *argp++ = (char *) source_version;
393 *argp++ = (char *) target_version;
399 if (directory != NULL)
402 *argp++ = (char *) directory;
404 for (i = 0; i < java_sources_count; i++)
405 *argp++ = (char *) java_sources[i];
407 /* Ensure argv length was correctly calculated. */
408 if (argp - argv != argc)
413 char *command = shell_quote_argv (argv);
414 printf ("%s\n", command);
418 exitstatus = execute ("javac", "javac", argv, false, false, false,
419 null_stderr, true, true, NULL);
420 err = (exitstatus != 0);
427 /* Try to compile a set of Java sources with jikes.
428 Return a failure indicator (true upon error). */
430 compile_using_jikes (const char * const *java_sources,
431 unsigned int java_sources_count,
432 const char *directory,
433 bool optimize, bool debug,
434 bool verbose, bool null_stderr)
444 1 + (optimize ? 1 : 0) + (debug ? 1 : 0) + (directory != NULL ? 2 : 0)
445 + java_sources_count;
446 argv = (char **) xmalloca ((argc + 1) * sizeof (char *));
454 if (directory != NULL)
457 *argp++ = (char *) directory;
459 for (i = 0; i < java_sources_count; i++)
460 *argp++ = (char *) java_sources[i];
462 /* Ensure argv length was correctly calculated. */
463 if (argp - argv != argc)
468 char *command = shell_quote_argv (argv);
469 printf ("%s\n", command);
473 exitstatus = execute ("jikes", "jikes", argv, false, false, false,
474 null_stderr, true, true, NULL);
475 err = (exitstatus != 0);
482 /* ====================== Usability test subroutines ====================== */
484 /* Write a given contents to a temporary file.
485 FILE_NAME is the name of a file inside TMPDIR that is known not to exist
487 Return a failure indicator (true upon error). */
489 write_temp_file (struct temp_dir *tmpdir, const char *file_name,
490 const char *contents)
494 register_temp_file (tmpdir, file_name);
495 fp = fopen_temp (file_name, "w");
498 error (0, errno, _("failed to create \"%s\""), file_name);
499 unregister_temp_file (tmpdir, file_name);
502 fputs (contents, fp);
503 if (fwriteerror_temp (fp))
505 error (0, errno, _("error while writing \"%s\" file"), file_name);
511 /* Return the class file version number of a class file on disk. */
513 get_classfile_version (const char *compiled_file_name)
515 unsigned char header[8];
518 /* Open the class file. */
519 fd = open (compiled_file_name, O_RDONLY | O_BINARY, 0);
522 /* Read its first 8 bytes. */
523 if (safe_read (fd, header, 8) == 8)
525 /* Verify the class file signature. */
526 if (header[0] == 0xCA && header[1] == 0xFE
527 && header[2] == 0xBA && header[3] == 0xBE)
533 /* Could not get the class file version. Return a very large one. */
537 /* Return true if $JAVAC is a version of gcj. */
539 is_envjavac_gcj (const char *javac)
541 static bool envjavac_tested;
542 static bool envjavac_gcj;
544 if (!envjavac_tested)
546 /* Test whether $JAVAC is gcj:
547 "$JAVAC --version 2>/dev/null | sed -e 1q | grep gcj > /dev/null" */
548 unsigned int command_length;
560 /* Setup the command "$JAVAC --version". */
561 command_length = strlen (javac) + 1 + 9 + 1;
562 command = (char *) xmalloca (command_length);
564 /* Don't shell_quote $JAVAC, because it may consist of a command
566 memcpy (p, javac, strlen (javac));
568 memcpy (p, " --version", 1 + 9 + 1);
570 /* Ensure command_length was correctly calculated. */
571 if (p - command > command_length)
574 /* Call $JAVAC --version 2>/dev/null. */
579 child = create_pipe_in (javac, "/bin/sh", argv, DEV_NULL, true, true,
584 /* Retrieve its result. */
585 fp = fdopen (fd[0], "r");
589 line = NULL; linesize = 0;
590 linelen = getline (&line, &linesize, fp);
591 if (linelen == (size_t)(-1))
596 /* It is safe to call c_strstr() instead of strstr() here; see the
597 comments in c-strstr.h. */
598 envjavac_gcj = (c_strstr (line, "gcj") != NULL);
602 /* Remove zombie process from process list, and retrieve exit status. */
604 wait_subprocess (child, javac, true, true, true, false, NULL);
606 envjavac_gcj = false;
611 envjavac_tested = true;
617 /* Return true if $JAVAC, known to be a version of gcj, is a version >= 4.3
620 is_envjavac_gcj43 (const char *javac)
622 static bool envjavac_tested;
623 static bool envjavac_gcj43;
625 if (!envjavac_tested)
627 /* Test whether $JAVAC is gcj:
628 "$JAVAC --version 2>/dev/null | sed -e 's,^[^0-9]*,,' -e 1q \
629 | sed -e '/^4\.[012]/d' | grep '^[4-9]' >/dev/null" */
630 unsigned int command_length;
642 /* Setup the command "$JAVAC --version". */
643 command_length = strlen (javac) + 1 + 9 + 1;
644 command = (char *) xmalloca (command_length);
646 /* Don't shell_quote $JAVAC, because it may consist of a command
648 memcpy (p, javac, strlen (javac));
650 memcpy (p, " --version", 1 + 9 + 1);
652 /* Ensure command_length was correctly calculated. */
653 if (p - command > command_length)
656 /* Call $JAVAC --version 2>/dev/null. */
661 child = create_pipe_in (javac, "/bin/sh", argv, DEV_NULL, true, true,
666 /* Retrieve its result. */
667 fp = fdopen (fd[0], "r");
671 line = NULL; linesize = 0;
672 linelen = getline (&line, &linesize, fp);
673 if (linelen == (size_t)(-1))
679 while (*p != '\0' && !(*p >= '0' && *p <= '9'))
682 !(*p == '4' && p[1] == '.' && p[2] >= '0' && p[2] <= '2')
683 && (*p >= '4' && *p <= '9');
687 /* Remove zombie process from process list, and retrieve exit status. */
689 wait_subprocess (child, javac, true, true, true, false, NULL);
691 envjavac_gcj43 = false;
696 envjavac_tested = true;
699 return envjavac_gcj43;
702 /* Test whether $JAVAC, known to be a version of gcj >= 4.3, can be used, and
703 whether it needs a -fsource and/or -ftarget option.
704 Return a failure indicator (true upon error). */
706 is_envjavac_gcj43_usable (const char *javac,
707 const char *source_version,
708 const char *target_version,
710 bool *fsource_option_p, bool *ftarget_option_p)
712 /* The cache depends on the source_version and target_version. */
720 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
721 struct result_t *resultp;
723 resultp = &result_cache[source_version_index (source_version)]
724 [target_version_index (target_version)];
725 if (!resultp->tested)
728 struct temp_dir *tmpdir;
729 char *conftest_file_name;
730 char *compiled_file_name;
731 const char *java_sources[1];
734 tmpdir = create_temp_dir ("java", NULL, false);
739 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
740 if (write_temp_file (tmpdir, conftest_file_name,
741 get_goodcode_snippet (source_version)))
743 free (conftest_file_name);
744 cleanup_temp_dir (tmpdir);
749 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
750 register_temp_file (tmpdir, compiled_file_name);
752 java_sources[0] = conftest_file_name;
753 if (!compile_using_envjavac (javac,
754 java_sources, 1, tmpdir->dir_name,
755 false, false, false, true)
756 && stat (compiled_file_name, &statbuf) >= 0
757 && get_classfile_version (compiled_file_name)
758 <= corresponding_classfile_version (target_version))
760 /* $JAVAC compiled conftest.java successfully. */
761 /* Try adding -fsource option if it is useful. */
763 xasprintf ("%s -fsource=%s", javac, source_version);
765 unlink (compiled_file_name);
767 java_sources[0] = conftest_file_name;
768 if (!compile_using_envjavac (javac_source,
769 java_sources, 1, tmpdir->dir_name,
770 false, false, false, true)
771 && stat (compiled_file_name, &statbuf) >= 0
772 && get_classfile_version (compiled_file_name)
773 <= corresponding_classfile_version (target_version))
775 const char *failcode = get_failcode_snippet (source_version);
777 if (failcode != NULL)
779 free (compiled_file_name);
780 free (conftest_file_name);
783 xconcatenated_filename (tmpdir->dir_name,
786 if (write_temp_file (tmpdir, conftest_file_name, failcode))
788 free (conftest_file_name);
790 cleanup_temp_dir (tmpdir);
795 xconcatenated_filename (tmpdir->dir_name,
796 "conftestfail.class",
798 register_temp_file (tmpdir, compiled_file_name);
800 java_sources[0] = conftest_file_name;
801 if (!compile_using_envjavac (javac,
804 false, false, false, true)
805 && stat (compiled_file_name, &statbuf) >= 0)
807 unlink (compiled_file_name);
809 java_sources[0] = conftest_file_name;
810 if (compile_using_envjavac (javac_source,
813 false, false, false, true))
814 /* $JAVAC compiled conftestfail.java successfully, and
815 "$JAVAC -fsource=$source_version" rejects it. So
816 the -fsource option is useful. */
817 resultp->fsource_option = true;
824 resultp->usable = true;
828 /* Try with -fsource and -ftarget options. */
830 xasprintf ("%s -fsource=%s -ftarget=%s",
831 javac, source_version, target_version);
833 unlink (compiled_file_name);
835 java_sources[0] = conftest_file_name;
836 if (!compile_using_envjavac (javac_target,
837 java_sources, 1, tmpdir->dir_name,
838 false, false, false, true)
839 && stat (compiled_file_name, &statbuf) >= 0
840 && get_classfile_version (compiled_file_name)
841 <= corresponding_classfile_version (target_version))
843 /* "$JAVAC -fsource $source_version -ftarget $target_version"
844 compiled conftest.java successfully. */
845 resultp->fsource_option = true;
846 resultp->ftarget_option = true;
847 resultp->usable = true;
853 free (compiled_file_name);
854 free (conftest_file_name);
856 resultp->tested = true;
859 *usablep = resultp->usable;
860 *fsource_option_p = resultp->fsource_option;
861 *ftarget_option_p = resultp->ftarget_option;
865 /* Test whether $JAVAC, known to be a version of gcj < 4.3, can be used for
866 compiling with target_version = 1.4 and source_version = 1.4.
867 Return a failure indicator (true upon error). */
869 is_envjavac_oldgcj_14_14_usable (const char *javac, bool *usablep)
871 static bool envjavac_tested;
872 static bool envjavac_usable;
874 if (!envjavac_tested)
877 struct temp_dir *tmpdir;
878 char *conftest_file_name;
879 char *compiled_file_name;
880 const char *java_sources[1];
883 tmpdir = create_temp_dir ("java", NULL, false);
888 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
889 if (write_temp_file (tmpdir, conftest_file_name,
890 get_goodcode_snippet ("1.4")))
892 free (conftest_file_name);
893 cleanup_temp_dir (tmpdir);
898 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
899 register_temp_file (tmpdir, compiled_file_name);
901 java_sources[0] = conftest_file_name;
902 if (!compile_using_envjavac (javac, java_sources, 1, tmpdir->dir_name,
903 false, false, false, true)
904 && stat (compiled_file_name, &statbuf) >= 0)
905 /* Compilation succeeded. */
906 envjavac_usable = true;
908 free (compiled_file_name);
909 free (conftest_file_name);
911 cleanup_temp_dir (tmpdir);
913 envjavac_tested = true;
916 *usablep = envjavac_usable;
920 /* Test whether $JAVAC, known to be a version of gcj < 4.3, can be used for
921 compiling with target_version = 1.4 and source_version = 1.3.
922 Return a failure indicator (true upon error). */
924 is_envjavac_oldgcj_14_13_usable (const char *javac,
925 bool *usablep, bool *need_no_assert_option_p)
927 static bool envjavac_tested;
928 static bool envjavac_usable;
929 static bool envjavac_need_no_assert_option;
931 if (!envjavac_tested)
933 /* Try $JAVAC and "$JAVAC -fno-assert". But add -fno-assert only if
934 it makes a difference. (It could already be part of $JAVAC.) */
935 struct temp_dir *tmpdir;
936 char *conftest_file_name;
937 char *compiled_file_name;
938 const char *java_sources[1];
941 char *javac_noassert;
942 bool javac_noassert_works;
944 tmpdir = create_temp_dir ("java", NULL, false);
949 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
950 if (write_temp_file (tmpdir, conftest_file_name,
951 get_goodcode_snippet ("1.3")))
953 free (conftest_file_name);
954 cleanup_temp_dir (tmpdir);
959 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
960 register_temp_file (tmpdir, compiled_file_name);
962 java_sources[0] = conftest_file_name;
963 if (!compile_using_envjavac (javac,
964 java_sources, 1, tmpdir->dir_name,
965 false, false, false, true)
966 && stat (compiled_file_name, &statbuf) >= 0)
967 /* Compilation succeeded. */
972 unlink (compiled_file_name);
974 javac_noassert = xasprintf ("%s -fno-assert", javac);
976 java_sources[0] = conftest_file_name;
977 if (!compile_using_envjavac (javac_noassert,
978 java_sources, 1, tmpdir->dir_name,
979 false, false, false, true)
980 && stat (compiled_file_name, &statbuf) >= 0)
981 /* Compilation succeeded. */
982 javac_noassert_works = true;
984 javac_noassert_works = false;
986 free (compiled_file_name);
987 free (conftest_file_name);
989 if (javac_works && javac_noassert_works)
992 xconcatenated_filename (tmpdir->dir_name, "conftestfail.java",
994 if (write_temp_file (tmpdir, conftest_file_name,
995 get_failcode_snippet ("1.3")))
997 free (conftest_file_name);
998 free (javac_noassert);
999 cleanup_temp_dir (tmpdir);
1003 compiled_file_name =
1004 xconcatenated_filename (tmpdir->dir_name, "conftestfail.class",
1006 register_temp_file (tmpdir, compiled_file_name);
1008 java_sources[0] = conftest_file_name;
1009 if (!compile_using_envjavac (javac,
1010 java_sources, 1, tmpdir->dir_name,
1011 false, false, false, true)
1012 && stat (compiled_file_name, &statbuf) >= 0)
1014 /* Compilation succeeded. */
1015 unlink (compiled_file_name);
1017 java_sources[0] = conftest_file_name;
1018 if (!(!compile_using_envjavac (javac_noassert,
1019 java_sources, 1, tmpdir->dir_name,
1020 false, false, false, true)
1021 && stat (compiled_file_name, &statbuf) >= 0))
1022 /* Compilation failed. */
1023 /* "$JAVAC -fno-assert" works better than $JAVAC. */
1027 free (compiled_file_name);
1028 free (conftest_file_name);
1031 cleanup_temp_dir (tmpdir);
1035 envjavac_usable = true;
1036 envjavac_need_no_assert_option = false;
1038 else if (javac_noassert_works)
1040 envjavac_usable = true;
1041 envjavac_need_no_assert_option = true;
1044 envjavac_tested = true;
1047 *usablep = envjavac_usable;
1048 *need_no_assert_option_p = envjavac_need_no_assert_option;
1052 /* Test whether $JAVAC, known to be not a version of gcj, can be used, and
1053 whether it needs a -source and/or -target option.
1054 Return a failure indicator (true upon error). */
1056 is_envjavac_nongcj_usable (const char *javac,
1057 const char *source_version,
1058 const char *target_version,
1060 bool *source_option_p, bool *target_option_p)
1062 /* The cache depends on the source_version and target_version. */
1070 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
1071 struct result_t *resultp;
1073 resultp = &result_cache[source_version_index (source_version)]
1074 [target_version_index (target_version)];
1075 if (!resultp->tested)
1078 struct temp_dir *tmpdir;
1079 char *conftest_file_name;
1080 char *compiled_file_name;
1081 const char *java_sources[1];
1082 struct stat statbuf;
1084 tmpdir = create_temp_dir ("java", NULL, false);
1088 conftest_file_name =
1089 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1090 if (write_temp_file (tmpdir, conftest_file_name,
1091 get_goodcode_snippet (source_version)))
1093 free (conftest_file_name);
1094 cleanup_temp_dir (tmpdir);
1098 compiled_file_name =
1099 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1100 register_temp_file (tmpdir, compiled_file_name);
1102 java_sources[0] = conftest_file_name;
1103 if (!compile_using_envjavac (javac,
1104 java_sources, 1, tmpdir->dir_name,
1105 false, false, false, true)
1106 && stat (compiled_file_name, &statbuf) >= 0
1107 && get_classfile_version (compiled_file_name)
1108 <= corresponding_classfile_version (target_version))
1110 /* $JAVAC compiled conftest.java successfully. */
1111 /* Try adding -source option if it is useful. */
1112 char *javac_source =
1113 xasprintf ("%s -source %s", javac, source_version);
1115 unlink (compiled_file_name);
1117 java_sources[0] = conftest_file_name;
1118 if (!compile_using_envjavac (javac_source,
1119 java_sources, 1, tmpdir->dir_name,
1120 false, false, false, true)
1121 && stat (compiled_file_name, &statbuf) >= 0
1122 && get_classfile_version (compiled_file_name)
1123 <= corresponding_classfile_version (target_version))
1125 const char *failcode = get_failcode_snippet (source_version);
1127 if (failcode != NULL)
1129 free (compiled_file_name);
1130 free (conftest_file_name);
1132 conftest_file_name =
1133 xconcatenated_filename (tmpdir->dir_name,
1134 "conftestfail.java",
1136 if (write_temp_file (tmpdir, conftest_file_name, failcode))
1138 free (conftest_file_name);
1139 free (javac_source);
1140 cleanup_temp_dir (tmpdir);
1144 compiled_file_name =
1145 xconcatenated_filename (tmpdir->dir_name,
1146 "conftestfail.class",
1148 register_temp_file (tmpdir, compiled_file_name);
1150 java_sources[0] = conftest_file_name;
1151 if (!compile_using_envjavac (javac,
1154 false, false, false, true)
1155 && stat (compiled_file_name, &statbuf) >= 0)
1157 unlink (compiled_file_name);
1159 java_sources[0] = conftest_file_name;
1160 if (compile_using_envjavac (javac_source,
1163 false, false, false, true))
1164 /* $JAVAC compiled conftestfail.java successfully, and
1165 "$JAVAC -source $source_version" rejects it. So the
1166 -source option is useful. */
1167 resultp->source_option = true;
1172 free (javac_source);
1174 resultp->usable = true;
1178 /* Try with -target option alone. (Sun javac 1.3.1 has the -target
1179 option but no -source option.) */
1180 char *javac_target =
1181 xasprintf ("%s -target %s", javac, target_version);
1183 unlink (compiled_file_name);
1185 java_sources[0] = conftest_file_name;
1186 if (!compile_using_envjavac (javac_target,
1187 java_sources, 1, tmpdir->dir_name,
1188 false, false, false, true)
1189 && stat (compiled_file_name, &statbuf) >= 0
1190 && get_classfile_version (compiled_file_name)
1191 <= corresponding_classfile_version (target_version))
1193 /* "$JAVAC -target $target_version" compiled conftest.java
1195 /* Try adding -source option if it is useful. */
1196 char *javac_target_source =
1197 xasprintf ("%s -source %s", javac_target, source_version);
1199 unlink (compiled_file_name);
1201 java_sources[0] = conftest_file_name;
1202 if (!compile_using_envjavac (javac_target_source,
1203 java_sources, 1, tmpdir->dir_name,
1204 false, false, false, true)
1205 && stat (compiled_file_name, &statbuf) >= 0
1206 && get_classfile_version (compiled_file_name)
1207 <= corresponding_classfile_version (target_version))
1209 const char *failcode = get_failcode_snippet (source_version);
1211 if (failcode != NULL)
1213 free (compiled_file_name);
1214 free (conftest_file_name);
1216 conftest_file_name =
1217 xconcatenated_filename (tmpdir->dir_name,
1218 "conftestfail.java",
1220 if (write_temp_file (tmpdir, conftest_file_name,
1223 free (conftest_file_name);
1224 free (javac_target_source);
1225 free (javac_target);
1226 cleanup_temp_dir (tmpdir);
1230 compiled_file_name =
1231 xconcatenated_filename (tmpdir->dir_name,
1232 "conftestfail.class",
1234 register_temp_file (tmpdir, compiled_file_name);
1236 java_sources[0] = conftest_file_name;
1237 if (!compile_using_envjavac (javac_target,
1240 false, false, false, true)
1241 && stat (compiled_file_name, &statbuf) >= 0)
1243 unlink (compiled_file_name);
1245 java_sources[0] = conftest_file_name;
1246 if (compile_using_envjavac (javac_target_source,
1249 false, false, false,
1251 /* "$JAVAC -target $target_version" compiled
1252 conftestfail.java successfully, and
1253 "$JAVAC -target $target_version -source $source_version"
1254 rejects it. So the -source option is useful. */
1255 resultp->source_option = true;
1260 free (javac_target_source);
1262 resultp->target_option = true;
1263 resultp->usable = true;
1267 /* Maybe this -target option requires a -source option? Try with
1268 -target and -source options. (Supported by Sun javac 1.4 and
1270 char *javac_target_source =
1271 xasprintf ("%s -source %s", javac_target, source_version);
1273 unlink (compiled_file_name);
1275 java_sources[0] = conftest_file_name;
1276 if (!compile_using_envjavac (javac_target_source,
1277 java_sources, 1, tmpdir->dir_name,
1278 false, false, false, true)
1279 && stat (compiled_file_name, &statbuf) >= 0
1280 && get_classfile_version (compiled_file_name)
1281 <= corresponding_classfile_version (target_version))
1283 /* "$JAVAC -target $target_version -source $source_version"
1284 compiled conftest.java successfully. */
1285 resultp->source_option = true;
1286 resultp->target_option = true;
1287 resultp->usable = true;
1290 free (javac_target_source);
1293 free (javac_target);
1296 free (compiled_file_name);
1297 free (conftest_file_name);
1299 resultp->tested = true;
1302 *usablep = resultp->usable;
1303 *source_option_p = resultp->source_option;
1304 *target_option_p = resultp->target_option;
1309 is_gcj_present (void)
1311 static bool gcj_tested;
1312 static bool gcj_present;
1316 /* Test for presence of gcj:
1317 "gcj --version 2> /dev/null | \
1318 sed -e 's,^[^0-9]*,,' -e 1q | \
1319 sed -e '/^3\.[01]/d' | grep '^[3-9]' > /dev/null" */
1326 argv[1] = "--version";
1328 child = create_pipe_in ("gcj", "gcj", argv, DEV_NULL, true, true,
1330 gcj_present = false;
1333 /* Read the subprocess output, drop all lines except the first,
1334 drop all characters before the first digit, and test whether
1335 the remaining string starts with a digit >= 3, but not with
1340 while (safe_read (fd[0], &c[count], 1) > 0)
1342 if (c[count] == '\n')
1346 if (!(c[0] >= '0' && c[0] <= '9'))
1348 gcj_present = (c[0] >= '3');
1353 if (c[0] == '3' && c[1] == '.'
1354 && (c[2] == '0' || c[2] == '1'))
1355 gcj_present = false;
1359 while (safe_read (fd[0], &c[0], 1) > 0)
1364 /* Remove zombie process from process list, and retrieve exit
1367 wait_subprocess (child, "gcj", false, true, true, false, NULL);
1368 if (exitstatus != 0)
1369 gcj_present = false;
1374 /* See if libgcj.jar is well installed. */
1375 struct temp_dir *tmpdir;
1377 tmpdir = create_temp_dir ("java", NULL, false);
1379 gcj_present = false;
1382 char *conftest_file_name;
1384 conftest_file_name =
1385 xconcatenated_filename (tmpdir->dir_name, "conftestlib.java",
1387 if (write_temp_file (tmpdir, conftest_file_name,
1388 "public class conftestlib {\n"
1389 " public static void main (String[] args) {\n"
1392 gcj_present = false;
1395 char *compiled_file_name;
1396 const char *java_sources[1];
1398 compiled_file_name =
1399 xconcatenated_filename (tmpdir->dir_name,
1400 "conftestlib.class",
1402 register_temp_file (tmpdir, compiled_file_name);
1404 java_sources[0] = conftest_file_name;
1405 if (compile_using_gcj (java_sources, 1, false,
1406 false, NULL, false, NULL,
1408 false, false, false, true))
1409 gcj_present = false;
1411 free (compiled_file_name);
1413 free (conftest_file_name);
1415 cleanup_temp_dir (tmpdir);
1427 static bool gcj_tested;
1432 /* Test for presence of gcj:
1433 "gcj --version 2> /dev/null | \
1434 sed -e 's,^[^0-9]*,,' -e 1q | \
1435 sed -e '/^4\.[012]/d' | grep '^[4-9]'" */
1442 argv[1] = "--version";
1444 child = create_pipe_in ("gcj", "gcj", argv, DEV_NULL, true, true,
1449 /* Read the subprocess output, drop all lines except the first,
1450 drop all characters before the first digit, and test whether
1451 the remaining string starts with a digit >= 4, but not with
1452 "4.0" or "4.1" or "4.2". */
1456 while (safe_read (fd[0], &c[count], 1) > 0)
1458 if (c[count] == '\n')
1462 if (!(c[0] >= '0' && c[0] <= '9'))
1464 gcj_43 = (c[0] >= '4');
1469 if (c[0] == '4' && c[1] == '.' && c[2] >= '0' && c[2] <= '2')
1474 while (safe_read (fd[0], &c[0], 1) > 0)
1479 /* Remove zombie process from process list, and retrieve exit
1482 wait_subprocess (child, "gcj", false, true, true, false, NULL);
1483 if (exitstatus != 0)
1493 /* Test whether gcj >= 4.3 can be used, and whether it needs a -fsource and/or
1495 Return a failure indicator (true upon error). */
1497 is_gcj43_usable (const char *source_version,
1498 const char *target_version,
1500 bool *fsource_option_p, bool *ftarget_option_p)
1502 /* The cache depends on the source_version and target_version. */
1507 bool fsource_option;
1508 bool ftarget_option;
1510 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
1511 struct result_t *resultp;
1513 resultp = &result_cache[source_version_index (source_version)]
1514 [target_version_index (target_version)];
1515 if (!resultp->tested)
1518 struct temp_dir *tmpdir;
1519 char *conftest_file_name;
1520 char *compiled_file_name;
1521 const char *java_sources[1];
1522 struct stat statbuf;
1524 tmpdir = create_temp_dir ("java", NULL, false);
1528 conftest_file_name =
1529 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1530 if (write_temp_file (tmpdir, conftest_file_name,
1531 get_goodcode_snippet (source_version)))
1533 free (conftest_file_name);
1534 cleanup_temp_dir (tmpdir);
1538 compiled_file_name =
1539 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1540 register_temp_file (tmpdir, compiled_file_name);
1542 java_sources[0] = conftest_file_name;
1543 if (!compile_using_gcj (java_sources, 1, false, false, NULL, false, NULL,
1544 tmpdir->dir_name, false, false, false, true)
1545 && stat (compiled_file_name, &statbuf) >= 0
1546 && get_classfile_version (compiled_file_name)
1547 <= corresponding_classfile_version (target_version))
1549 /* gcj compiled conftest.java successfully. */
1550 /* Try adding -fsource option if it is useful. */
1551 unlink (compiled_file_name);
1553 java_sources[0] = conftest_file_name;
1554 if (!compile_using_gcj (java_sources, 1,
1555 false, true, source_version, false, NULL,
1556 tmpdir->dir_name, false, false, false, true)
1557 && stat (compiled_file_name, &statbuf) >= 0
1558 && get_classfile_version (compiled_file_name)
1559 <= corresponding_classfile_version (target_version))
1561 const char *failcode = get_failcode_snippet (source_version);
1563 if (failcode != NULL)
1565 free (compiled_file_name);
1566 free (conftest_file_name);
1568 conftest_file_name =
1569 xconcatenated_filename (tmpdir->dir_name,
1570 "conftestfail.java",
1572 if (write_temp_file (tmpdir, conftest_file_name, failcode))
1574 free (conftest_file_name);
1575 cleanup_temp_dir (tmpdir);
1579 compiled_file_name =
1580 xconcatenated_filename (tmpdir->dir_name,
1581 "conftestfail.class",
1583 register_temp_file (tmpdir, compiled_file_name);
1585 java_sources[0] = conftest_file_name;
1586 if (!compile_using_gcj (java_sources, 1,
1587 false, false, NULL, false, NULL,
1589 false, false, false, true)
1590 && stat (compiled_file_name, &statbuf) >= 0)
1592 unlink (compiled_file_name);
1594 java_sources[0] = conftest_file_name;
1595 if (compile_using_gcj (java_sources, 1,
1596 false, true, source_version,
1599 false, false, false, true))
1600 /* gcj compiled conftestfail.java successfully, and
1601 "gcj -fsource=$source_version" rejects it. So
1602 the -fsource option is useful. */
1603 resultp->fsource_option = true;
1608 resultp->usable = true;
1612 /* Try with -fsource and -ftarget options. */
1613 unlink (compiled_file_name);
1615 java_sources[0] = conftest_file_name;
1616 if (!compile_using_gcj (java_sources, 1,
1617 false, true, source_version,
1618 true, target_version,
1620 false, false, false, true)
1621 && stat (compiled_file_name, &statbuf) >= 0
1622 && get_classfile_version (compiled_file_name)
1623 <= corresponding_classfile_version (target_version))
1625 /* "gcj -fsource $source_version -ftarget $target_version"
1626 compiled conftest.java successfully. */
1627 resultp->fsource_option = true;
1628 resultp->ftarget_option = true;
1629 resultp->usable = true;
1633 free (compiled_file_name);
1634 free (conftest_file_name);
1636 resultp->tested = true;
1639 *usablep = resultp->usable;
1640 *fsource_option_p = resultp->fsource_option;
1641 *ftarget_option_p = resultp->ftarget_option;
1645 /* Test whether gcj < 4.3 can be used for compiling with target_version = 1.4
1646 and source_version = 1.4.
1647 Return a failure indicator (true upon error). */
1649 is_oldgcj_14_14_usable (bool *usablep)
1651 static bool gcj_tested;
1652 static bool gcj_usable;
1657 struct temp_dir *tmpdir;
1658 char *conftest_file_name;
1659 char *compiled_file_name;
1660 const char *java_sources[1];
1661 struct stat statbuf;
1663 tmpdir = create_temp_dir ("java", NULL, false);
1667 conftest_file_name =
1668 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1669 if (write_temp_file (tmpdir, conftest_file_name,
1670 get_goodcode_snippet ("1.4")))
1672 free (conftest_file_name);
1673 cleanup_temp_dir (tmpdir);
1677 compiled_file_name =
1678 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1679 register_temp_file (tmpdir, compiled_file_name);
1681 java_sources[0] = conftest_file_name;
1682 if (!compile_using_gcj (java_sources, 1, false, false, NULL, false, NULL,
1683 tmpdir->dir_name, false, false, false, true)
1684 && stat (compiled_file_name, &statbuf) >= 0)
1685 /* Compilation succeeded. */
1688 free (compiled_file_name);
1689 free (conftest_file_name);
1691 cleanup_temp_dir (tmpdir);
1696 *usablep = gcj_usable;
1700 /* Test whether gcj < 4.3 can be used for compiling with target_version = 1.4
1701 and source_version = 1.3.
1702 Return a failure indicator (true upon error). */
1704 is_oldgcj_14_13_usable (bool *usablep, bool *need_no_assert_option_p)
1706 static bool gcj_tested;
1707 static bool gcj_usable;
1708 static bool gcj_need_no_assert_option;
1712 /* Try gcj and "gcj -fno-assert". But add -fno-assert only if
1713 it works (not gcj < 3.3). */
1714 struct temp_dir *tmpdir;
1715 char *conftest_file_name;
1716 char *compiled_file_name;
1717 const char *java_sources[1];
1718 struct stat statbuf;
1720 tmpdir = create_temp_dir ("java", NULL, false);
1724 conftest_file_name =
1725 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1726 if (write_temp_file (tmpdir, conftest_file_name,
1727 get_goodcode_snippet ("1.3")))
1729 free (conftest_file_name);
1730 cleanup_temp_dir (tmpdir);
1734 compiled_file_name =
1735 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1736 register_temp_file (tmpdir, compiled_file_name);
1738 java_sources[0] = conftest_file_name;
1739 if (!compile_using_gcj (java_sources, 1, true, false, NULL, false, NULL,
1740 tmpdir->dir_name, false, false, false, true)
1741 && stat (compiled_file_name, &statbuf) >= 0)
1742 /* Compilation succeeded. */
1745 gcj_need_no_assert_option = true;
1749 unlink (compiled_file_name);
1751 java_sources[0] = conftest_file_name;
1752 if (!compile_using_gcj (java_sources, 1, false,
1753 false, NULL, false, NULL,
1754 tmpdir->dir_name, false, false, false, true)
1755 && stat (compiled_file_name, &statbuf) >= 0)
1756 /* Compilation succeeded. */
1759 gcj_need_no_assert_option = false;
1763 free (compiled_file_name);
1764 free (conftest_file_name);
1766 cleanup_temp_dir (tmpdir);
1771 *usablep = gcj_usable;
1772 *need_no_assert_option_p = gcj_need_no_assert_option;
1777 is_javac_present (void)
1779 static bool javac_tested;
1780 static bool javac_present;
1784 /* Test for presence of javac: "javac 2> /dev/null ; test $? -le 2" */
1790 exitstatus = execute ("javac", "javac", argv, false, false, true, true,
1792 javac_present = (exitstatus == 0 || exitstatus == 1 || exitstatus == 2);
1793 javac_tested = true;
1796 return javac_present;
1799 /* Test whether javac can be used and whether it needs a -source and/or
1801 Return a failure indicator (true upon error). */
1803 is_javac_usable (const char *source_version, const char *target_version,
1804 bool *usablep, bool *source_option_p, bool *target_option_p)
1806 /* The cache depends on the source_version and target_version. */
1814 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
1815 struct result_t *resultp;
1817 resultp = &result_cache[source_version_index (source_version)]
1818 [target_version_index (target_version)];
1819 if (!resultp->tested)
1822 struct temp_dir *tmpdir;
1823 char *conftest_file_name;
1824 char *compiled_file_name;
1825 const char *java_sources[1];
1826 struct stat statbuf;
1828 tmpdir = create_temp_dir ("java", NULL, false);
1832 conftest_file_name =
1833 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1834 if (write_temp_file (tmpdir, conftest_file_name,
1835 get_goodcode_snippet (source_version)))
1837 free (conftest_file_name);
1838 cleanup_temp_dir (tmpdir);
1842 compiled_file_name =
1843 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1844 register_temp_file (tmpdir, compiled_file_name);
1846 java_sources[0] = conftest_file_name;
1847 if (!compile_using_javac (java_sources, 1,
1848 false, source_version,
1849 false, target_version,
1850 tmpdir->dir_name, false, false, false, true)
1851 && stat (compiled_file_name, &statbuf) >= 0
1852 && get_classfile_version (compiled_file_name)
1853 <= corresponding_classfile_version (target_version))
1855 /* javac compiled conftest.java successfully. */
1856 /* Try adding -source option if it is useful. */
1857 unlink (compiled_file_name);
1859 java_sources[0] = conftest_file_name;
1860 if (!compile_using_javac (java_sources, 1,
1861 true, source_version,
1862 false, target_version,
1863 tmpdir->dir_name, false, false, false, true)
1864 && stat (compiled_file_name, &statbuf) >= 0
1865 && get_classfile_version (compiled_file_name)
1866 <= corresponding_classfile_version (target_version))
1868 const char *failcode = get_failcode_snippet (source_version);
1870 if (failcode != NULL)
1872 free (compiled_file_name);
1873 free (conftest_file_name);
1875 conftest_file_name =
1876 xconcatenated_filename (tmpdir->dir_name,
1877 "conftestfail.java",
1879 if (write_temp_file (tmpdir, conftest_file_name, failcode))
1881 free (conftest_file_name);
1882 cleanup_temp_dir (tmpdir);
1886 compiled_file_name =
1887 xconcatenated_filename (tmpdir->dir_name,
1888 "conftestfail.class",
1890 register_temp_file (tmpdir, compiled_file_name);
1892 java_sources[0] = conftest_file_name;
1893 if (!compile_using_javac (java_sources, 1,
1894 false, source_version,
1895 false, target_version,
1897 false, false, false, true)
1898 && stat (compiled_file_name, &statbuf) >= 0)
1900 unlink (compiled_file_name);
1902 java_sources[0] = conftest_file_name;
1903 if (compile_using_javac (java_sources, 1,
1904 true, source_version,
1905 false, target_version,
1907 false, false, false, true))
1908 /* javac compiled conftestfail.java successfully, and
1909 "javac -source $source_version" rejects it. So the
1910 -source option is useful. */
1911 resultp->source_option = true;
1916 resultp->usable = true;
1920 /* Try with -target option alone. (Sun javac 1.3.1 has the -target
1921 option but no -source option.) */
1922 unlink (compiled_file_name);
1924 java_sources[0] = conftest_file_name;
1925 if (!compile_using_javac (java_sources, 1,
1926 false, source_version,
1927 true, target_version,
1929 false, false, false, true)
1930 && stat (compiled_file_name, &statbuf) >= 0
1931 && get_classfile_version (compiled_file_name)
1932 <= corresponding_classfile_version (target_version))
1934 /* "javac -target $target_version" compiled conftest.java
1936 /* Try adding -source option if it is useful. */
1937 unlink (compiled_file_name);
1939 java_sources[0] = conftest_file_name;
1940 if (!compile_using_javac (java_sources, 1,
1941 true, source_version,
1942 true, target_version,
1944 false, false, false, true)
1945 && stat (compiled_file_name, &statbuf) >= 0
1946 && get_classfile_version (compiled_file_name)
1947 <= corresponding_classfile_version (target_version))
1949 const char *failcode = get_failcode_snippet (source_version);
1951 if (failcode != NULL)
1953 free (compiled_file_name);
1954 free (conftest_file_name);
1956 conftest_file_name =
1957 xconcatenated_filename (tmpdir->dir_name,
1958 "conftestfail.java",
1960 if (write_temp_file (tmpdir, conftest_file_name,
1963 free (conftest_file_name);
1964 cleanup_temp_dir (tmpdir);
1968 compiled_file_name =
1969 xconcatenated_filename (tmpdir->dir_name,
1970 "conftestfail.class",
1972 register_temp_file (tmpdir, compiled_file_name);
1974 java_sources[0] = conftest_file_name;
1975 if (!compile_using_javac (java_sources, 1,
1976 false, source_version,
1977 true, target_version,
1979 false, false, false, true)
1980 && stat (compiled_file_name, &statbuf) >= 0)
1982 unlink (compiled_file_name);
1984 java_sources[0] = conftest_file_name;
1985 if (compile_using_javac (java_sources, 1,
1986 true, source_version,
1987 true, target_version,
1989 false, false, false, true))
1990 /* "javac -target $target_version" compiled
1991 conftestfail.java successfully, and
1992 "javac -target $target_version -source $source_version"
1993 rejects it. So the -source option is useful. */
1994 resultp->source_option = true;
1999 resultp->target_option = true;
2000 resultp->usable = true;
2004 /* Maybe this -target option requires a -source option? Try with
2005 -target and -source options. (Supported by Sun javac 1.4 and
2007 unlink (compiled_file_name);
2009 java_sources[0] = conftest_file_name;
2010 if (!compile_using_javac (java_sources, 1,
2011 true, source_version,
2012 true, target_version,
2014 false, false, false, true)
2015 && stat (compiled_file_name, &statbuf) >= 0
2016 && get_classfile_version (compiled_file_name)
2017 <= corresponding_classfile_version (target_version))
2019 /* "javac -target $target_version -source $source_version"
2020 compiled conftest.java successfully. */
2021 resultp->source_option = true;
2022 resultp->target_option = true;
2023 resultp->usable = true;
2028 free (compiled_file_name);
2029 free (conftest_file_name);
2031 resultp->tested = true;
2034 *usablep = resultp->usable;
2035 *source_option_p = resultp->source_option;
2036 *target_option_p = resultp->target_option;
2041 is_jikes_present (void)
2043 static bool jikes_tested;
2044 static bool jikes_present;
2048 /* Test for presence of jikes: "jikes 2> /dev/null ; test $? = 1" */
2054 exitstatus = execute ("jikes", "jikes", argv, false, false, true, true,
2056 jikes_present = (exitstatus == 0 || exitstatus == 1);
2057 jikes_tested = true;
2060 return jikes_present;
2063 /* ============================= Main function ============================= */
2066 compile_java_class (const char * const *java_sources,
2067 unsigned int java_sources_count,
2068 const char * const *classpaths,
2069 unsigned int classpaths_count,
2070 const char *source_version,
2071 const char *target_version,
2072 const char *directory,
2073 bool optimize, bool debug,
2074 bool use_minimal_classpath,
2078 char *old_JAVA_HOME;
2081 const char *javac = getenv ("JAVAC");
2082 if (javac != NULL && javac[0] != '\0')
2084 bool usable = false;
2085 bool no_assert_option = false;
2086 bool source_option = false;
2087 bool target_option = false;
2088 bool fsource_option = false;
2089 bool ftarget_option = false;
2091 if (target_version == NULL)
2092 target_version = default_target_version ();
2094 if (is_envjavac_gcj (javac))
2096 /* It's a version of gcj. */
2097 if (is_envjavac_gcj43 (javac))
2099 /* It's a version of gcj >= 4.3. Assume the classfile versions
2101 if (is_envjavac_gcj43_usable (javac,
2102 source_version, target_version,
2104 &fsource_option, &ftarget_option))
2112 /* It's a version of gcj < 4.3. Ignore the version of the
2113 class files that it creates. */
2114 if (strcmp (target_version, "1.4") == 0
2115 && strcmp (source_version, "1.4") == 0)
2117 if (is_envjavac_oldgcj_14_14_usable (javac, &usable))
2123 else if (strcmp (target_version, "1.4") == 0
2124 && strcmp (source_version, "1.3") == 0)
2126 if (is_envjavac_oldgcj_14_13_usable (javac,
2138 /* It's not gcj. Assume the classfile versions are correct. */
2139 if (is_envjavac_nongcj_usable (javac,
2140 source_version, target_version,
2142 &source_option, &target_option))
2151 char *old_classpath;
2152 char *javac_with_options;
2154 /* Set CLASSPATH. */
2156 set_classpath (classpaths, classpaths_count, false, verbose);
2158 javac_with_options =
2160 ? xasprintf ("%s -fno-assert", javac)
2161 : xasprintf ("%s%s%s%s%s%s%s%s%s",
2163 source_option ? " -source " : "",
2164 source_option ? source_version : "",
2165 target_option ? " -target " : "",
2166 target_option ? target_version : "",
2167 fsource_option ? " -fsource=" : "",
2168 fsource_option ? source_version : "",
2169 ftarget_option ? " -ftarget=" : "",
2170 ftarget_option ? target_version : ""));
2172 err = compile_using_envjavac (javac_with_options,
2173 java_sources, java_sources_count,
2174 directory, optimize, debug, verbose,
2177 free (javac_with_options);
2179 /* Reset CLASSPATH. */
2180 reset_classpath (old_classpath);
2187 /* Unset the JAVA_HOME environment variable. */
2188 old_JAVA_HOME = getenv ("JAVA_HOME");
2189 if (old_JAVA_HOME != NULL)
2191 old_JAVA_HOME = xstrdup (old_JAVA_HOME);
2192 unsetenv ("JAVA_HOME");
2195 if (is_gcj_present ())
2197 /* It's a version of gcj. */
2198 bool usable = false;
2199 bool no_assert_option = false;
2200 bool fsource_option = false;
2201 bool ftarget_option = false;
2203 if (target_version == NULL)
2204 target_version = default_target_version ();
2208 /* It's a version of gcj >= 4.3. Assume the classfile versions
2210 if (is_gcj43_usable (source_version, target_version,
2211 &usable, &fsource_option, &ftarget_option))
2219 /* It's a version of gcj < 4.3. Ignore the version of the class
2220 files that it creates.
2221 Test whether it supports the desired target-version and
2223 if (strcmp (target_version, "1.4") == 0
2224 && strcmp (source_version, "1.4") == 0)
2226 if (is_oldgcj_14_14_usable (&usable))
2232 else if (strcmp (target_version, "1.4") == 0
2233 && strcmp (source_version, "1.3") == 0)
2235 if (is_oldgcj_14_13_usable (&usable, &no_assert_option))
2245 char *old_classpath;
2247 /* Set CLASSPATH. We could also use the --CLASSPATH=... option
2248 of gcj. Note that --classpath=... option is different: its
2249 argument should also contain gcj's libgcj.jar, but we don't
2250 know its location. */
2252 set_classpath (classpaths, classpaths_count, use_minimal_classpath,
2255 err = compile_using_gcj (java_sources, java_sources_count,
2257 fsource_option, source_version,
2258 ftarget_option, target_version,
2259 directory, optimize, debug, verbose, false);
2261 /* Reset CLASSPATH. */
2262 reset_classpath (old_classpath);
2268 if (is_javac_present ())
2270 bool usable = false;
2271 bool source_option = false;
2272 bool target_option = false;
2274 if (target_version == NULL)
2275 target_version = default_target_version ();
2277 if (is_javac_usable (source_version, target_version,
2278 &usable, &source_option, &target_option))
2286 char *old_classpath;
2288 /* Set CLASSPATH. We don't use the "-classpath ..." option because
2289 in JDK 1.1.x its argument should also contain the JDK's
2290 classes.zip, but we don't know its location. (In JDK 1.3.0 it
2293 set_classpath (classpaths, classpaths_count, use_minimal_classpath,
2296 err = compile_using_javac (java_sources, java_sources_count,
2297 source_option, source_version,
2298 target_option, target_version,
2299 directory, optimize, debug, verbose,
2302 /* Reset CLASSPATH. */
2303 reset_classpath (old_classpath);
2309 if (is_jikes_present ())
2311 /* Test whether it supports the desired target-version and
2313 bool usable = (strcmp (source_version, "1.3") == 0);
2317 char *old_classpath;
2319 /* Set CLASSPATH. We could also use the "-classpath ..." option.
2320 Since jikes doesn't come with its own standard library, it
2321 needs a classes.zip or rt.jar or libgcj.jar in the CLASSPATH.
2322 To increase the chance of success, we reuse the current CLASSPATH
2323 if the user has set it. */
2325 set_classpath (classpaths, classpaths_count, false, verbose);
2327 err = compile_using_jikes (java_sources, java_sources_count,
2328 directory, optimize, debug, verbose,
2331 /* Reset CLASSPATH. */
2332 reset_classpath (old_classpath);
2338 error (0, 0, _("Java compiler not found, try installing gcj or set $JAVAC"));
2342 if (old_JAVA_HOME != NULL)
2344 xsetenv ("JAVA_HOME", old_JAVA_HOME, 1);
2345 free (old_JAVA_HOME);