1 /* Compile a Java program.
2 Copyright (C) 2001-2003, 2006-2011 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)
54 /* The results of open() in this file are not used with fchdir,
55 therefore save some unnecessary work in fchdir.c. */
60 /* Survey of Java compilers.
62 A = does it work without CLASSPATH being set
63 C = option to set CLASSPATH, other than setting it in the environment
64 O = option for optimizing
65 g = option for debugging
68 Program from A C O g T
70 $JAVAC unknown N n/a -O -g true
71 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
72 javac JDK 1.1.8 Y -classpath P -O -g javac 2>/dev/null; test $? = 1
73 javac JDK 1.3.0 Y -classpath P -O -g javac 2>/dev/null; test $? -le 2
74 jikes Jikes 1.14 N -classpath P -O -g jikes 2>/dev/null; test $? = 1
76 All compilers support the option "-d DIRECTORY" for the base directory
77 of the classes to be written.
79 The CLASSPATH is a colon separated list of pathnames. (On Windows: a
80 semicolon separated list of pathnames.)
82 We try the Java compilers in the following order:
83 1. getenv ("JAVAC"), because the user must be able to override our
85 2. "gcj -C", because it is a completely free compiler,
86 3. "javac", because it is a standard compiler,
87 4. "jikes", comes last because it has some deviating interpretation
88 of the Java Language Specification and because it requires a
89 CLASSPATH environment variable.
91 We unset the JAVA_HOME environment variable, because a wrong setting of
92 this variable can confuse the JDK's javac.
95 /* Return the default target_version. */
97 default_target_version (void)
99 /* Use a cache. Assumes that the PATH environment variable doesn't change
100 during the lifetime of the program. */
101 static const char *java_version_cache;
102 if (java_version_cache == NULL)
104 /* Determine the version from the found JVM. */
105 java_version_cache = javaexec_version ();
106 if (java_version_cache == NULL
107 || !(java_version_cache[0] == '1' && java_version_cache[1] == '.'
108 && (java_version_cache[2] >= '1' && java_version_cache[2] <= '6')
109 && java_version_cache[3] == '\0'))
110 java_version_cache = "1.1";
112 return java_version_cache;
115 /* ======================= Source version dependent ======================= */
117 /* Convert a source version to an index. */
118 #define SOURCE_VERSION_BOUND 3 /* exclusive upper bound */
120 source_version_index (const char *source_version)
122 if (source_version[0] == '1' && source_version[1] == '.'
123 && (source_version[2] >= '3' && source_version[2] <= '5')
124 && source_version[3] == '\0')
125 return source_version[2] - '3';
126 error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
130 /* Return a snippet of code that should compile in the given source version. */
132 get_goodcode_snippet (const char *source_version)
134 if (strcmp (source_version, "1.3") == 0)
135 return "class conftest {}\n";
136 if (strcmp (source_version, "1.4") == 0)
137 return "class conftest { static { assert(true); } }\n";
138 if (strcmp (source_version, "1.5") == 0)
139 return "class conftest<T> { T foo() { return null; } }\n";
140 error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
144 /* Return a snippet of code that should fail to compile in the given source
145 version, or NULL (standing for a snippet that would fail to compile with
148 get_failcode_snippet (const char *source_version)
150 if (strcmp (source_version, "1.3") == 0)
151 return "class conftestfail { static { assert(true); } }\n";
152 if (strcmp (source_version, "1.4") == 0)
153 return "class conftestfail<T> { T foo() { return null; } }\n";
154 if (strcmp (source_version, "1.5") == 0)
156 error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
160 /* ======================= Target version dependent ======================= */
162 /* Convert a target version to an index. */
163 #define TARGET_VERSION_BOUND 6 /* exclusive upper bound */
165 target_version_index (const char *target_version)
167 if (target_version[0] == '1' && target_version[1] == '.'
168 && (target_version[2] >= '1' && target_version[2] <= '6')
169 && target_version[3] == '\0')
170 return target_version[2] - '1';
171 error (EXIT_FAILURE, 0, _("invalid target_version argument to compile_java_class"));
175 /* Return the class file version number corresponding to a given target
178 corresponding_classfile_version (const char *target_version)
180 if (strcmp (target_version, "1.1") == 0)
182 if (strcmp (target_version, "1.2") == 0)
184 if (strcmp (target_version, "1.3") == 0)
186 if (strcmp (target_version, "1.4") == 0)
188 if (strcmp (target_version, "1.5") == 0)
190 if (strcmp (target_version, "1.6") == 0)
192 error (EXIT_FAILURE, 0, _("invalid target_version argument to compile_java_class"));
196 /* ======================== Compilation subroutines ======================== */
198 /* Try to compile a set of Java sources with $JAVAC.
199 Return a failure indicator (true upon error). */
201 compile_using_envjavac (const char *javac,
202 const char * const *java_sources,
203 unsigned int java_sources_count,
204 const char *directory,
205 bool optimize, bool debug,
206 bool verbose, bool null_stderr)
208 /* Because $JAVAC may consist of a command and options, we use the
209 shell. Because $JAVAC has been set by the user, we leave all
210 environment variables in place, including JAVA_HOME, and we don't
211 erase the user's CLASSPATH. */
213 unsigned int command_length;
220 command_length = strlen (javac);
225 if (directory != NULL)
226 command_length += 4 + shell_quote_length (directory);
227 for (i = 0; i < java_sources_count; i++)
228 command_length += 1 + shell_quote_length (java_sources[i]);
231 command = (char *) xmalloca (command_length);
233 /* Don't shell_quote $JAVAC, because it may consist of a command
235 memcpy (p, javac, strlen (javac));
239 memcpy (p, " -O", 3);
244 memcpy (p, " -g", 3);
247 if (directory != NULL)
249 memcpy (p, " -d ", 4);
251 p = shell_quote_copy (p, directory);
253 for (i = 0; i < java_sources_count; i++)
256 p = shell_quote_copy (p, java_sources[i]);
259 /* Ensure command_length was correctly calculated. */
260 if (p - command > command_length)
264 printf ("%s\n", command);
270 exitstatus = execute (javac, "/bin/sh", argv, false, false, false,
271 null_stderr, true, true, NULL);
272 err = (exitstatus != 0);
279 /* Try to compile a set of Java sources with gcj.
280 Return a failure indicator (true upon error). */
282 compile_using_gcj (const char * const *java_sources,
283 unsigned int java_sources_count,
284 bool no_assert_option,
285 bool fsource_option, const char *source_version,
286 bool ftarget_option, const char *target_version,
287 const char *directory,
288 bool optimize, bool debug,
289 bool verbose, bool null_stderr)
301 2 + (no_assert_option ? 1 : 0) + (fsource_option ? 1 : 0)
302 + (ftarget_option ? 1 : 0) + (optimize ? 1 : 0) + (debug ? 1 : 0)
303 + (directory != NULL ? 2 : 0) + java_sources_count;
304 argv = (char **) xmalloca ((argc + 1) * sizeof (char *));
309 if (no_assert_option)
310 *argp++ = "-fno-assert";
313 fsource_arg = (char *) xmalloca (9 + strlen (source_version) + 1);
314 memcpy (fsource_arg, "-fsource=", 9);
315 strcpy (fsource_arg + 9, source_version);
316 *argp++ = fsource_arg;
322 ftarget_arg = (char *) xmalloca (9 + strlen (target_version) + 1);
323 memcpy (ftarget_arg, "-ftarget=", 9);
324 strcpy (ftarget_arg + 9, target_version);
325 *argp++ = ftarget_arg;
333 if (directory != NULL)
336 *argp++ = (char *) directory;
338 for (i = 0; i < java_sources_count; i++)
339 *argp++ = (char *) java_sources[i];
341 /* Ensure argv length was correctly calculated. */
342 if (argp - argv != argc)
347 char *command = shell_quote_argv (argv);
348 printf ("%s\n", command);
352 exitstatus = execute ("gcj", "gcj", argv, false, false, false, null_stderr,
354 err = (exitstatus != 0);
356 if (ftarget_arg != NULL)
358 if (fsource_arg != NULL)
365 /* Try to compile a set of Java sources with javac.
366 Return a failure indicator (true upon error). */
368 compile_using_javac (const char * const *java_sources,
369 unsigned int java_sources_count,
370 bool source_option, const char *source_version,
371 bool target_option, const char *target_version,
372 const char *directory,
373 bool optimize, bool debug,
374 bool verbose, bool null_stderr)
384 1 + (source_option ? 2 : 0) + (target_option ? 2 : 0) + (optimize ? 1 : 0)
385 + (debug ? 1 : 0) + (directory != NULL ? 2 : 0) + java_sources_count;
386 argv = (char **) xmalloca ((argc + 1) * sizeof (char *));
393 *argp++ = (char *) source_version;
398 *argp++ = (char *) target_version;
404 if (directory != NULL)
407 *argp++ = (char *) directory;
409 for (i = 0; i < java_sources_count; i++)
410 *argp++ = (char *) java_sources[i];
412 /* Ensure argv length was correctly calculated. */
413 if (argp - argv != argc)
418 char *command = shell_quote_argv (argv);
419 printf ("%s\n", command);
423 exitstatus = execute ("javac", "javac", argv, false, false, false,
424 null_stderr, true, true, NULL);
425 err = (exitstatus != 0);
432 /* Try to compile a set of Java sources with jikes.
433 Return a failure indicator (true upon error). */
435 compile_using_jikes (const char * const *java_sources,
436 unsigned int java_sources_count,
437 const char *directory,
438 bool optimize, bool debug,
439 bool verbose, bool null_stderr)
449 1 + (optimize ? 1 : 0) + (debug ? 1 : 0) + (directory != NULL ? 2 : 0)
450 + java_sources_count;
451 argv = (char **) xmalloca ((argc + 1) * sizeof (char *));
459 if (directory != NULL)
462 *argp++ = (char *) directory;
464 for (i = 0; i < java_sources_count; i++)
465 *argp++ = (char *) java_sources[i];
467 /* Ensure argv length was correctly calculated. */
468 if (argp - argv != argc)
473 char *command = shell_quote_argv (argv);
474 printf ("%s\n", command);
478 exitstatus = execute ("jikes", "jikes", argv, false, false, false,
479 null_stderr, true, true, NULL);
480 err = (exitstatus != 0);
487 /* ====================== Usability test subroutines ====================== */
489 /* Write a given contents to a temporary file.
490 FILE_NAME is the name of a file inside TMPDIR that is known not to exist
492 Return a failure indicator (true upon error). */
494 write_temp_file (struct temp_dir *tmpdir, const char *file_name,
495 const char *contents)
499 register_temp_file (tmpdir, file_name);
500 fp = fopen_temp (file_name, "w");
503 error (0, errno, _("failed to create \"%s\""), file_name);
504 unregister_temp_file (tmpdir, file_name);
507 fputs (contents, fp);
508 if (fwriteerror_temp (fp))
510 error (0, errno, _("error while writing \"%s\" file"), file_name);
516 /* Return the class file version number of a class file on disk. */
518 get_classfile_version (const char *compiled_file_name)
520 unsigned char header[8];
523 /* Open the class file. */
524 fd = open (compiled_file_name, O_RDONLY | O_BINARY, 0);
527 /* Read its first 8 bytes. */
528 if (safe_read (fd, header, 8) == 8)
530 /* Verify the class file signature. */
531 if (header[0] == 0xCA && header[1] == 0xFE
532 && header[2] == 0xBA && header[3] == 0xBE)
538 /* Could not get the class file version. Return a very large one. */
542 /* Return true if $JAVAC is a version of gcj. */
544 is_envjavac_gcj (const char *javac)
546 static bool envjavac_tested;
547 static bool envjavac_gcj;
549 if (!envjavac_tested)
551 /* Test whether $JAVAC is gcj:
552 "$JAVAC --version 2>/dev/null | sed -e 1q | grep gcj > /dev/null" */
553 unsigned int command_length;
565 /* Setup the command "$JAVAC --version". */
566 command_length = strlen (javac) + 1 + 9 + 1;
567 command = (char *) xmalloca (command_length);
569 /* Don't shell_quote $JAVAC, because it may consist of a command
571 memcpy (p, javac, strlen (javac));
573 memcpy (p, " --version", 1 + 9 + 1);
575 /* Ensure command_length was correctly calculated. */
576 if (p - command > command_length)
579 /* Call $JAVAC --version 2>/dev/null. */
584 child = create_pipe_in (javac, "/bin/sh", argv, DEV_NULL, true, true,
589 /* Retrieve its result. */
590 fp = fdopen (fd[0], "r");
594 line = NULL; linesize = 0;
595 linelen = getline (&line, &linesize, fp);
596 if (linelen == (size_t)(-1))
601 /* It is safe to call c_strstr() instead of strstr() here; see the
602 comments in c-strstr.h. */
603 envjavac_gcj = (c_strstr (line, "gcj") != NULL);
607 /* Remove zombie process from process list, and retrieve exit status. */
609 wait_subprocess (child, javac, true, true, true, false, NULL);
611 envjavac_gcj = false;
616 envjavac_tested = true;
622 /* Return true if $JAVAC, known to be a version of gcj, is a version >= 4.3
625 is_envjavac_gcj43 (const char *javac)
627 static bool envjavac_tested;
628 static bool envjavac_gcj43;
630 if (!envjavac_tested)
632 /* Test whether $JAVAC is gcj:
633 "$JAVAC --version 2>/dev/null | sed -e 's,^[^0-9]*,,' -e 1q \
634 | sed -e '/^4\.[012]/d' | grep '^[4-9]' >/dev/null" */
635 unsigned int command_length;
647 /* Setup the command "$JAVAC --version". */
648 command_length = strlen (javac) + 1 + 9 + 1;
649 command = (char *) xmalloca (command_length);
651 /* Don't shell_quote $JAVAC, because it may consist of a command
653 memcpy (p, javac, strlen (javac));
655 memcpy (p, " --version", 1 + 9 + 1);
657 /* Ensure command_length was correctly calculated. */
658 if (p - command > command_length)
661 /* Call $JAVAC --version 2>/dev/null. */
666 child = create_pipe_in (javac, "/bin/sh", argv, DEV_NULL, true, true,
671 /* Retrieve its result. */
672 fp = fdopen (fd[0], "r");
676 line = NULL; linesize = 0;
677 linelen = getline (&line, &linesize, fp);
678 if (linelen == (size_t)(-1))
684 while (*p != '\0' && !(*p >= '0' && *p <= '9'))
687 !(*p == '4' && p[1] == '.' && p[2] >= '0' && p[2] <= '2')
688 && (*p >= '4' && *p <= '9');
692 /* Remove zombie process from process list, and retrieve exit status. */
694 wait_subprocess (child, javac, true, true, true, false, NULL);
696 envjavac_gcj43 = false;
701 envjavac_tested = true;
704 return envjavac_gcj43;
707 /* Test whether $JAVAC, known to be a version of gcj >= 4.3, can be used, and
708 whether it needs a -fsource and/or -ftarget option.
709 Return a failure indicator (true upon error). */
711 is_envjavac_gcj43_usable (const char *javac,
712 const char *source_version,
713 const char *target_version,
715 bool *fsource_option_p, bool *ftarget_option_p)
717 /* The cache depends on the source_version and target_version. */
725 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
726 struct result_t *resultp;
728 resultp = &result_cache[source_version_index (source_version)]
729 [target_version_index (target_version)];
730 if (!resultp->tested)
733 struct temp_dir *tmpdir;
734 char *conftest_file_name;
735 char *compiled_file_name;
736 const char *java_sources[1];
739 tmpdir = create_temp_dir ("java", NULL, false);
744 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
745 if (write_temp_file (tmpdir, conftest_file_name,
746 get_goodcode_snippet (source_version)))
748 free (conftest_file_name);
749 cleanup_temp_dir (tmpdir);
754 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
755 register_temp_file (tmpdir, compiled_file_name);
757 java_sources[0] = conftest_file_name;
758 if (!compile_using_envjavac (javac,
759 java_sources, 1, tmpdir->dir_name,
760 false, false, false, true)
761 && stat (compiled_file_name, &statbuf) >= 0
762 && get_classfile_version (compiled_file_name)
763 <= corresponding_classfile_version (target_version))
765 /* $JAVAC compiled conftest.java successfully. */
766 /* Try adding -fsource option if it is useful. */
768 xasprintf ("%s -fsource=%s", javac, source_version);
770 unlink (compiled_file_name);
772 java_sources[0] = conftest_file_name;
773 if (!compile_using_envjavac (javac_source,
774 java_sources, 1, tmpdir->dir_name,
775 false, false, false, true)
776 && stat (compiled_file_name, &statbuf) >= 0
777 && get_classfile_version (compiled_file_name)
778 <= corresponding_classfile_version (target_version))
780 const char *failcode = get_failcode_snippet (source_version);
782 if (failcode != NULL)
784 free (compiled_file_name);
785 free (conftest_file_name);
788 xconcatenated_filename (tmpdir->dir_name,
791 if (write_temp_file (tmpdir, conftest_file_name, failcode))
793 free (conftest_file_name);
795 cleanup_temp_dir (tmpdir);
800 xconcatenated_filename (tmpdir->dir_name,
801 "conftestfail.class",
803 register_temp_file (tmpdir, compiled_file_name);
805 java_sources[0] = conftest_file_name;
806 if (!compile_using_envjavac (javac,
809 false, false, false, true)
810 && stat (compiled_file_name, &statbuf) >= 0)
812 unlink (compiled_file_name);
814 java_sources[0] = conftest_file_name;
815 if (compile_using_envjavac (javac_source,
818 false, false, false, true))
819 /* $JAVAC compiled conftestfail.java successfully, and
820 "$JAVAC -fsource=$source_version" rejects it. So
821 the -fsource option is useful. */
822 resultp->fsource_option = true;
829 resultp->usable = true;
833 /* Try with -fsource and -ftarget options. */
835 xasprintf ("%s -fsource=%s -ftarget=%s",
836 javac, source_version, target_version);
838 unlink (compiled_file_name);
840 java_sources[0] = conftest_file_name;
841 if (!compile_using_envjavac (javac_target,
842 java_sources, 1, tmpdir->dir_name,
843 false, false, false, true)
844 && stat (compiled_file_name, &statbuf) >= 0
845 && get_classfile_version (compiled_file_name)
846 <= corresponding_classfile_version (target_version))
848 /* "$JAVAC -fsource $source_version -ftarget $target_version"
849 compiled conftest.java successfully. */
850 resultp->fsource_option = true;
851 resultp->ftarget_option = true;
852 resultp->usable = true;
858 free (compiled_file_name);
859 free (conftest_file_name);
861 resultp->tested = true;
864 *usablep = resultp->usable;
865 *fsource_option_p = resultp->fsource_option;
866 *ftarget_option_p = resultp->ftarget_option;
870 /* Test whether $JAVAC, known to be a version of gcj < 4.3, can be used for
871 compiling with target_version = 1.4 and source_version = 1.4.
872 Return a failure indicator (true upon error). */
874 is_envjavac_oldgcj_14_14_usable (const char *javac, bool *usablep)
876 static bool envjavac_tested;
877 static bool envjavac_usable;
879 if (!envjavac_tested)
882 struct temp_dir *tmpdir;
883 char *conftest_file_name;
884 char *compiled_file_name;
885 const char *java_sources[1];
888 tmpdir = create_temp_dir ("java", NULL, false);
893 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
894 if (write_temp_file (tmpdir, conftest_file_name,
895 get_goodcode_snippet ("1.4")))
897 free (conftest_file_name);
898 cleanup_temp_dir (tmpdir);
903 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
904 register_temp_file (tmpdir, compiled_file_name);
906 java_sources[0] = conftest_file_name;
907 if (!compile_using_envjavac (javac, java_sources, 1, tmpdir->dir_name,
908 false, false, false, true)
909 && stat (compiled_file_name, &statbuf) >= 0)
910 /* Compilation succeeded. */
911 envjavac_usable = true;
913 free (compiled_file_name);
914 free (conftest_file_name);
916 cleanup_temp_dir (tmpdir);
918 envjavac_tested = true;
921 *usablep = envjavac_usable;
925 /* Test whether $JAVAC, known to be a version of gcj < 4.3, can be used for
926 compiling with target_version = 1.4 and source_version = 1.3.
927 Return a failure indicator (true upon error). */
929 is_envjavac_oldgcj_14_13_usable (const char *javac,
930 bool *usablep, bool *need_no_assert_option_p)
932 static bool envjavac_tested;
933 static bool envjavac_usable;
934 static bool envjavac_need_no_assert_option;
936 if (!envjavac_tested)
938 /* Try $JAVAC and "$JAVAC -fno-assert". But add -fno-assert only if
939 it makes a difference. (It could already be part of $JAVAC.) */
940 struct temp_dir *tmpdir;
941 char *conftest_file_name;
942 char *compiled_file_name;
943 const char *java_sources[1];
946 char *javac_noassert;
947 bool javac_noassert_works;
949 tmpdir = create_temp_dir ("java", NULL, false);
954 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
955 if (write_temp_file (tmpdir, conftest_file_name,
956 get_goodcode_snippet ("1.3")))
958 free (conftest_file_name);
959 cleanup_temp_dir (tmpdir);
964 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
965 register_temp_file (tmpdir, compiled_file_name);
967 java_sources[0] = conftest_file_name;
968 if (!compile_using_envjavac (javac,
969 java_sources, 1, tmpdir->dir_name,
970 false, false, false, true)
971 && stat (compiled_file_name, &statbuf) >= 0)
972 /* Compilation succeeded. */
977 unlink (compiled_file_name);
979 javac_noassert = xasprintf ("%s -fno-assert", javac);
981 java_sources[0] = conftest_file_name;
982 if (!compile_using_envjavac (javac_noassert,
983 java_sources, 1, tmpdir->dir_name,
984 false, false, false, true)
985 && stat (compiled_file_name, &statbuf) >= 0)
986 /* Compilation succeeded. */
987 javac_noassert_works = true;
989 javac_noassert_works = false;
991 free (compiled_file_name);
992 free (conftest_file_name);
994 if (javac_works && javac_noassert_works)
997 xconcatenated_filename (tmpdir->dir_name, "conftestfail.java",
999 if (write_temp_file (tmpdir, conftest_file_name,
1000 get_failcode_snippet ("1.3")))
1002 free (conftest_file_name);
1003 free (javac_noassert);
1004 cleanup_temp_dir (tmpdir);
1008 compiled_file_name =
1009 xconcatenated_filename (tmpdir->dir_name, "conftestfail.class",
1011 register_temp_file (tmpdir, compiled_file_name);
1013 java_sources[0] = conftest_file_name;
1014 if (!compile_using_envjavac (javac,
1015 java_sources, 1, tmpdir->dir_name,
1016 false, false, false, true)
1017 && stat (compiled_file_name, &statbuf) >= 0)
1019 /* Compilation succeeded. */
1020 unlink (compiled_file_name);
1022 java_sources[0] = conftest_file_name;
1023 if (!(!compile_using_envjavac (javac_noassert,
1024 java_sources, 1, tmpdir->dir_name,
1025 false, false, false, true)
1026 && stat (compiled_file_name, &statbuf) >= 0))
1027 /* Compilation failed. */
1028 /* "$JAVAC -fno-assert" works better than $JAVAC. */
1032 free (compiled_file_name);
1033 free (conftest_file_name);
1036 cleanup_temp_dir (tmpdir);
1040 envjavac_usable = true;
1041 envjavac_need_no_assert_option = false;
1043 else if (javac_noassert_works)
1045 envjavac_usable = true;
1046 envjavac_need_no_assert_option = true;
1049 envjavac_tested = true;
1052 *usablep = envjavac_usable;
1053 *need_no_assert_option_p = envjavac_need_no_assert_option;
1057 /* Test whether $JAVAC, known to be not a version of gcj, can be used, and
1058 whether it needs a -source and/or -target option.
1059 Return a failure indicator (true upon error). */
1061 is_envjavac_nongcj_usable (const char *javac,
1062 const char *source_version,
1063 const char *target_version,
1065 bool *source_option_p, bool *target_option_p)
1067 /* The cache depends on the source_version and target_version. */
1075 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
1076 struct result_t *resultp;
1078 resultp = &result_cache[source_version_index (source_version)]
1079 [target_version_index (target_version)];
1080 if (!resultp->tested)
1083 struct temp_dir *tmpdir;
1084 char *conftest_file_name;
1085 char *compiled_file_name;
1086 const char *java_sources[1];
1087 struct stat statbuf;
1089 tmpdir = create_temp_dir ("java", NULL, false);
1093 conftest_file_name =
1094 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1095 if (write_temp_file (tmpdir, conftest_file_name,
1096 get_goodcode_snippet (source_version)))
1098 free (conftest_file_name);
1099 cleanup_temp_dir (tmpdir);
1103 compiled_file_name =
1104 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1105 register_temp_file (tmpdir, compiled_file_name);
1107 java_sources[0] = conftest_file_name;
1108 if (!compile_using_envjavac (javac,
1109 java_sources, 1, tmpdir->dir_name,
1110 false, false, false, true)
1111 && stat (compiled_file_name, &statbuf) >= 0
1112 && get_classfile_version (compiled_file_name)
1113 <= corresponding_classfile_version (target_version))
1115 /* $JAVAC compiled conftest.java successfully. */
1116 /* Try adding -source option if it is useful. */
1117 char *javac_source =
1118 xasprintf ("%s -source %s", javac, source_version);
1120 unlink (compiled_file_name);
1122 java_sources[0] = conftest_file_name;
1123 if (!compile_using_envjavac (javac_source,
1124 java_sources, 1, tmpdir->dir_name,
1125 false, false, false, true)
1126 && stat (compiled_file_name, &statbuf) >= 0
1127 && get_classfile_version (compiled_file_name)
1128 <= corresponding_classfile_version (target_version))
1130 const char *failcode = get_failcode_snippet (source_version);
1132 if (failcode != NULL)
1134 free (compiled_file_name);
1135 free (conftest_file_name);
1137 conftest_file_name =
1138 xconcatenated_filename (tmpdir->dir_name,
1139 "conftestfail.java",
1141 if (write_temp_file (tmpdir, conftest_file_name, failcode))
1143 free (conftest_file_name);
1144 free (javac_source);
1145 cleanup_temp_dir (tmpdir);
1149 compiled_file_name =
1150 xconcatenated_filename (tmpdir->dir_name,
1151 "conftestfail.class",
1153 register_temp_file (tmpdir, compiled_file_name);
1155 java_sources[0] = conftest_file_name;
1156 if (!compile_using_envjavac (javac,
1159 false, false, false, true)
1160 && stat (compiled_file_name, &statbuf) >= 0)
1162 unlink (compiled_file_name);
1164 java_sources[0] = conftest_file_name;
1165 if (compile_using_envjavac (javac_source,
1168 false, false, false, true))
1169 /* $JAVAC compiled conftestfail.java successfully, and
1170 "$JAVAC -source $source_version" rejects it. So the
1171 -source option is useful. */
1172 resultp->source_option = true;
1177 free (javac_source);
1179 resultp->usable = true;
1183 /* Try with -target option alone. (Sun javac 1.3.1 has the -target
1184 option but no -source option.) */
1185 char *javac_target =
1186 xasprintf ("%s -target %s", javac, target_version);
1188 unlink (compiled_file_name);
1190 java_sources[0] = conftest_file_name;
1191 if (!compile_using_envjavac (javac_target,
1192 java_sources, 1, tmpdir->dir_name,
1193 false, false, false, true)
1194 && stat (compiled_file_name, &statbuf) >= 0
1195 && get_classfile_version (compiled_file_name)
1196 <= corresponding_classfile_version (target_version))
1198 /* "$JAVAC -target $target_version" compiled conftest.java
1200 /* Try adding -source option if it is useful. */
1201 char *javac_target_source =
1202 xasprintf ("%s -source %s", javac_target, source_version);
1204 unlink (compiled_file_name);
1206 java_sources[0] = conftest_file_name;
1207 if (!compile_using_envjavac (javac_target_source,
1208 java_sources, 1, tmpdir->dir_name,
1209 false, false, false, true)
1210 && stat (compiled_file_name, &statbuf) >= 0
1211 && get_classfile_version (compiled_file_name)
1212 <= corresponding_classfile_version (target_version))
1214 const char *failcode = get_failcode_snippet (source_version);
1216 if (failcode != NULL)
1218 free (compiled_file_name);
1219 free (conftest_file_name);
1221 conftest_file_name =
1222 xconcatenated_filename (tmpdir->dir_name,
1223 "conftestfail.java",
1225 if (write_temp_file (tmpdir, conftest_file_name,
1228 free (conftest_file_name);
1229 free (javac_target_source);
1230 free (javac_target);
1231 cleanup_temp_dir (tmpdir);
1235 compiled_file_name =
1236 xconcatenated_filename (tmpdir->dir_name,
1237 "conftestfail.class",
1239 register_temp_file (tmpdir, compiled_file_name);
1241 java_sources[0] = conftest_file_name;
1242 if (!compile_using_envjavac (javac_target,
1245 false, false, false, true)
1246 && stat (compiled_file_name, &statbuf) >= 0)
1248 unlink (compiled_file_name);
1250 java_sources[0] = conftest_file_name;
1251 if (compile_using_envjavac (javac_target_source,
1254 false, false, false,
1256 /* "$JAVAC -target $target_version" compiled
1257 conftestfail.java successfully, and
1258 "$JAVAC -target $target_version -source $source_version"
1259 rejects it. So the -source option is useful. */
1260 resultp->source_option = true;
1265 free (javac_target_source);
1267 resultp->target_option = true;
1268 resultp->usable = true;
1272 /* Maybe this -target option requires a -source option? Try with
1273 -target and -source options. (Supported by Sun javac 1.4 and
1275 char *javac_target_source =
1276 xasprintf ("%s -source %s", javac_target, source_version);
1278 unlink (compiled_file_name);
1280 java_sources[0] = conftest_file_name;
1281 if (!compile_using_envjavac (javac_target_source,
1282 java_sources, 1, tmpdir->dir_name,
1283 false, false, false, true)
1284 && stat (compiled_file_name, &statbuf) >= 0
1285 && get_classfile_version (compiled_file_name)
1286 <= corresponding_classfile_version (target_version))
1288 /* "$JAVAC -target $target_version -source $source_version"
1289 compiled conftest.java successfully. */
1290 resultp->source_option = true;
1291 resultp->target_option = true;
1292 resultp->usable = true;
1295 free (javac_target_source);
1298 free (javac_target);
1301 free (compiled_file_name);
1302 free (conftest_file_name);
1304 resultp->tested = true;
1307 *usablep = resultp->usable;
1308 *source_option_p = resultp->source_option;
1309 *target_option_p = resultp->target_option;
1314 is_gcj_present (void)
1316 static bool gcj_tested;
1317 static bool gcj_present;
1321 /* Test for presence of gcj:
1322 "gcj --version 2> /dev/null | \
1323 sed -e 's,^[^0-9]*,,' -e 1q | \
1324 sed -e '/^3\.[01]/d' | grep '^[3-9]' > /dev/null" */
1331 argv[1] = "--version";
1333 child = create_pipe_in ("gcj", "gcj", argv, DEV_NULL, true, true,
1335 gcj_present = false;
1338 /* Read the subprocess output, drop all lines except the first,
1339 drop all characters before the first digit, and test whether
1340 the remaining string starts with a digit >= 3, but not with
1345 while (safe_read (fd[0], &c[count], 1) > 0)
1347 if (c[count] == '\n')
1351 if (!(c[0] >= '0' && c[0] <= '9'))
1353 gcj_present = (c[0] >= '3');
1358 if (c[0] == '3' && c[1] == '.'
1359 && (c[2] == '0' || c[2] == '1'))
1360 gcj_present = false;
1364 while (safe_read (fd[0], &c[0], 1) > 0)
1369 /* Remove zombie process from process list, and retrieve exit
1372 wait_subprocess (child, "gcj", false, true, true, false, NULL);
1373 if (exitstatus != 0)
1374 gcj_present = false;
1379 /* See if libgcj.jar is well installed. */
1380 struct temp_dir *tmpdir;
1382 tmpdir = create_temp_dir ("java", NULL, false);
1384 gcj_present = false;
1387 char *conftest_file_name;
1389 conftest_file_name =
1390 xconcatenated_filename (tmpdir->dir_name, "conftestlib.java",
1392 if (write_temp_file (tmpdir, conftest_file_name,
1393 "public class conftestlib {\n"
1394 " public static void main (String[] args) {\n"
1397 gcj_present = false;
1400 char *compiled_file_name;
1401 const char *java_sources[1];
1403 compiled_file_name =
1404 xconcatenated_filename (tmpdir->dir_name,
1405 "conftestlib.class",
1407 register_temp_file (tmpdir, compiled_file_name);
1409 java_sources[0] = conftest_file_name;
1410 if (compile_using_gcj (java_sources, 1, false,
1411 false, NULL, false, NULL,
1413 false, false, false, true))
1414 gcj_present = false;
1416 free (compiled_file_name);
1418 free (conftest_file_name);
1420 cleanup_temp_dir (tmpdir);
1432 static bool gcj_tested;
1437 /* Test for presence of gcj:
1438 "gcj --version 2> /dev/null | \
1439 sed -e 's,^[^0-9]*,,' -e 1q | \
1440 sed -e '/^4\.[012]/d' | grep '^[4-9]'" */
1447 argv[1] = "--version";
1449 child = create_pipe_in ("gcj", "gcj", argv, DEV_NULL, true, true,
1454 /* Read the subprocess output, drop all lines except the first,
1455 drop all characters before the first digit, and test whether
1456 the remaining string starts with a digit >= 4, but not with
1457 "4.0" or "4.1" or "4.2". */
1461 while (safe_read (fd[0], &c[count], 1) > 0)
1463 if (c[count] == '\n')
1467 if (!(c[0] >= '0' && c[0] <= '9'))
1469 gcj_43 = (c[0] >= '4');
1474 if (c[0] == '4' && c[1] == '.' && c[2] >= '0' && c[2] <= '2')
1479 while (safe_read (fd[0], &c[0], 1) > 0)
1484 /* Remove zombie process from process list, and retrieve exit
1487 wait_subprocess (child, "gcj", false, true, true, false, NULL);
1488 if (exitstatus != 0)
1498 /* Test whether gcj >= 4.3 can be used, and whether it needs a -fsource and/or
1500 Return a failure indicator (true upon error). */
1502 is_gcj43_usable (const char *source_version,
1503 const char *target_version,
1505 bool *fsource_option_p, bool *ftarget_option_p)
1507 /* The cache depends on the source_version and target_version. */
1512 bool fsource_option;
1513 bool ftarget_option;
1515 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
1516 struct result_t *resultp;
1518 resultp = &result_cache[source_version_index (source_version)]
1519 [target_version_index (target_version)];
1520 if (!resultp->tested)
1523 struct temp_dir *tmpdir;
1524 char *conftest_file_name;
1525 char *compiled_file_name;
1526 const char *java_sources[1];
1527 struct stat statbuf;
1529 tmpdir = create_temp_dir ("java", NULL, false);
1533 conftest_file_name =
1534 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1535 if (write_temp_file (tmpdir, conftest_file_name,
1536 get_goodcode_snippet (source_version)))
1538 free (conftest_file_name);
1539 cleanup_temp_dir (tmpdir);
1543 compiled_file_name =
1544 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1545 register_temp_file (tmpdir, compiled_file_name);
1547 java_sources[0] = conftest_file_name;
1548 if (!compile_using_gcj (java_sources, 1, false, false, NULL, false, NULL,
1549 tmpdir->dir_name, false, false, false, true)
1550 && stat (compiled_file_name, &statbuf) >= 0
1551 && get_classfile_version (compiled_file_name)
1552 <= corresponding_classfile_version (target_version))
1554 /* gcj compiled conftest.java successfully. */
1555 /* Try adding -fsource option if it is useful. */
1556 unlink (compiled_file_name);
1558 java_sources[0] = conftest_file_name;
1559 if (!compile_using_gcj (java_sources, 1,
1560 false, true, source_version, false, NULL,
1561 tmpdir->dir_name, false, false, false, true)
1562 && stat (compiled_file_name, &statbuf) >= 0
1563 && get_classfile_version (compiled_file_name)
1564 <= corresponding_classfile_version (target_version))
1566 const char *failcode = get_failcode_snippet (source_version);
1568 if (failcode != NULL)
1570 free (compiled_file_name);
1571 free (conftest_file_name);
1573 conftest_file_name =
1574 xconcatenated_filename (tmpdir->dir_name,
1575 "conftestfail.java",
1577 if (write_temp_file (tmpdir, conftest_file_name, failcode))
1579 free (conftest_file_name);
1580 cleanup_temp_dir (tmpdir);
1584 compiled_file_name =
1585 xconcatenated_filename (tmpdir->dir_name,
1586 "conftestfail.class",
1588 register_temp_file (tmpdir, compiled_file_name);
1590 java_sources[0] = conftest_file_name;
1591 if (!compile_using_gcj (java_sources, 1,
1592 false, false, NULL, false, NULL,
1594 false, false, false, true)
1595 && stat (compiled_file_name, &statbuf) >= 0)
1597 unlink (compiled_file_name);
1599 java_sources[0] = conftest_file_name;
1600 if (compile_using_gcj (java_sources, 1,
1601 false, true, source_version,
1604 false, false, false, true))
1605 /* gcj compiled conftestfail.java successfully, and
1606 "gcj -fsource=$source_version" rejects it. So
1607 the -fsource option is useful. */
1608 resultp->fsource_option = true;
1613 resultp->usable = true;
1617 /* Try with -fsource and -ftarget options. */
1618 unlink (compiled_file_name);
1620 java_sources[0] = conftest_file_name;
1621 if (!compile_using_gcj (java_sources, 1,
1622 false, true, source_version,
1623 true, target_version,
1625 false, false, false, true)
1626 && stat (compiled_file_name, &statbuf) >= 0
1627 && get_classfile_version (compiled_file_name)
1628 <= corresponding_classfile_version (target_version))
1630 /* "gcj -fsource $source_version -ftarget $target_version"
1631 compiled conftest.java successfully. */
1632 resultp->fsource_option = true;
1633 resultp->ftarget_option = true;
1634 resultp->usable = true;
1638 free (compiled_file_name);
1639 free (conftest_file_name);
1641 resultp->tested = true;
1644 *usablep = resultp->usable;
1645 *fsource_option_p = resultp->fsource_option;
1646 *ftarget_option_p = resultp->ftarget_option;
1650 /* Test whether gcj < 4.3 can be used for compiling with target_version = 1.4
1651 and source_version = 1.4.
1652 Return a failure indicator (true upon error). */
1654 is_oldgcj_14_14_usable (bool *usablep)
1656 static bool gcj_tested;
1657 static bool gcj_usable;
1662 struct temp_dir *tmpdir;
1663 char *conftest_file_name;
1664 char *compiled_file_name;
1665 const char *java_sources[1];
1666 struct stat statbuf;
1668 tmpdir = create_temp_dir ("java", NULL, false);
1672 conftest_file_name =
1673 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1674 if (write_temp_file (tmpdir, conftest_file_name,
1675 get_goodcode_snippet ("1.4")))
1677 free (conftest_file_name);
1678 cleanup_temp_dir (tmpdir);
1682 compiled_file_name =
1683 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1684 register_temp_file (tmpdir, compiled_file_name);
1686 java_sources[0] = conftest_file_name;
1687 if (!compile_using_gcj (java_sources, 1, false, false, NULL, false, NULL,
1688 tmpdir->dir_name, false, false, false, true)
1689 && stat (compiled_file_name, &statbuf) >= 0)
1690 /* Compilation succeeded. */
1693 free (compiled_file_name);
1694 free (conftest_file_name);
1696 cleanup_temp_dir (tmpdir);
1701 *usablep = gcj_usable;
1705 /* Test whether gcj < 4.3 can be used for compiling with target_version = 1.4
1706 and source_version = 1.3.
1707 Return a failure indicator (true upon error). */
1709 is_oldgcj_14_13_usable (bool *usablep, bool *need_no_assert_option_p)
1711 static bool gcj_tested;
1712 static bool gcj_usable;
1713 static bool gcj_need_no_assert_option;
1717 /* Try gcj and "gcj -fno-assert". But add -fno-assert only if
1718 it works (not gcj < 3.3). */
1719 struct temp_dir *tmpdir;
1720 char *conftest_file_name;
1721 char *compiled_file_name;
1722 const char *java_sources[1];
1723 struct stat statbuf;
1725 tmpdir = create_temp_dir ("java", NULL, false);
1729 conftest_file_name =
1730 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1731 if (write_temp_file (tmpdir, conftest_file_name,
1732 get_goodcode_snippet ("1.3")))
1734 free (conftest_file_name);
1735 cleanup_temp_dir (tmpdir);
1739 compiled_file_name =
1740 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1741 register_temp_file (tmpdir, compiled_file_name);
1743 java_sources[0] = conftest_file_name;
1744 if (!compile_using_gcj (java_sources, 1, true, false, NULL, false, NULL,
1745 tmpdir->dir_name, false, false, false, true)
1746 && stat (compiled_file_name, &statbuf) >= 0)
1747 /* Compilation succeeded. */
1750 gcj_need_no_assert_option = true;
1754 unlink (compiled_file_name);
1756 java_sources[0] = conftest_file_name;
1757 if (!compile_using_gcj (java_sources, 1, false,
1758 false, NULL, false, NULL,
1759 tmpdir->dir_name, false, false, false, true)
1760 && stat (compiled_file_name, &statbuf) >= 0)
1761 /* Compilation succeeded. */
1764 gcj_need_no_assert_option = false;
1768 free (compiled_file_name);
1769 free (conftest_file_name);
1771 cleanup_temp_dir (tmpdir);
1776 *usablep = gcj_usable;
1777 *need_no_assert_option_p = gcj_need_no_assert_option;
1782 is_javac_present (void)
1784 static bool javac_tested;
1785 static bool javac_present;
1789 /* Test for presence of javac: "javac 2> /dev/null ; test $? -le 2" */
1795 exitstatus = execute ("javac", "javac", argv, false, false, true, true,
1797 javac_present = (exitstatus == 0 || exitstatus == 1 || exitstatus == 2);
1798 javac_tested = true;
1801 return javac_present;
1804 /* Test whether javac can be used and whether it needs a -source and/or
1806 Return a failure indicator (true upon error). */
1808 is_javac_usable (const char *source_version, const char *target_version,
1809 bool *usablep, bool *source_option_p, bool *target_option_p)
1811 /* The cache depends on the source_version and target_version. */
1819 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
1820 struct result_t *resultp;
1822 resultp = &result_cache[source_version_index (source_version)]
1823 [target_version_index (target_version)];
1824 if (!resultp->tested)
1827 struct temp_dir *tmpdir;
1828 char *conftest_file_name;
1829 char *compiled_file_name;
1830 const char *java_sources[1];
1831 struct stat statbuf;
1833 tmpdir = create_temp_dir ("java", NULL, false);
1837 conftest_file_name =
1838 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1839 if (write_temp_file (tmpdir, conftest_file_name,
1840 get_goodcode_snippet (source_version)))
1842 free (conftest_file_name);
1843 cleanup_temp_dir (tmpdir);
1847 compiled_file_name =
1848 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1849 register_temp_file (tmpdir, compiled_file_name);
1851 java_sources[0] = conftest_file_name;
1852 if (!compile_using_javac (java_sources, 1,
1853 false, source_version,
1854 false, target_version,
1855 tmpdir->dir_name, false, false, false, true)
1856 && stat (compiled_file_name, &statbuf) >= 0
1857 && get_classfile_version (compiled_file_name)
1858 <= corresponding_classfile_version (target_version))
1860 /* javac compiled conftest.java successfully. */
1861 /* Try adding -source option if it is useful. */
1862 unlink (compiled_file_name);
1864 java_sources[0] = conftest_file_name;
1865 if (!compile_using_javac (java_sources, 1,
1866 true, source_version,
1867 false, target_version,
1868 tmpdir->dir_name, false, false, false, true)
1869 && stat (compiled_file_name, &statbuf) >= 0
1870 && get_classfile_version (compiled_file_name)
1871 <= corresponding_classfile_version (target_version))
1873 const char *failcode = get_failcode_snippet (source_version);
1875 if (failcode != NULL)
1877 free (compiled_file_name);
1878 free (conftest_file_name);
1880 conftest_file_name =
1881 xconcatenated_filename (tmpdir->dir_name,
1882 "conftestfail.java",
1884 if (write_temp_file (tmpdir, conftest_file_name, failcode))
1886 free (conftest_file_name);
1887 cleanup_temp_dir (tmpdir);
1891 compiled_file_name =
1892 xconcatenated_filename (tmpdir->dir_name,
1893 "conftestfail.class",
1895 register_temp_file (tmpdir, compiled_file_name);
1897 java_sources[0] = conftest_file_name;
1898 if (!compile_using_javac (java_sources, 1,
1899 false, source_version,
1900 false, target_version,
1902 false, false, false, true)
1903 && stat (compiled_file_name, &statbuf) >= 0)
1905 unlink (compiled_file_name);
1907 java_sources[0] = conftest_file_name;
1908 if (compile_using_javac (java_sources, 1,
1909 true, source_version,
1910 false, target_version,
1912 false, false, false, true))
1913 /* javac compiled conftestfail.java successfully, and
1914 "javac -source $source_version" rejects it. So the
1915 -source option is useful. */
1916 resultp->source_option = true;
1921 resultp->usable = true;
1925 /* Try with -target option alone. (Sun javac 1.3.1 has the -target
1926 option but no -source option.) */
1927 unlink (compiled_file_name);
1929 java_sources[0] = conftest_file_name;
1930 if (!compile_using_javac (java_sources, 1,
1931 false, source_version,
1932 true, target_version,
1934 false, false, false, true)
1935 && stat (compiled_file_name, &statbuf) >= 0
1936 && get_classfile_version (compiled_file_name)
1937 <= corresponding_classfile_version (target_version))
1939 /* "javac -target $target_version" compiled conftest.java
1941 /* Try adding -source option if it is useful. */
1942 unlink (compiled_file_name);
1944 java_sources[0] = conftest_file_name;
1945 if (!compile_using_javac (java_sources, 1,
1946 true, source_version,
1947 true, target_version,
1949 false, false, false, true)
1950 && stat (compiled_file_name, &statbuf) >= 0
1951 && get_classfile_version (compiled_file_name)
1952 <= corresponding_classfile_version (target_version))
1954 const char *failcode = get_failcode_snippet (source_version);
1956 if (failcode != NULL)
1958 free (compiled_file_name);
1959 free (conftest_file_name);
1961 conftest_file_name =
1962 xconcatenated_filename (tmpdir->dir_name,
1963 "conftestfail.java",
1965 if (write_temp_file (tmpdir, conftest_file_name,
1968 free (conftest_file_name);
1969 cleanup_temp_dir (tmpdir);
1973 compiled_file_name =
1974 xconcatenated_filename (tmpdir->dir_name,
1975 "conftestfail.class",
1977 register_temp_file (tmpdir, compiled_file_name);
1979 java_sources[0] = conftest_file_name;
1980 if (!compile_using_javac (java_sources, 1,
1981 false, source_version,
1982 true, target_version,
1984 false, false, false, true)
1985 && stat (compiled_file_name, &statbuf) >= 0)
1987 unlink (compiled_file_name);
1989 java_sources[0] = conftest_file_name;
1990 if (compile_using_javac (java_sources, 1,
1991 true, source_version,
1992 true, target_version,
1994 false, false, false, true))
1995 /* "javac -target $target_version" compiled
1996 conftestfail.java successfully, and
1997 "javac -target $target_version -source $source_version"
1998 rejects it. So the -source option is useful. */
1999 resultp->source_option = true;
2004 resultp->target_option = true;
2005 resultp->usable = true;
2009 /* Maybe this -target option requires a -source option? Try with
2010 -target and -source options. (Supported by Sun javac 1.4 and
2012 unlink (compiled_file_name);
2014 java_sources[0] = conftest_file_name;
2015 if (!compile_using_javac (java_sources, 1,
2016 true, source_version,
2017 true, target_version,
2019 false, false, false, true)
2020 && stat (compiled_file_name, &statbuf) >= 0
2021 && get_classfile_version (compiled_file_name)
2022 <= corresponding_classfile_version (target_version))
2024 /* "javac -target $target_version -source $source_version"
2025 compiled conftest.java successfully. */
2026 resultp->source_option = true;
2027 resultp->target_option = true;
2028 resultp->usable = true;
2033 free (compiled_file_name);
2034 free (conftest_file_name);
2036 resultp->tested = true;
2039 *usablep = resultp->usable;
2040 *source_option_p = resultp->source_option;
2041 *target_option_p = resultp->target_option;
2046 is_jikes_present (void)
2048 static bool jikes_tested;
2049 static bool jikes_present;
2053 /* Test for presence of jikes: "jikes 2> /dev/null ; test $? = 1" */
2059 exitstatus = execute ("jikes", "jikes", argv, false, false, true, true,
2061 jikes_present = (exitstatus == 0 || exitstatus == 1);
2062 jikes_tested = true;
2065 return jikes_present;
2068 /* ============================= Main function ============================= */
2071 compile_java_class (const char * const *java_sources,
2072 unsigned int java_sources_count,
2073 const char * const *classpaths,
2074 unsigned int classpaths_count,
2075 const char *source_version,
2076 const char *target_version,
2077 const char *directory,
2078 bool optimize, bool debug,
2079 bool use_minimal_classpath,
2083 char *old_JAVA_HOME;
2086 const char *javac = getenv ("JAVAC");
2087 if (javac != NULL && javac[0] != '\0')
2089 bool usable = false;
2090 bool no_assert_option = false;
2091 bool source_option = false;
2092 bool target_option = false;
2093 bool fsource_option = false;
2094 bool ftarget_option = false;
2096 if (target_version == NULL)
2097 target_version = default_target_version ();
2099 if (is_envjavac_gcj (javac))
2101 /* It's a version of gcj. */
2102 if (is_envjavac_gcj43 (javac))
2104 /* It's a version of gcj >= 4.3. Assume the classfile versions
2106 if (is_envjavac_gcj43_usable (javac,
2107 source_version, target_version,
2109 &fsource_option, &ftarget_option))
2117 /* It's a version of gcj < 4.3. Ignore the version of the
2118 class files that it creates. */
2119 if (strcmp (target_version, "1.4") == 0
2120 && strcmp (source_version, "1.4") == 0)
2122 if (is_envjavac_oldgcj_14_14_usable (javac, &usable))
2128 else if (strcmp (target_version, "1.4") == 0
2129 && strcmp (source_version, "1.3") == 0)
2131 if (is_envjavac_oldgcj_14_13_usable (javac,
2143 /* It's not gcj. Assume the classfile versions are correct. */
2144 if (is_envjavac_nongcj_usable (javac,
2145 source_version, target_version,
2147 &source_option, &target_option))
2156 char *old_classpath;
2157 char *javac_with_options;
2159 /* Set CLASSPATH. */
2161 set_classpath (classpaths, classpaths_count, false, verbose);
2163 javac_with_options =
2165 ? xasprintf ("%s -fno-assert", javac)
2166 : xasprintf ("%s%s%s%s%s%s%s%s%s",
2168 source_option ? " -source " : "",
2169 source_option ? source_version : "",
2170 target_option ? " -target " : "",
2171 target_option ? target_version : "",
2172 fsource_option ? " -fsource=" : "",
2173 fsource_option ? source_version : "",
2174 ftarget_option ? " -ftarget=" : "",
2175 ftarget_option ? target_version : ""));
2177 err = compile_using_envjavac (javac_with_options,
2178 java_sources, java_sources_count,
2179 directory, optimize, debug, verbose,
2182 free (javac_with_options);
2184 /* Reset CLASSPATH. */
2185 reset_classpath (old_classpath);
2192 /* Unset the JAVA_HOME environment variable. */
2193 old_JAVA_HOME = getenv ("JAVA_HOME");
2194 if (old_JAVA_HOME != NULL)
2196 old_JAVA_HOME = xstrdup (old_JAVA_HOME);
2197 unsetenv ("JAVA_HOME");
2200 if (is_gcj_present ())
2202 /* It's a version of gcj. */
2203 bool usable = false;
2204 bool no_assert_option = false;
2205 bool fsource_option = false;
2206 bool ftarget_option = false;
2208 if (target_version == NULL)
2209 target_version = default_target_version ();
2213 /* It's a version of gcj >= 4.3. Assume the classfile versions
2215 if (is_gcj43_usable (source_version, target_version,
2216 &usable, &fsource_option, &ftarget_option))
2224 /* It's a version of gcj < 4.3. Ignore the version of the class
2225 files that it creates.
2226 Test whether it supports the desired target-version and
2228 if (strcmp (target_version, "1.4") == 0
2229 && strcmp (source_version, "1.4") == 0)
2231 if (is_oldgcj_14_14_usable (&usable))
2237 else if (strcmp (target_version, "1.4") == 0
2238 && strcmp (source_version, "1.3") == 0)
2240 if (is_oldgcj_14_13_usable (&usable, &no_assert_option))
2250 char *old_classpath;
2252 /* Set CLASSPATH. We could also use the --CLASSPATH=... option
2253 of gcj. Note that --classpath=... option is different: its
2254 argument should also contain gcj's libgcj.jar, but we don't
2255 know its location. */
2257 set_classpath (classpaths, classpaths_count, use_minimal_classpath,
2260 err = compile_using_gcj (java_sources, java_sources_count,
2262 fsource_option, source_version,
2263 ftarget_option, target_version,
2264 directory, optimize, debug, verbose, false);
2266 /* Reset CLASSPATH. */
2267 reset_classpath (old_classpath);
2273 if (is_javac_present ())
2275 bool usable = false;
2276 bool source_option = false;
2277 bool target_option = false;
2279 if (target_version == NULL)
2280 target_version = default_target_version ();
2282 if (is_javac_usable (source_version, target_version,
2283 &usable, &source_option, &target_option))
2291 char *old_classpath;
2293 /* Set CLASSPATH. We don't use the "-classpath ..." option because
2294 in JDK 1.1.x its argument should also contain the JDK's
2295 classes.zip, but we don't know its location. (In JDK 1.3.0 it
2298 set_classpath (classpaths, classpaths_count, use_minimal_classpath,
2301 err = compile_using_javac (java_sources, java_sources_count,
2302 source_option, source_version,
2303 target_option, target_version,
2304 directory, optimize, debug, verbose,
2307 /* Reset CLASSPATH. */
2308 reset_classpath (old_classpath);
2314 if (is_jikes_present ())
2316 /* Test whether it supports the desired target-version and
2318 bool usable = (strcmp (source_version, "1.3") == 0);
2322 char *old_classpath;
2324 /* Set CLASSPATH. We could also use the "-classpath ..." option.
2325 Since jikes doesn't come with its own standard library, it
2326 needs a classes.zip or rt.jar or libgcj.jar in the CLASSPATH.
2327 To increase the chance of success, we reuse the current CLASSPATH
2328 if the user has set it. */
2330 set_classpath (classpaths, classpaths_count, false, verbose);
2332 err = compile_using_jikes (java_sources, java_sources_count,
2333 directory, optimize, debug, verbose,
2336 /* Reset CLASSPATH. */
2337 reset_classpath (old_classpath);
2343 error (0, 0, _("Java compiler not found, try installing gcj or set $JAVAC"));
2347 if (old_JAVA_HOME != NULL)
2349 xsetenv ("JAVA_HOME", old_JAVA_HOME, 1);
2350 free (old_JAVA_HOME);