1 /* Compile a Java program.
2 Copyright (C) 2001-2003, 2006-2007 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 2, or (at your option)
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, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
31 #include <sys/types.h>
34 #include "javaversion.h"
37 #include "wait-process.h"
38 #include "classpath.h"
41 #include "binary-io.h"
42 #include "safe-read.h"
46 #include "fwriteerror.h"
47 #include "clean-temp.h"
49 #include "xvasprintf.h"
53 #define _(str) gettext (str)
55 /* The results of open() in this file are not used with fchdir,
56 therefore save some unnecessary work in fchdir.c. */
61 /* Survey of Java compilers.
63 A = does it work without CLASSPATH being set
64 C = option to set CLASSPATH, other than setting it in the environment
65 O = option for optimizing
66 g = option for debugging
69 Program from A C O g T
71 $JAVAC unknown N n/a -O -g true
72 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
73 javac JDK 1.1.8 Y -classpath P -O -g javac 2>/dev/null; test $? = 1
74 javac JDK 1.3.0 Y -classpath P -O -g javac 2>/dev/null; test $? -le 2
75 jikes Jikes 1.14 N -classpath P -O -g jikes 2>/dev/null; test $? = 1
77 All compilers support the option "-d DIRECTORY" for the base directory
78 of the classes to be written.
80 The CLASSPATH is a colon separated list of pathnames. (On Windows: a
81 semicolon separated list of pathnames.)
83 We try the Java compilers in the following order:
84 1. getenv ("JAVAC"), because the user must be able to override our
86 2. "gcj -C", because it is a completely free compiler,
87 3. "javac", because it is a standard compiler,
88 4. "jikes", comes last because it has some deviating interpretation
89 of the Java Language Specification and because it requires a
90 CLASSPATH environment variable.
92 We unset the JAVA_HOME environment variable, because a wrong setting of
93 this variable can confuse the JDK's javac.
96 /* Return the default target_version. */
98 default_target_version (void)
100 /* Use a cache. Assumes that the PATH environment variable doesn't change
101 during the lifetime of the program. */
102 static const char *java_version_cache;
103 if (java_version_cache == NULL)
105 /* Determine the version from the found JVM. */
106 java_version_cache = javaexec_version ();
107 if (java_version_cache == NULL
108 || !(java_version_cache[0] == '1' && java_version_cache[1] == '.'
109 && (java_version_cache[2] >= '1' && java_version_cache[2] <= '6')
110 && java_version_cache[3] == '\0'))
111 java_version_cache = "1.1";
113 return java_version_cache;
116 /* ======================= Source version dependent ======================= */
118 /* Convert a source version to an index. */
119 #define SOURCE_VERSION_BOUND 3 /* exclusive upper bound */
121 source_version_index (const char *source_version)
123 if (source_version[0] == '1' && source_version[1] == '.'
124 && (source_version[2] >= '3' && source_version[2] <= '5')
125 && source_version[3] == '\0')
126 return source_version[2] - '3';
127 error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
131 /* Return a snippet of code that should compile in the given source version. */
133 get_goodcode_snippet (const char *source_version)
135 if (strcmp (source_version, "1.3") == 0)
136 return "class conftest {}\n";
137 if (strcmp (source_version, "1.4") == 0)
138 return "class conftest { static { assert(true); } }\n";
139 if (strcmp (source_version, "1.5") == 0)
140 return "class conftest<T> { T foo() { return null; } }\n";
141 error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
145 /* Return a snippet of code that should fail to compile in the given source
146 version, or NULL (standing for a snippet that would fail to compile with
149 get_failcode_snippet (const char *source_version)
151 if (strcmp (source_version, "1.3") == 0)
152 return "class conftestfail { static { assert(true); } }\n";
153 if (strcmp (source_version, "1.4") == 0)
154 return "class conftestfail<T> { T foo() { return null; } }\n";
155 if (strcmp (source_version, "1.5") == 0)
157 error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class"));
161 /* ======================= Target version dependent ======================= */
163 /* Convert a target version to an index. */
164 #define TARGET_VERSION_BOUND 6 /* exclusive upper bound */
166 target_version_index (const char *target_version)
168 if (target_version[0] == '1' && target_version[1] == '.'
169 && (target_version[2] >= '1' && target_version[2] <= '6')
170 && target_version[3] == '\0')
171 return target_version[2] - '1';
172 error (EXIT_FAILURE, 0, _("invalid target_version argument to compile_java_class"));
176 /* Return the class file version number corresponding to a given target
179 corresponding_classfile_version (const char *target_version)
181 if (strcmp (target_version, "1.1") == 0)
183 if (strcmp (target_version, "1.2") == 0)
185 if (strcmp (target_version, "1.3") == 0)
187 if (strcmp (target_version, "1.4") == 0)
189 if (strcmp (target_version, "1.5") == 0)
191 if (strcmp (target_version, "1.6") == 0)
193 error (EXIT_FAILURE, 0, _("invalid target_version argument to compile_java_class"));
197 /* ======================== Compilation subroutines ======================== */
199 /* Try to compile a set of Java sources with $JAVAC.
200 Return a failure indicator (true upon error). */
202 compile_using_envjavac (const char *javac,
203 const char * const *java_sources,
204 unsigned int java_sources_count,
205 const char *directory,
206 bool optimize, bool debug,
207 bool verbose, bool null_stderr)
209 /* Because $JAVAC may consist of a command and options, we use the
210 shell. Because $JAVAC has been set by the user, we leave all
211 environment variables in place, including JAVA_HOME, and we don't
212 erase the user's CLASSPATH. */
214 unsigned int command_length;
221 command_length = strlen (javac);
226 if (directory != NULL)
227 command_length += 4 + shell_quote_length (directory);
228 for (i = 0; i < java_sources_count; i++)
229 command_length += 1 + shell_quote_length (java_sources[i]);
232 command = (char *) xmalloca (command_length);
234 /* Don't shell_quote $JAVAC, because it may consist of a command
236 memcpy (p, javac, strlen (javac));
240 memcpy (p, " -O", 3);
245 memcpy (p, " -g", 3);
248 if (directory != NULL)
250 memcpy (p, " -d ", 4);
252 p = shell_quote_copy (p, directory);
254 for (i = 0; i < java_sources_count; i++)
257 p = shell_quote_copy (p, java_sources[i]);
260 /* Ensure command_length was correctly calculated. */
261 if (p - command > command_length)
265 printf ("%s\n", command);
271 exitstatus = execute (javac, "/bin/sh", argv, false, false, false,
272 null_stderr, true, true);
273 err = (exitstatus != 0);
280 /* Try to compile a set of Java sources with gcj.
281 Return a failure indicator (true upon error). */
283 compile_using_gcj (const char * const *java_sources,
284 unsigned int java_sources_count,
285 bool no_assert_option,
286 bool fsource_option, const char *source_version,
287 bool ftarget_option, const char *target_version,
288 const char *directory,
289 bool optimize, bool debug,
290 bool verbose, bool null_stderr)
302 2 + (no_assert_option ? 1 : 0) + (fsource_option ? 1 : 0)
303 + (ftarget_option ? 1 : 0) + (optimize ? 1 : 0) + (debug ? 1 : 0)
304 + (directory != NULL ? 2 : 0) + java_sources_count;
305 argv = (char **) xmalloca ((argc + 1) * sizeof (char *));
310 if (no_assert_option)
311 *argp++ = "-fno-assert";
314 fsource_arg = (char *) xmalloca (9 + strlen (source_version) + 1);
315 memcpy (fsource_arg, "-fsource=", 9);
316 strcpy (fsource_arg + 9, source_version);
317 *argp++ = fsource_arg;
323 ftarget_arg = (char *) xmalloca (9 + strlen (target_version) + 1);
324 memcpy (ftarget_arg, "-ftarget=", 9);
325 strcpy (ftarget_arg + 9, target_version);
326 *argp++ = ftarget_arg;
334 if (directory != NULL)
337 *argp++ = (char *) directory;
339 for (i = 0; i < java_sources_count; i++)
340 *argp++ = (char *) java_sources[i];
342 /* Ensure argv length was correctly calculated. */
343 if (argp - argv != argc)
348 char *command = shell_quote_argv (argv);
349 printf ("%s\n", command);
353 exitstatus = execute ("gcj", "gcj", argv, false, false, false, null_stderr,
355 err = (exitstatus != 0);
357 if (ftarget_arg != NULL)
359 if (fsource_arg != NULL)
366 /* Try to compile a set of Java sources with javac.
367 Return a failure indicator (true upon error). */
369 compile_using_javac (const char * const *java_sources,
370 unsigned int java_sources_count,
371 bool source_option, const char *source_version,
372 bool target_option, const char *target_version,
373 const char *directory,
374 bool optimize, bool debug,
375 bool verbose, bool null_stderr)
385 1 + (source_option ? 2 : 0) + (target_option ? 2 : 0) + (optimize ? 1 : 0)
386 + (debug ? 1 : 0) + (directory != NULL ? 2 : 0) + java_sources_count;
387 argv = (char **) xmalloca ((argc + 1) * sizeof (char *));
394 *argp++ = (char *) source_version;
399 *argp++ = (char *) target_version;
405 if (directory != NULL)
408 *argp++ = (char *) directory;
410 for (i = 0; i < java_sources_count; i++)
411 *argp++ = (char *) java_sources[i];
413 /* Ensure argv length was correctly calculated. */
414 if (argp - argv != argc)
419 char *command = shell_quote_argv (argv);
420 printf ("%s\n", command);
424 exitstatus = execute ("javac", "javac", argv, false, false, false,
425 null_stderr, true, true);
426 err = (exitstatus != 0);
433 /* Try to compile a set of Java sources with jikes.
434 Return a failure indicator (true upon error). */
436 compile_using_jikes (const char * const *java_sources,
437 unsigned int java_sources_count,
438 const char *directory,
439 bool optimize, bool debug,
440 bool verbose, bool null_stderr)
450 1 + (optimize ? 1 : 0) + (debug ? 1 : 0) + (directory != NULL ? 2 : 0)
451 + java_sources_count;
452 argv = (char **) xmalloca ((argc + 1) * sizeof (char *));
460 if (directory != NULL)
463 *argp++ = (char *) directory;
465 for (i = 0; i < java_sources_count; i++)
466 *argp++ = (char *) java_sources[i];
468 /* Ensure argv length was correctly calculated. */
469 if (argp - argv != argc)
474 char *command = shell_quote_argv (argv);
475 printf ("%s\n", command);
479 exitstatus = execute ("jikes", "jikes", argv, false, false, false,
480 null_stderr, true, true);
481 err = (exitstatus != 0);
488 /* ====================== Usability test subroutines ====================== */
490 /* Write a given contents to a temporary file.
491 FILE_NAME is the name of a file inside TMPDIR that is known not to exist
493 Return a failure indicator (true upon error). */
495 write_temp_file (struct temp_dir *tmpdir, const char *file_name,
496 const char *contents)
500 register_temp_file (tmpdir, file_name);
501 fp = fopen_temp (file_name, "w");
504 error (0, errno, _("failed to create \"%s\""), file_name);
505 unregister_temp_file (tmpdir, file_name);
508 fputs (contents, fp);
509 if (fwriteerror_temp (fp))
511 error (0, errno, _("error while writing \"%s\" file"), file_name);
517 /* Return the class file version number of a class file on disk. */
519 get_classfile_version (const char *compiled_file_name)
521 unsigned char header[8];
524 /* Open the class file. */
525 fd = open (compiled_file_name, O_RDONLY | O_BINARY, 0);
528 /* Read its first 8 bytes. */
529 if (safe_read (fd, header, 8) == 8)
531 /* Verify the class file signature. */
532 if (header[0] == 0xCA && header[1] == 0xFE
533 && header[2] == 0xBA && header[3] == 0xBE)
539 /* Could not get the class file version. Return a very large one. */
543 /* Return true if $JAVAC is a version of gcj. */
545 is_envjavac_gcj (const char *javac)
547 static bool envjavac_tested;
548 static bool envjavac_gcj;
550 if (!envjavac_tested)
552 /* Test whether $JAVAC is gcj:
553 "$JAVAC --version 2>/dev/null | sed -e 1q | grep gcj > /dev/null" */
554 unsigned int command_length;
566 /* Setup the command "$JAVAC --version". */
567 command_length = strlen (javac) + 1 + 9 + 1;
568 command = (char *) xmalloca (command_length);
570 /* Don't shell_quote $JAVAC, because it may consist of a command
572 memcpy (p, javac, strlen (javac));
574 memcpy (p, " --version", 1 + 9 + 1);
576 /* Ensure command_length was correctly calculated. */
577 if (p - command > command_length)
580 /* Call $JAVAC --version 2>/dev/null. */
585 child = create_pipe_in (javac, "/bin/sh", argv, DEV_NULL, true, true,
590 /* Retrieve its result. */
591 fp = fdopen (fd[0], "r");
595 line = NULL; linesize = 0;
596 linelen = getline (&line, &linesize, fp);
597 if (linelen == (size_t)(-1))
602 /* It is safe to call c_strstr() instead of strstr() here; see the
603 comments in c-strstr.h. */
604 envjavac_gcj = (c_strstr (line, "gcj") != NULL);
608 /* Remove zombie process from process list, and retrieve exit status. */
609 exitstatus = wait_subprocess (child, javac, true, true, true, false);
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. */
693 exitstatus = wait_subprocess (child, javac, true, true, true, false);
695 envjavac_gcj43 = false;
700 envjavac_tested = true;
703 return envjavac_gcj43;
706 /* Test whether $JAVAC, known to be a version of gcj >= 4.3, can be used, and
707 whether it needs a -fsource and/or -ftarget option.
708 Return a failure indicator (true upon error). */
710 is_envjavac_gcj43_usable (const char *javac,
711 const char *source_version,
712 const char *target_version,
714 bool *fsource_option_p, bool *ftarget_option_p)
716 /* The cache depends on the source_version and target_version. */
724 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
725 struct result_t *resultp;
727 resultp = &result_cache[source_version_index (source_version)]
728 [target_version_index (target_version)];
729 if (!resultp->tested)
732 struct temp_dir *tmpdir;
733 char *conftest_file_name;
734 char *compiled_file_name;
735 const char *java_sources[1];
738 tmpdir = create_temp_dir ("java", NULL, false);
743 concatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
744 if (write_temp_file (tmpdir, conftest_file_name,
745 get_goodcode_snippet (source_version)))
747 free (conftest_file_name);
748 cleanup_temp_dir (tmpdir);
753 concatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
754 register_temp_file (tmpdir, compiled_file_name);
756 java_sources[0] = conftest_file_name;
757 if (!compile_using_envjavac (javac,
758 java_sources, 1, tmpdir->dir_name,
759 false, false, false, true)
760 && stat (compiled_file_name, &statbuf) >= 0
761 && get_classfile_version (compiled_file_name)
762 <= corresponding_classfile_version (target_version))
764 /* $JAVAC compiled conftest.java successfully. */
765 /* Try adding -fsource option if it is useful. */
767 xasprintf ("%s -fsource=%s", javac, source_version);
769 unlink (compiled_file_name);
771 java_sources[0] = conftest_file_name;
772 if (!compile_using_envjavac (javac_source,
773 java_sources, 1, tmpdir->dir_name,
774 false, false, false, true)
775 && stat (compiled_file_name, &statbuf) >= 0
776 && get_classfile_version (compiled_file_name)
777 <= corresponding_classfile_version (target_version))
779 const char *failcode = get_failcode_snippet (source_version);
781 if (failcode != NULL)
783 free (compiled_file_name);
784 free (conftest_file_name);
787 concatenated_filename (tmpdir->dir_name,
790 if (write_temp_file (tmpdir, conftest_file_name, failcode))
792 free (conftest_file_name);
794 cleanup_temp_dir (tmpdir);
799 concatenated_filename (tmpdir->dir_name,
800 "conftestfail.class",
802 register_temp_file (tmpdir, compiled_file_name);
804 java_sources[0] = conftest_file_name;
805 if (!compile_using_envjavac (javac,
808 false, false, false, true)
809 && stat (compiled_file_name, &statbuf) >= 0)
811 unlink (compiled_file_name);
813 java_sources[0] = conftest_file_name;
814 if (compile_using_envjavac (javac_source,
817 false, false, false, true))
818 /* $JAVAC compiled conftestfail.java successfully, and
819 "$JAVAC -fsource=$source_version" rejects it. So
820 the -fsource option is useful. */
821 resultp->fsource_option = true;
828 resultp->usable = true;
832 /* Try with -fsource and -ftarget options. */
834 xasprintf ("%s -fsource=%s -ftarget=%s",
835 javac, source_version, target_version);
837 unlink (compiled_file_name);
839 java_sources[0] = conftest_file_name;
840 if (!compile_using_envjavac (javac_target,
841 java_sources, 1, tmpdir->dir_name,
842 false, false, false, true)
843 && stat (compiled_file_name, &statbuf) >= 0
844 && get_classfile_version (compiled_file_name)
845 <= corresponding_classfile_version (target_version))
847 /* "$JAVAC -fsource $source_version -ftarget $target_version"
848 compiled conftest.java successfully. */
849 resultp->fsource_option = true;
850 resultp->ftarget_option = true;
851 resultp->usable = true;
857 free (compiled_file_name);
858 free (conftest_file_name);
860 resultp->tested = true;
863 *usablep = resultp->usable;
864 *fsource_option_p = resultp->fsource_option;
865 *ftarget_option_p = resultp->ftarget_option;
869 /* Test whether $JAVAC, known to be a version of gcj < 4.3, can be used for
870 compiling with target_version = 1.4 and source_version = 1.4.
871 Return a failure indicator (true upon error). */
873 is_envjavac_oldgcj_14_14_usable (const char *javac, bool *usablep)
875 static bool envjavac_tested;
876 static bool envjavac_usable;
878 if (!envjavac_tested)
881 struct temp_dir *tmpdir;
882 char *conftest_file_name;
883 char *compiled_file_name;
884 const char *java_sources[1];
887 tmpdir = create_temp_dir ("java", NULL, false);
892 concatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
893 if (write_temp_file (tmpdir, conftest_file_name,
894 get_goodcode_snippet ("1.4")))
896 free (conftest_file_name);
897 cleanup_temp_dir (tmpdir);
902 concatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
903 register_temp_file (tmpdir, compiled_file_name);
905 java_sources[0] = conftest_file_name;
906 if (!compile_using_envjavac (javac, java_sources, 1, tmpdir->dir_name,
907 false, false, false, true)
908 && stat (compiled_file_name, &statbuf) >= 0)
909 /* Compilation succeeded. */
910 envjavac_usable = true;
912 free (compiled_file_name);
913 free (conftest_file_name);
915 cleanup_temp_dir (tmpdir);
917 envjavac_tested = true;
920 *usablep = envjavac_usable;
924 /* Test whether $JAVAC, known to be a version of gcj < 4.3, can be used for
925 compiling with target_version = 1.4 and source_version = 1.3.
926 Return a failure indicator (true upon error). */
928 is_envjavac_oldgcj_14_13_usable (const char *javac,
929 bool *usablep, bool *need_no_assert_option_p)
931 static bool envjavac_tested;
932 static bool envjavac_usable;
933 static bool envjavac_need_no_assert_option;
935 if (!envjavac_tested)
937 /* Try $JAVAC and "$JAVAC -fno-assert". But add -fno-assert only if
938 it makes a difference. (It could already be part of $JAVAC.) */
939 struct temp_dir *tmpdir;
940 char *conftest_file_name;
941 char *compiled_file_name;
942 const char *java_sources[1];
945 char *javac_noassert;
946 bool javac_noassert_works;
948 tmpdir = create_temp_dir ("java", NULL, false);
953 concatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
954 if (write_temp_file (tmpdir, conftest_file_name,
955 get_goodcode_snippet ("1.3")))
957 free (conftest_file_name);
958 cleanup_temp_dir (tmpdir);
963 concatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
964 register_temp_file (tmpdir, compiled_file_name);
966 java_sources[0] = conftest_file_name;
967 if (!compile_using_envjavac (javac,
968 java_sources, 1, tmpdir->dir_name,
969 false, false, false, true)
970 && stat (compiled_file_name, &statbuf) >= 0)
971 /* Compilation succeeded. */
976 unlink (compiled_file_name);
978 javac_noassert = xasprintf ("%s -fno-assert", javac);
980 java_sources[0] = conftest_file_name;
981 if (!compile_using_envjavac (javac_noassert,
982 java_sources, 1, tmpdir->dir_name,
983 false, false, false, true)
984 && stat (compiled_file_name, &statbuf) >= 0)
985 /* Compilation succeeded. */
986 javac_noassert_works = true;
988 javac_noassert_works = false;
990 free (compiled_file_name);
991 free (conftest_file_name);
993 if (javac_works && javac_noassert_works)
996 concatenated_filename (tmpdir->dir_name, "conftestfail.java",
998 if (write_temp_file (tmpdir, conftest_file_name,
999 get_failcode_snippet ("1.3")))
1001 free (conftest_file_name);
1002 free (javac_noassert);
1003 cleanup_temp_dir (tmpdir);
1007 compiled_file_name =
1008 concatenated_filename (tmpdir->dir_name, "conftestfail.class",
1010 register_temp_file (tmpdir, compiled_file_name);
1012 java_sources[0] = conftest_file_name;
1013 if (!compile_using_envjavac (javac,
1014 java_sources, 1, tmpdir->dir_name,
1015 false, false, false, true)
1016 && stat (compiled_file_name, &statbuf) >= 0)
1018 /* Compilation succeeded. */
1019 unlink (compiled_file_name);
1021 java_sources[0] = conftest_file_name;
1022 if (!(!compile_using_envjavac (javac_noassert,
1023 java_sources, 1, tmpdir->dir_name,
1024 false, false, false, true)
1025 && stat (compiled_file_name, &statbuf) >= 0))
1026 /* Compilation failed. */
1027 /* "$JAVAC -fno-assert" works better than $JAVAC. */
1031 free (compiled_file_name);
1032 free (conftest_file_name);
1035 cleanup_temp_dir (tmpdir);
1039 envjavac_usable = true;
1040 envjavac_need_no_assert_option = false;
1042 else if (javac_noassert_works)
1044 envjavac_usable = true;
1045 envjavac_need_no_assert_option = true;
1048 envjavac_tested = true;
1051 *usablep = envjavac_usable;
1052 *need_no_assert_option_p = envjavac_need_no_assert_option;
1056 /* Test whether $JAVAC, known to be not a version of gcj, can be used, and
1057 whether it needs a -source and/or -target option.
1058 Return a failure indicator (true upon error). */
1060 is_envjavac_nongcj_usable (const char *javac,
1061 const char *source_version,
1062 const char *target_version,
1064 bool *source_option_p, bool *target_option_p)
1066 /* The cache depends on the source_version and target_version. */
1074 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
1075 struct result_t *resultp;
1077 resultp = &result_cache[source_version_index (source_version)]
1078 [target_version_index (target_version)];
1079 if (!resultp->tested)
1082 struct temp_dir *tmpdir;
1083 char *conftest_file_name;
1084 char *compiled_file_name;
1085 const char *java_sources[1];
1086 struct stat statbuf;
1088 tmpdir = create_temp_dir ("java", NULL, false);
1092 conftest_file_name =
1093 concatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1094 if (write_temp_file (tmpdir, conftest_file_name,
1095 get_goodcode_snippet (source_version)))
1097 free (conftest_file_name);
1098 cleanup_temp_dir (tmpdir);
1102 compiled_file_name =
1103 concatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1104 register_temp_file (tmpdir, compiled_file_name);
1106 java_sources[0] = conftest_file_name;
1107 if (!compile_using_envjavac (javac,
1108 java_sources, 1, tmpdir->dir_name,
1109 false, false, false, true)
1110 && stat (compiled_file_name, &statbuf) >= 0
1111 && get_classfile_version (compiled_file_name)
1112 <= corresponding_classfile_version (target_version))
1114 /* $JAVAC compiled conftest.java successfully. */
1115 /* Try adding -source option if it is useful. */
1116 char *javac_source =
1117 xasprintf ("%s -source %s", javac, source_version);
1119 unlink (compiled_file_name);
1121 java_sources[0] = conftest_file_name;
1122 if (!compile_using_envjavac (javac_source,
1123 java_sources, 1, tmpdir->dir_name,
1124 false, false, false, true)
1125 && stat (compiled_file_name, &statbuf) >= 0
1126 && get_classfile_version (compiled_file_name)
1127 <= corresponding_classfile_version (target_version))
1129 const char *failcode = get_failcode_snippet (source_version);
1131 if (failcode != NULL)
1133 free (compiled_file_name);
1134 free (conftest_file_name);
1136 conftest_file_name =
1137 concatenated_filename (tmpdir->dir_name,
1138 "conftestfail.java",
1140 if (write_temp_file (tmpdir, conftest_file_name, failcode))
1142 free (conftest_file_name);
1143 free (javac_source);
1144 cleanup_temp_dir (tmpdir);
1148 compiled_file_name =
1149 concatenated_filename (tmpdir->dir_name,
1150 "conftestfail.class",
1152 register_temp_file (tmpdir, compiled_file_name);
1154 java_sources[0] = conftest_file_name;
1155 if (!compile_using_envjavac (javac,
1158 false, false, false, true)
1159 && stat (compiled_file_name, &statbuf) >= 0)
1161 unlink (compiled_file_name);
1163 java_sources[0] = conftest_file_name;
1164 if (compile_using_envjavac (javac_source,
1167 false, false, false, true))
1168 /* $JAVAC compiled conftestfail.java successfully, and
1169 "$JAVAC -source $source_version" rejects it. So the
1170 -source option is useful. */
1171 resultp->source_option = true;
1176 free (javac_source);
1178 resultp->usable = true;
1182 /* Try with -target option alone. (Sun javac 1.3.1 has the -target
1183 option but no -source option.) */
1184 char *javac_target =
1185 xasprintf ("%s -target %s", javac, target_version);
1187 unlink (compiled_file_name);
1189 java_sources[0] = conftest_file_name;
1190 if (!compile_using_envjavac (javac_target,
1191 java_sources, 1, tmpdir->dir_name,
1192 false, false, false, true)
1193 && stat (compiled_file_name, &statbuf) >= 0
1194 && get_classfile_version (compiled_file_name)
1195 <= corresponding_classfile_version (target_version))
1197 /* "$JAVAC -target $target_version" compiled conftest.java
1199 /* Try adding -source option if it is useful. */
1200 char *javac_target_source =
1201 xasprintf ("%s -source %s", javac_target, source_version);
1203 unlink (compiled_file_name);
1205 java_sources[0] = conftest_file_name;
1206 if (!compile_using_envjavac (javac_target_source,
1207 java_sources, 1, tmpdir->dir_name,
1208 false, false, false, true)
1209 && stat (compiled_file_name, &statbuf) >= 0
1210 && get_classfile_version (compiled_file_name)
1211 <= corresponding_classfile_version (target_version))
1213 const char *failcode = get_failcode_snippet (source_version);
1215 if (failcode != NULL)
1217 free (compiled_file_name);
1218 free (conftest_file_name);
1220 conftest_file_name =
1221 concatenated_filename (tmpdir->dir_name,
1222 "conftestfail.java",
1224 if (write_temp_file (tmpdir, conftest_file_name,
1227 free (conftest_file_name);
1228 free (javac_target_source);
1229 free (javac_target);
1230 cleanup_temp_dir (tmpdir);
1234 compiled_file_name =
1235 concatenated_filename (tmpdir->dir_name,
1236 "conftestfail.class",
1238 register_temp_file (tmpdir, compiled_file_name);
1240 java_sources[0] = conftest_file_name;
1241 if (!compile_using_envjavac (javac_target,
1244 false, false, false, true)
1245 && stat (compiled_file_name, &statbuf) >= 0)
1247 unlink (compiled_file_name);
1249 java_sources[0] = conftest_file_name;
1250 if (compile_using_envjavac (javac_target_source,
1253 false, false, false,
1255 /* "$JAVAC -target $target_version" compiled
1256 conftestfail.java successfully, and
1257 "$JAVAC -target $target_version -source $source_version"
1258 rejects it. So the -source option is useful. */
1259 resultp->source_option = true;
1264 free (javac_target_source);
1266 resultp->target_option = true;
1267 resultp->usable = true;
1271 /* Maybe this -target option requires a -source option? Try with
1272 -target and -source options. (Supported by Sun javac 1.4 and
1274 char *javac_target_source =
1275 xasprintf ("%s -source %s", javac_target, source_version);
1277 unlink (compiled_file_name);
1279 java_sources[0] = conftest_file_name;
1280 if (!compile_using_envjavac (javac_target_source,
1281 java_sources, 1, tmpdir->dir_name,
1282 false, false, false, true)
1283 && stat (compiled_file_name, &statbuf) >= 0
1284 && get_classfile_version (compiled_file_name)
1285 <= corresponding_classfile_version (target_version))
1287 /* "$JAVAC -target $target_version -source $source_version"
1288 compiled conftest.java successfully. */
1289 resultp->source_option = true;
1290 resultp->target_option = true;
1291 resultp->usable = true;
1294 free (javac_target_source);
1297 free (javac_target);
1300 free (compiled_file_name);
1301 free (conftest_file_name);
1303 resultp->tested = true;
1306 *usablep = resultp->usable;
1307 *source_option_p = resultp->source_option;
1308 *target_option_p = resultp->target_option;
1313 is_gcj_present (void)
1315 static bool gcj_tested;
1316 static bool gcj_present;
1320 /* Test for presence of gcj:
1321 "gcj --version 2> /dev/null | \
1322 sed -e 's,^[^0-9]*,,' -e 1q | \
1323 sed -e '/^3\.[01]/d' | grep '^[3-9]' > /dev/null" */
1330 argv[1] = "--version";
1332 child = create_pipe_in ("gcj", "gcj", argv, DEV_NULL, true, true,
1334 gcj_present = false;
1337 /* Read the subprocess output, drop all lines except the first,
1338 drop all characters before the first digit, and test whether
1339 the remaining string starts with a digit >= 3, but not with
1344 while (safe_read (fd[0], &c[count], 1) > 0)
1346 if (c[count] == '\n')
1350 if (!(c[0] >= '0' && c[0] <= '9'))
1352 gcj_present = (c[0] >= '3');
1357 if (c[0] == '3' && c[1] == '.'
1358 && (c[2] == '0' || c[2] == '1'))
1359 gcj_present = false;
1363 while (safe_read (fd[0], &c[0], 1) > 0)
1368 /* Remove zombie process from process list, and retrieve exit
1371 wait_subprocess (child, "gcj", false, true, true, false);
1372 if (exitstatus != 0)
1373 gcj_present = false;
1378 /* See if libgcj.jar is well installed. */
1379 struct temp_dir *tmpdir;
1381 tmpdir = create_temp_dir ("java", NULL, false);
1383 gcj_present = false;
1386 char *conftest_file_name;
1388 conftest_file_name =
1389 concatenated_filename (tmpdir->dir_name, "conftestlib.java",
1391 if (write_temp_file (tmpdir, conftest_file_name,
1392 "public class conftestlib {\n"
1393 " public static void main (String[] args) {\n"
1396 gcj_present = false;
1399 char *compiled_file_name;
1400 const char *java_sources[1];
1402 compiled_file_name =
1403 concatenated_filename (tmpdir->dir_name,
1404 "conftestlib.class",
1406 register_temp_file (tmpdir, compiled_file_name);
1408 java_sources[0] = conftest_file_name;
1409 if (compile_using_gcj (java_sources, 1, false,
1410 false, NULL, false, NULL,
1412 false, false, false, true))
1413 gcj_present = false;
1415 free (compiled_file_name);
1417 free (conftest_file_name);
1419 cleanup_temp_dir (tmpdir);
1431 static bool gcj_tested;
1436 /* Test for presence of gcj:
1437 "gcj --version 2> /dev/null | \
1438 sed -e 's,^[^0-9]*,,' -e 1q | \
1439 sed -e '/^4\.[012]/d' | grep '^[4-9]'" */
1446 argv[1] = "--version";
1448 child = create_pipe_in ("gcj", "gcj", argv, DEV_NULL, true, true,
1453 /* Read the subprocess output, drop all lines except the first,
1454 drop all characters before the first digit, and test whether
1455 the remaining string starts with a digit >= 4, but not with
1456 "4.0" or "4.1" or "4.2". */
1460 while (safe_read (fd[0], &c[count], 1) > 0)
1462 if (c[count] == '\n')
1466 if (!(c[0] >= '0' && c[0] <= '9'))
1468 gcj_43 = (c[0] >= '4');
1473 if (c[0] == '4' && c[1] == '.' && c[2] >= '0' && c[2] <= '2')
1478 while (safe_read (fd[0], &c[0], 1) > 0)
1483 /* Remove zombie process from process list, and retrieve exit
1486 wait_subprocess (child, "gcj", false, true, true, false);
1487 if (exitstatus != 0)
1497 /* Test whether gcj >= 4.3 can be used, and whether it needs a -fsource and/or
1499 Return a failure indicator (true upon error). */
1501 is_gcj43_usable (const char *source_version,
1502 const char *target_version,
1504 bool *fsource_option_p, bool *ftarget_option_p)
1506 /* The cache depends on the source_version and target_version. */
1511 bool fsource_option;
1512 bool ftarget_option;
1514 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
1515 struct result_t *resultp;
1517 resultp = &result_cache[source_version_index (source_version)]
1518 [target_version_index (target_version)];
1519 if (!resultp->tested)
1522 struct temp_dir *tmpdir;
1523 char *conftest_file_name;
1524 char *compiled_file_name;
1525 const char *java_sources[1];
1526 struct stat statbuf;
1528 tmpdir = create_temp_dir ("java", NULL, false);
1532 conftest_file_name =
1533 concatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1534 if (write_temp_file (tmpdir, conftest_file_name,
1535 get_goodcode_snippet (source_version)))
1537 free (conftest_file_name);
1538 cleanup_temp_dir (tmpdir);
1542 compiled_file_name =
1543 concatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1544 register_temp_file (tmpdir, compiled_file_name);
1546 java_sources[0] = conftest_file_name;
1547 if (!compile_using_gcj (java_sources, 1, false, false, NULL, false, NULL,
1548 tmpdir->dir_name, false, false, false, true)
1549 && stat (compiled_file_name, &statbuf) >= 0
1550 && get_classfile_version (compiled_file_name)
1551 <= corresponding_classfile_version (target_version))
1553 /* gcj compiled conftest.java successfully. */
1554 /* Try adding -fsource option if it is useful. */
1555 unlink (compiled_file_name);
1557 java_sources[0] = conftest_file_name;
1558 if (!compile_using_gcj (java_sources, 1,
1559 false, true, source_version, false, NULL,
1560 tmpdir->dir_name, false, false, false, true)
1561 && stat (compiled_file_name, &statbuf) >= 0
1562 && get_classfile_version (compiled_file_name)
1563 <= corresponding_classfile_version (target_version))
1565 const char *failcode = get_failcode_snippet (source_version);
1567 if (failcode != NULL)
1569 free (compiled_file_name);
1570 free (conftest_file_name);
1572 conftest_file_name =
1573 concatenated_filename (tmpdir->dir_name,
1574 "conftestfail.java",
1576 if (write_temp_file (tmpdir, conftest_file_name, failcode))
1578 free (conftest_file_name);
1579 cleanup_temp_dir (tmpdir);
1583 compiled_file_name =
1584 concatenated_filename (tmpdir->dir_name,
1585 "conftestfail.class",
1587 register_temp_file (tmpdir, compiled_file_name);
1589 java_sources[0] = conftest_file_name;
1590 if (!compile_using_gcj (java_sources, 1,
1591 false, false, NULL, false, NULL,
1593 false, false, false, true)
1594 && stat (compiled_file_name, &statbuf) >= 0)
1596 unlink (compiled_file_name);
1598 java_sources[0] = conftest_file_name;
1599 if (compile_using_gcj (java_sources, 1,
1600 false, true, source_version,
1603 false, false, false, true))
1604 /* gcj compiled conftestfail.java successfully, and
1605 "gcj -fsource=$source_version" rejects it. So
1606 the -fsource option is useful. */
1607 resultp->fsource_option = true;
1612 resultp->usable = true;
1616 /* Try with -fsource and -ftarget options. */
1617 unlink (compiled_file_name);
1619 java_sources[0] = conftest_file_name;
1620 if (!compile_using_gcj (java_sources, 1,
1621 false, true, source_version,
1622 true, target_version,
1624 false, false, false, true)
1625 && stat (compiled_file_name, &statbuf) >= 0
1626 && get_classfile_version (compiled_file_name)
1627 <= corresponding_classfile_version (target_version))
1629 /* "gcj -fsource $source_version -ftarget $target_version"
1630 compiled conftest.java successfully. */
1631 resultp->fsource_option = true;
1632 resultp->ftarget_option = true;
1633 resultp->usable = true;
1637 free (compiled_file_name);
1638 free (conftest_file_name);
1640 resultp->tested = true;
1643 *usablep = resultp->usable;
1644 *fsource_option_p = resultp->fsource_option;
1645 *ftarget_option_p = resultp->ftarget_option;
1649 /* Test whether gcj < 4.3 can be used for compiling with target_version = 1.4
1650 and source_version = 1.4.
1651 Return a failure indicator (true upon error). */
1653 is_oldgcj_14_14_usable (bool *usablep)
1655 static bool gcj_tested;
1656 static bool gcj_usable;
1661 struct temp_dir *tmpdir;
1662 char *conftest_file_name;
1663 char *compiled_file_name;
1664 const char *java_sources[1];
1665 struct stat statbuf;
1667 tmpdir = create_temp_dir ("java", NULL, false);
1671 conftest_file_name =
1672 concatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1673 if (write_temp_file (tmpdir, conftest_file_name,
1674 get_goodcode_snippet ("1.4")))
1676 free (conftest_file_name);
1677 cleanup_temp_dir (tmpdir);
1681 compiled_file_name =
1682 concatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1683 register_temp_file (tmpdir, compiled_file_name);
1685 java_sources[0] = conftest_file_name;
1686 if (!compile_using_gcj (java_sources, 1, false, false, NULL, false, NULL,
1687 tmpdir->dir_name, false, false, false, true)
1688 && stat (compiled_file_name, &statbuf) >= 0)
1689 /* Compilation succeeded. */
1692 free (compiled_file_name);
1693 free (conftest_file_name);
1695 cleanup_temp_dir (tmpdir);
1700 *usablep = gcj_usable;
1704 /* Test whether gcj < 4.3 can be used for compiling with target_version = 1.4
1705 and source_version = 1.3.
1706 Return a failure indicator (true upon error). */
1708 is_oldgcj_14_13_usable (bool *usablep, bool *need_no_assert_option_p)
1710 static bool gcj_tested;
1711 static bool gcj_usable;
1712 static bool gcj_need_no_assert_option;
1716 /* Try gcj and "gcj -fno-assert". But add -fno-assert only if
1717 it works (not gcj < 3.3). */
1718 struct temp_dir *tmpdir;
1719 char *conftest_file_name;
1720 char *compiled_file_name;
1721 const char *java_sources[1];
1722 struct stat statbuf;
1724 tmpdir = create_temp_dir ("java", NULL, false);
1728 conftest_file_name =
1729 concatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1730 if (write_temp_file (tmpdir, conftest_file_name,
1731 get_goodcode_snippet ("1.3")))
1733 free (conftest_file_name);
1734 cleanup_temp_dir (tmpdir);
1738 compiled_file_name =
1739 concatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1740 register_temp_file (tmpdir, compiled_file_name);
1742 java_sources[0] = conftest_file_name;
1743 if (!compile_using_gcj (java_sources, 1, true, false, NULL, false, NULL,
1744 tmpdir->dir_name, false, false, false, true)
1745 && stat (compiled_file_name, &statbuf) >= 0)
1746 /* Compilation succeeded. */
1749 gcj_need_no_assert_option = true;
1753 unlink (compiled_file_name);
1755 java_sources[0] = conftest_file_name;
1756 if (!compile_using_gcj (java_sources, 1, false,
1757 false, NULL, false, NULL,
1758 tmpdir->dir_name, false, false, false, true)
1759 && stat (compiled_file_name, &statbuf) >= 0)
1760 /* Compilation succeeded. */
1763 gcj_need_no_assert_option = false;
1767 free (compiled_file_name);
1768 free (conftest_file_name);
1770 cleanup_temp_dir (tmpdir);
1775 *usablep = gcj_usable;
1776 *need_no_assert_option_p = gcj_need_no_assert_option;
1781 is_javac_present (void)
1783 static bool javac_tested;
1784 static bool javac_present;
1788 /* Test for presence of javac: "javac 2> /dev/null ; test $? -le 2" */
1794 exitstatus = execute ("javac", "javac", argv, false, false, true, true,
1796 javac_present = (exitstatus == 0 || exitstatus == 1 || exitstatus == 2);
1797 javac_tested = true;
1800 return javac_present;
1803 /* Test whether javac can be used and whether it needs a -source and/or
1805 Return a failure indicator (true upon error). */
1807 is_javac_usable (const char *source_version, const char *target_version,
1808 bool *usablep, bool *source_option_p, bool *target_option_p)
1810 /* The cache depends on the source_version and target_version. */
1818 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND];
1819 struct result_t *resultp;
1821 resultp = &result_cache[source_version_index (source_version)]
1822 [target_version_index (target_version)];
1823 if (!resultp->tested)
1826 struct temp_dir *tmpdir;
1827 char *conftest_file_name;
1828 char *compiled_file_name;
1829 const char *java_sources[1];
1830 struct stat statbuf;
1832 tmpdir = create_temp_dir ("java", NULL, false);
1836 conftest_file_name =
1837 concatenated_filename (tmpdir->dir_name, "conftest.java", NULL);
1838 if (write_temp_file (tmpdir, conftest_file_name,
1839 get_goodcode_snippet (source_version)))
1841 free (conftest_file_name);
1842 cleanup_temp_dir (tmpdir);
1846 compiled_file_name =
1847 concatenated_filename (tmpdir->dir_name, "conftest.class", NULL);
1848 register_temp_file (tmpdir, compiled_file_name);
1850 java_sources[0] = conftest_file_name;
1851 if (!compile_using_javac (java_sources, 1,
1852 false, source_version,
1853 false, target_version,
1854 tmpdir->dir_name, false, false, false, true)
1855 && stat (compiled_file_name, &statbuf) >= 0
1856 && get_classfile_version (compiled_file_name)
1857 <= corresponding_classfile_version (target_version))
1859 /* javac compiled conftest.java successfully. */
1860 /* Try adding -source option if it is useful. */
1861 unlink (compiled_file_name);
1863 java_sources[0] = conftest_file_name;
1864 if (!compile_using_javac (java_sources, 1,
1865 true, source_version,
1866 false, target_version,
1867 tmpdir->dir_name, false, false, false, true)
1868 && stat (compiled_file_name, &statbuf) >= 0
1869 && get_classfile_version (compiled_file_name)
1870 <= corresponding_classfile_version (target_version))
1872 const char *failcode = get_failcode_snippet (source_version);
1874 if (failcode != NULL)
1876 free (compiled_file_name);
1877 free (conftest_file_name);
1879 conftest_file_name =
1880 concatenated_filename (tmpdir->dir_name,
1881 "conftestfail.java",
1883 if (write_temp_file (tmpdir, conftest_file_name, failcode))
1885 free (conftest_file_name);
1886 cleanup_temp_dir (tmpdir);
1890 compiled_file_name =
1891 concatenated_filename (tmpdir->dir_name,
1892 "conftestfail.class",
1894 register_temp_file (tmpdir, compiled_file_name);
1896 java_sources[0] = conftest_file_name;
1897 if (!compile_using_javac (java_sources, 1,
1898 false, source_version,
1899 false, target_version,
1901 false, false, false, true)
1902 && stat (compiled_file_name, &statbuf) >= 0)
1904 unlink (compiled_file_name);
1906 java_sources[0] = conftest_file_name;
1907 if (compile_using_javac (java_sources, 1,
1908 true, source_version,
1909 false, target_version,
1911 false, false, false, true))
1912 /* javac compiled conftestfail.java successfully, and
1913 "javac -source $source_version" rejects it. So the
1914 -source option is useful. */
1915 resultp->source_option = true;
1920 resultp->usable = true;
1924 /* Try with -target option alone. (Sun javac 1.3.1 has the -target
1925 option but no -source option.) */
1926 unlink (compiled_file_name);
1928 java_sources[0] = conftest_file_name;
1929 if (!compile_using_javac (java_sources, 1,
1930 false, source_version,
1931 true, target_version,
1933 false, false, false, true)
1934 && stat (compiled_file_name, &statbuf) >= 0
1935 && get_classfile_version (compiled_file_name)
1936 <= corresponding_classfile_version (target_version))
1938 /* "javac -target $target_version" compiled conftest.java
1940 /* Try adding -source option if it is useful. */
1941 unlink (compiled_file_name);
1943 java_sources[0] = conftest_file_name;
1944 if (!compile_using_javac (java_sources, 1,
1945 true, source_version,
1946 true, target_version,
1948 false, false, false, true)
1949 && stat (compiled_file_name, &statbuf) >= 0
1950 && get_classfile_version (compiled_file_name)
1951 <= corresponding_classfile_version (target_version))
1953 const char *failcode = get_failcode_snippet (source_version);
1955 if (failcode != NULL)
1957 free (compiled_file_name);
1958 free (conftest_file_name);
1960 conftest_file_name =
1961 concatenated_filename (tmpdir->dir_name,
1962 "conftestfail.java",
1964 if (write_temp_file (tmpdir, conftest_file_name,
1967 free (conftest_file_name);
1968 cleanup_temp_dir (tmpdir);
1972 compiled_file_name =
1973 concatenated_filename (tmpdir->dir_name,
1974 "conftestfail.class",
1976 register_temp_file (tmpdir, compiled_file_name);
1978 java_sources[0] = conftest_file_name;
1979 if (!compile_using_javac (java_sources, 1,
1980 false, source_version,
1981 true, target_version,
1983 false, false, false, true)
1984 && stat (compiled_file_name, &statbuf) >= 0)
1986 unlink (compiled_file_name);
1988 java_sources[0] = conftest_file_name;
1989 if (compile_using_javac (java_sources, 1,
1990 true, source_version,
1991 true, target_version,
1993 false, false, false, true))
1994 /* "javac -target $target_version" compiled
1995 conftestfail.java successfully, and
1996 "javac -target $target_version -source $source_version"
1997 rejects it. So the -source option is useful. */
1998 resultp->source_option = true;
2003 resultp->target_option = true;
2004 resultp->usable = true;
2008 /* Maybe this -target option requires a -source option? Try with
2009 -target and -source options. (Supported by Sun javac 1.4 and
2011 unlink (compiled_file_name);
2013 java_sources[0] = conftest_file_name;
2014 if (!compile_using_javac (java_sources, 1,
2015 true, source_version,
2016 true, target_version,
2018 false, false, false, true)
2019 && stat (compiled_file_name, &statbuf) >= 0
2020 && get_classfile_version (compiled_file_name)
2021 <= corresponding_classfile_version (target_version))
2023 /* "javac -target $target_version -source $source_version"
2024 compiled conftest.java successfully. */
2025 resultp->source_option = true;
2026 resultp->target_option = true;
2027 resultp->usable = true;
2032 free (compiled_file_name);
2033 free (conftest_file_name);
2035 resultp->tested = true;
2038 *usablep = resultp->usable;
2039 *source_option_p = resultp->source_option;
2040 *target_option_p = resultp->target_option;
2045 is_jikes_present (void)
2047 static bool jikes_tested;
2048 static bool jikes_present;
2052 /* Test for presence of jikes: "jikes 2> /dev/null ; test $? = 1" */
2058 exitstatus = execute ("jikes", "jikes", argv, false, false, true, true,
2060 jikes_present = (exitstatus == 0 || exitstatus == 1);
2061 jikes_tested = true;
2064 return jikes_present;
2067 /* ============================= Main function ============================= */
2070 compile_java_class (const char * const *java_sources,
2071 unsigned int java_sources_count,
2072 const char * const *classpaths,
2073 unsigned int classpaths_count,
2074 const char *source_version,
2075 const char *target_version,
2076 const char *directory,
2077 bool optimize, bool debug,
2078 bool use_minimal_classpath,
2082 char *old_JAVA_HOME;
2085 const char *javac = getenv ("JAVAC");
2086 if (javac != NULL && javac[0] != '\0')
2088 bool usable = false;
2089 bool no_assert_option = false;
2090 bool source_option = false;
2091 bool target_option = false;
2092 bool fsource_option = false;
2093 bool ftarget_option = false;
2095 if (target_version == NULL)
2096 target_version = default_target_version ();
2098 if (is_envjavac_gcj (javac))
2100 /* It's a version of gcj. */
2101 if (is_envjavac_gcj43 (javac))
2103 /* It's a version of gcj >= 4.3. Assume the classfile versions
2105 if (is_envjavac_gcj43_usable (javac,
2106 source_version, target_version,
2108 &fsource_option, &ftarget_option))
2116 /* It's a version of gcj < 4.3. Ignore the version of the
2117 class files that it creates. */
2118 if (strcmp (target_version, "1.4") == 0
2119 && strcmp (source_version, "1.4") == 0)
2121 if (is_envjavac_oldgcj_14_14_usable (javac, &usable))
2127 else if (strcmp (target_version, "1.4") == 0
2128 && strcmp (source_version, "1.3") == 0)
2130 if (is_envjavac_oldgcj_14_13_usable (javac,
2142 /* It's not gcj. Assume the classfile versions are correct. */
2143 if (is_envjavac_nongcj_usable (javac,
2144 source_version, target_version,
2146 &source_option, &target_option))
2155 char *old_classpath;
2156 char *javac_with_options;
2158 /* Set CLASSPATH. */
2160 set_classpath (classpaths, classpaths_count, false, verbose);
2162 javac_with_options =
2164 ? xasprintf ("%s -fno-assert", javac)
2165 : xasprintf ("%s%s%s%s%s%s%s%s%s",
2167 source_option ? " -source " : "",
2168 source_option ? source_version : "",
2169 target_option ? " -target " : "",
2170 target_option ? target_version : "",
2171 fsource_option ? " -fsource=" : "",
2172 fsource_option ? source_version : "",
2173 ftarget_option ? " -ftarget=" : "",
2174 ftarget_option ? target_version : ""));
2176 err = compile_using_envjavac (javac_with_options,
2177 java_sources, java_sources_count,
2178 directory, optimize, debug, verbose,
2181 free (javac_with_options);
2183 /* Reset CLASSPATH. */
2184 reset_classpath (old_classpath);
2191 /* Unset the JAVA_HOME environment variable. */
2192 old_JAVA_HOME = getenv ("JAVA_HOME");
2193 if (old_JAVA_HOME != NULL)
2195 old_JAVA_HOME = xstrdup (old_JAVA_HOME);
2196 unsetenv ("JAVA_HOME");
2199 if (is_gcj_present ())
2201 /* It's a version of gcj. */
2202 bool usable = false;
2203 bool no_assert_option = false;
2204 bool fsource_option = false;
2205 bool ftarget_option = false;
2207 if (target_version == NULL)
2208 target_version = default_target_version ();
2212 /* It's a version of gcj >= 4.3. Assume the classfile versions
2214 if (is_gcj43_usable (source_version, target_version,
2215 &usable, &fsource_option, &ftarget_option))
2223 /* It's a version of gcj < 4.3. Ignore the version of the class
2224 files that it creates.
2225 Test whether it supports the desired target-version and
2227 if (strcmp (target_version, "1.4") == 0
2228 && strcmp (source_version, "1.4") == 0)
2230 if (is_oldgcj_14_14_usable (&usable))
2236 else if (strcmp (target_version, "1.4") == 0
2237 && strcmp (source_version, "1.3") == 0)
2239 if (is_oldgcj_14_13_usable (&usable, &no_assert_option))
2249 char *old_classpath;
2251 /* Set CLASSPATH. We could also use the --CLASSPATH=... option
2252 of gcj. Note that --classpath=... option is different: its
2253 argument should also contain gcj's libgcj.jar, but we don't
2254 know its location. */
2256 set_classpath (classpaths, classpaths_count, use_minimal_classpath,
2259 err = compile_using_gcj (java_sources, java_sources_count,
2261 fsource_option, source_version,
2262 ftarget_option, target_version,
2263 directory, optimize, debug, verbose, false);
2265 /* Reset CLASSPATH. */
2266 reset_classpath (old_classpath);
2272 if (is_javac_present ())
2274 bool usable = false;
2275 bool source_option = false;
2276 bool target_option = false;
2278 if (target_version == NULL)
2279 target_version = default_target_version ();
2281 if (is_javac_usable (source_version, target_version,
2282 &usable, &source_option, &target_option))
2290 char *old_classpath;
2292 /* Set CLASSPATH. We don't use the "-classpath ..." option because
2293 in JDK 1.1.x its argument should also contain the JDK's
2294 classes.zip, but we don't know its location. (In JDK 1.3.0 it
2297 set_classpath (classpaths, classpaths_count, use_minimal_classpath,
2300 err = compile_using_javac (java_sources, java_sources_count,
2301 source_option, source_version,
2302 target_option, target_version,
2303 directory, optimize, debug, verbose,
2306 /* Reset CLASSPATH. */
2307 reset_classpath (old_classpath);
2313 if (is_jikes_present ())
2315 /* Test whether it supports the desired target-version and
2317 bool usable = (strcmp (source_version, "1.3") == 0);
2321 char *old_classpath;
2323 /* Set CLASSPATH. We could also use the "-classpath ..." option.
2324 Since jikes doesn't come with its own standard library, it
2325 needs a classes.zip or rt.jar or libgcj.jar in the CLASSPATH.
2326 To increase the chance of success, we reuse the current CLASSPATH
2327 if the user has set it. */
2329 set_classpath (classpaths, classpaths_count, false, verbose);
2331 err = compile_using_jikes (java_sources, java_sources_count,
2332 directory, optimize, debug, verbose,
2335 /* Reset CLASSPATH. */
2336 reset_classpath (old_classpath);
2342 error (0, 0, _("Java compiler not found, try installing gcj or set $JAVAC"));
2346 if (old_JAVA_HOME != NULL)
2348 xsetenv ("JAVA_HOME", old_JAVA_HOME, 1);
2349 free (old_JAVA_HOME);