vma-iter: Add support for Android.
[gnulib.git] / lib / javacomp.c
blob53ef57140ba09b2de3e5afe53a7a89c12f64fb6e
1 /* Compile a Java program.
2 Copyright (C) 2001-2003, 2006-2019 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 <https://www.gnu.org/licenses/>. */
18 #include <config.h>
19 #include <alloca.h>
21 /* Specification. */
22 #include "javacomp.h"
24 #include <errno.h>
25 #include <limits.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
33 #include "javaversion.h"
34 #include "execute.h"
35 #include "spawn-pipe.h"
36 #include "wait-process.h"
37 #include "classpath.h"
38 #include "xsetenv.h"
39 #include "sh-quote.h"
40 #include "binary-io.h"
41 #include "safe-read.h"
42 #include "xalloc.h"
43 #include "xmalloca.h"
44 #include "concat-filename.h"
45 #include "fwriteerror.h"
46 #include "clean-temp.h"
47 #include "error.h"
48 #include "xvasprintf.h"
49 #include "c-strstr.h"
50 #include "gettext.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
61 T = test for presence
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
79 preferences,
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. */
91 static const char *
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 = "1.1";
103 else if ((java_version_cache[0] == '1'
104 && java_version_cache[1] == '.'
105 && java_version_cache[2] >= '1' && java_version_cache[2] <= '8'
106 && java_version_cache[3] == '\0')
107 || (java_version_cache[0] == '9'
108 && java_version_cache[1] == '\0')
109 || (java_version_cache[0] == '1'
110 && (java_version_cache[1] >= '0'
111 && java_version_cache[1] <= '1')
112 && java_version_cache[2] == '\0'))
113 /* It's one of the valid target version values. */
115 else if (java_version_cache[0] == '1'
116 && (java_version_cache[1] >= '2'
117 && java_version_cache[1] <= '7')
118 && java_version_cache[2] == '\0')
119 /* Assume that these (not yet released) Java versions will behave
120 like the preceding ones. */
121 java_version_cache = "11";
122 else
123 java_version_cache = "1.1";
125 return java_version_cache;
128 /* ======================= Source version dependent ======================= */
130 /* Convert a source version to an index. */
131 #define SOURCE_VERSION_BOUND 8 /* exclusive upper bound */
132 static unsigned int
133 source_version_index (const char *source_version)
135 if (source_version[0] == '1' && source_version[1] == '.')
137 if ((source_version[2] >= '3' && source_version[2] <= '5')
138 && source_version[3] == '\0')
139 return source_version[2] - '3';
140 if ((source_version[2] >= '7' && source_version[2] <= '8')
141 && source_version[3] == '\0')
142 return source_version[2] - '4';
144 else if (source_version[0] == '9' && source_version[1] == '\0')
145 return 5;
146 else if (source_version[0] == '1'
147 && (source_version[1] >= '0' && source_version[1] <= '1')
148 && source_version[2] == '\0')
149 return source_version[1] - '0' + 6;
150 error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
151 return 0;
154 /* Return a snippet of code that should compile in the given source version. */
155 static const char *
156 get_goodcode_snippet (const char *source_version)
158 if (strcmp (source_version, "1.3") == 0)
159 return "class conftest {}\n";
160 if (strcmp (source_version, "1.4") == 0)
161 return "class conftest { static { assert(true); } }\n";
162 if (strcmp (source_version, "1.5") == 0)
163 return "class conftest<T> { T foo() { return null; } }\n";
164 if (strcmp (source_version, "1.7") == 0)
165 return "class conftest { void foo () { switch (\"A\") {} } }\n";
166 if (strcmp (source_version, "1.8") == 0)
167 return "class conftest { void foo () { Runnable r = () -> {}; } }\n";
168 if (strcmp (source_version, "9") == 0)
169 return "interface conftest { private void foo () {} }\n";
170 if (strcmp (source_version, "10") == 0)
171 return "class conftest { public void m() { var i = new Integer(0); } }\n";
172 if (strcmp (source_version, "11") == 0)
173 return "class conftest { Readable r = (var b) -> 0; }\n";
174 error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
175 return NULL;
178 /* Return a snippet of code that should fail to compile in the given source
179 version, or NULL (standing for a snippet that would fail to compile with
180 any compiler). */
181 static const char *
182 get_failcode_snippet (const char *source_version)
184 if (strcmp (source_version, "1.3") == 0)
185 return "class conftestfail { static { assert(true); } }\n";
186 if (strcmp (source_version, "1.4") == 0)
187 return "class conftestfail<T> { T foo() { return null; } }\n";
188 if (strcmp (source_version, "1.5") == 0)
189 return "class conftestfail { void foo () { switch (\"A\") {} } }\n";
190 if (strcmp (source_version, "1.7") == 0)
191 return "class conftestfail { void foo () { Runnable r = () -> {}; } }\n";
192 if (strcmp (source_version, "1.8") == 0)
193 return "interface conftestfail { private void foo () {} }\n";
194 if (strcmp (source_version, "9") == 0)
195 return "class conftestfail { public void m() { var i = new Integer(0); } }\n";
196 if (strcmp (source_version, "10") == 0)
197 return "class conftestfail { Readable r = (var b) -> 0; }\n";
198 if (strcmp (source_version, "11") == 0)
199 return NULL;
200 error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
201 return NULL;
204 /* ======================= Target version dependent ======================= */
206 /* Convert a target version to an index. */
207 #define TARGET_VERSION_BOUND 11 /* exclusive upper bound */
208 static unsigned int
209 target_version_index (const char *target_version)
211 if (target_version[0] == '1' && target_version[1] == '.'
212 && (target_version[2] >= '1' && target_version[2] <= '8')
213 && target_version[3] == '\0')
214 return target_version[2] - '1';
215 else if (target_version[0] == '9' && target_version[1] == '\0')
216 return 8;
217 else if (target_version[0] == '1'
218 && (target_version[1] >= '0' && target_version[1] <= '1')
219 && target_version[2] == '\0')
220 return target_version[1] - '0' + 9;
221 error (EXIT_FAILURE, 0, _("invalid target_version argument to compile_java_class"));
222 return 0;
225 /* Return the class file version number corresponding to a given target
226 version. */
227 static int
228 corresponding_classfile_version (const char *target_version)
230 if (strcmp (target_version, "1.1") == 0)
231 return 45;
232 if (strcmp (target_version, "1.2") == 0)
233 return 46;
234 if (strcmp (target_version, "1.3") == 0)
235 return 47;
236 if (strcmp (target_version, "1.4") == 0)
237 return 48;
238 if (strcmp (target_version, "1.5") == 0)
239 return 49;
240 if (strcmp (target_version, "1.6") == 0)
241 return 50;
242 if (strcmp (target_version, "1.7") == 0)
243 return 51;
244 if (strcmp (target_version, "1.8") == 0)
245 return 52;
246 if (strcmp (target_version, "9") == 0)
247 return 53;
248 if (strcmp (target_version, "10") == 0)
249 return 54;
250 if (strcmp (target_version, "11") == 0)
251 return 55;
252 error (EXIT_FAILURE, 0, _("invalid target_version argument to compile_java_class"));
253 return 0;
256 /* Return the source version to pass to javac. */
257 static const char *
258 get_source_version_for_javac (const char *source_version,
259 const char *target_version)
261 /* The javac option '-source 1.5' has the same meaning as '-source 1.6',
262 but since Java 9 supports only the latter, prefer the latter if a
263 target_version >= 1.6 is requested. */
264 if (strcmp (source_version, "1.5") == 0
265 && !(target_version[0] == '1' && target_version[1] == '.'
266 && (target_version[2] >= '1' && target_version[2] <= '5')
267 && target_version[3] == '\0'))
268 return "1.6";
269 return source_version;
272 /* ======================== Compilation subroutines ======================== */
274 /* Try to compile a set of Java sources with $JAVAC.
275 Return a failure indicator (true upon error). */
276 static bool
277 compile_using_envjavac (const char *javac,
278 const char * const *java_sources,
279 unsigned int java_sources_count,
280 const char *directory,
281 bool optimize, bool debug,
282 bool verbose, bool null_stderr)
284 /* Because $JAVAC may consist of a command and options, we use the
285 shell. Because $JAVAC has been set by the user, we leave all
286 environment variables in place, including JAVA_HOME, and we don't
287 erase the user's CLASSPATH. */
288 bool err;
289 unsigned int command_length;
290 char *command;
291 char *argv[4];
292 int exitstatus;
293 unsigned int i;
294 char *p;
296 command_length = strlen (javac);
297 if (optimize)
298 command_length += 3;
299 if (debug)
300 command_length += 3;
301 if (directory != NULL)
302 command_length += 4 + shell_quote_length (directory);
303 for (i = 0; i < java_sources_count; i++)
304 command_length += 1 + shell_quote_length (java_sources[i]);
305 command_length += 1;
307 command = (char *) xmalloca (command_length);
308 p = command;
309 /* Don't shell_quote $JAVAC, because it may consist of a command
310 and options. */
311 memcpy (p, javac, strlen (javac));
312 p += strlen (javac);
313 if (optimize)
315 memcpy (p, " -O", 3);
316 p += 3;
318 if (debug)
320 memcpy (p, " -g", 3);
321 p += 3;
323 if (directory != NULL)
325 memcpy (p, " -d ", 4);
326 p += 4;
327 p = shell_quote_copy (p, directory);
329 for (i = 0; i < java_sources_count; i++)
331 *p++ = ' ';
332 p = shell_quote_copy (p, java_sources[i]);
334 *p++ = '\0';
335 /* Ensure command_length was correctly calculated. */
336 if (p - command > command_length)
337 abort ();
339 if (verbose)
340 printf ("%s\n", command);
342 argv[0] = BOURNE_SHELL;
343 argv[1] = "-c";
344 argv[2] = command;
345 argv[3] = NULL;
346 exitstatus = execute (javac, BOURNE_SHELL, argv, false, false, false,
347 null_stderr, true, true, NULL);
348 err = (exitstatus != 0);
350 freea (command);
352 return err;
355 /* Try to compile a set of Java sources with gcj.
356 Return a failure indicator (true upon error). */
357 static bool
358 compile_using_gcj (const char * const *java_sources,
359 unsigned int java_sources_count,
360 bool no_assert_option,
361 bool fsource_option, const char *source_version,
362 bool ftarget_option, const char *target_version,
363 const char *directory,
364 bool optimize, bool debug,
365 bool verbose, bool null_stderr)
367 bool err;
368 unsigned int argc;
369 char **argv;
370 char **argp;
371 char *fsource_arg;
372 char *ftarget_arg;
373 int exitstatus;
374 unsigned int i;
376 argc =
377 2 + (no_assert_option ? 1 : 0) + (fsource_option ? 1 : 0)
378 + (ftarget_option ? 1 : 0) + (optimize ? 1 : 0) + (debug ? 1 : 0)
379 + (directory != NULL ? 2 : 0) + java_sources_count;
380 argv = (char **) xmalloca ((argc + 1) * sizeof (char *));
382 argp = argv;
383 *argp++ = "gcj";
384 *argp++ = "-C";
385 if (no_assert_option)
386 *argp++ = "-fno-assert";
387 if (fsource_option)
389 fsource_arg = (char *) xmalloca (9 + strlen (source_version) + 1);
390 memcpy (fsource_arg, "-fsource=", 9);
391 strcpy (fsource_arg + 9, source_version);
392 *argp++ = fsource_arg;
394 else
395 fsource_arg = NULL;
396 if (ftarget_option)
398 ftarget_arg = (char *) xmalloca (9 + strlen (target_version) + 1);
399 memcpy (ftarget_arg, "-ftarget=", 9);
400 strcpy (ftarget_arg + 9, target_version);
401 *argp++ = ftarget_arg;
403 else
404 ftarget_arg = NULL;
405 if (optimize)
406 *argp++ = "-O";
407 if (debug)
408 *argp++ = "-g";
409 if (directory != NULL)
411 *argp++ = "-d";
412 *argp++ = (char *) directory;
414 for (i = 0; i < java_sources_count; i++)
415 *argp++ = (char *) java_sources[i];
416 *argp = NULL;
417 /* Ensure argv length was correctly calculated. */
418 if (argp - argv != argc)
419 abort ();
421 if (verbose)
423 char *command = shell_quote_argv (argv);
424 printf ("%s\n", command);
425 free (command);
428 exitstatus = execute ("gcj", "gcj", argv, false, false, false, null_stderr,
429 true, true, NULL);
430 err = (exitstatus != 0);
432 if (ftarget_arg != NULL)
433 freea (ftarget_arg);
434 if (fsource_arg != NULL)
435 freea (fsource_arg);
436 freea (argv);
438 return err;
441 /* Try to compile a set of Java sources with javac.
442 Return a failure indicator (true upon error). */
443 static bool
444 compile_using_javac (const char * const *java_sources,
445 unsigned int java_sources_count,
446 bool source_option, const char *source_version,
447 bool target_option, const char *target_version,
448 const char *directory,
449 bool optimize, bool debug,
450 bool verbose, bool null_stderr)
452 bool err;
453 unsigned int argc;
454 char **argv;
455 char **argp;
456 int exitstatus;
457 unsigned int i;
459 argc =
460 1 + (source_option ? 2 : 0) + (target_option ? 2 : 0) + (optimize ? 1 : 0)
461 + (debug ? 1 : 0) + (directory != NULL ? 2 : 0) + java_sources_count;
462 argv = (char **) xmalloca ((argc + 1) * sizeof (char *));
464 argp = argv;
465 *argp++ = "javac";
466 if (source_option)
468 *argp++ = "-source";
469 *argp++ = (char *) source_version;
471 if (target_option)
473 *argp++ = "-target";
474 *argp++ = (char *) target_version;
476 if (optimize)
477 *argp++ = "-O";
478 if (debug)
479 *argp++ = "-g";
480 if (directory != NULL)
482 *argp++ = "-d";
483 *argp++ = (char *) directory;
485 for (i = 0; i < java_sources_count; i++)
486 *argp++ = (char *) java_sources[i];
487 *argp = NULL;
488 /* Ensure argv length was correctly calculated. */
489 if (argp - argv != argc)
490 abort ();
492 if (verbose)
494 char *command = shell_quote_argv (argv);
495 printf ("%s\n", command);
496 free (command);
499 exitstatus = execute ("javac", "javac", argv, false, false, false,
500 null_stderr, true, true, NULL);
501 err = (exitstatus != 0);
503 freea (argv);
505 return err;
508 /* Try to compile a set of Java sources with jikes.
509 Return a failure indicator (true upon error). */
510 static bool
511 compile_using_jikes (const char * const *java_sources,
512 unsigned int java_sources_count,
513 const char *directory,
514 bool optimize, bool debug,
515 bool verbose, bool null_stderr)
517 bool err;
518 unsigned int argc;
519 char **argv;
520 char **argp;
521 int exitstatus;
522 unsigned int i;
524 argc =
525 1 + (optimize ? 1 : 0) + (debug ? 1 : 0) + (directory != NULL ? 2 : 0)
526 + java_sources_count;
527 argv = (char **) xmalloca ((argc + 1) * sizeof (char *));
529 argp = argv;
530 *argp++ = "jikes";
531 if (optimize)
532 *argp++ = "-O";
533 if (debug)
534 *argp++ = "-g";
535 if (directory != NULL)
537 *argp++ = "-d";
538 *argp++ = (char *) directory;
540 for (i = 0; i < java_sources_count; i++)
541 *argp++ = (char *) java_sources[i];
542 *argp = NULL;
543 /* Ensure argv length was correctly calculated. */
544 if (argp - argv != argc)
545 abort ();
547 if (verbose)
549 char *command = shell_quote_argv (argv);
550 printf ("%s\n", command);
551 free (command);
554 exitstatus = execute ("jikes", "jikes", argv, false, false, false,
555 null_stderr, true, true, NULL);
556 err = (exitstatus != 0);
558 freea (argv);
560 return err;
563 /* ====================== Usability test subroutines ====================== */
565 /* Write a given contents to a temporary file.
566 FILE_NAME is the name of a file inside TMPDIR that is known not to exist
567 yet.
568 Return a failure indicator (true upon error). */
569 static bool
570 write_temp_file (struct temp_dir *tmpdir, const char *file_name,
571 const char *contents)
573 FILE *fp;
575 register_temp_file (tmpdir, file_name);
576 fp = fopen_temp (file_name, "w");
577 if (fp == NULL)
579 error (0, errno, _("failed to create \"%s\""), file_name);
580 unregister_temp_file (tmpdir, file_name);
581 return true;
583 fputs (contents, fp);
584 if (fwriteerror_temp (fp))
586 error (0, errno, _("error while writing \"%s\" file"), file_name);
587 return true;
589 return false;
592 /* Return the class file version number of a class file on disk. */
593 static int
594 get_classfile_version (const char *compiled_file_name)
596 unsigned char header[8];
597 int fd;
599 /* Open the class file. */
600 fd = open (compiled_file_name, O_RDONLY | O_BINARY, 0);
601 if (fd >= 0)
603 /* Read its first 8 bytes. */
604 if (safe_read (fd, header, 8) == 8)
606 /* Verify the class file signature. */
607 if (header[0] == 0xCA && header[1] == 0xFE
608 && header[2] == 0xBA && header[3] == 0xBE)
610 close (fd);
611 return header[7];
614 close (fd);
617 /* Could not get the class file version. Return a very large one. */
618 return INT_MAX;
621 /* Return true if $JAVAC is a version of gcj. */
622 static bool
623 is_envjavac_gcj (const char *javac)
625 static bool envjavac_tested;
626 static bool envjavac_gcj;
628 if (!envjavac_tested)
630 /* Test whether $JAVAC is gcj:
631 "$JAVAC --version 2>/dev/null | sed -e 1q | grep gcj > /dev/null" */
632 unsigned int command_length;
633 char *command;
634 char *argv[4];
635 pid_t child;
636 int fd[1];
637 FILE *fp;
638 char *line;
639 size_t linesize;
640 size_t linelen;
641 int exitstatus;
642 char *p;
644 /* Setup the command "$JAVAC --version". */
645 command_length = strlen (javac) + 1 + 9 + 1;
646 command = (char *) xmalloca (command_length);
647 p = command;
648 /* Don't shell_quote $JAVAC, because it may consist of a command
649 and options. */
650 memcpy (p, javac, strlen (javac));
651 p += strlen (javac);
652 memcpy (p, " --version", 1 + 9 + 1);
653 p += 1 + 9 + 1;
654 /* Ensure command_length was correctly calculated. */
655 if (p - command > command_length)
656 abort ();
658 /* Call $JAVAC --version 2>/dev/null. */
659 argv[0] = BOURNE_SHELL;
660 argv[1] = "-c";
661 argv[2] = command;
662 argv[3] = NULL;
663 child = create_pipe_in (javac, BOURNE_SHELL, argv, DEV_NULL, true, true,
664 false, fd);
665 if (child == -1)
666 goto failed;
668 /* Retrieve its result. */
669 fp = fdopen (fd[0], "r");
670 if (fp == NULL)
671 goto failed;
673 line = NULL; linesize = 0;
674 linelen = getline (&line, &linesize, fp);
675 if (linelen == (size_t)(-1))
677 fclose (fp);
678 goto failed;
680 /* It is safe to call c_strstr() instead of strstr() here; see the
681 comments in c-strstr.h. */
682 envjavac_gcj = (c_strstr (line, "gcj") != NULL);
684 fclose (fp);
686 /* Remove zombie process from process list, and retrieve exit status. */
687 exitstatus =
688 wait_subprocess (child, javac, true, true, true, false, NULL);
689 if (exitstatus != 0)
690 envjavac_gcj = false;
692 failed:
693 freea (command);
695 envjavac_tested = true;
698 return envjavac_gcj;
701 /* Return true if $JAVAC, known to be a version of gcj, is a version >= 4.3
702 of gcj. */
703 static bool
704 is_envjavac_gcj43 (const char *javac)
706 static bool envjavac_tested;
707 static bool envjavac_gcj43;
709 if (!envjavac_tested)
711 /* Test whether $JAVAC is gcj:
712 "$JAVAC --version 2>/dev/null | sed -e 's,^[^0-9]*,,' -e 1q \
713 | sed -e '/^4\.[012]/d' | grep '^[4-9]' >/dev/null" */
714 unsigned int command_length;
715 char *command;
716 char *argv[4];
717 pid_t child;
718 int fd[1];
719 FILE *fp;
720 char *line;
721 size_t linesize;
722 size_t linelen;
723 int exitstatus;
724 char *p;
726 /* Setup the command "$JAVAC --version". */
727 command_length = strlen (javac) + 1 + 9 + 1;
728 command = (char *) xmalloca (command_length);
729 p = command;
730 /* Don't shell_quote $JAVAC, because it may consist of a command
731 and options. */
732 memcpy (p, javac, strlen (javac));
733 p += strlen (javac);
734 memcpy (p, " --version", 1 + 9 + 1);
735 p += 1 + 9 + 1;
736 /* Ensure command_length was correctly calculated. */
737 if (p - command > command_length)
738 abort ();
740 /* Call $JAVAC --version 2>/dev/null. */
741 argv[0] = BOURNE_SHELL;
742 argv[1] = "-c";
743 argv[2] = command;
744 argv[3] = NULL;
745 child = create_pipe_in (javac, BOURNE_SHELL, argv, DEV_NULL, true, true,
746 false, fd);
747 if (child == -1)
748 goto failed;
750 /* Retrieve its result. */
751 fp = fdopen (fd[0], "r");
752 if (fp == NULL)
753 goto failed;
755 line = NULL; linesize = 0;
756 linelen = getline (&line, &linesize, fp);
757 if (linelen == (size_t)(-1))
759 fclose (fp);
760 goto failed;
762 p = line;
763 while (*p != '\0' && !(*p >= '0' && *p <= '9'))
764 p++;
765 envjavac_gcj43 =
766 !(*p == '4' && p[1] == '.' && p[2] >= '0' && p[2] <= '2')
767 && (*p >= '4' && *p <= '9');
769 fclose (fp);
771 /* Remove zombie process from process list, and retrieve exit status. */
772 exitstatus =
773 wait_subprocess (child, javac, true, true, true, false, NULL);
774 if (exitstatus != 0)
775 envjavac_gcj43 = false;
777 failed:
778 freea (command);
780 envjavac_tested = true;
783 return envjavac_gcj43;
786 /* Test whether $JAVAC, known to be a version of gcj >= 4.3, can be used, and
787 whether it needs a -fsource and/or -ftarget option.
788 Return a failure indicator (true upon error). */
789 static bool
790 is_envjavac_gcj43_usable (const char *javac,
791 const char *source_version,
792 const char *target_version,
793 bool *usablep,
794 bool *fsource_option_p, bool *ftarget_option_p)
796 /* The cache depends on the source_version and target_version. */
797 struct result_t
799 bool tested;
800 bool usable;
801 bool fsource_option;
802 bool ftarget_option;
804 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
805 struct result_t *resultp;
807 resultp = &result_cache[source_version_index (source_version)]
808 [target_version_index (target_version)];
809 if (!resultp->tested)
811 /* Try $JAVAC. */
812 struct temp_dir *tmpdir;
813 char *conftest_file_name;
814 char *compiled_file_name;
815 const char *java_sources[1];
816 struct stat statbuf;
818 tmpdir = create_temp_dir ("java", NULL, false);
819 if (tmpdir == NULL)
820 return true;
822 conftest_file_name =
823 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
824 if (write_temp_file (tmpdir, conftest_file_name,
825 get_goodcode_snippet (source_version)))
827 free (conftest_file_name);
828 cleanup_temp_dir (tmpdir);
829 return true;
832 compiled_file_name =
833 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
834 register_temp_file (tmpdir, compiled_file_name);
836 java_sources[0] = conftest_file_name;
837 if (!compile_using_envjavac (javac,
838 java_sources, 1, tmpdir->dir_name,
839 false, false, false, true)
840 && stat (compiled_file_name, &statbuf) >= 0
841 && get_classfile_version (compiled_file_name)
842 <= corresponding_classfile_version (target_version))
844 /* $JAVAC compiled conftest.java successfully. */
845 /* Try adding -fsource option if it is useful. */
846 char *javac_source =
847 xasprintf ("%s -fsource=%s", javac, source_version);
849 unlink (compiled_file_name);
851 java_sources[0] = conftest_file_name;
852 if (!compile_using_envjavac (javac_source,
853 java_sources, 1, tmpdir->dir_name,
854 false, false, false, true)
855 && stat (compiled_file_name, &statbuf) >= 0
856 && get_classfile_version (compiled_file_name)
857 <= corresponding_classfile_version (target_version))
859 const char *failcode = get_failcode_snippet (source_version);
861 if (failcode != NULL)
863 free (compiled_file_name);
864 free (conftest_file_name);
866 conftest_file_name =
867 xconcatenated_filename (tmpdir->dir_name,
868 "conftestfail.java",
869 NULL);
870 if (write_temp_file (tmpdir, conftest_file_name, failcode))
872 free (conftest_file_name);
873 free (javac_source);
874 cleanup_temp_dir (tmpdir);
875 return true;
878 compiled_file_name =
879 xconcatenated_filename (tmpdir->dir_name,
880 "conftestfail.class",
881 NULL);
882 register_temp_file (tmpdir, compiled_file_name);
884 java_sources[0] = conftest_file_name;
885 if (!compile_using_envjavac (javac,
886 java_sources, 1,
887 tmpdir->dir_name,
888 false, false, false, true)
889 && stat (compiled_file_name, &statbuf) >= 0)
891 unlink (compiled_file_name);
893 java_sources[0] = conftest_file_name;
894 if (compile_using_envjavac (javac_source,
895 java_sources, 1,
896 tmpdir->dir_name,
897 false, false, false, true))
898 /* $JAVAC compiled conftestfail.java successfully, and
899 "$JAVAC -fsource=$source_version" rejects it. So
900 the -fsource option is useful. */
901 resultp->fsource_option = true;
906 free (javac_source);
908 resultp->usable = true;
910 else
912 /* Try with -fsource and -ftarget options. */
913 char *javac_target =
914 xasprintf ("%s -fsource=%s -ftarget=%s",
915 javac, source_version, target_version);
917 unlink (compiled_file_name);
919 java_sources[0] = conftest_file_name;
920 if (!compile_using_envjavac (javac_target,
921 java_sources, 1, tmpdir->dir_name,
922 false, false, false, true)
923 && stat (compiled_file_name, &statbuf) >= 0
924 && get_classfile_version (compiled_file_name)
925 <= corresponding_classfile_version (target_version))
927 /* "$JAVAC -fsource $source_version -ftarget $target_version"
928 compiled conftest.java successfully. */
929 resultp->fsource_option = true;
930 resultp->ftarget_option = true;
931 resultp->usable = true;
934 free (javac_target);
937 free (compiled_file_name);
938 free (conftest_file_name);
940 resultp->tested = true;
943 *usablep = resultp->usable;
944 *fsource_option_p = resultp->fsource_option;
945 *ftarget_option_p = resultp->ftarget_option;
946 return false;
949 /* Test whether $JAVAC, known to be a version of gcj < 4.3, can be used for
950 compiling with target_version = 1.4 and source_version = 1.4.
951 Return a failure indicator (true upon error). */
952 static bool
953 is_envjavac_oldgcj_14_14_usable (const char *javac, bool *usablep)
955 static bool envjavac_tested;
956 static bool envjavac_usable;
958 if (!envjavac_tested)
960 /* Try $JAVAC. */
961 struct temp_dir *tmpdir;
962 char *conftest_file_name;
963 char *compiled_file_name;
964 const char *java_sources[1];
965 struct stat statbuf;
967 tmpdir = create_temp_dir ("java", NULL, false);
968 if (tmpdir == NULL)
969 return true;
971 conftest_file_name =
972 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
973 if (write_temp_file (tmpdir, conftest_file_name,
974 get_goodcode_snippet ("1.4")))
976 free (conftest_file_name);
977 cleanup_temp_dir (tmpdir);
978 return true;
981 compiled_file_name =
982 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
983 register_temp_file (tmpdir, compiled_file_name);
985 java_sources[0] = conftest_file_name;
986 if (!compile_using_envjavac (javac, java_sources, 1, tmpdir->dir_name,
987 false, false, false, true)
988 && stat (compiled_file_name, &statbuf) >= 0)
989 /* Compilation succeeded. */
990 envjavac_usable = true;
992 free (compiled_file_name);
993 free (conftest_file_name);
995 cleanup_temp_dir (tmpdir);
997 envjavac_tested = true;
1000 *usablep = envjavac_usable;
1001 return false;
1004 /* Test whether $JAVAC, known to be a version of gcj < 4.3, can be used for
1005 compiling with target_version = 1.4 and source_version = 1.3.
1006 Return a failure indicator (true upon error). */
1007 static bool
1008 is_envjavac_oldgcj_14_13_usable (const char *javac,
1009 bool *usablep, bool *need_no_assert_option_p)
1011 static bool envjavac_tested;
1012 static bool envjavac_usable;
1013 static bool envjavac_need_no_assert_option;
1015 if (!envjavac_tested)
1017 /* Try $JAVAC and "$JAVAC -fno-assert". But add -fno-assert only if
1018 it makes a difference. (It could already be part of $JAVAC.) */
1019 struct temp_dir *tmpdir;
1020 char *conftest_file_name;
1021 char *compiled_file_name;
1022 const char *java_sources[1];
1023 struct stat statbuf;
1024 bool javac_works;
1025 char *javac_noassert;
1026 bool javac_noassert_works;
1028 tmpdir = create_temp_dir ("java", NULL, false);
1029 if (tmpdir == NULL)
1030 return true;
1032 conftest_file_name =
1033 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1034 if (write_temp_file (tmpdir, conftest_file_name,
1035 get_goodcode_snippet ("1.3")))
1037 free (conftest_file_name);
1038 cleanup_temp_dir (tmpdir);
1039 return true;
1042 compiled_file_name =
1043 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1044 register_temp_file (tmpdir, compiled_file_name);
1046 java_sources[0] = conftest_file_name;
1047 if (!compile_using_envjavac (javac,
1048 java_sources, 1, tmpdir->dir_name,
1049 false, false, false, true)
1050 && stat (compiled_file_name, &statbuf) >= 0)
1051 /* Compilation succeeded. */
1052 javac_works = true;
1053 else
1054 javac_works = false;
1056 unlink (compiled_file_name);
1058 javac_noassert = xasprintf ("%s -fno-assert", javac);
1060 java_sources[0] = conftest_file_name;
1061 if (!compile_using_envjavac (javac_noassert,
1062 java_sources, 1, tmpdir->dir_name,
1063 false, false, false, true)
1064 && stat (compiled_file_name, &statbuf) >= 0)
1065 /* Compilation succeeded. */
1066 javac_noassert_works = true;
1067 else
1068 javac_noassert_works = false;
1070 free (compiled_file_name);
1071 free (conftest_file_name);
1073 if (javac_works && javac_noassert_works)
1075 conftest_file_name =
1076 xconcatenated_filename (tmpdir->dir_name, "conftestfail.java",
1077 NULL);
1078 if (write_temp_file (tmpdir, conftest_file_name,
1079 get_failcode_snippet ("1.3")))
1081 free (conftest_file_name);
1082 free (javac_noassert);
1083 cleanup_temp_dir (tmpdir);
1084 return true;
1087 compiled_file_name =
1088 xconcatenated_filename (tmpdir->dir_name, "conftestfail.class",
1089 NULL);
1090 register_temp_file (tmpdir, compiled_file_name);
1092 java_sources[0] = conftest_file_name;
1093 if (!compile_using_envjavac (javac,
1094 java_sources, 1, tmpdir->dir_name,
1095 false, false, false, true)
1096 && stat (compiled_file_name, &statbuf) >= 0)
1098 /* Compilation succeeded. */
1099 unlink (compiled_file_name);
1101 java_sources[0] = conftest_file_name;
1102 if (!(!compile_using_envjavac (javac_noassert,
1103 java_sources, 1, tmpdir->dir_name,
1104 false, false, false, true)
1105 && stat (compiled_file_name, &statbuf) >= 0))
1106 /* Compilation failed. */
1107 /* "$JAVAC -fno-assert" works better than $JAVAC. */
1108 javac_works = true;
1111 free (compiled_file_name);
1112 free (conftest_file_name);
1115 cleanup_temp_dir (tmpdir);
1117 if (javac_works)
1119 envjavac_usable = true;
1120 envjavac_need_no_assert_option = false;
1122 else if (javac_noassert_works)
1124 envjavac_usable = true;
1125 envjavac_need_no_assert_option = true;
1128 envjavac_tested = true;
1131 *usablep = envjavac_usable;
1132 *need_no_assert_option_p = envjavac_need_no_assert_option;
1133 return false;
1136 /* Test whether $JAVAC, known to be not a version of gcj, can be used, and
1137 whether it needs a -source and/or -target option.
1138 Return a failure indicator (true upon error). */
1139 static bool
1140 is_envjavac_nongcj_usable (const char *javac,
1141 const char *source_version,
1142 const char *source_version_for_javac,
1143 const char *target_version,
1144 bool *usablep,
1145 bool *source_option_p, bool *target_option_p)
1147 /* The cache depends on the source_version and target_version. */
1148 struct result_t
1150 bool tested;
1151 bool usable;
1152 bool source_option;
1153 bool target_option;
1155 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
1156 struct result_t *resultp;
1158 resultp = &result_cache[source_version_index (source_version)]
1159 [target_version_index (target_version)];
1160 if (!resultp->tested)
1162 /* Try $JAVAC. */
1163 struct temp_dir *tmpdir;
1164 char *conftest_file_name;
1165 char *compiled_file_name;
1166 const char *java_sources[1];
1167 struct stat statbuf;
1169 tmpdir = create_temp_dir ("java", NULL, false);
1170 if (tmpdir == NULL)
1171 return true;
1173 conftest_file_name =
1174 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1175 if (write_temp_file (tmpdir, conftest_file_name,
1176 get_goodcode_snippet (source_version)))
1178 free (conftest_file_name);
1179 cleanup_temp_dir (tmpdir);
1180 return true;
1183 compiled_file_name =
1184 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1185 register_temp_file (tmpdir, compiled_file_name);
1187 java_sources[0] = conftest_file_name;
1188 if (!compile_using_envjavac (javac,
1189 java_sources, 1, tmpdir->dir_name,
1190 false, false, false, true)
1191 && stat (compiled_file_name, &statbuf) >= 0
1192 && get_classfile_version (compiled_file_name)
1193 <= corresponding_classfile_version (target_version))
1195 /* $JAVAC compiled conftest.java successfully. */
1196 /* Try adding -source option if it is useful. */
1197 char *javac_source =
1198 xasprintf ("%s -source %s", javac, source_version_for_javac);
1200 unlink (compiled_file_name);
1202 java_sources[0] = conftest_file_name;
1203 if (!compile_using_envjavac (javac_source,
1204 java_sources, 1, tmpdir->dir_name,
1205 false, false, false, true)
1206 && stat (compiled_file_name, &statbuf) >= 0
1207 && get_classfile_version (compiled_file_name)
1208 <= corresponding_classfile_version (target_version))
1210 const char *failcode = get_failcode_snippet (source_version);
1212 if (failcode != NULL)
1214 free (compiled_file_name);
1215 free (conftest_file_name);
1217 conftest_file_name =
1218 xconcatenated_filename (tmpdir->dir_name,
1219 "conftestfail.java",
1220 NULL);
1221 if (write_temp_file (tmpdir, conftest_file_name, failcode))
1223 free (conftest_file_name);
1224 free (javac_source);
1225 cleanup_temp_dir (tmpdir);
1226 return true;
1229 compiled_file_name =
1230 xconcatenated_filename (tmpdir->dir_name,
1231 "conftestfail.class",
1232 NULL);
1233 register_temp_file (tmpdir, compiled_file_name);
1235 java_sources[0] = conftest_file_name;
1236 if (!compile_using_envjavac (javac,
1237 java_sources, 1,
1238 tmpdir->dir_name,
1239 false, false, false, true)
1240 && stat (compiled_file_name, &statbuf) >= 0)
1242 unlink (compiled_file_name);
1244 java_sources[0] = conftest_file_name;
1245 if (compile_using_envjavac (javac_source,
1246 java_sources, 1,
1247 tmpdir->dir_name,
1248 false, false, false, true))
1249 /* $JAVAC compiled conftestfail.java successfully, and
1250 "$JAVAC -source $source_version_for_javac" rejects it.
1251 So the -source option is useful. */
1252 resultp->source_option = true;
1257 free (javac_source);
1259 resultp->usable = true;
1261 else
1263 /* Try with -target option alone. (Sun javac 1.3.1 has the -target
1264 option but no -source option.) */
1265 char *javac_target =
1266 xasprintf ("%s -target %s", javac, target_version);
1268 unlink (compiled_file_name);
1270 java_sources[0] = conftest_file_name;
1271 if (!compile_using_envjavac (javac_target,
1272 java_sources, 1, tmpdir->dir_name,
1273 false, false, false, true)
1274 && stat (compiled_file_name, &statbuf) >= 0
1275 && get_classfile_version (compiled_file_name)
1276 <= corresponding_classfile_version (target_version))
1278 /* "$JAVAC -target $target_version" compiled conftest.java
1279 successfully. */
1280 /* Try adding -source option if it is useful. */
1281 char *javac_target_source =
1282 xasprintf ("%s -source %s", javac_target, source_version_for_javac);
1284 unlink (compiled_file_name);
1286 java_sources[0] = conftest_file_name;
1287 if (!compile_using_envjavac (javac_target_source,
1288 java_sources, 1, tmpdir->dir_name,
1289 false, false, false, true)
1290 && stat (compiled_file_name, &statbuf) >= 0
1291 && get_classfile_version (compiled_file_name)
1292 <= corresponding_classfile_version (target_version))
1294 const char *failcode = get_failcode_snippet (source_version);
1296 if (failcode != NULL)
1298 free (compiled_file_name);
1299 free (conftest_file_name);
1301 conftest_file_name =
1302 xconcatenated_filename (tmpdir->dir_name,
1303 "conftestfail.java",
1304 NULL);
1305 if (write_temp_file (tmpdir, conftest_file_name,
1306 failcode))
1308 free (conftest_file_name);
1309 free (javac_target_source);
1310 free (javac_target);
1311 cleanup_temp_dir (tmpdir);
1312 return true;
1315 compiled_file_name =
1316 xconcatenated_filename (tmpdir->dir_name,
1317 "conftestfail.class",
1318 NULL);
1319 register_temp_file (tmpdir, compiled_file_name);
1321 java_sources[0] = conftest_file_name;
1322 if (!compile_using_envjavac (javac_target,
1323 java_sources, 1,
1324 tmpdir->dir_name,
1325 false, false, false, true)
1326 && stat (compiled_file_name, &statbuf) >= 0)
1328 unlink (compiled_file_name);
1330 java_sources[0] = conftest_file_name;
1331 if (compile_using_envjavac (javac_target_source,
1332 java_sources, 1,
1333 tmpdir->dir_name,
1334 false, false, false,
1335 true))
1336 /* "$JAVAC -target $target_version" compiled
1337 conftestfail.java successfully, and
1338 "$JAVAC -target $target_version -source $source_version_for_javac"
1339 rejects it. So the -source option is useful. */
1340 resultp->source_option = true;
1345 free (javac_target_source);
1347 resultp->target_option = true;
1348 resultp->usable = true;
1350 else
1352 /* Maybe this -target option requires a -source option? Try with
1353 -target and -source options. (Supported by Sun javac 1.4 and
1354 higher.) */
1355 char *javac_target_source =
1356 xasprintf ("%s -source %s", javac_target, source_version_for_javac);
1358 unlink (compiled_file_name);
1360 java_sources[0] = conftest_file_name;
1361 if (!compile_using_envjavac (javac_target_source,
1362 java_sources, 1, tmpdir->dir_name,
1363 false, false, false, true)
1364 && stat (compiled_file_name, &statbuf) >= 0
1365 && get_classfile_version (compiled_file_name)
1366 <= corresponding_classfile_version (target_version))
1368 /* "$JAVAC -target $target_version -source $source_version_for_javac"
1369 compiled conftest.java successfully. */
1370 resultp->source_option = true;
1371 resultp->target_option = true;
1372 resultp->usable = true;
1375 free (javac_target_source);
1378 free (javac_target);
1381 free (compiled_file_name);
1382 free (conftest_file_name);
1384 resultp->tested = true;
1387 *usablep = resultp->usable;
1388 *source_option_p = resultp->source_option;
1389 *target_option_p = resultp->target_option;
1390 return false;
1393 static bool
1394 is_gcj_present (void)
1396 static bool gcj_tested;
1397 static bool gcj_present;
1399 if (!gcj_tested)
1401 /* Test for presence of gcj:
1402 "gcj --version 2> /dev/null | \
1403 sed -e 's,^[^0-9]*,,' -e 1q | \
1404 sed -e '/^3\.[01]/d' | grep '^[3-9]' > /dev/null" */
1405 char *argv[3];
1406 pid_t child;
1407 int fd[1];
1408 int exitstatus;
1410 argv[0] = "gcj";
1411 argv[1] = "--version";
1412 argv[2] = NULL;
1413 child = create_pipe_in ("gcj", "gcj", argv, DEV_NULL, true, true,
1414 false, fd);
1415 gcj_present = false;
1416 if (child != -1)
1418 /* Read the subprocess output, drop all lines except the first,
1419 drop all characters before the first digit, and test whether
1420 the remaining string starts with a digit >= 3, but not with
1421 "3.0" or "3.1". */
1422 char c[3];
1423 size_t count = 0;
1425 while (safe_read (fd[0], &c[count], 1) > 0)
1427 if (c[count] == '\n')
1428 break;
1429 if (count == 0)
1431 if (!(c[0] >= '0' && c[0] <= '9'))
1432 continue;
1433 gcj_present = (c[0] >= '3');
1435 count++;
1436 if (count == 3)
1438 if (c[0] == '3' && c[1] == '.'
1439 && (c[2] == '0' || c[2] == '1'))
1440 gcj_present = false;
1441 break;
1444 while (safe_read (fd[0], &c[0], 1) > 0)
1447 close (fd[0]);
1449 /* Remove zombie process from process list, and retrieve exit
1450 status. */
1451 exitstatus =
1452 wait_subprocess (child, "gcj", false, true, true, false, NULL);
1453 if (exitstatus != 0)
1454 gcj_present = false;
1457 if (gcj_present)
1459 /* See if libgcj.jar is well installed. */
1460 struct temp_dir *tmpdir;
1462 tmpdir = create_temp_dir ("java", NULL, false);
1463 if (tmpdir == NULL)
1464 gcj_present = false;
1465 else
1467 char *conftest_file_name;
1469 conftest_file_name =
1470 xconcatenated_filename (tmpdir->dir_name, "conftestlib.java",
1471 NULL);
1472 if (write_temp_file (tmpdir, conftest_file_name,
1473 "public class conftestlib {\n"
1474 " public static void main (String[] args) {\n"
1475 " }\n"
1476 "}\n"))
1477 gcj_present = false;
1478 else
1480 char *compiled_file_name;
1481 const char *java_sources[1];
1483 compiled_file_name =
1484 xconcatenated_filename (tmpdir->dir_name,
1485 "conftestlib.class",
1486 NULL);
1487 register_temp_file (tmpdir, compiled_file_name);
1489 java_sources[0] = conftest_file_name;
1490 if (compile_using_gcj (java_sources, 1, false,
1491 false, NULL, false, NULL,
1492 tmpdir->dir_name,
1493 false, false, false, true))
1494 gcj_present = false;
1496 free (compiled_file_name);
1498 free (conftest_file_name);
1500 cleanup_temp_dir (tmpdir);
1503 gcj_tested = true;
1506 return gcj_present;
1509 static bool
1510 is_gcj_43 (void)
1512 static bool gcj_tested;
1513 static bool gcj_43;
1515 if (!gcj_tested)
1517 /* Test for presence of gcj:
1518 "gcj --version 2> /dev/null | \
1519 sed -e 's,^[^0-9]*,,' -e 1q | \
1520 sed -e '/^4\.[012]/d' | grep '^[4-9]'" */
1521 char *argv[3];
1522 pid_t child;
1523 int fd[1];
1524 int exitstatus;
1526 argv[0] = "gcj";
1527 argv[1] = "--version";
1528 argv[2] = NULL;
1529 child = create_pipe_in ("gcj", "gcj", argv, DEV_NULL, true, true,
1530 false, fd);
1531 gcj_43 = false;
1532 if (child != -1)
1534 /* Read the subprocess output, drop all lines except the first,
1535 drop all characters before the first digit, and test whether
1536 the remaining string starts with a digit >= 4, but not with
1537 "4.0" or "4.1" or "4.2". */
1538 char c[3];
1539 size_t count = 0;
1541 while (safe_read (fd[0], &c[count], 1) > 0)
1543 if (c[count] == '\n')
1544 break;
1545 if (count == 0)
1547 if (!(c[0] >= '0' && c[0] <= '9'))
1548 continue;
1549 gcj_43 = (c[0] >= '4');
1551 count++;
1552 if (count == 3)
1554 if (c[0] == '4' && c[1] == '.' && c[2] >= '0' && c[2] <= '2')
1555 gcj_43 = false;
1556 break;
1559 while (safe_read (fd[0], &c[0], 1) > 0)
1562 close (fd[0]);
1564 /* Remove zombie process from process list, and retrieve exit
1565 status. */
1566 exitstatus =
1567 wait_subprocess (child, "gcj", false, true, true, false, NULL);
1568 if (exitstatus != 0)
1569 gcj_43 = false;
1572 gcj_tested = true;
1575 return gcj_43;
1578 /* Test whether gcj >= 4.3 can be used, and whether it needs a -fsource and/or
1579 -ftarget option.
1580 Return a failure indicator (true upon error). */
1581 static bool
1582 is_gcj43_usable (const char *source_version,
1583 const char *target_version,
1584 bool *usablep,
1585 bool *fsource_option_p, bool *ftarget_option_p)
1587 /* The cache depends on the source_version and target_version. */
1588 struct result_t
1590 bool tested;
1591 bool usable;
1592 bool fsource_option;
1593 bool ftarget_option;
1595 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
1596 struct result_t *resultp;
1598 resultp = &result_cache[source_version_index (source_version)]
1599 [target_version_index (target_version)];
1600 if (!resultp->tested)
1602 /* Try gcj. */
1603 struct temp_dir *tmpdir;
1604 char *conftest_file_name;
1605 char *compiled_file_name;
1606 const char *java_sources[1];
1607 struct stat statbuf;
1609 tmpdir = create_temp_dir ("java", NULL, false);
1610 if (tmpdir == NULL)
1611 return true;
1613 conftest_file_name =
1614 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1615 if (write_temp_file (tmpdir, conftest_file_name,
1616 get_goodcode_snippet (source_version)))
1618 free (conftest_file_name);
1619 cleanup_temp_dir (tmpdir);
1620 return true;
1623 compiled_file_name =
1624 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1625 register_temp_file (tmpdir, compiled_file_name);
1627 java_sources[0] = conftest_file_name;
1628 if (!compile_using_gcj (java_sources, 1, false, false, NULL, false, NULL,
1629 tmpdir->dir_name, false, false, false, true)
1630 && stat (compiled_file_name, &statbuf) >= 0
1631 && get_classfile_version (compiled_file_name)
1632 <= corresponding_classfile_version (target_version))
1634 /* gcj compiled conftest.java successfully. */
1635 /* Try adding -fsource option if it is useful. */
1636 unlink (compiled_file_name);
1638 java_sources[0] = conftest_file_name;
1639 if (!compile_using_gcj (java_sources, 1,
1640 false, true, source_version, false, NULL,
1641 tmpdir->dir_name, false, false, false, true)
1642 && stat (compiled_file_name, &statbuf) >= 0
1643 && get_classfile_version (compiled_file_name)
1644 <= corresponding_classfile_version (target_version))
1646 const char *failcode = get_failcode_snippet (source_version);
1648 if (failcode != NULL)
1650 free (compiled_file_name);
1651 free (conftest_file_name);
1653 conftest_file_name =
1654 xconcatenated_filename (tmpdir->dir_name,
1655 "conftestfail.java",
1656 NULL);
1657 if (write_temp_file (tmpdir, conftest_file_name, failcode))
1659 free (conftest_file_name);
1660 cleanup_temp_dir (tmpdir);
1661 return true;
1664 compiled_file_name =
1665 xconcatenated_filename (tmpdir->dir_name,
1666 "conftestfail.class",
1667 NULL);
1668 register_temp_file (tmpdir, compiled_file_name);
1670 java_sources[0] = conftest_file_name;
1671 if (!compile_using_gcj (java_sources, 1,
1672 false, false, NULL, false, NULL,
1673 tmpdir->dir_name,
1674 false, false, false, true)
1675 && stat (compiled_file_name, &statbuf) >= 0)
1677 unlink (compiled_file_name);
1679 java_sources[0] = conftest_file_name;
1680 if (compile_using_gcj (java_sources, 1,
1681 false, true, source_version,
1682 false, NULL,
1683 tmpdir->dir_name,
1684 false, false, false, true))
1685 /* gcj compiled conftestfail.java successfully, and
1686 "gcj -fsource=$source_version" rejects it. So
1687 the -fsource option is useful. */
1688 resultp->fsource_option = true;
1693 resultp->usable = true;
1695 else
1697 /* Try with -fsource and -ftarget options. */
1698 unlink (compiled_file_name);
1700 java_sources[0] = conftest_file_name;
1701 if (!compile_using_gcj (java_sources, 1,
1702 false, true, source_version,
1703 true, target_version,
1704 tmpdir->dir_name,
1705 false, false, false, true)
1706 && stat (compiled_file_name, &statbuf) >= 0
1707 && get_classfile_version (compiled_file_name)
1708 <= corresponding_classfile_version (target_version))
1710 /* "gcj -fsource $source_version -ftarget $target_version"
1711 compiled conftest.java successfully. */
1712 resultp->fsource_option = true;
1713 resultp->ftarget_option = true;
1714 resultp->usable = true;
1718 free (compiled_file_name);
1719 free (conftest_file_name);
1721 resultp->tested = true;
1724 *usablep = resultp->usable;
1725 *fsource_option_p = resultp->fsource_option;
1726 *ftarget_option_p = resultp->ftarget_option;
1727 return false;
1730 /* Test whether gcj < 4.3 can be used for compiling with target_version = 1.4
1731 and source_version = 1.4.
1732 Return a failure indicator (true upon error). */
1733 static bool
1734 is_oldgcj_14_14_usable (bool *usablep)
1736 static bool gcj_tested;
1737 static bool gcj_usable;
1739 if (!gcj_tested)
1741 /* Try gcj. */
1742 struct temp_dir *tmpdir;
1743 char *conftest_file_name;
1744 char *compiled_file_name;
1745 const char *java_sources[1];
1746 struct stat statbuf;
1748 tmpdir = create_temp_dir ("java", NULL, false);
1749 if (tmpdir == NULL)
1750 return true;
1752 conftest_file_name =
1753 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1754 if (write_temp_file (tmpdir, conftest_file_name,
1755 get_goodcode_snippet ("1.4")))
1757 free (conftest_file_name);
1758 cleanup_temp_dir (tmpdir);
1759 return true;
1762 compiled_file_name =
1763 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1764 register_temp_file (tmpdir, compiled_file_name);
1766 java_sources[0] = conftest_file_name;
1767 if (!compile_using_gcj (java_sources, 1, false, false, NULL, false, NULL,
1768 tmpdir->dir_name, false, false, false, true)
1769 && stat (compiled_file_name, &statbuf) >= 0)
1770 /* Compilation succeeded. */
1771 gcj_usable = true;
1773 free (compiled_file_name);
1774 free (conftest_file_name);
1776 cleanup_temp_dir (tmpdir);
1778 gcj_tested = true;
1781 *usablep = gcj_usable;
1782 return false;
1785 /* Test whether gcj < 4.3 can be used for compiling with target_version = 1.4
1786 and source_version = 1.3.
1787 Return a failure indicator (true upon error). */
1788 static bool
1789 is_oldgcj_14_13_usable (bool *usablep, bool *need_no_assert_option_p)
1791 static bool gcj_tested;
1792 static bool gcj_usable;
1793 static bool gcj_need_no_assert_option;
1795 if (!gcj_tested)
1797 /* Try gcj and "gcj -fno-assert". But add -fno-assert only if
1798 it works (not gcj < 3.3). */
1799 struct temp_dir *tmpdir;
1800 char *conftest_file_name;
1801 char *compiled_file_name;
1802 const char *java_sources[1];
1803 struct stat statbuf;
1805 tmpdir = create_temp_dir ("java", NULL, false);
1806 if (tmpdir == NULL)
1807 return true;
1809 conftest_file_name =
1810 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1811 if (write_temp_file (tmpdir, conftest_file_name,
1812 get_goodcode_snippet ("1.3")))
1814 free (conftest_file_name);
1815 cleanup_temp_dir (tmpdir);
1816 return true;
1819 compiled_file_name =
1820 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1821 register_temp_file (tmpdir, compiled_file_name);
1823 java_sources[0] = conftest_file_name;
1824 if (!compile_using_gcj (java_sources, 1, true, false, NULL, false, NULL,
1825 tmpdir->dir_name, false, false, false, true)
1826 && stat (compiled_file_name, &statbuf) >= 0)
1827 /* Compilation succeeded. */
1829 gcj_usable = true;
1830 gcj_need_no_assert_option = true;
1832 else
1834 unlink (compiled_file_name);
1836 java_sources[0] = conftest_file_name;
1837 if (!compile_using_gcj (java_sources, 1, false,
1838 false, NULL, false, NULL,
1839 tmpdir->dir_name, false, false, false, true)
1840 && stat (compiled_file_name, &statbuf) >= 0)
1841 /* Compilation succeeded. */
1843 gcj_usable = true;
1844 gcj_need_no_assert_option = false;
1848 free (compiled_file_name);
1849 free (conftest_file_name);
1851 cleanup_temp_dir (tmpdir);
1853 gcj_tested = true;
1856 *usablep = gcj_usable;
1857 *need_no_assert_option_p = gcj_need_no_assert_option;
1858 return false;
1861 static bool
1862 is_javac_present (void)
1864 static bool javac_tested;
1865 static bool javac_present;
1867 if (!javac_tested)
1869 /* Test for presence of javac: "javac 2> /dev/null ; test $? -le 2" */
1870 char *argv[2];
1871 int exitstatus;
1873 argv[0] = "javac";
1874 argv[1] = NULL;
1875 exitstatus = execute ("javac", "javac", argv, false, false, true, true,
1876 true, false, NULL);
1877 javac_present = (exitstatus == 0 || exitstatus == 1 || exitstatus == 2);
1878 javac_tested = true;
1881 return javac_present;
1884 /* Test whether javac can be used and whether it needs a -source and/or
1885 -target option.
1886 Return a failure indicator (true upon error). */
1887 static bool
1888 is_javac_usable (const char *source_version,
1889 const char *source_version_for_javac,
1890 const char *target_version,
1891 bool *usablep, bool *source_option_p, bool *target_option_p)
1893 /* The cache depends on the source_version and target_version. */
1894 struct result_t
1896 bool tested;
1897 bool usable;
1898 bool source_option;
1899 bool target_option;
1901 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
1902 struct result_t *resultp;
1904 resultp = &result_cache[source_version_index (source_version)]
1905 [target_version_index (target_version)];
1906 if (!resultp->tested)
1908 /* Try javac. */
1909 struct temp_dir *tmpdir;
1910 char *conftest_file_name;
1911 char *compiled_file_name;
1912 const char *java_sources[1];
1913 struct stat statbuf;
1915 tmpdir = create_temp_dir ("java", NULL, false);
1916 if (tmpdir == NULL)
1917 return true;
1919 conftest_file_name =
1920 xconcatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1921 if (write_temp_file (tmpdir, conftest_file_name,
1922 get_goodcode_snippet (source_version)))
1924 free (conftest_file_name);
1925 cleanup_temp_dir (tmpdir);
1926 return true;
1929 compiled_file_name =
1930 xconcatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1931 register_temp_file (tmpdir, compiled_file_name);
1933 java_sources[0] = conftest_file_name;
1934 if (!compile_using_javac (java_sources, 1,
1935 false, source_version_for_javac,
1936 false, target_version,
1937 tmpdir->dir_name, false, false, false, true)
1938 && stat (compiled_file_name, &statbuf) >= 0
1939 && get_classfile_version (compiled_file_name)
1940 <= corresponding_classfile_version (target_version))
1942 /* javac compiled conftest.java successfully. */
1943 /* Try adding -source option if it is useful. */
1944 unlink (compiled_file_name);
1946 java_sources[0] = conftest_file_name;
1947 if (!compile_using_javac (java_sources, 1,
1948 true, source_version_for_javac,
1949 false, target_version,
1950 tmpdir->dir_name, false, false, false, true)
1951 && stat (compiled_file_name, &statbuf) >= 0
1952 && get_classfile_version (compiled_file_name)
1953 <= corresponding_classfile_version (target_version))
1955 const char *failcode = get_failcode_snippet (source_version);
1957 if (failcode != NULL)
1959 free (compiled_file_name);
1960 free (conftest_file_name);
1962 conftest_file_name =
1963 xconcatenated_filename (tmpdir->dir_name,
1964 "conftestfail.java",
1965 NULL);
1966 if (write_temp_file (tmpdir, conftest_file_name, failcode))
1968 free (conftest_file_name);
1969 cleanup_temp_dir (tmpdir);
1970 return true;
1973 compiled_file_name =
1974 xconcatenated_filename (tmpdir->dir_name,
1975 "conftestfail.class",
1976 NULL);
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_for_javac,
1982 false, target_version,
1983 tmpdir->dir_name,
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_for_javac,
1992 false, target_version,
1993 tmpdir->dir_name,
1994 false, false, false, true))
1995 /* javac compiled conftestfail.java successfully, and
1996 "javac -source $source_version_for_javac" rejects it.
1997 So the -source option is useful. */
1998 resultp->source_option = true;
2003 resultp->usable = true;
2005 else
2007 /* Try with -target option alone. (Sun javac 1.3.1 has the -target
2008 option but no -source option.) */
2009 unlink (compiled_file_name);
2011 java_sources[0] = conftest_file_name;
2012 if (!compile_using_javac (java_sources, 1,
2013 false, source_version_for_javac,
2014 true, target_version,
2015 tmpdir->dir_name,
2016 false, false, false, true)
2017 && stat (compiled_file_name, &statbuf) >= 0
2018 && get_classfile_version (compiled_file_name)
2019 <= corresponding_classfile_version (target_version))
2021 /* "javac -target $target_version" compiled conftest.java
2022 successfully. */
2023 /* Try adding -source option if it is useful. */
2024 unlink (compiled_file_name);
2026 java_sources[0] = conftest_file_name;
2027 if (!compile_using_javac (java_sources, 1,
2028 true, source_version_for_javac,
2029 true, target_version,
2030 tmpdir->dir_name,
2031 false, false, false, true)
2032 && stat (compiled_file_name, &statbuf) >= 0
2033 && get_classfile_version (compiled_file_name)
2034 <= corresponding_classfile_version (target_version))
2036 const char *failcode = get_failcode_snippet (source_version);
2038 if (failcode != NULL)
2040 free (compiled_file_name);
2041 free (conftest_file_name);
2043 conftest_file_name =
2044 xconcatenated_filename (tmpdir->dir_name,
2045 "conftestfail.java",
2046 NULL);
2047 if (write_temp_file (tmpdir, conftest_file_name,
2048 failcode))
2050 free (conftest_file_name);
2051 cleanup_temp_dir (tmpdir);
2052 return true;
2055 compiled_file_name =
2056 xconcatenated_filename (tmpdir->dir_name,
2057 "conftestfail.class",
2058 NULL);
2059 register_temp_file (tmpdir, compiled_file_name);
2061 java_sources[0] = conftest_file_name;
2062 if (!compile_using_javac (java_sources, 1,
2063 false, source_version_for_javac,
2064 true, target_version,
2065 tmpdir->dir_name,
2066 false, false, false, true)
2067 && stat (compiled_file_name, &statbuf) >= 0)
2069 unlink (compiled_file_name);
2071 java_sources[0] = conftest_file_name;
2072 if (compile_using_javac (java_sources, 1,
2073 true, source_version_for_javac,
2074 true, target_version,
2075 tmpdir->dir_name,
2076 false, false, false, true))
2077 /* "javac -target $target_version" compiled
2078 conftestfail.java successfully, and
2079 "javac -target $target_version -source $source_version_for_javac"
2080 rejects it. So the -source option is useful. */
2081 resultp->source_option = true;
2086 resultp->target_option = true;
2087 resultp->usable = true;
2089 else
2091 /* Maybe this -target option requires a -source option? Try with
2092 -target and -source options. (Supported by Sun javac 1.4 and
2093 higher.) */
2094 unlink (compiled_file_name);
2096 java_sources[0] = conftest_file_name;
2097 if (!compile_using_javac (java_sources, 1,
2098 true, source_version_for_javac,
2099 true, target_version,
2100 tmpdir->dir_name,
2101 false, false, false, true)
2102 && stat (compiled_file_name, &statbuf) >= 0
2103 && get_classfile_version (compiled_file_name)
2104 <= corresponding_classfile_version (target_version))
2106 /* "javac -target $target_version -source $source_version_for_javac"
2107 compiled conftest.java successfully. */
2108 resultp->source_option = true;
2109 resultp->target_option = true;
2110 resultp->usable = true;
2115 free (compiled_file_name);
2116 free (conftest_file_name);
2118 resultp->tested = true;
2121 *usablep = resultp->usable;
2122 *source_option_p = resultp->source_option;
2123 *target_option_p = resultp->target_option;
2124 return false;
2127 static bool
2128 is_jikes_present (void)
2130 static bool jikes_tested;
2131 static bool jikes_present;
2133 if (!jikes_tested)
2135 /* Test for presence of jikes: "jikes 2> /dev/null ; test $? = 1" */
2136 char *argv[2];
2137 int exitstatus;
2139 argv[0] = "jikes";
2140 argv[1] = NULL;
2141 exitstatus = execute ("jikes", "jikes", argv, false, false, true, true,
2142 true, false, NULL);
2143 jikes_present = (exitstatus == 0 || exitstatus == 1);
2144 jikes_tested = true;
2147 return jikes_present;
2150 /* ============================= Main function ============================= */
2152 bool
2153 compile_java_class (const char * const *java_sources,
2154 unsigned int java_sources_count,
2155 const char * const *classpaths,
2156 unsigned int classpaths_count,
2157 const char *source_version,
2158 const char *target_version,
2159 const char *directory,
2160 bool optimize, bool debug,
2161 bool use_minimal_classpath,
2162 bool verbose)
2164 bool err = false;
2165 char *old_JAVA_HOME;
2168 const char *javac = getenv ("JAVAC");
2169 if (javac != NULL && javac[0] != '\0')
2171 bool usable = false;
2172 bool no_assert_option = false;
2173 bool source_option = false;
2174 bool target_option = false;
2175 bool fsource_option = false;
2176 bool ftarget_option = false;
2177 const char *source_version_for_javac;
2179 if (target_version == NULL)
2180 target_version = default_target_version ();
2182 source_version_for_javac =
2183 get_source_version_for_javac (source_version, target_version);
2185 if (is_envjavac_gcj (javac))
2187 /* It's a version of gcj. */
2188 if (is_envjavac_gcj43 (javac))
2190 /* It's a version of gcj >= 4.3. Assume the classfile versions
2191 are correct. */
2192 if (is_envjavac_gcj43_usable (javac,
2193 source_version, target_version,
2194 &usable,
2195 &fsource_option, &ftarget_option))
2197 err = true;
2198 goto done1;
2201 else
2203 /* It's a version of gcj < 4.3. Ignore the version of the
2204 class files that it creates. */
2205 if (strcmp (target_version, "1.4") == 0
2206 && strcmp (source_version, "1.4") == 0)
2208 if (is_envjavac_oldgcj_14_14_usable (javac, &usable))
2210 err = true;
2211 goto done1;
2214 else if (strcmp (target_version, "1.4") == 0
2215 && strcmp (source_version, "1.3") == 0)
2217 if (is_envjavac_oldgcj_14_13_usable (javac,
2218 &usable,
2219 &no_assert_option))
2221 err = true;
2222 goto done1;
2227 else
2229 /* It's not gcj. Assume the classfile versions are correct. */
2230 if (is_envjavac_nongcj_usable (javac,
2231 source_version,
2232 source_version_for_javac,
2233 target_version,
2234 &usable,
2235 &source_option, &target_option))
2237 err = true;
2238 goto done1;
2242 if (usable)
2244 char *old_classpath;
2245 char *javac_with_options;
2247 /* Set CLASSPATH. */
2248 old_classpath =
2249 set_classpath (classpaths, classpaths_count, false, verbose);
2251 javac_with_options =
2252 (no_assert_option
2253 ? xasprintf ("%s -fno-assert", javac)
2254 : xasprintf ("%s%s%s%s%s%s%s%s%s",
2255 javac,
2256 source_option ? " -source " : "",
2257 source_option ? source_version_for_javac : "",
2258 target_option ? " -target " : "",
2259 target_option ? target_version : "",
2260 fsource_option ? " -fsource=" : "",
2261 fsource_option ? source_version : "",
2262 ftarget_option ? " -ftarget=" : "",
2263 ftarget_option ? target_version : ""));
2265 err = compile_using_envjavac (javac_with_options,
2266 java_sources, java_sources_count,
2267 directory, optimize, debug, verbose,
2268 false);
2270 free (javac_with_options);
2272 /* Reset CLASSPATH. */
2273 reset_classpath (old_classpath);
2275 goto done1;
2280 /* Unset the JAVA_HOME environment variable. */
2281 old_JAVA_HOME = getenv ("JAVA_HOME");
2282 if (old_JAVA_HOME != NULL)
2284 old_JAVA_HOME = xstrdup (old_JAVA_HOME);
2285 unsetenv ("JAVA_HOME");
2288 if (is_gcj_present ())
2290 /* It's a version of gcj. */
2291 bool usable = false;
2292 bool no_assert_option = false;
2293 bool fsource_option = false;
2294 bool ftarget_option = false;
2296 if (target_version == NULL)
2297 target_version = default_target_version ();
2299 if (is_gcj_43 ())
2301 /* It's a version of gcj >= 4.3. Assume the classfile versions
2302 are correct. */
2303 if (is_gcj43_usable (source_version, target_version,
2304 &usable, &fsource_option, &ftarget_option))
2306 err = true;
2307 goto done1;
2310 else
2312 /* It's a version of gcj < 4.3. Ignore the version of the class
2313 files that it creates.
2314 Test whether it supports the desired target-version and
2315 source-version. */
2316 if (strcmp (target_version, "1.4") == 0
2317 && strcmp (source_version, "1.4") == 0)
2319 if (is_oldgcj_14_14_usable (&usable))
2321 err = true;
2322 goto done1;
2325 else if (strcmp (target_version, "1.4") == 0
2326 && strcmp (source_version, "1.3") == 0)
2328 if (is_oldgcj_14_13_usable (&usable, &no_assert_option))
2330 err = true;
2331 goto done1;
2336 if (usable)
2338 char *old_classpath;
2340 /* Set CLASSPATH. We could also use the --CLASSPATH=... option
2341 of gcj. Note that --classpath=... option is different: its
2342 argument should also contain gcj's libgcj.jar, but we don't
2343 know its location. */
2344 old_classpath =
2345 set_classpath (classpaths, classpaths_count, use_minimal_classpath,
2346 verbose);
2348 err = compile_using_gcj (java_sources, java_sources_count,
2349 no_assert_option,
2350 fsource_option, source_version,
2351 ftarget_option, target_version,
2352 directory, optimize, debug, verbose, false);
2354 /* Reset CLASSPATH. */
2355 reset_classpath (old_classpath);
2357 goto done2;
2361 if (is_javac_present ())
2363 bool usable = false;
2364 bool source_option = false;
2365 bool target_option = false;
2366 const char *source_version_for_javac;
2368 if (target_version == NULL)
2369 target_version = default_target_version ();
2371 source_version_for_javac =
2372 get_source_version_for_javac (source_version, target_version);
2374 if (is_javac_usable (source_version, source_version_for_javac,
2375 target_version,
2376 &usable, &source_option, &target_option))
2378 err = true;
2379 goto done1;
2382 if (usable)
2384 char *old_classpath;
2386 /* Set CLASSPATH. We don't use the "-classpath ..." option because
2387 in JDK 1.1.x its argument should also contain the JDK's
2388 classes.zip, but we don't know its location. (In JDK 1.3.0 it
2389 would work.) */
2390 old_classpath =
2391 set_classpath (classpaths, classpaths_count, use_minimal_classpath,
2392 verbose);
2394 err = compile_using_javac (java_sources, java_sources_count,
2395 source_option, source_version_for_javac,
2396 target_option, target_version,
2397 directory, optimize, debug, verbose,
2398 false);
2400 /* Reset CLASSPATH. */
2401 reset_classpath (old_classpath);
2403 goto done2;
2407 if (is_jikes_present ())
2409 /* Test whether it supports the desired target-version and
2410 source-version. */
2411 bool usable = (strcmp (source_version, "1.3") == 0);
2413 if (usable)
2415 char *old_classpath;
2417 /* Set CLASSPATH. We could also use the "-classpath ..." option.
2418 Since jikes doesn't come with its own standard library, it
2419 needs a classes.zip or rt.jar or libgcj.jar in the CLASSPATH.
2420 To increase the chance of success, we reuse the current CLASSPATH
2421 if the user has set it. */
2422 old_classpath =
2423 set_classpath (classpaths, classpaths_count, false, verbose);
2425 err = compile_using_jikes (java_sources, java_sources_count,
2426 directory, optimize, debug, verbose,
2427 false);
2429 /* Reset CLASSPATH. */
2430 reset_classpath (old_classpath);
2432 goto done2;
2436 error (0, 0, _("Java compiler not found, try installing gcj or set $JAVAC"));
2437 err = true;
2439 done2:
2440 if (old_JAVA_HOME != NULL)
2442 xsetenv ("JAVA_HOME", old_JAVA_HOME, 1);
2443 free (old_JAVA_HOME);
2446 done1:
2447 return err;