1 /* Compile a Java program.
2 Copyright (C) 2001-2003, 2006-2018 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/>. */
30 #include <sys/types.h>
33 #include "javaversion.h"
35 #include "spawn-pipe.h"
36 #include "wait-process.h"
37 #include "classpath.h"
40 #include "binary-io.h"
41 #include "safe-read.h"
44 #include "concat-filename.h"
45 #include "fwriteerror.h"
46 #include "clean-temp.h"
48 #include "xvasprintf.h"
52 #define _(str) gettext (str)
55 /* Survey of Java compilers.
57 A = does it work without CLASSPATH being set
58 C = option to set CLASSPATH, other than setting it in the environment
59 O = option for optimizing
60 g = option for debugging
63 Program from A C O g T
65 $JAVAC unknown N n/a -O -g true
66 gcj -C GCC 3.2 Y --classpath=P -O -g gcj --version | sed -e 's,^[^0-9]*,,' -e 1q | sed -e '/^3\.[01]/d' | grep '^[3-9]' >/dev/null
67 javac JDK 1.1.8 Y -classpath P -O -g javac 2>/dev/null; test $? = 1
68 javac JDK 1.3.0 Y -classpath P -O -g javac 2>/dev/null; test $? -le 2
69 jikes Jikes 1.14 N -classpath P -O -g jikes 2>/dev/null; test $? = 1
71 All compilers support the option "-d DIRECTORY" for the base directory
72 of the classes to be written.
74 The CLASSPATH is a colon separated list of pathnames. (On Windows: a
75 semicolon separated list of pathnames.)
77 We try the Java compilers in the following order:
78 1. getenv ("JAVAC"), because the user must be able to override our
80 2. "gcj -C", because it is a completely free compiler,
81 3. "javac", because it is a standard compiler,
82 4. "jikes", comes last because it has some deviating interpretation
83 of the Java Language Specification and because it requires a
84 CLASSPATH environment variable.
86 We unset the JAVA_HOME environment variable, because a wrong setting of
87 this variable can confuse the JDK's javac.
90 /* Return the default target_version. */
92 default_target_version (void)
94 /* Use a cache. Assumes that the PATH environment variable doesn't change
95 during the lifetime of the program. */
96 static const char *java_version_cache
;
97 if (java_version_cache
== NULL
)
99 /* Determine the version from the found JVM. */
100 java_version_cache
= javaexec_version ();
101 if (java_version_cache
== NULL
102 || !((java_version_cache
[0] == '1'
103 && java_version_cache
[1] == '.'
104 && java_version_cache
[2] >= '1' && java_version_cache
[2] <= '8'
105 && java_version_cache
[3] == '\0')
106 || (java_version_cache
[0] == '9'
107 && java_version_cache
[1] == '\0')
108 || (java_version_cache
[0] == '1'
109 && java_version_cache
[1] == '0'
110 && java_version_cache
[2] == '\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 7 /* exclusive upper bound */
121 source_version_index (const char *source_version
)
123 if (source_version
[0] == '1' && source_version
[1] == '.')
125 if ((source_version
[2] >= '3' && source_version
[2] <= '5')
126 && source_version
[3] == '\0')
127 return source_version
[2] - '3';
128 if ((source_version
[2] >= '7' && source_version
[2] <= '8')
129 && source_version
[3] == '\0')
130 return source_version
[2] - '4';
132 else if (source_version
[0] == '9' && source_version
[1] == '\0')
134 else if (source_version
[0] == '1' && source_version
[1] == '0'
135 && source_version
[2] == '\0')
137 error (EXIT_FAILURE
, 0, _("invalid source_version argument to compile_java_class"));
141 /* Return a snippet of code that should compile in the given source version. */
143 get_goodcode_snippet (const char *source_version
)
145 if (strcmp (source_version
, "1.3") == 0)
146 return "class conftest {}\n";
147 if (strcmp (source_version
, "1.4") == 0)
148 return "class conftest { static { assert(true); } }\n";
149 if (strcmp (source_version
, "1.5") == 0)
150 return "class conftest<T> { T foo() { return null; } }\n";
151 if (strcmp (source_version
, "1.7") == 0)
152 return "class conftest { void foo () { switch (\"A\") {} } }\n";
153 if (strcmp (source_version
, "1.8") == 0)
154 return "class conftest { void foo () { Runnable r = () -> {}; } }\n";
155 if (strcmp (source_version
, "9") == 0)
156 return "interface conftest { private void foo () {} }\n";
157 if (strcmp (source_version
, "10") == 0)
158 return "class conftest { public void m() { var i = new Integer(0); } }\n";
159 error (EXIT_FAILURE
, 0, _("invalid source_version argument to compile_java_class"));
163 /* Return a snippet of code that should fail to compile in the given source
164 version, or NULL (standing for a snippet that would fail to compile with
167 get_failcode_snippet (const char *source_version
)
169 if (strcmp (source_version
, "1.3") == 0)
170 return "class conftestfail { static { assert(true); } }\n";
171 if (strcmp (source_version
, "1.4") == 0)
172 return "class conftestfail<T> { T foo() { return null; } }\n";
173 if (strcmp (source_version
, "1.5") == 0)
174 return "class conftestfail { void foo () { switch (\"A\") {} } }\n";
175 if (strcmp (source_version
, "1.7") == 0)
176 return "class conftestfail { void foo () { Runnable r = () -> {}; } }\n";
177 if (strcmp (source_version
, "1.8") == 0)
178 return "interface conftestfail { private void foo () {} }\n";
179 if (strcmp (source_version
, "9") == 0)
180 return "class conftestfail { public void m() { var i = new Integer(0); } }\n";
181 if (strcmp (source_version
, "10") == 0)
183 error (EXIT_FAILURE
, 0, _("invalid source_version argument to compile_java_class"));
187 /* ======================= Target version dependent ======================= */
189 /* Convert a target version to an index. */
190 #define TARGET_VERSION_BOUND 10 /* exclusive upper bound */
192 target_version_index (const char *target_version
)
194 if (target_version
[0] == '1' && target_version
[1] == '.'
195 && (target_version
[2] >= '1' && target_version
[2] <= '8')
196 && target_version
[3] == '\0')
197 return target_version
[2] - '1';
198 else if (target_version
[0] == '9' && target_version
[1] == '\0')
200 else if (target_version
[0] == '1' && target_version
[1] == '0'
201 && target_version
[2] == '\0')
203 error (EXIT_FAILURE
, 0, _("invalid target_version argument to compile_java_class"));
207 /* Return the class file version number corresponding to a given target
210 corresponding_classfile_version (const char *target_version
)
212 if (strcmp (target_version
, "1.1") == 0)
214 if (strcmp (target_version
, "1.2") == 0)
216 if (strcmp (target_version
, "1.3") == 0)
218 if (strcmp (target_version
, "1.4") == 0)
220 if (strcmp (target_version
, "1.5") == 0)
222 if (strcmp (target_version
, "1.6") == 0)
224 if (strcmp (target_version
, "1.7") == 0)
226 if (strcmp (target_version
, "1.8") == 0)
228 if (strcmp (target_version
, "9") == 0)
230 if (strcmp (target_version
, "10") == 0)
232 error (EXIT_FAILURE
, 0, _("invalid target_version argument to compile_java_class"));
236 /* Return the source version to pass to javac. */
238 get_source_version_for_javac (const char *source_version
,
239 const char *target_version
)
241 /* The javac option '-source 1.5' has the same meaning as '-source 1.6',
242 but since Java 9 supports only the latter, prefer the latter if a
243 target_version >= 1.6 is requested. */
244 if (strcmp (source_version
, "1.5") == 0
245 && !(target_version
[0] == '1' && target_version
[1] == '.'
246 && (target_version
[2] >= '1' && target_version
[2] <= '5')
247 && target_version
[3] == '\0'))
249 return source_version
;
252 /* ======================== Compilation subroutines ======================== */
254 /* Try to compile a set of Java sources with $JAVAC.
255 Return a failure indicator (true upon error). */
257 compile_using_envjavac (const char *javac
,
258 const char * const *java_sources
,
259 unsigned int java_sources_count
,
260 const char *directory
,
261 bool optimize
, bool debug
,
262 bool verbose
, bool null_stderr
)
264 /* Because $JAVAC may consist of a command and options, we use the
265 shell. Because $JAVAC has been set by the user, we leave all
266 environment variables in place, including JAVA_HOME, and we don't
267 erase the user's CLASSPATH. */
269 unsigned int command_length
;
276 command_length
= strlen (javac
);
281 if (directory
!= NULL
)
282 command_length
+= 4 + shell_quote_length (directory
);
283 for (i
= 0; i
< java_sources_count
; i
++)
284 command_length
+= 1 + shell_quote_length (java_sources
[i
]);
287 command
= (char *) xmalloca (command_length
);
289 /* Don't shell_quote $JAVAC, because it may consist of a command
291 memcpy (p
, javac
, strlen (javac
));
295 memcpy (p
, " -O", 3);
300 memcpy (p
, " -g", 3);
303 if (directory
!= NULL
)
305 memcpy (p
, " -d ", 4);
307 p
= shell_quote_copy (p
, directory
);
309 for (i
= 0; i
< java_sources_count
; i
++)
312 p
= shell_quote_copy (p
, java_sources
[i
]);
315 /* Ensure command_length was correctly calculated. */
316 if (p
- command
> command_length
)
320 printf ("%s\n", command
);
326 exitstatus
= execute (javac
, "/bin/sh", argv
, false, false, false,
327 null_stderr
, true, true, NULL
);
328 err
= (exitstatus
!= 0);
335 /* Try to compile a set of Java sources with gcj.
336 Return a failure indicator (true upon error). */
338 compile_using_gcj (const char * const *java_sources
,
339 unsigned int java_sources_count
,
340 bool no_assert_option
,
341 bool fsource_option
, const char *source_version
,
342 bool ftarget_option
, const char *target_version
,
343 const char *directory
,
344 bool optimize
, bool debug
,
345 bool verbose
, bool null_stderr
)
357 2 + (no_assert_option
? 1 : 0) + (fsource_option
? 1 : 0)
358 + (ftarget_option
? 1 : 0) + (optimize
? 1 : 0) + (debug
? 1 : 0)
359 + (directory
!= NULL
? 2 : 0) + java_sources_count
;
360 argv
= (char **) xmalloca ((argc
+ 1) * sizeof (char *));
365 if (no_assert_option
)
366 *argp
++ = "-fno-assert";
369 fsource_arg
= (char *) xmalloca (9 + strlen (source_version
) + 1);
370 memcpy (fsource_arg
, "-fsource=", 9);
371 strcpy (fsource_arg
+ 9, source_version
);
372 *argp
++ = fsource_arg
;
378 ftarget_arg
= (char *) xmalloca (9 + strlen (target_version
) + 1);
379 memcpy (ftarget_arg
, "-ftarget=", 9);
380 strcpy (ftarget_arg
+ 9, target_version
);
381 *argp
++ = ftarget_arg
;
389 if (directory
!= NULL
)
392 *argp
++ = (char *) directory
;
394 for (i
= 0; i
< java_sources_count
; i
++)
395 *argp
++ = (char *) java_sources
[i
];
397 /* Ensure argv length was correctly calculated. */
398 if (argp
- argv
!= argc
)
403 char *command
= shell_quote_argv (argv
);
404 printf ("%s\n", command
);
408 exitstatus
= execute ("gcj", "gcj", argv
, false, false, false, null_stderr
,
410 err
= (exitstatus
!= 0);
412 if (ftarget_arg
!= NULL
)
414 if (fsource_arg
!= NULL
)
421 /* Try to compile a set of Java sources with javac.
422 Return a failure indicator (true upon error). */
424 compile_using_javac (const char * const *java_sources
,
425 unsigned int java_sources_count
,
426 bool source_option
, const char *source_version
,
427 bool target_option
, const char *target_version
,
428 const char *directory
,
429 bool optimize
, bool debug
,
430 bool verbose
, bool null_stderr
)
440 1 + (source_option
? 2 : 0) + (target_option
? 2 : 0) + (optimize
? 1 : 0)
441 + (debug
? 1 : 0) + (directory
!= NULL
? 2 : 0) + java_sources_count
;
442 argv
= (char **) xmalloca ((argc
+ 1) * sizeof (char *));
449 *argp
++ = (char *) source_version
;
454 *argp
++ = (char *) target_version
;
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 ("javac", "javac", argv
, false, false, false,
480 null_stderr
, true, true, NULL
);
481 err
= (exitstatus
!= 0);
488 /* Try to compile a set of Java sources with jikes.
489 Return a failure indicator (true upon error). */
491 compile_using_jikes (const char * const *java_sources
,
492 unsigned int java_sources_count
,
493 const char *directory
,
494 bool optimize
, bool debug
,
495 bool verbose
, bool null_stderr
)
505 1 + (optimize
? 1 : 0) + (debug
? 1 : 0) + (directory
!= NULL
? 2 : 0)
506 + java_sources_count
;
507 argv
= (char **) xmalloca ((argc
+ 1) * sizeof (char *));
515 if (directory
!= NULL
)
518 *argp
++ = (char *) directory
;
520 for (i
= 0; i
< java_sources_count
; i
++)
521 *argp
++ = (char *) java_sources
[i
];
523 /* Ensure argv length was correctly calculated. */
524 if (argp
- argv
!= argc
)
529 char *command
= shell_quote_argv (argv
);
530 printf ("%s\n", command
);
534 exitstatus
= execute ("jikes", "jikes", argv
, false, false, false,
535 null_stderr
, true, true, NULL
);
536 err
= (exitstatus
!= 0);
543 /* ====================== Usability test subroutines ====================== */
545 /* Write a given contents to a temporary file.
546 FILE_NAME is the name of a file inside TMPDIR that is known not to exist
548 Return a failure indicator (true upon error). */
550 write_temp_file (struct temp_dir
*tmpdir
, const char *file_name
,
551 const char *contents
)
555 register_temp_file (tmpdir
, file_name
);
556 fp
= fopen_temp (file_name
, "w");
559 error (0, errno
, _("failed to create \"%s\""), file_name
);
560 unregister_temp_file (tmpdir
, file_name
);
563 fputs (contents
, fp
);
564 if (fwriteerror_temp (fp
))
566 error (0, errno
, _("error while writing \"%s\" file"), file_name
);
572 /* Return the class file version number of a class file on disk. */
574 get_classfile_version (const char *compiled_file_name
)
576 unsigned char header
[8];
579 /* Open the class file. */
580 fd
= open (compiled_file_name
, O_RDONLY
| O_BINARY
, 0);
583 /* Read its first 8 bytes. */
584 if (safe_read (fd
, header
, 8) == 8)
586 /* Verify the class file signature. */
587 if (header
[0] == 0xCA && header
[1] == 0xFE
588 && header
[2] == 0xBA && header
[3] == 0xBE)
597 /* Could not get the class file version. Return a very large one. */
601 /* Return true if $JAVAC is a version of gcj. */
603 is_envjavac_gcj (const char *javac
)
605 static bool envjavac_tested
;
606 static bool envjavac_gcj
;
608 if (!envjavac_tested
)
610 /* Test whether $JAVAC is gcj:
611 "$JAVAC --version 2>/dev/null | sed -e 1q | grep gcj > /dev/null" */
612 unsigned int command_length
;
624 /* Setup the command "$JAVAC --version". */
625 command_length
= strlen (javac
) + 1 + 9 + 1;
626 command
= (char *) xmalloca (command_length
);
628 /* Don't shell_quote $JAVAC, because it may consist of a command
630 memcpy (p
, javac
, strlen (javac
));
632 memcpy (p
, " --version", 1 + 9 + 1);
634 /* Ensure command_length was correctly calculated. */
635 if (p
- command
> command_length
)
638 /* Call $JAVAC --version 2>/dev/null. */
643 child
= create_pipe_in (javac
, "/bin/sh", argv
, DEV_NULL
, true, true,
648 /* Retrieve its result. */
649 fp
= fdopen (fd
[0], "r");
653 line
= NULL
; linesize
= 0;
654 linelen
= getline (&line
, &linesize
, fp
);
655 if (linelen
== (size_t)(-1))
660 /* It is safe to call c_strstr() instead of strstr() here; see the
661 comments in c-strstr.h. */
662 envjavac_gcj
= (c_strstr (line
, "gcj") != NULL
);
666 /* Remove zombie process from process list, and retrieve exit status. */
668 wait_subprocess (child
, javac
, true, true, true, false, NULL
);
670 envjavac_gcj
= false;
675 envjavac_tested
= true;
681 /* Return true if $JAVAC, known to be a version of gcj, is a version >= 4.3
684 is_envjavac_gcj43 (const char *javac
)
686 static bool envjavac_tested
;
687 static bool envjavac_gcj43
;
689 if (!envjavac_tested
)
691 /* Test whether $JAVAC is gcj:
692 "$JAVAC --version 2>/dev/null | sed -e 's,^[^0-9]*,,' -e 1q \
693 | sed -e '/^4\.[012]/d' | grep '^[4-9]' >/dev/null" */
694 unsigned int command_length
;
706 /* Setup the command "$JAVAC --version". */
707 command_length
= strlen (javac
) + 1 + 9 + 1;
708 command
= (char *) xmalloca (command_length
);
710 /* Don't shell_quote $JAVAC, because it may consist of a command
712 memcpy (p
, javac
, strlen (javac
));
714 memcpy (p
, " --version", 1 + 9 + 1);
716 /* Ensure command_length was correctly calculated. */
717 if (p
- command
> command_length
)
720 /* Call $JAVAC --version 2>/dev/null. */
725 child
= create_pipe_in (javac
, "/bin/sh", argv
, DEV_NULL
, true, true,
730 /* Retrieve its result. */
731 fp
= fdopen (fd
[0], "r");
735 line
= NULL
; linesize
= 0;
736 linelen
= getline (&line
, &linesize
, fp
);
737 if (linelen
== (size_t)(-1))
743 while (*p
!= '\0' && !(*p
>= '0' && *p
<= '9'))
746 !(*p
== '4' && p
[1] == '.' && p
[2] >= '0' && p
[2] <= '2')
747 && (*p
>= '4' && *p
<= '9');
751 /* Remove zombie process from process list, and retrieve exit status. */
753 wait_subprocess (child
, javac
, true, true, true, false, NULL
);
755 envjavac_gcj43
= false;
760 envjavac_tested
= true;
763 return envjavac_gcj43
;
766 /* Test whether $JAVAC, known to be a version of gcj >= 4.3, can be used, and
767 whether it needs a -fsource and/or -ftarget option.
768 Return a failure indicator (true upon error). */
770 is_envjavac_gcj43_usable (const char *javac
,
771 const char *source_version
,
772 const char *target_version
,
774 bool *fsource_option_p
, bool *ftarget_option_p
)
776 /* The cache depends on the source_version and target_version. */
784 static struct result_t result_cache
[SOURCE_VERSION_BOUND
][TARGET_VERSION_BOUND
];
785 struct result_t
*resultp
;
787 resultp
= &result_cache
[source_version_index (source_version
)]
788 [target_version_index (target_version
)];
789 if (!resultp
->tested
)
792 struct temp_dir
*tmpdir
;
793 char *conftest_file_name
;
794 char *compiled_file_name
;
795 const char *java_sources
[1];
798 tmpdir
= create_temp_dir ("java", NULL
, false);
803 xconcatenated_filename (tmpdir
->dir_name
, "conftest.java", NULL
);
804 if (write_temp_file (tmpdir
, conftest_file_name
,
805 get_goodcode_snippet (source_version
)))
807 free (conftest_file_name
);
808 cleanup_temp_dir (tmpdir
);
813 xconcatenated_filename (tmpdir
->dir_name
, "conftest.class", NULL
);
814 register_temp_file (tmpdir
, compiled_file_name
);
816 java_sources
[0] = conftest_file_name
;
817 if (!compile_using_envjavac (javac
,
818 java_sources
, 1, tmpdir
->dir_name
,
819 false, false, false, true)
820 && stat (compiled_file_name
, &statbuf
) >= 0
821 && get_classfile_version (compiled_file_name
)
822 <= corresponding_classfile_version (target_version
))
824 /* $JAVAC compiled conftest.java successfully. */
825 /* Try adding -fsource option if it is useful. */
827 xasprintf ("%s -fsource=%s", javac
, source_version
);
829 unlink (compiled_file_name
);
831 java_sources
[0] = conftest_file_name
;
832 if (!compile_using_envjavac (javac_source
,
833 java_sources
, 1, tmpdir
->dir_name
,
834 false, false, false, true)
835 && stat (compiled_file_name
, &statbuf
) >= 0
836 && get_classfile_version (compiled_file_name
)
837 <= corresponding_classfile_version (target_version
))
839 const char *failcode
= get_failcode_snippet (source_version
);
841 if (failcode
!= NULL
)
843 free (compiled_file_name
);
844 free (conftest_file_name
);
847 xconcatenated_filename (tmpdir
->dir_name
,
850 if (write_temp_file (tmpdir
, conftest_file_name
, failcode
))
852 free (conftest_file_name
);
854 cleanup_temp_dir (tmpdir
);
859 xconcatenated_filename (tmpdir
->dir_name
,
860 "conftestfail.class",
862 register_temp_file (tmpdir
, compiled_file_name
);
864 java_sources
[0] = conftest_file_name
;
865 if (!compile_using_envjavac (javac
,
868 false, false, false, true)
869 && stat (compiled_file_name
, &statbuf
) >= 0)
871 unlink (compiled_file_name
);
873 java_sources
[0] = conftest_file_name
;
874 if (compile_using_envjavac (javac_source
,
877 false, false, false, true))
878 /* $JAVAC compiled conftestfail.java successfully, and
879 "$JAVAC -fsource=$source_version" rejects it. So
880 the -fsource option is useful. */
881 resultp
->fsource_option
= true;
888 resultp
->usable
= true;
892 /* Try with -fsource and -ftarget options. */
894 xasprintf ("%s -fsource=%s -ftarget=%s",
895 javac
, source_version
, target_version
);
897 unlink (compiled_file_name
);
899 java_sources
[0] = conftest_file_name
;
900 if (!compile_using_envjavac (javac_target
,
901 java_sources
, 1, tmpdir
->dir_name
,
902 false, false, false, true)
903 && stat (compiled_file_name
, &statbuf
) >= 0
904 && get_classfile_version (compiled_file_name
)
905 <= corresponding_classfile_version (target_version
))
907 /* "$JAVAC -fsource $source_version -ftarget $target_version"
908 compiled conftest.java successfully. */
909 resultp
->fsource_option
= true;
910 resultp
->ftarget_option
= true;
911 resultp
->usable
= true;
917 free (compiled_file_name
);
918 free (conftest_file_name
);
920 resultp
->tested
= true;
923 *usablep
= resultp
->usable
;
924 *fsource_option_p
= resultp
->fsource_option
;
925 *ftarget_option_p
= resultp
->ftarget_option
;
929 /* Test whether $JAVAC, known to be a version of gcj < 4.3, can be used for
930 compiling with target_version = 1.4 and source_version = 1.4.
931 Return a failure indicator (true upon error). */
933 is_envjavac_oldgcj_14_14_usable (const char *javac
, bool *usablep
)
935 static bool envjavac_tested
;
936 static bool envjavac_usable
;
938 if (!envjavac_tested
)
941 struct temp_dir
*tmpdir
;
942 char *conftest_file_name
;
943 char *compiled_file_name
;
944 const char *java_sources
[1];
947 tmpdir
= create_temp_dir ("java", NULL
, false);
952 xconcatenated_filename (tmpdir
->dir_name
, "conftest.java", NULL
);
953 if (write_temp_file (tmpdir
, conftest_file_name
,
954 get_goodcode_snippet ("1.4")))
956 free (conftest_file_name
);
957 cleanup_temp_dir (tmpdir
);
962 xconcatenated_filename (tmpdir
->dir_name
, "conftest.class", NULL
);
963 register_temp_file (tmpdir
, compiled_file_name
);
965 java_sources
[0] = conftest_file_name
;
966 if (!compile_using_envjavac (javac
, java_sources
, 1, tmpdir
->dir_name
,
967 false, false, false, true)
968 && stat (compiled_file_name
, &statbuf
) >= 0)
969 /* Compilation succeeded. */
970 envjavac_usable
= true;
972 free (compiled_file_name
);
973 free (conftest_file_name
);
975 cleanup_temp_dir (tmpdir
);
977 envjavac_tested
= true;
980 *usablep
= envjavac_usable
;
984 /* Test whether $JAVAC, known to be a version of gcj < 4.3, can be used for
985 compiling with target_version = 1.4 and source_version = 1.3.
986 Return a failure indicator (true upon error). */
988 is_envjavac_oldgcj_14_13_usable (const char *javac
,
989 bool *usablep
, bool *need_no_assert_option_p
)
991 static bool envjavac_tested
;
992 static bool envjavac_usable
;
993 static bool envjavac_need_no_assert_option
;
995 if (!envjavac_tested
)
997 /* Try $JAVAC and "$JAVAC -fno-assert". But add -fno-assert only if
998 it makes a difference. (It could already be part of $JAVAC.) */
999 struct temp_dir
*tmpdir
;
1000 char *conftest_file_name
;
1001 char *compiled_file_name
;
1002 const char *java_sources
[1];
1003 struct stat statbuf
;
1005 char *javac_noassert
;
1006 bool javac_noassert_works
;
1008 tmpdir
= create_temp_dir ("java", NULL
, false);
1012 conftest_file_name
=
1013 xconcatenated_filename (tmpdir
->dir_name
, "conftest.java", NULL
);
1014 if (write_temp_file (tmpdir
, conftest_file_name
,
1015 get_goodcode_snippet ("1.3")))
1017 free (conftest_file_name
);
1018 cleanup_temp_dir (tmpdir
);
1022 compiled_file_name
=
1023 xconcatenated_filename (tmpdir
->dir_name
, "conftest.class", NULL
);
1024 register_temp_file (tmpdir
, compiled_file_name
);
1026 java_sources
[0] = conftest_file_name
;
1027 if (!compile_using_envjavac (javac
,
1028 java_sources
, 1, tmpdir
->dir_name
,
1029 false, false, false, true)
1030 && stat (compiled_file_name
, &statbuf
) >= 0)
1031 /* Compilation succeeded. */
1034 javac_works
= false;
1036 unlink (compiled_file_name
);
1038 javac_noassert
= xasprintf ("%s -fno-assert", javac
);
1040 java_sources
[0] = conftest_file_name
;
1041 if (!compile_using_envjavac (javac_noassert
,
1042 java_sources
, 1, tmpdir
->dir_name
,
1043 false, false, false, true)
1044 && stat (compiled_file_name
, &statbuf
) >= 0)
1045 /* Compilation succeeded. */
1046 javac_noassert_works
= true;
1048 javac_noassert_works
= false;
1050 free (compiled_file_name
);
1051 free (conftest_file_name
);
1053 if (javac_works
&& javac_noassert_works
)
1055 conftest_file_name
=
1056 xconcatenated_filename (tmpdir
->dir_name
, "conftestfail.java",
1058 if (write_temp_file (tmpdir
, conftest_file_name
,
1059 get_failcode_snippet ("1.3")))
1061 free (conftest_file_name
);
1062 free (javac_noassert
);
1063 cleanup_temp_dir (tmpdir
);
1067 compiled_file_name
=
1068 xconcatenated_filename (tmpdir
->dir_name
, "conftestfail.class",
1070 register_temp_file (tmpdir
, compiled_file_name
);
1072 java_sources
[0] = conftest_file_name
;
1073 if (!compile_using_envjavac (javac
,
1074 java_sources
, 1, tmpdir
->dir_name
,
1075 false, false, false, true)
1076 && stat (compiled_file_name
, &statbuf
) >= 0)
1078 /* Compilation succeeded. */
1079 unlink (compiled_file_name
);
1081 java_sources
[0] = conftest_file_name
;
1082 if (!(!compile_using_envjavac (javac_noassert
,
1083 java_sources
, 1, tmpdir
->dir_name
,
1084 false, false, false, true)
1085 && stat (compiled_file_name
, &statbuf
) >= 0))
1086 /* Compilation failed. */
1087 /* "$JAVAC -fno-assert" works better than $JAVAC. */
1091 free (compiled_file_name
);
1092 free (conftest_file_name
);
1095 cleanup_temp_dir (tmpdir
);
1099 envjavac_usable
= true;
1100 envjavac_need_no_assert_option
= false;
1102 else if (javac_noassert_works
)
1104 envjavac_usable
= true;
1105 envjavac_need_no_assert_option
= true;
1108 envjavac_tested
= true;
1111 *usablep
= envjavac_usable
;
1112 *need_no_assert_option_p
= envjavac_need_no_assert_option
;
1116 /* Test whether $JAVAC, known to be not a version of gcj, can be used, and
1117 whether it needs a -source and/or -target option.
1118 Return a failure indicator (true upon error). */
1120 is_envjavac_nongcj_usable (const char *javac
,
1121 const char *source_version
,
1122 const char *source_version_for_javac
,
1123 const char *target_version
,
1125 bool *source_option_p
, bool *target_option_p
)
1127 /* The cache depends on the source_version and target_version. */
1135 static struct result_t result_cache
[SOURCE_VERSION_BOUND
][TARGET_VERSION_BOUND
];
1136 struct result_t
*resultp
;
1138 resultp
= &result_cache
[source_version_index (source_version
)]
1139 [target_version_index (target_version
)];
1140 if (!resultp
->tested
)
1143 struct temp_dir
*tmpdir
;
1144 char *conftest_file_name
;
1145 char *compiled_file_name
;
1146 const char *java_sources
[1];
1147 struct stat statbuf
;
1149 tmpdir
= create_temp_dir ("java", NULL
, false);
1153 conftest_file_name
=
1154 xconcatenated_filename (tmpdir
->dir_name
, "conftest.java", NULL
);
1155 if (write_temp_file (tmpdir
, conftest_file_name
,
1156 get_goodcode_snippet (source_version
)))
1158 free (conftest_file_name
);
1159 cleanup_temp_dir (tmpdir
);
1163 compiled_file_name
=
1164 xconcatenated_filename (tmpdir
->dir_name
, "conftest.class", NULL
);
1165 register_temp_file (tmpdir
, compiled_file_name
);
1167 java_sources
[0] = conftest_file_name
;
1168 if (!compile_using_envjavac (javac
,
1169 java_sources
, 1, tmpdir
->dir_name
,
1170 false, false, false, true)
1171 && stat (compiled_file_name
, &statbuf
) >= 0
1172 && get_classfile_version (compiled_file_name
)
1173 <= corresponding_classfile_version (target_version
))
1175 /* $JAVAC compiled conftest.java successfully. */
1176 /* Try adding -source option if it is useful. */
1177 char *javac_source
=
1178 xasprintf ("%s -source %s", javac
, source_version_for_javac
);
1180 unlink (compiled_file_name
);
1182 java_sources
[0] = conftest_file_name
;
1183 if (!compile_using_envjavac (javac_source
,
1184 java_sources
, 1, tmpdir
->dir_name
,
1185 false, false, false, true)
1186 && stat (compiled_file_name
, &statbuf
) >= 0
1187 && get_classfile_version (compiled_file_name
)
1188 <= corresponding_classfile_version (target_version
))
1190 const char *failcode
= get_failcode_snippet (source_version
);
1192 if (failcode
!= NULL
)
1194 free (compiled_file_name
);
1195 free (conftest_file_name
);
1197 conftest_file_name
=
1198 xconcatenated_filename (tmpdir
->dir_name
,
1199 "conftestfail.java",
1201 if (write_temp_file (tmpdir
, conftest_file_name
, failcode
))
1203 free (conftest_file_name
);
1204 free (javac_source
);
1205 cleanup_temp_dir (tmpdir
);
1209 compiled_file_name
=
1210 xconcatenated_filename (tmpdir
->dir_name
,
1211 "conftestfail.class",
1213 register_temp_file (tmpdir
, compiled_file_name
);
1215 java_sources
[0] = conftest_file_name
;
1216 if (!compile_using_envjavac (javac
,
1219 false, false, false, true)
1220 && stat (compiled_file_name
, &statbuf
) >= 0)
1222 unlink (compiled_file_name
);
1224 java_sources
[0] = conftest_file_name
;
1225 if (compile_using_envjavac (javac_source
,
1228 false, false, false, true))
1229 /* $JAVAC compiled conftestfail.java successfully, and
1230 "$JAVAC -source $source_version_for_javac" rejects it.
1231 So the -source option is useful. */
1232 resultp
->source_option
= true;
1237 free (javac_source
);
1239 resultp
->usable
= true;
1243 /* Try with -target option alone. (Sun javac 1.3.1 has the -target
1244 option but no -source option.) */
1245 char *javac_target
=
1246 xasprintf ("%s -target %s", javac
, target_version
);
1248 unlink (compiled_file_name
);
1250 java_sources
[0] = conftest_file_name
;
1251 if (!compile_using_envjavac (javac_target
,
1252 java_sources
, 1, tmpdir
->dir_name
,
1253 false, false, false, true)
1254 && stat (compiled_file_name
, &statbuf
) >= 0
1255 && get_classfile_version (compiled_file_name
)
1256 <= corresponding_classfile_version (target_version
))
1258 /* "$JAVAC -target $target_version" compiled conftest.java
1260 /* Try adding -source option if it is useful. */
1261 char *javac_target_source
=
1262 xasprintf ("%s -source %s", javac_target
, source_version_for_javac
);
1264 unlink (compiled_file_name
);
1266 java_sources
[0] = conftest_file_name
;
1267 if (!compile_using_envjavac (javac_target_source
,
1268 java_sources
, 1, tmpdir
->dir_name
,
1269 false, false, false, true)
1270 && stat (compiled_file_name
, &statbuf
) >= 0
1271 && get_classfile_version (compiled_file_name
)
1272 <= corresponding_classfile_version (target_version
))
1274 const char *failcode
= get_failcode_snippet (source_version
);
1276 if (failcode
!= NULL
)
1278 free (compiled_file_name
);
1279 free (conftest_file_name
);
1281 conftest_file_name
=
1282 xconcatenated_filename (tmpdir
->dir_name
,
1283 "conftestfail.java",
1285 if (write_temp_file (tmpdir
, conftest_file_name
,
1288 free (conftest_file_name
);
1289 free (javac_target_source
);
1290 free (javac_target
);
1291 cleanup_temp_dir (tmpdir
);
1295 compiled_file_name
=
1296 xconcatenated_filename (tmpdir
->dir_name
,
1297 "conftestfail.class",
1299 register_temp_file (tmpdir
, compiled_file_name
);
1301 java_sources
[0] = conftest_file_name
;
1302 if (!compile_using_envjavac (javac_target
,
1305 false, false, false, true)
1306 && stat (compiled_file_name
, &statbuf
) >= 0)
1308 unlink (compiled_file_name
);
1310 java_sources
[0] = conftest_file_name
;
1311 if (compile_using_envjavac (javac_target_source
,
1314 false, false, false,
1316 /* "$JAVAC -target $target_version" compiled
1317 conftestfail.java successfully, and
1318 "$JAVAC -target $target_version -source $source_version_for_javac"
1319 rejects it. So the -source option is useful. */
1320 resultp
->source_option
= true;
1325 free (javac_target_source
);
1327 resultp
->target_option
= true;
1328 resultp
->usable
= true;
1332 /* Maybe this -target option requires a -source option? Try with
1333 -target and -source options. (Supported by Sun javac 1.4 and
1335 char *javac_target_source
=
1336 xasprintf ("%s -source %s", javac_target
, source_version_for_javac
);
1338 unlink (compiled_file_name
);
1340 java_sources
[0] = conftest_file_name
;
1341 if (!compile_using_envjavac (javac_target_source
,
1342 java_sources
, 1, tmpdir
->dir_name
,
1343 false, false, false, true)
1344 && stat (compiled_file_name
, &statbuf
) >= 0
1345 && get_classfile_version (compiled_file_name
)
1346 <= corresponding_classfile_version (target_version
))
1348 /* "$JAVAC -target $target_version -source $source_version_for_javac"
1349 compiled conftest.java successfully. */
1350 resultp
->source_option
= true;
1351 resultp
->target_option
= true;
1352 resultp
->usable
= true;
1355 free (javac_target_source
);
1358 free (javac_target
);
1361 free (compiled_file_name
);
1362 free (conftest_file_name
);
1364 resultp
->tested
= true;
1367 *usablep
= resultp
->usable
;
1368 *source_option_p
= resultp
->source_option
;
1369 *target_option_p
= resultp
->target_option
;
1374 is_gcj_present (void)
1376 static bool gcj_tested
;
1377 static bool gcj_present
;
1381 /* Test for presence of gcj:
1382 "gcj --version 2> /dev/null | \
1383 sed -e 's,^[^0-9]*,,' -e 1q | \
1384 sed -e '/^3\.[01]/d' | grep '^[3-9]' > /dev/null" */
1391 argv
[1] = "--version";
1393 child
= create_pipe_in ("gcj", "gcj", argv
, DEV_NULL
, true, true,
1395 gcj_present
= false;
1398 /* Read the subprocess output, drop all lines except the first,
1399 drop all characters before the first digit, and test whether
1400 the remaining string starts with a digit >= 3, but not with
1405 while (safe_read (fd
[0], &c
[count
], 1) > 0)
1407 if (c
[count
] == '\n')
1411 if (!(c
[0] >= '0' && c
[0] <= '9'))
1413 gcj_present
= (c
[0] >= '3');
1418 if (c
[0] == '3' && c
[1] == '.'
1419 && (c
[2] == '0' || c
[2] == '1'))
1420 gcj_present
= false;
1424 while (safe_read (fd
[0], &c
[0], 1) > 0)
1429 /* Remove zombie process from process list, and retrieve exit
1432 wait_subprocess (child
, "gcj", false, true, true, false, NULL
);
1433 if (exitstatus
!= 0)
1434 gcj_present
= false;
1439 /* See if libgcj.jar is well installed. */
1440 struct temp_dir
*tmpdir
;
1442 tmpdir
= create_temp_dir ("java", NULL
, false);
1444 gcj_present
= false;
1447 char *conftest_file_name
;
1449 conftest_file_name
=
1450 xconcatenated_filename (tmpdir
->dir_name
, "conftestlib.java",
1452 if (write_temp_file (tmpdir
, conftest_file_name
,
1453 "public class conftestlib {\n"
1454 " public static void main (String[] args) {\n"
1457 gcj_present
= false;
1460 char *compiled_file_name
;
1461 const char *java_sources
[1];
1463 compiled_file_name
=
1464 xconcatenated_filename (tmpdir
->dir_name
,
1465 "conftestlib.class",
1467 register_temp_file (tmpdir
, compiled_file_name
);
1469 java_sources
[0] = conftest_file_name
;
1470 if (compile_using_gcj (java_sources
, 1, false,
1471 false, NULL
, false, NULL
,
1473 false, false, false, true))
1474 gcj_present
= false;
1476 free (compiled_file_name
);
1478 free (conftest_file_name
);
1480 cleanup_temp_dir (tmpdir
);
1492 static bool gcj_tested
;
1497 /* Test for presence of gcj:
1498 "gcj --version 2> /dev/null | \
1499 sed -e 's,^[^0-9]*,,' -e 1q | \
1500 sed -e '/^4\.[012]/d' | grep '^[4-9]'" */
1507 argv
[1] = "--version";
1509 child
= create_pipe_in ("gcj", "gcj", argv
, DEV_NULL
, true, true,
1514 /* Read the subprocess output, drop all lines except the first,
1515 drop all characters before the first digit, and test whether
1516 the remaining string starts with a digit >= 4, but not with
1517 "4.0" or "4.1" or "4.2". */
1521 while (safe_read (fd
[0], &c
[count
], 1) > 0)
1523 if (c
[count
] == '\n')
1527 if (!(c
[0] >= '0' && c
[0] <= '9'))
1529 gcj_43
= (c
[0] >= '4');
1534 if (c
[0] == '4' && c
[1] == '.' && c
[2] >= '0' && c
[2] <= '2')
1539 while (safe_read (fd
[0], &c
[0], 1) > 0)
1544 /* Remove zombie process from process list, and retrieve exit
1547 wait_subprocess (child
, "gcj", false, true, true, false, NULL
);
1548 if (exitstatus
!= 0)
1558 /* Test whether gcj >= 4.3 can be used, and whether it needs a -fsource and/or
1560 Return a failure indicator (true upon error). */
1562 is_gcj43_usable (const char *source_version
,
1563 const char *target_version
,
1565 bool *fsource_option_p
, bool *ftarget_option_p
)
1567 /* The cache depends on the source_version and target_version. */
1572 bool fsource_option
;
1573 bool ftarget_option
;
1575 static struct result_t result_cache
[SOURCE_VERSION_BOUND
][TARGET_VERSION_BOUND
];
1576 struct result_t
*resultp
;
1578 resultp
= &result_cache
[source_version_index (source_version
)]
1579 [target_version_index (target_version
)];
1580 if (!resultp
->tested
)
1583 struct temp_dir
*tmpdir
;
1584 char *conftest_file_name
;
1585 char *compiled_file_name
;
1586 const char *java_sources
[1];
1587 struct stat statbuf
;
1589 tmpdir
= create_temp_dir ("java", NULL
, false);
1593 conftest_file_name
=
1594 xconcatenated_filename (tmpdir
->dir_name
, "conftest.java", NULL
);
1595 if (write_temp_file (tmpdir
, conftest_file_name
,
1596 get_goodcode_snippet (source_version
)))
1598 free (conftest_file_name
);
1599 cleanup_temp_dir (tmpdir
);
1603 compiled_file_name
=
1604 xconcatenated_filename (tmpdir
->dir_name
, "conftest.class", NULL
);
1605 register_temp_file (tmpdir
, compiled_file_name
);
1607 java_sources
[0] = conftest_file_name
;
1608 if (!compile_using_gcj (java_sources
, 1, false, false, NULL
, false, NULL
,
1609 tmpdir
->dir_name
, false, false, false, true)
1610 && stat (compiled_file_name
, &statbuf
) >= 0
1611 && get_classfile_version (compiled_file_name
)
1612 <= corresponding_classfile_version (target_version
))
1614 /* gcj compiled conftest.java successfully. */
1615 /* Try adding -fsource option if it is useful. */
1616 unlink (compiled_file_name
);
1618 java_sources
[0] = conftest_file_name
;
1619 if (!compile_using_gcj (java_sources
, 1,
1620 false, true, source_version
, false, NULL
,
1621 tmpdir
->dir_name
, false, false, false, true)
1622 && stat (compiled_file_name
, &statbuf
) >= 0
1623 && get_classfile_version (compiled_file_name
)
1624 <= corresponding_classfile_version (target_version
))
1626 const char *failcode
= get_failcode_snippet (source_version
);
1628 if (failcode
!= NULL
)
1630 free (compiled_file_name
);
1631 free (conftest_file_name
);
1633 conftest_file_name
=
1634 xconcatenated_filename (tmpdir
->dir_name
,
1635 "conftestfail.java",
1637 if (write_temp_file (tmpdir
, conftest_file_name
, failcode
))
1639 free (conftest_file_name
);
1640 cleanup_temp_dir (tmpdir
);
1644 compiled_file_name
=
1645 xconcatenated_filename (tmpdir
->dir_name
,
1646 "conftestfail.class",
1648 register_temp_file (tmpdir
, compiled_file_name
);
1650 java_sources
[0] = conftest_file_name
;
1651 if (!compile_using_gcj (java_sources
, 1,
1652 false, false, NULL
, false, NULL
,
1654 false, false, false, true)
1655 && stat (compiled_file_name
, &statbuf
) >= 0)
1657 unlink (compiled_file_name
);
1659 java_sources
[0] = conftest_file_name
;
1660 if (compile_using_gcj (java_sources
, 1,
1661 false, true, source_version
,
1664 false, false, false, true))
1665 /* gcj compiled conftestfail.java successfully, and
1666 "gcj -fsource=$source_version" rejects it. So
1667 the -fsource option is useful. */
1668 resultp
->fsource_option
= true;
1673 resultp
->usable
= true;
1677 /* Try with -fsource and -ftarget options. */
1678 unlink (compiled_file_name
);
1680 java_sources
[0] = conftest_file_name
;
1681 if (!compile_using_gcj (java_sources
, 1,
1682 false, true, source_version
,
1683 true, target_version
,
1685 false, false, false, true)
1686 && stat (compiled_file_name
, &statbuf
) >= 0
1687 && get_classfile_version (compiled_file_name
)
1688 <= corresponding_classfile_version (target_version
))
1690 /* "gcj -fsource $source_version -ftarget $target_version"
1691 compiled conftest.java successfully. */
1692 resultp
->fsource_option
= true;
1693 resultp
->ftarget_option
= true;
1694 resultp
->usable
= true;
1698 free (compiled_file_name
);
1699 free (conftest_file_name
);
1701 resultp
->tested
= true;
1704 *usablep
= resultp
->usable
;
1705 *fsource_option_p
= resultp
->fsource_option
;
1706 *ftarget_option_p
= resultp
->ftarget_option
;
1710 /* Test whether gcj < 4.3 can be used for compiling with target_version = 1.4
1711 and source_version = 1.4.
1712 Return a failure indicator (true upon error). */
1714 is_oldgcj_14_14_usable (bool *usablep
)
1716 static bool gcj_tested
;
1717 static bool gcj_usable
;
1722 struct temp_dir
*tmpdir
;
1723 char *conftest_file_name
;
1724 char *compiled_file_name
;
1725 const char *java_sources
[1];
1726 struct stat statbuf
;
1728 tmpdir
= create_temp_dir ("java", NULL
, false);
1732 conftest_file_name
=
1733 xconcatenated_filename (tmpdir
->dir_name
, "conftest.java", NULL
);
1734 if (write_temp_file (tmpdir
, conftest_file_name
,
1735 get_goodcode_snippet ("1.4")))
1737 free (conftest_file_name
);
1738 cleanup_temp_dir (tmpdir
);
1742 compiled_file_name
=
1743 xconcatenated_filename (tmpdir
->dir_name
, "conftest.class", NULL
);
1744 register_temp_file (tmpdir
, compiled_file_name
);
1746 java_sources
[0] = conftest_file_name
;
1747 if (!compile_using_gcj (java_sources
, 1, false, false, NULL
, false, NULL
,
1748 tmpdir
->dir_name
, false, false, false, true)
1749 && stat (compiled_file_name
, &statbuf
) >= 0)
1750 /* Compilation succeeded. */
1753 free (compiled_file_name
);
1754 free (conftest_file_name
);
1756 cleanup_temp_dir (tmpdir
);
1761 *usablep
= gcj_usable
;
1765 /* Test whether gcj < 4.3 can be used for compiling with target_version = 1.4
1766 and source_version = 1.3.
1767 Return a failure indicator (true upon error). */
1769 is_oldgcj_14_13_usable (bool *usablep
, bool *need_no_assert_option_p
)
1771 static bool gcj_tested
;
1772 static bool gcj_usable
;
1773 static bool gcj_need_no_assert_option
;
1777 /* Try gcj and "gcj -fno-assert". But add -fno-assert only if
1778 it works (not gcj < 3.3). */
1779 struct temp_dir
*tmpdir
;
1780 char *conftest_file_name
;
1781 char *compiled_file_name
;
1782 const char *java_sources
[1];
1783 struct stat statbuf
;
1785 tmpdir
= create_temp_dir ("java", NULL
, false);
1789 conftest_file_name
=
1790 xconcatenated_filename (tmpdir
->dir_name
, "conftest.java", NULL
);
1791 if (write_temp_file (tmpdir
, conftest_file_name
,
1792 get_goodcode_snippet ("1.3")))
1794 free (conftest_file_name
);
1795 cleanup_temp_dir (tmpdir
);
1799 compiled_file_name
=
1800 xconcatenated_filename (tmpdir
->dir_name
, "conftest.class", NULL
);
1801 register_temp_file (tmpdir
, compiled_file_name
);
1803 java_sources
[0] = conftest_file_name
;
1804 if (!compile_using_gcj (java_sources
, 1, true, false, NULL
, false, NULL
,
1805 tmpdir
->dir_name
, false, false, false, true)
1806 && stat (compiled_file_name
, &statbuf
) >= 0)
1807 /* Compilation succeeded. */
1810 gcj_need_no_assert_option
= true;
1814 unlink (compiled_file_name
);
1816 java_sources
[0] = conftest_file_name
;
1817 if (!compile_using_gcj (java_sources
, 1, false,
1818 false, NULL
, false, NULL
,
1819 tmpdir
->dir_name
, false, false, false, true)
1820 && stat (compiled_file_name
, &statbuf
) >= 0)
1821 /* Compilation succeeded. */
1824 gcj_need_no_assert_option
= false;
1828 free (compiled_file_name
);
1829 free (conftest_file_name
);
1831 cleanup_temp_dir (tmpdir
);
1836 *usablep
= gcj_usable
;
1837 *need_no_assert_option_p
= gcj_need_no_assert_option
;
1842 is_javac_present (void)
1844 static bool javac_tested
;
1845 static bool javac_present
;
1849 /* Test for presence of javac: "javac 2> /dev/null ; test $? -le 2" */
1855 exitstatus
= execute ("javac", "javac", argv
, false, false, true, true,
1857 javac_present
= (exitstatus
== 0 || exitstatus
== 1 || exitstatus
== 2);
1858 javac_tested
= true;
1861 return javac_present
;
1864 /* Test whether javac can be used and whether it needs a -source and/or
1866 Return a failure indicator (true upon error). */
1868 is_javac_usable (const char *source_version
,
1869 const char *source_version_for_javac
,
1870 const char *target_version
,
1871 bool *usablep
, bool *source_option_p
, bool *target_option_p
)
1873 /* The cache depends on the source_version and target_version. */
1881 static struct result_t result_cache
[SOURCE_VERSION_BOUND
][TARGET_VERSION_BOUND
];
1882 struct result_t
*resultp
;
1884 resultp
= &result_cache
[source_version_index (source_version
)]
1885 [target_version_index (target_version
)];
1886 if (!resultp
->tested
)
1889 struct temp_dir
*tmpdir
;
1890 char *conftest_file_name
;
1891 char *compiled_file_name
;
1892 const char *java_sources
[1];
1893 struct stat statbuf
;
1895 tmpdir
= create_temp_dir ("java", NULL
, false);
1899 conftest_file_name
=
1900 xconcatenated_filename (tmpdir
->dir_name
, "conftest.java", NULL
);
1901 if (write_temp_file (tmpdir
, conftest_file_name
,
1902 get_goodcode_snippet (source_version
)))
1904 free (conftest_file_name
);
1905 cleanup_temp_dir (tmpdir
);
1909 compiled_file_name
=
1910 xconcatenated_filename (tmpdir
->dir_name
, "conftest.class", NULL
);
1911 register_temp_file (tmpdir
, compiled_file_name
);
1913 java_sources
[0] = conftest_file_name
;
1914 if (!compile_using_javac (java_sources
, 1,
1915 false, source_version_for_javac
,
1916 false, target_version
,
1917 tmpdir
->dir_name
, false, false, false, true)
1918 && stat (compiled_file_name
, &statbuf
) >= 0
1919 && get_classfile_version (compiled_file_name
)
1920 <= corresponding_classfile_version (target_version
))
1922 /* javac compiled conftest.java successfully. */
1923 /* Try adding -source option if it is useful. */
1924 unlink (compiled_file_name
);
1926 java_sources
[0] = conftest_file_name
;
1927 if (!compile_using_javac (java_sources
, 1,
1928 true, source_version_for_javac
,
1929 false, target_version
,
1930 tmpdir
->dir_name
, false, false, false, true)
1931 && stat (compiled_file_name
, &statbuf
) >= 0
1932 && get_classfile_version (compiled_file_name
)
1933 <= corresponding_classfile_version (target_version
))
1935 const char *failcode
= get_failcode_snippet (source_version
);
1937 if (failcode
!= NULL
)
1939 free (compiled_file_name
);
1940 free (conftest_file_name
);
1942 conftest_file_name
=
1943 xconcatenated_filename (tmpdir
->dir_name
,
1944 "conftestfail.java",
1946 if (write_temp_file (tmpdir
, conftest_file_name
, failcode
))
1948 free (conftest_file_name
);
1949 cleanup_temp_dir (tmpdir
);
1953 compiled_file_name
=
1954 xconcatenated_filename (tmpdir
->dir_name
,
1955 "conftestfail.class",
1957 register_temp_file (tmpdir
, compiled_file_name
);
1959 java_sources
[0] = conftest_file_name
;
1960 if (!compile_using_javac (java_sources
, 1,
1961 false, source_version_for_javac
,
1962 false, target_version
,
1964 false, false, false, true)
1965 && stat (compiled_file_name
, &statbuf
) >= 0)
1967 unlink (compiled_file_name
);
1969 java_sources
[0] = conftest_file_name
;
1970 if (compile_using_javac (java_sources
, 1,
1971 true, source_version_for_javac
,
1972 false, target_version
,
1974 false, false, false, true))
1975 /* javac compiled conftestfail.java successfully, and
1976 "javac -source $source_version_for_javac" rejects it.
1977 So the -source option is useful. */
1978 resultp
->source_option
= true;
1983 resultp
->usable
= true;
1987 /* Try with -target option alone. (Sun javac 1.3.1 has the -target
1988 option but no -source option.) */
1989 unlink (compiled_file_name
);
1991 java_sources
[0] = conftest_file_name
;
1992 if (!compile_using_javac (java_sources
, 1,
1993 false, source_version_for_javac
,
1994 true, target_version
,
1996 false, false, false, true)
1997 && stat (compiled_file_name
, &statbuf
) >= 0
1998 && get_classfile_version (compiled_file_name
)
1999 <= corresponding_classfile_version (target_version
))
2001 /* "javac -target $target_version" compiled conftest.java
2003 /* Try adding -source option if it is useful. */
2004 unlink (compiled_file_name
);
2006 java_sources
[0] = conftest_file_name
;
2007 if (!compile_using_javac (java_sources
, 1,
2008 true, source_version_for_javac
,
2009 true, target_version
,
2011 false, false, false, true)
2012 && stat (compiled_file_name
, &statbuf
) >= 0
2013 && get_classfile_version (compiled_file_name
)
2014 <= corresponding_classfile_version (target_version
))
2016 const char *failcode
= get_failcode_snippet (source_version
);
2018 if (failcode
!= NULL
)
2020 free (compiled_file_name
);
2021 free (conftest_file_name
);
2023 conftest_file_name
=
2024 xconcatenated_filename (tmpdir
->dir_name
,
2025 "conftestfail.java",
2027 if (write_temp_file (tmpdir
, conftest_file_name
,
2030 free (conftest_file_name
);
2031 cleanup_temp_dir (tmpdir
);
2035 compiled_file_name
=
2036 xconcatenated_filename (tmpdir
->dir_name
,
2037 "conftestfail.class",
2039 register_temp_file (tmpdir
, compiled_file_name
);
2041 java_sources
[0] = conftest_file_name
;
2042 if (!compile_using_javac (java_sources
, 1,
2043 false, source_version_for_javac
,
2044 true, target_version
,
2046 false, false, false, true)
2047 && stat (compiled_file_name
, &statbuf
) >= 0)
2049 unlink (compiled_file_name
);
2051 java_sources
[0] = conftest_file_name
;
2052 if (compile_using_javac (java_sources
, 1,
2053 true, source_version_for_javac
,
2054 true, target_version
,
2056 false, false, false, true))
2057 /* "javac -target $target_version" compiled
2058 conftestfail.java successfully, and
2059 "javac -target $target_version -source $source_version_for_javac"
2060 rejects it. So the -source option is useful. */
2061 resultp
->source_option
= true;
2066 resultp
->target_option
= true;
2067 resultp
->usable
= true;
2071 /* Maybe this -target option requires a -source option? Try with
2072 -target and -source options. (Supported by Sun javac 1.4 and
2074 unlink (compiled_file_name
);
2076 java_sources
[0] = conftest_file_name
;
2077 if (!compile_using_javac (java_sources
, 1,
2078 true, source_version_for_javac
,
2079 true, target_version
,
2081 false, false, false, true)
2082 && stat (compiled_file_name
, &statbuf
) >= 0
2083 && get_classfile_version (compiled_file_name
)
2084 <= corresponding_classfile_version (target_version
))
2086 /* "javac -target $target_version -source $source_version_for_javac"
2087 compiled conftest.java successfully. */
2088 resultp
->source_option
= true;
2089 resultp
->target_option
= true;
2090 resultp
->usable
= true;
2095 free (compiled_file_name
);
2096 free (conftest_file_name
);
2098 resultp
->tested
= true;
2101 *usablep
= resultp
->usable
;
2102 *source_option_p
= resultp
->source_option
;
2103 *target_option_p
= resultp
->target_option
;
2108 is_jikes_present (void)
2110 static bool jikes_tested
;
2111 static bool jikes_present
;
2115 /* Test for presence of jikes: "jikes 2> /dev/null ; test $? = 1" */
2121 exitstatus
= execute ("jikes", "jikes", argv
, false, false, true, true,
2123 jikes_present
= (exitstatus
== 0 || exitstatus
== 1);
2124 jikes_tested
= true;
2127 return jikes_present
;
2130 /* ============================= Main function ============================= */
2133 compile_java_class (const char * const *java_sources
,
2134 unsigned int java_sources_count
,
2135 const char * const *classpaths
,
2136 unsigned int classpaths_count
,
2137 const char *source_version
,
2138 const char *target_version
,
2139 const char *directory
,
2140 bool optimize
, bool debug
,
2141 bool use_minimal_classpath
,
2145 char *old_JAVA_HOME
;
2148 const char *javac
= getenv ("JAVAC");
2149 if (javac
!= NULL
&& javac
[0] != '\0')
2151 bool usable
= false;
2152 bool no_assert_option
= false;
2153 bool source_option
= false;
2154 bool target_option
= false;
2155 bool fsource_option
= false;
2156 bool ftarget_option
= false;
2157 const char *source_version_for_javac
;
2159 if (target_version
== NULL
)
2160 target_version
= default_target_version ();
2162 source_version_for_javac
=
2163 get_source_version_for_javac (source_version
, target_version
);
2165 if (is_envjavac_gcj (javac
))
2167 /* It's a version of gcj. */
2168 if (is_envjavac_gcj43 (javac
))
2170 /* It's a version of gcj >= 4.3. Assume the classfile versions
2172 if (is_envjavac_gcj43_usable (javac
,
2173 source_version
, target_version
,
2175 &fsource_option
, &ftarget_option
))
2183 /* It's a version of gcj < 4.3. Ignore the version of the
2184 class files that it creates. */
2185 if (strcmp (target_version
, "1.4") == 0
2186 && strcmp (source_version
, "1.4") == 0)
2188 if (is_envjavac_oldgcj_14_14_usable (javac
, &usable
))
2194 else if (strcmp (target_version
, "1.4") == 0
2195 && strcmp (source_version
, "1.3") == 0)
2197 if (is_envjavac_oldgcj_14_13_usable (javac
,
2209 /* It's not gcj. Assume the classfile versions are correct. */
2210 if (is_envjavac_nongcj_usable (javac
,
2212 source_version_for_javac
,
2215 &source_option
, &target_option
))
2224 char *old_classpath
;
2225 char *javac_with_options
;
2227 /* Set CLASSPATH. */
2229 set_classpath (classpaths
, classpaths_count
, false, verbose
);
2231 javac_with_options
=
2233 ? xasprintf ("%s -fno-assert", javac
)
2234 : xasprintf ("%s%s%s%s%s%s%s%s%s",
2236 source_option
? " -source " : "",
2237 source_option
? source_version_for_javac
: "",
2238 target_option
? " -target " : "",
2239 target_option
? target_version
: "",
2240 fsource_option
? " -fsource=" : "",
2241 fsource_option
? source_version
: "",
2242 ftarget_option
? " -ftarget=" : "",
2243 ftarget_option
? target_version
: ""));
2245 err
= compile_using_envjavac (javac_with_options
,
2246 java_sources
, java_sources_count
,
2247 directory
, optimize
, debug
, verbose
,
2250 free (javac_with_options
);
2252 /* Reset CLASSPATH. */
2253 reset_classpath (old_classpath
);
2260 /* Unset the JAVA_HOME environment variable. */
2261 old_JAVA_HOME
= getenv ("JAVA_HOME");
2262 if (old_JAVA_HOME
!= NULL
)
2264 old_JAVA_HOME
= xstrdup (old_JAVA_HOME
);
2265 unsetenv ("JAVA_HOME");
2268 if (is_gcj_present ())
2270 /* It's a version of gcj. */
2271 bool usable
= false;
2272 bool no_assert_option
= false;
2273 bool fsource_option
= false;
2274 bool ftarget_option
= false;
2276 if (target_version
== NULL
)
2277 target_version
= default_target_version ();
2281 /* It's a version of gcj >= 4.3. Assume the classfile versions
2283 if (is_gcj43_usable (source_version
, target_version
,
2284 &usable
, &fsource_option
, &ftarget_option
))
2292 /* It's a version of gcj < 4.3. Ignore the version of the class
2293 files that it creates.
2294 Test whether it supports the desired target-version and
2296 if (strcmp (target_version
, "1.4") == 0
2297 && strcmp (source_version
, "1.4") == 0)
2299 if (is_oldgcj_14_14_usable (&usable
))
2305 else if (strcmp (target_version
, "1.4") == 0
2306 && strcmp (source_version
, "1.3") == 0)
2308 if (is_oldgcj_14_13_usable (&usable
, &no_assert_option
))
2318 char *old_classpath
;
2320 /* Set CLASSPATH. We could also use the --CLASSPATH=... option
2321 of gcj. Note that --classpath=... option is different: its
2322 argument should also contain gcj's libgcj.jar, but we don't
2323 know its location. */
2325 set_classpath (classpaths
, classpaths_count
, use_minimal_classpath
,
2328 err
= compile_using_gcj (java_sources
, java_sources_count
,
2330 fsource_option
, source_version
,
2331 ftarget_option
, target_version
,
2332 directory
, optimize
, debug
, verbose
, false);
2334 /* Reset CLASSPATH. */
2335 reset_classpath (old_classpath
);
2341 if (is_javac_present ())
2343 bool usable
= false;
2344 bool source_option
= false;
2345 bool target_option
= false;
2346 const char *source_version_for_javac
;
2348 if (target_version
== NULL
)
2349 target_version
= default_target_version ();
2351 source_version_for_javac
=
2352 get_source_version_for_javac (source_version
, target_version
);
2354 if (is_javac_usable (source_version
, source_version_for_javac
,
2356 &usable
, &source_option
, &target_option
))
2364 char *old_classpath
;
2366 /* Set CLASSPATH. We don't use the "-classpath ..." option because
2367 in JDK 1.1.x its argument should also contain the JDK's
2368 classes.zip, but we don't know its location. (In JDK 1.3.0 it
2371 set_classpath (classpaths
, classpaths_count
, use_minimal_classpath
,
2374 err
= compile_using_javac (java_sources
, java_sources_count
,
2375 source_option
, source_version_for_javac
,
2376 target_option
, target_version
,
2377 directory
, optimize
, debug
, verbose
,
2380 /* Reset CLASSPATH. */
2381 reset_classpath (old_classpath
);
2387 if (is_jikes_present ())
2389 /* Test whether it supports the desired target-version and
2391 bool usable
= (strcmp (source_version
, "1.3") == 0);
2395 char *old_classpath
;
2397 /* Set CLASSPATH. We could also use the "-classpath ..." option.
2398 Since jikes doesn't come with its own standard library, it
2399 needs a classes.zip or rt.jar or libgcj.jar in the CLASSPATH.
2400 To increase the chance of success, we reuse the current CLASSPATH
2401 if the user has set it. */
2403 set_classpath (classpaths
, classpaths_count
, false, verbose
);
2405 err
= compile_using_jikes (java_sources
, java_sources_count
,
2406 directory
, optimize
, debug
, verbose
,
2409 /* Reset CLASSPATH. */
2410 reset_classpath (old_classpath
);
2416 error (0, 0, _("Java compiler not found, try installing gcj or set $JAVAC"));
2420 if (old_JAVA_HOME
!= NULL
)
2422 xsetenv ("JAVA_HOME", old_JAVA_HOME
, 1);
2423 free (old_JAVA_HOME
);