1 /* Compile a Java program.
2 Copyright (C) 2001-2003, 2006-2020 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
= "1.1";
103 else if ((java_version_cache
[0] == '1'
104 && java_version_cache
[1] == '.'
105 && java_version_cache
[2] >= '1' && java_version_cache
[2] <= '8'
106 && java_version_cache
[3] == '\0')
107 || (java_version_cache
[0] == '9'
108 && java_version_cache
[1] == '\0')
109 || (java_version_cache
[0] == '1'
110 && (java_version_cache
[1] >= '0'
111 && java_version_cache
[1] <= '1')
112 && java_version_cache
[2] == '\0'))
113 /* It's one of the valid target version values. */
115 else if (java_version_cache
[0] == '1'
116 && (java_version_cache
[1] >= '2'
117 && java_version_cache
[1] <= '7')
118 && java_version_cache
[2] == '\0')
119 /* Assume that these (not yet released) Java versions will behave
120 like the preceding ones. */
121 java_version_cache
= "11";
123 java_version_cache
= "1.1";
125 return java_version_cache
;
128 /* ======================= Source version dependent ======================= */
130 /* Convert a source version to an index. */
131 #define SOURCE_VERSION_BOUND 8 /* exclusive upper bound */
133 source_version_index (const char *source_version
)
135 if (source_version
[0] == '1' && source_version
[1] == '.')
137 if ((source_version
[2] >= '3' && source_version
[2] <= '5')
138 && source_version
[3] == '\0')
139 return source_version
[2] - '3';
140 if ((source_version
[2] >= '7' && source_version
[2] <= '8')
141 && source_version
[3] == '\0')
142 return source_version
[2] - '4';
144 else if (source_version
[0] == '9' && source_version
[1] == '\0')
146 else if (source_version
[0] == '1'
147 && (source_version
[1] >= '0' && source_version
[1] <= '1')
148 && source_version
[2] == '\0')
149 return source_version
[1] - '0' + 6;
150 error (EXIT_FAILURE
, 0, _("invalid source_version argument to compile_java_class"));
154 /* Return a snippet of code that should compile in the given source version. */
156 get_goodcode_snippet (const char *source_version
)
158 if (strcmp (source_version
, "1.3") == 0)
159 return "class conftest {}\n";
160 if (strcmp (source_version
, "1.4") == 0)
161 return "class conftest { static { assert(true); } }\n";
162 if (strcmp (source_version
, "1.5") == 0)
163 return "class conftest<T> { T foo() { return null; } }\n";
164 if (strcmp (source_version
, "1.7") == 0)
165 return "class conftest { void foo () { switch (\"A\") {} } }\n";
166 if (strcmp (source_version
, "1.8") == 0)
167 return "class conftest { void foo () { Runnable r = () -> {}; } }\n";
168 if (strcmp (source_version
, "9") == 0)
169 return "interface conftest { private void foo () {} }\n";
170 if (strcmp (source_version
, "10") == 0)
171 return "class conftest { public void m() { var i = new Integer(0); } }\n";
172 if (strcmp (source_version
, "11") == 0)
173 return "class conftest { Readable r = (var b) -> 0; }\n";
174 error (EXIT_FAILURE
, 0, _("invalid source_version argument to compile_java_class"));
178 /* Return a snippet of code that should fail to compile in the given source
179 version, or NULL (standing for a snippet that would fail to compile with
182 get_failcode_snippet (const char *source_version
)
184 if (strcmp (source_version
, "1.3") == 0)
185 return "class conftestfail { static { assert(true); } }\n";
186 if (strcmp (source_version
, "1.4") == 0)
187 return "class conftestfail<T> { T foo() { return null; } }\n";
188 if (strcmp (source_version
, "1.5") == 0)
189 return "class conftestfail { void foo () { switch (\"A\") {} } }\n";
190 if (strcmp (source_version
, "1.7") == 0)
191 return "class conftestfail { void foo () { Runnable r = () -> {}; } }\n";
192 if (strcmp (source_version
, "1.8") == 0)
193 return "interface conftestfail { private void foo () {} }\n";
194 if (strcmp (source_version
, "9") == 0)
195 return "class conftestfail { public void m() { var i = new Integer(0); } }\n";
196 if (strcmp (source_version
, "10") == 0)
197 return "class conftestfail { Readable r = (var b) -> 0; }\n";
198 if (strcmp (source_version
, "11") == 0)
200 error (EXIT_FAILURE
, 0, _("invalid source_version argument to compile_java_class"));
204 /* ======================= Target version dependent ======================= */
206 /* Convert a target version to an index. */
207 #define TARGET_VERSION_BOUND 11 /* exclusive upper bound */
209 target_version_index (const char *target_version
)
211 if (target_version
[0] == '1' && target_version
[1] == '.'
212 && (target_version
[2] >= '1' && target_version
[2] <= '8')
213 && target_version
[3] == '\0')
214 return target_version
[2] - '1';
215 else if (target_version
[0] == '9' && target_version
[1] == '\0')
217 else if (target_version
[0] == '1'
218 && (target_version
[1] >= '0' && target_version
[1] <= '1')
219 && target_version
[2] == '\0')
220 return target_version
[1] - '0' + 9;
221 error (EXIT_FAILURE
, 0, _("invalid target_version argument to compile_java_class"));
225 /* Return the class file version number corresponding to a given target
228 corresponding_classfile_version (const char *target_version
)
230 if (strcmp (target_version
, "1.1") == 0)
232 if (strcmp (target_version
, "1.2") == 0)
234 if (strcmp (target_version
, "1.3") == 0)
236 if (strcmp (target_version
, "1.4") == 0)
238 if (strcmp (target_version
, "1.5") == 0)
240 if (strcmp (target_version
, "1.6") == 0)
242 if (strcmp (target_version
, "1.7") == 0)
244 if (strcmp (target_version
, "1.8") == 0)
246 if (strcmp (target_version
, "9") == 0)
248 if (strcmp (target_version
, "10") == 0)
250 if (strcmp (target_version
, "11") == 0)
252 error (EXIT_FAILURE
, 0, _("invalid target_version argument to compile_java_class"));
256 /* Return the source version to pass to javac. */
258 get_source_version_for_javac (const char *source_version
,
259 const char *target_version
)
261 /* The javac option '-source 1.5' has the same meaning as '-source 1.6',
262 but since Java 9 supports only the latter, prefer the latter if a
263 target_version >= 1.6 is requested. */
264 if (strcmp (source_version
, "1.5") == 0
265 && !(target_version
[0] == '1' && target_version
[1] == '.'
266 && (target_version
[2] >= '1' && target_version
[2] <= '5')
267 && target_version
[3] == '\0'))
269 return source_version
;
272 /* ======================== Compilation subroutines ======================== */
274 /* Try to compile a set of Java sources with $JAVAC.
275 Return a failure indicator (true upon error). */
277 compile_using_envjavac (const char *javac
,
278 const char * const *java_sources
,
279 unsigned int java_sources_count
,
280 const char *directory
,
281 bool optimize
, bool debug
,
282 bool verbose
, bool null_stderr
)
284 /* Because $JAVAC may consist of a command and options, we use the
285 shell. Because $JAVAC has been set by the user, we leave all
286 environment variables in place, including JAVA_HOME, and we don't
287 erase the user's CLASSPATH. */
289 unsigned int command_length
;
296 command_length
= strlen (javac
);
301 if (directory
!= NULL
)
302 command_length
+= 4 + shell_quote_length (directory
);
303 for (i
= 0; i
< java_sources_count
; i
++)
304 command_length
+= 1 + shell_quote_length (java_sources
[i
]);
307 command
= (char *) xmalloca (command_length
);
309 /* Don't shell_quote $JAVAC, because it may consist of a command
311 memcpy (p
, javac
, strlen (javac
));
315 memcpy (p
, " -O", 3);
320 memcpy (p
, " -g", 3);
323 if (directory
!= NULL
)
325 memcpy (p
, " -d ", 4);
327 p
= shell_quote_copy (p
, directory
);
329 for (i
= 0; i
< java_sources_count
; i
++)
332 p
= shell_quote_copy (p
, java_sources
[i
]);
335 /* Ensure command_length was correctly calculated. */
336 if (p
- command
> command_length
)
340 printf ("%s\n", command
);
342 argv
[0] = BOURNE_SHELL
;
346 exitstatus
= execute (javac
, BOURNE_SHELL
, argv
, NULL
,
347 false, false, false, null_stderr
,
349 err
= (exitstatus
!= 0);
356 /* Try to compile a set of Java sources with gcj.
357 Return a failure indicator (true upon error). */
359 compile_using_gcj (const char * const *java_sources
,
360 unsigned int java_sources_count
,
361 bool no_assert_option
,
362 bool fsource_option
, const char *source_version
,
363 bool ftarget_option
, const char *target_version
,
364 const char *directory
,
365 bool optimize
, bool debug
,
366 bool verbose
, bool null_stderr
)
378 2 + (no_assert_option
? 1 : 0) + (fsource_option
? 1 : 0)
379 + (ftarget_option
? 1 : 0) + (optimize
? 1 : 0) + (debug
? 1 : 0)
380 + (directory
!= NULL
? 2 : 0) + java_sources_count
;
381 argv
= (char **) xmalloca ((argc
+ 1) * sizeof (char *));
386 if (no_assert_option
)
387 *argp
++ = "-fno-assert";
390 fsource_arg
= (char *) xmalloca (9 + strlen (source_version
) + 1);
391 memcpy (fsource_arg
, "-fsource=", 9);
392 strcpy (fsource_arg
+ 9, source_version
);
393 *argp
++ = fsource_arg
;
399 ftarget_arg
= (char *) xmalloca (9 + strlen (target_version
) + 1);
400 memcpy (ftarget_arg
, "-ftarget=", 9);
401 strcpy (ftarget_arg
+ 9, target_version
);
402 *argp
++ = ftarget_arg
;
410 if (directory
!= NULL
)
413 *argp
++ = (char *) directory
;
415 for (i
= 0; i
< java_sources_count
; i
++)
416 *argp
++ = (char *) java_sources
[i
];
418 /* Ensure argv length was correctly calculated. */
419 if (argp
- argv
!= argc
)
424 char *command
= shell_quote_argv (argv
);
425 printf ("%s\n", command
);
429 exitstatus
= execute ("gcj", "gcj", argv
, NULL
,
430 false, false, false, null_stderr
,
432 err
= (exitstatus
!= 0);
434 if (ftarget_arg
!= NULL
)
436 if (fsource_arg
!= NULL
)
443 /* Try to compile a set of Java sources with javac.
444 Return a failure indicator (true upon error). */
446 compile_using_javac (const char * const *java_sources
,
447 unsigned int java_sources_count
,
448 bool source_option
, const char *source_version
,
449 bool target_option
, const char *target_version
,
450 const char *directory
,
451 bool optimize
, bool debug
,
452 bool verbose
, bool null_stderr
)
462 1 + (source_option
? 2 : 0) + (target_option
? 2 : 0) + (optimize
? 1 : 0)
463 + (debug
? 1 : 0) + (directory
!= NULL
? 2 : 0) + java_sources_count
;
464 argv
= (char **) xmalloca ((argc
+ 1) * sizeof (char *));
471 *argp
++ = (char *) source_version
;
476 *argp
++ = (char *) target_version
;
482 if (directory
!= NULL
)
485 *argp
++ = (char *) directory
;
487 for (i
= 0; i
< java_sources_count
; i
++)
488 *argp
++ = (char *) java_sources
[i
];
490 /* Ensure argv length was correctly calculated. */
491 if (argp
- argv
!= argc
)
496 char *command
= shell_quote_argv (argv
);
497 printf ("%s\n", command
);
501 exitstatus
= execute ("javac", "javac", argv
, NULL
,
503 null_stderr
, true, true, NULL
);
504 err
= (exitstatus
!= 0);
511 /* Try to compile a set of Java sources with jikes.
512 Return a failure indicator (true upon error). */
514 compile_using_jikes (const char * const *java_sources
,
515 unsigned int java_sources_count
,
516 const char *directory
,
517 bool optimize
, bool debug
,
518 bool verbose
, bool null_stderr
)
528 1 + (optimize
? 1 : 0) + (debug
? 1 : 0) + (directory
!= NULL
? 2 : 0)
529 + java_sources_count
;
530 argv
= (char **) xmalloca ((argc
+ 1) * sizeof (char *));
538 if (directory
!= NULL
)
541 *argp
++ = (char *) directory
;
543 for (i
= 0; i
< java_sources_count
; i
++)
544 *argp
++ = (char *) java_sources
[i
];
546 /* Ensure argv length was correctly calculated. */
547 if (argp
- argv
!= argc
)
552 char *command
= shell_quote_argv (argv
);
553 printf ("%s\n", command
);
557 exitstatus
= execute ("jikes", "jikes", argv
, NULL
,
558 false, false, false, null_stderr
,
560 err
= (exitstatus
!= 0);
567 /* ====================== Usability test subroutines ====================== */
569 /* Write a given contents to a temporary file.
570 FILE_NAME is the name of a file inside TMPDIR that is known not to exist
572 Return a failure indicator (true upon error). */
574 write_temp_file (struct temp_dir
*tmpdir
, const char *file_name
,
575 const char *contents
)
579 register_temp_file (tmpdir
, file_name
);
580 fp
= fopen_temp (file_name
, "we", false);
583 error (0, errno
, _("failed to create \"%s\""), file_name
);
584 unregister_temp_file (tmpdir
, file_name
);
587 fputs (contents
, fp
);
588 if (fwriteerror_temp (fp
))
590 error (0, errno
, _("error while writing \"%s\" file"), file_name
);
596 /* Return the class file version number of a class file on disk. */
598 get_classfile_version (const char *compiled_file_name
)
600 unsigned char header
[8];
603 /* Open the class file. */
604 fd
= open (compiled_file_name
, O_RDONLY
| O_BINARY
| O_CLOEXEC
, 0);
607 /* Read its first 8 bytes. */
608 if (safe_read (fd
, header
, 8) == 8)
610 /* Verify the class file signature. */
611 if (header
[0] == 0xCA && header
[1] == 0xFE
612 && header
[2] == 0xBA && header
[3] == 0xBE)
621 /* Could not get the class file version. Return a very large one. */
625 /* Return true if $JAVAC is a version of gcj. */
627 is_envjavac_gcj (const char *javac
)
629 static bool envjavac_tested
;
630 static bool envjavac_gcj
;
632 if (!envjavac_tested
)
634 /* Test whether $JAVAC is gcj:
635 "$JAVAC --version 2>/dev/null | sed -e 1q | grep gcj > /dev/null" */
636 unsigned int command_length
;
648 /* Setup the command "$JAVAC --version". */
649 command_length
= strlen (javac
) + 1 + 9 + 1;
650 command
= (char *) xmalloca (command_length
);
652 /* Don't shell_quote $JAVAC, because it may consist of a command
654 memcpy (p
, javac
, strlen (javac
));
656 memcpy (p
, " --version", 1 + 9 + 1);
658 /* Ensure command_length was correctly calculated. */
659 if (p
- command
> command_length
)
662 /* Call $JAVAC --version 2>/dev/null. */
663 argv
[0] = BOURNE_SHELL
;
667 child
= create_pipe_in (javac
, BOURNE_SHELL
, argv
, NULL
,
668 DEV_NULL
, true, true, false, fd
);
672 /* Retrieve its result. */
673 fp
= fdopen (fd
[0], "r");
677 line
= NULL
; linesize
= 0;
678 linelen
= getline (&line
, &linesize
, fp
);
679 if (linelen
== (size_t)(-1))
684 /* It is safe to call c_strstr() instead of strstr() here; see the
685 comments in c-strstr.h. */
686 envjavac_gcj
= (c_strstr (line
, "gcj") != NULL
);
690 /* Remove zombie process from process list, and retrieve exit status. */
692 wait_subprocess (child
, javac
, true, true, true, false, NULL
);
694 envjavac_gcj
= false;
699 envjavac_tested
= true;
705 /* Return true if $JAVAC, known to be a version of gcj, is a version >= 4.3
708 is_envjavac_gcj43 (const char *javac
)
710 static bool envjavac_tested
;
711 static bool envjavac_gcj43
;
713 if (!envjavac_tested
)
715 /* Test whether $JAVAC is gcj:
716 "$JAVAC --version 2>/dev/null | sed -e 's,^[^0-9]*,,' -e 1q \
717 | sed -e '/^4\.[012]/d' | grep '^[4-9]' >/dev/null" */
718 unsigned int command_length
;
730 /* Setup the command "$JAVAC --version". */
731 command_length
= strlen (javac
) + 1 + 9 + 1;
732 command
= (char *) xmalloca (command_length
);
734 /* Don't shell_quote $JAVAC, because it may consist of a command
736 memcpy (p
, javac
, strlen (javac
));
738 memcpy (p
, " --version", 1 + 9 + 1);
740 /* Ensure command_length was correctly calculated. */
741 if (p
- command
> command_length
)
744 /* Call $JAVAC --version 2>/dev/null. */
745 argv
[0] = BOURNE_SHELL
;
749 child
= create_pipe_in (javac
, BOURNE_SHELL
, argv
, NULL
,
750 DEV_NULL
, true, true, false, fd
);
754 /* Retrieve its result. */
755 fp
= fdopen (fd
[0], "r");
759 line
= NULL
; linesize
= 0;
760 linelen
= getline (&line
, &linesize
, fp
);
761 if (linelen
== (size_t)(-1))
767 while (*p
!= '\0' && !(*p
>= '0' && *p
<= '9'))
770 !(*p
== '4' && p
[1] == '.' && p
[2] >= '0' && p
[2] <= '2')
771 && (*p
>= '4' && *p
<= '9');
775 /* Remove zombie process from process list, and retrieve exit status. */
777 wait_subprocess (child
, javac
, true, true, true, false, NULL
);
779 envjavac_gcj43
= false;
784 envjavac_tested
= true;
787 return envjavac_gcj43
;
790 /* Test whether $JAVAC, known to be a version of gcj >= 4.3, can be used, and
791 whether it needs a -fsource and/or -ftarget option.
792 Return a failure indicator (true upon error). */
794 is_envjavac_gcj43_usable (const char *javac
,
795 const char *source_version
,
796 const char *target_version
,
798 bool *fsource_option_p
, bool *ftarget_option_p
)
800 /* The cache depends on the source_version and target_version. */
808 static struct result_t result_cache
[SOURCE_VERSION_BOUND
][TARGET_VERSION_BOUND
];
809 struct result_t
*resultp
;
811 resultp
= &result_cache
[source_version_index (source_version
)]
812 [target_version_index (target_version
)];
813 if (!resultp
->tested
)
816 struct temp_dir
*tmpdir
;
817 char *conftest_file_name
;
818 char *compiled_file_name
;
819 const char *java_sources
[1];
822 tmpdir
= create_temp_dir ("java", NULL
, false);
827 xconcatenated_filename (tmpdir
->dir_name
, "conftest.java", NULL
);
828 if (write_temp_file (tmpdir
, conftest_file_name
,
829 get_goodcode_snippet (source_version
)))
831 free (conftest_file_name
);
832 cleanup_temp_dir (tmpdir
);
837 xconcatenated_filename (tmpdir
->dir_name
, "conftest.class", NULL
);
838 register_temp_file (tmpdir
, compiled_file_name
);
840 java_sources
[0] = conftest_file_name
;
841 if (!compile_using_envjavac (javac
,
842 java_sources
, 1, tmpdir
->dir_name
,
843 false, false, false, true)
844 && stat (compiled_file_name
, &statbuf
) >= 0
845 && get_classfile_version (compiled_file_name
)
846 <= corresponding_classfile_version (target_version
))
848 /* $JAVAC compiled conftest.java successfully. */
849 /* Try adding -fsource option if it is useful. */
851 xasprintf ("%s -fsource=%s", javac
, source_version
);
853 unlink (compiled_file_name
);
855 java_sources
[0] = conftest_file_name
;
856 if (!compile_using_envjavac (javac_source
,
857 java_sources
, 1, tmpdir
->dir_name
,
858 false, false, false, true)
859 && stat (compiled_file_name
, &statbuf
) >= 0
860 && get_classfile_version (compiled_file_name
)
861 <= corresponding_classfile_version (target_version
))
863 const char *failcode
= get_failcode_snippet (source_version
);
865 if (failcode
!= NULL
)
867 free (compiled_file_name
);
868 free (conftest_file_name
);
871 xconcatenated_filename (tmpdir
->dir_name
,
874 if (write_temp_file (tmpdir
, conftest_file_name
, failcode
))
876 free (conftest_file_name
);
878 cleanup_temp_dir (tmpdir
);
883 xconcatenated_filename (tmpdir
->dir_name
,
884 "conftestfail.class",
886 register_temp_file (tmpdir
, compiled_file_name
);
888 java_sources
[0] = conftest_file_name
;
889 if (!compile_using_envjavac (javac
,
892 false, false, false, true)
893 && stat (compiled_file_name
, &statbuf
) >= 0)
895 unlink (compiled_file_name
);
897 java_sources
[0] = conftest_file_name
;
898 if (compile_using_envjavac (javac_source
,
901 false, false, false, true))
902 /* $JAVAC compiled conftestfail.java successfully, and
903 "$JAVAC -fsource=$source_version" rejects it. So
904 the -fsource option is useful. */
905 resultp
->fsource_option
= true;
912 resultp
->usable
= true;
916 /* Try with -fsource and -ftarget options. */
918 xasprintf ("%s -fsource=%s -ftarget=%s",
919 javac
, source_version
, target_version
);
921 unlink (compiled_file_name
);
923 java_sources
[0] = conftest_file_name
;
924 if (!compile_using_envjavac (javac_target
,
925 java_sources
, 1, tmpdir
->dir_name
,
926 false, false, false, true)
927 && stat (compiled_file_name
, &statbuf
) >= 0
928 && get_classfile_version (compiled_file_name
)
929 <= corresponding_classfile_version (target_version
))
931 /* "$JAVAC -fsource $source_version -ftarget $target_version"
932 compiled conftest.java successfully. */
933 resultp
->fsource_option
= true;
934 resultp
->ftarget_option
= true;
935 resultp
->usable
= true;
941 free (compiled_file_name
);
942 free (conftest_file_name
);
944 resultp
->tested
= true;
947 *usablep
= resultp
->usable
;
948 *fsource_option_p
= resultp
->fsource_option
;
949 *ftarget_option_p
= resultp
->ftarget_option
;
953 /* Test whether $JAVAC, known to be a version of gcj < 4.3, can be used for
954 compiling with target_version = 1.4 and source_version = 1.4.
955 Return a failure indicator (true upon error). */
957 is_envjavac_oldgcj_14_14_usable (const char *javac
, bool *usablep
)
959 static bool envjavac_tested
;
960 static bool envjavac_usable
;
962 if (!envjavac_tested
)
965 struct temp_dir
*tmpdir
;
966 char *conftest_file_name
;
967 char *compiled_file_name
;
968 const char *java_sources
[1];
971 tmpdir
= create_temp_dir ("java", NULL
, false);
976 xconcatenated_filename (tmpdir
->dir_name
, "conftest.java", NULL
);
977 if (write_temp_file (tmpdir
, conftest_file_name
,
978 get_goodcode_snippet ("1.4")))
980 free (conftest_file_name
);
981 cleanup_temp_dir (tmpdir
);
986 xconcatenated_filename (tmpdir
->dir_name
, "conftest.class", NULL
);
987 register_temp_file (tmpdir
, compiled_file_name
);
989 java_sources
[0] = conftest_file_name
;
990 if (!compile_using_envjavac (javac
, java_sources
, 1, tmpdir
->dir_name
,
991 false, false, false, true)
992 && stat (compiled_file_name
, &statbuf
) >= 0)
993 /* Compilation succeeded. */
994 envjavac_usable
= true;
996 free (compiled_file_name
);
997 free (conftest_file_name
);
999 cleanup_temp_dir (tmpdir
);
1001 envjavac_tested
= true;
1004 *usablep
= envjavac_usable
;
1008 /* Test whether $JAVAC, known to be a version of gcj < 4.3, can be used for
1009 compiling with target_version = 1.4 and source_version = 1.3.
1010 Return a failure indicator (true upon error). */
1012 is_envjavac_oldgcj_14_13_usable (const char *javac
,
1013 bool *usablep
, bool *need_no_assert_option_p
)
1015 static bool envjavac_tested
;
1016 static bool envjavac_usable
;
1017 static bool envjavac_need_no_assert_option
;
1019 if (!envjavac_tested
)
1021 /* Try $JAVAC and "$JAVAC -fno-assert". But add -fno-assert only if
1022 it makes a difference. (It could already be part of $JAVAC.) */
1023 struct temp_dir
*tmpdir
;
1024 char *conftest_file_name
;
1025 char *compiled_file_name
;
1026 const char *java_sources
[1];
1027 struct stat statbuf
;
1029 char *javac_noassert
;
1030 bool javac_noassert_works
;
1032 tmpdir
= create_temp_dir ("java", NULL
, false);
1036 conftest_file_name
=
1037 xconcatenated_filename (tmpdir
->dir_name
, "conftest.java", NULL
);
1038 if (write_temp_file (tmpdir
, conftest_file_name
,
1039 get_goodcode_snippet ("1.3")))
1041 free (conftest_file_name
);
1042 cleanup_temp_dir (tmpdir
);
1046 compiled_file_name
=
1047 xconcatenated_filename (tmpdir
->dir_name
, "conftest.class", NULL
);
1048 register_temp_file (tmpdir
, compiled_file_name
);
1050 java_sources
[0] = conftest_file_name
;
1051 if (!compile_using_envjavac (javac
,
1052 java_sources
, 1, tmpdir
->dir_name
,
1053 false, false, false, true)
1054 && stat (compiled_file_name
, &statbuf
) >= 0)
1055 /* Compilation succeeded. */
1058 javac_works
= false;
1060 unlink (compiled_file_name
);
1062 javac_noassert
= xasprintf ("%s -fno-assert", javac
);
1064 java_sources
[0] = conftest_file_name
;
1065 if (!compile_using_envjavac (javac_noassert
,
1066 java_sources
, 1, tmpdir
->dir_name
,
1067 false, false, false, true)
1068 && stat (compiled_file_name
, &statbuf
) >= 0)
1069 /* Compilation succeeded. */
1070 javac_noassert_works
= true;
1072 javac_noassert_works
= false;
1074 free (compiled_file_name
);
1075 free (conftest_file_name
);
1077 if (javac_works
&& javac_noassert_works
)
1079 conftest_file_name
=
1080 xconcatenated_filename (tmpdir
->dir_name
, "conftestfail.java",
1082 if (write_temp_file (tmpdir
, conftest_file_name
,
1083 get_failcode_snippet ("1.3")))
1085 free (conftest_file_name
);
1086 free (javac_noassert
);
1087 cleanup_temp_dir (tmpdir
);
1091 compiled_file_name
=
1092 xconcatenated_filename (tmpdir
->dir_name
, "conftestfail.class",
1094 register_temp_file (tmpdir
, compiled_file_name
);
1096 java_sources
[0] = conftest_file_name
;
1097 if (!compile_using_envjavac (javac
,
1098 java_sources
, 1, tmpdir
->dir_name
,
1099 false, false, false, true)
1100 && stat (compiled_file_name
, &statbuf
) >= 0)
1102 /* Compilation succeeded. */
1103 unlink (compiled_file_name
);
1105 java_sources
[0] = conftest_file_name
;
1106 if (!(!compile_using_envjavac (javac_noassert
,
1107 java_sources
, 1, tmpdir
->dir_name
,
1108 false, false, false, true)
1109 && stat (compiled_file_name
, &statbuf
) >= 0))
1110 /* Compilation failed. */
1111 /* "$JAVAC -fno-assert" works better than $JAVAC. */
1115 free (compiled_file_name
);
1116 free (conftest_file_name
);
1119 cleanup_temp_dir (tmpdir
);
1123 envjavac_usable
= true;
1124 envjavac_need_no_assert_option
= false;
1126 else if (javac_noassert_works
)
1128 envjavac_usable
= true;
1129 envjavac_need_no_assert_option
= true;
1132 envjavac_tested
= true;
1135 *usablep
= envjavac_usable
;
1136 *need_no_assert_option_p
= envjavac_need_no_assert_option
;
1140 /* Test whether $JAVAC, known to be not a version of gcj, can be used, and
1141 whether it needs a -source and/or -target option.
1142 Return a failure indicator (true upon error). */
1144 is_envjavac_nongcj_usable (const char *javac
,
1145 const char *source_version
,
1146 const char *source_version_for_javac
,
1147 const char *target_version
,
1149 bool *source_option_p
, bool *target_option_p
)
1151 /* The cache depends on the source_version and target_version. */
1159 static struct result_t result_cache
[SOURCE_VERSION_BOUND
][TARGET_VERSION_BOUND
];
1160 struct result_t
*resultp
;
1162 resultp
= &result_cache
[source_version_index (source_version
)]
1163 [target_version_index (target_version
)];
1164 if (!resultp
->tested
)
1167 struct temp_dir
*tmpdir
;
1168 char *conftest_file_name
;
1169 char *compiled_file_name
;
1170 const char *java_sources
[1];
1171 struct stat statbuf
;
1173 tmpdir
= create_temp_dir ("java", NULL
, false);
1177 conftest_file_name
=
1178 xconcatenated_filename (tmpdir
->dir_name
, "conftest.java", NULL
);
1179 if (write_temp_file (tmpdir
, conftest_file_name
,
1180 get_goodcode_snippet (source_version
)))
1182 free (conftest_file_name
);
1183 cleanup_temp_dir (tmpdir
);
1187 compiled_file_name
=
1188 xconcatenated_filename (tmpdir
->dir_name
, "conftest.class", NULL
);
1189 register_temp_file (tmpdir
, compiled_file_name
);
1191 java_sources
[0] = conftest_file_name
;
1192 if (!compile_using_envjavac (javac
,
1193 java_sources
, 1, tmpdir
->dir_name
,
1194 false, false, false, true)
1195 && stat (compiled_file_name
, &statbuf
) >= 0
1196 && get_classfile_version (compiled_file_name
)
1197 <= corresponding_classfile_version (target_version
))
1199 /* $JAVAC compiled conftest.java successfully. */
1200 /* Try adding -source option if it is useful. */
1201 char *javac_source
=
1202 xasprintf ("%s -source %s", javac
, source_version_for_javac
);
1204 unlink (compiled_file_name
);
1206 java_sources
[0] = conftest_file_name
;
1207 if (!compile_using_envjavac (javac_source
,
1208 java_sources
, 1, tmpdir
->dir_name
,
1209 false, false, false, true)
1210 && stat (compiled_file_name
, &statbuf
) >= 0
1211 && get_classfile_version (compiled_file_name
)
1212 <= corresponding_classfile_version (target_version
))
1214 const char *failcode
= get_failcode_snippet (source_version
);
1216 if (failcode
!= NULL
)
1218 free (compiled_file_name
);
1219 free (conftest_file_name
);
1221 conftest_file_name
=
1222 xconcatenated_filename (tmpdir
->dir_name
,
1223 "conftestfail.java",
1225 if (write_temp_file (tmpdir
, conftest_file_name
, failcode
))
1227 free (conftest_file_name
);
1228 free (javac_source
);
1229 cleanup_temp_dir (tmpdir
);
1233 compiled_file_name
=
1234 xconcatenated_filename (tmpdir
->dir_name
,
1235 "conftestfail.class",
1237 register_temp_file (tmpdir
, compiled_file_name
);
1239 java_sources
[0] = conftest_file_name
;
1240 if (!compile_using_envjavac (javac
,
1243 false, false, false, true)
1244 && stat (compiled_file_name
, &statbuf
) >= 0)
1246 unlink (compiled_file_name
);
1248 java_sources
[0] = conftest_file_name
;
1249 if (compile_using_envjavac (javac_source
,
1252 false, false, false, true))
1253 /* $JAVAC compiled conftestfail.java successfully, and
1254 "$JAVAC -source $source_version_for_javac" rejects it.
1255 So the -source option is useful. */
1256 resultp
->source_option
= true;
1261 free (javac_source
);
1263 resultp
->usable
= true;
1267 /* Try with -target option alone. (Sun javac 1.3.1 has the -target
1268 option but no -source option.) */
1269 char *javac_target
=
1270 xasprintf ("%s -target %s", javac
, target_version
);
1272 unlink (compiled_file_name
);
1274 java_sources
[0] = conftest_file_name
;
1275 if (!compile_using_envjavac (javac_target
,
1276 java_sources
, 1, tmpdir
->dir_name
,
1277 false, false, false, true)
1278 && stat (compiled_file_name
, &statbuf
) >= 0
1279 && get_classfile_version (compiled_file_name
)
1280 <= corresponding_classfile_version (target_version
))
1282 /* "$JAVAC -target $target_version" compiled conftest.java
1284 /* Try adding -source option if it is useful. */
1285 char *javac_target_source
=
1286 xasprintf ("%s -source %s", javac_target
, source_version_for_javac
);
1288 unlink (compiled_file_name
);
1290 java_sources
[0] = conftest_file_name
;
1291 if (!compile_using_envjavac (javac_target_source
,
1292 java_sources
, 1, tmpdir
->dir_name
,
1293 false, false, false, true)
1294 && stat (compiled_file_name
, &statbuf
) >= 0
1295 && get_classfile_version (compiled_file_name
)
1296 <= corresponding_classfile_version (target_version
))
1298 const char *failcode
= get_failcode_snippet (source_version
);
1300 if (failcode
!= NULL
)
1302 free (compiled_file_name
);
1303 free (conftest_file_name
);
1305 conftest_file_name
=
1306 xconcatenated_filename (tmpdir
->dir_name
,
1307 "conftestfail.java",
1309 if (write_temp_file (tmpdir
, conftest_file_name
,
1312 free (conftest_file_name
);
1313 free (javac_target_source
);
1314 free (javac_target
);
1315 cleanup_temp_dir (tmpdir
);
1319 compiled_file_name
=
1320 xconcatenated_filename (tmpdir
->dir_name
,
1321 "conftestfail.class",
1323 register_temp_file (tmpdir
, compiled_file_name
);
1325 java_sources
[0] = conftest_file_name
;
1326 if (!compile_using_envjavac (javac_target
,
1329 false, false, false, true)
1330 && stat (compiled_file_name
, &statbuf
) >= 0)
1332 unlink (compiled_file_name
);
1334 java_sources
[0] = conftest_file_name
;
1335 if (compile_using_envjavac (javac_target_source
,
1338 false, false, false,
1340 /* "$JAVAC -target $target_version" compiled
1341 conftestfail.java successfully, and
1342 "$JAVAC -target $target_version -source $source_version_for_javac"
1343 rejects it. So the -source option is useful. */
1344 resultp
->source_option
= true;
1349 free (javac_target_source
);
1351 resultp
->target_option
= true;
1352 resultp
->usable
= true;
1356 /* Maybe this -target option requires a -source option? Try with
1357 -target and -source options. (Supported by Sun javac 1.4 and
1359 char *javac_target_source
=
1360 xasprintf ("%s -source %s", javac_target
, source_version_for_javac
);
1362 unlink (compiled_file_name
);
1364 java_sources
[0] = conftest_file_name
;
1365 if (!compile_using_envjavac (javac_target_source
,
1366 java_sources
, 1, tmpdir
->dir_name
,
1367 false, false, false, true)
1368 && stat (compiled_file_name
, &statbuf
) >= 0
1369 && get_classfile_version (compiled_file_name
)
1370 <= corresponding_classfile_version (target_version
))
1372 /* "$JAVAC -target $target_version -source $source_version_for_javac"
1373 compiled conftest.java successfully. */
1374 resultp
->source_option
= true;
1375 resultp
->target_option
= true;
1376 resultp
->usable
= true;
1379 free (javac_target_source
);
1382 free (javac_target
);
1385 free (compiled_file_name
);
1386 free (conftest_file_name
);
1388 resultp
->tested
= true;
1391 *usablep
= resultp
->usable
;
1392 *source_option_p
= resultp
->source_option
;
1393 *target_option_p
= resultp
->target_option
;
1398 is_gcj_present (void)
1400 static bool gcj_tested
;
1401 static bool gcj_present
;
1405 /* Test for presence of gcj:
1406 "gcj --version 2> /dev/null | \
1407 sed -e 's,^[^0-9]*,,' -e 1q | \
1408 sed -e '/^3\.[01]/d' | grep '^[3-9]' > /dev/null" */
1415 argv
[1] = "--version";
1417 child
= create_pipe_in ("gcj", "gcj", argv
, NULL
,
1418 DEV_NULL
, true, true, false, fd
);
1419 gcj_present
= false;
1422 /* Read the subprocess output, drop all lines except the first,
1423 drop all characters before the first digit, and test whether
1424 the remaining string starts with a digit >= 3, but not with
1429 while (safe_read (fd
[0], &c
[count
], 1) > 0)
1431 if (c
[count
] == '\n')
1435 if (!(c
[0] >= '0' && c
[0] <= '9'))
1437 gcj_present
= (c
[0] >= '3');
1442 if (c
[0] == '3' && c
[1] == '.'
1443 && (c
[2] == '0' || c
[2] == '1'))
1444 gcj_present
= false;
1448 while (safe_read (fd
[0], &c
[0], 1) > 0)
1453 /* Remove zombie process from process list, and retrieve exit
1456 wait_subprocess (child
, "gcj", false, true, true, false, NULL
);
1457 if (exitstatus
!= 0)
1458 gcj_present
= false;
1463 /* See if libgcj.jar is well installed. */
1464 struct temp_dir
*tmpdir
;
1466 tmpdir
= create_temp_dir ("java", NULL
, false);
1468 gcj_present
= false;
1471 char *conftest_file_name
;
1473 conftest_file_name
=
1474 xconcatenated_filename (tmpdir
->dir_name
, "conftestlib.java",
1476 if (write_temp_file (tmpdir
, conftest_file_name
,
1477 "public class conftestlib {\n"
1478 " public static void main (String[] args) {\n"
1481 gcj_present
= false;
1484 char *compiled_file_name
;
1485 const char *java_sources
[1];
1487 compiled_file_name
=
1488 xconcatenated_filename (tmpdir
->dir_name
,
1489 "conftestlib.class",
1491 register_temp_file (tmpdir
, compiled_file_name
);
1493 java_sources
[0] = conftest_file_name
;
1494 if (compile_using_gcj (java_sources
, 1, false,
1495 false, NULL
, false, NULL
,
1497 false, false, false, true))
1498 gcj_present
= false;
1500 free (compiled_file_name
);
1502 free (conftest_file_name
);
1504 cleanup_temp_dir (tmpdir
);
1516 static bool gcj_tested
;
1521 /* Test for presence of gcj:
1522 "gcj --version 2> /dev/null | \
1523 sed -e 's,^[^0-9]*,,' -e 1q | \
1524 sed -e '/^4\.[012]/d' | grep '^[4-9]'" */
1531 argv
[1] = "--version";
1533 child
= create_pipe_in ("gcj", "gcj", argv
, NULL
,
1534 DEV_NULL
, true, true, false, fd
);
1538 /* Read the subprocess output, drop all lines except the first,
1539 drop all characters before the first digit, and test whether
1540 the remaining string starts with a digit >= 4, but not with
1541 "4.0" or "4.1" or "4.2". */
1545 while (safe_read (fd
[0], &c
[count
], 1) > 0)
1547 if (c
[count
] == '\n')
1551 if (!(c
[0] >= '0' && c
[0] <= '9'))
1553 gcj_43
= (c
[0] >= '4');
1558 if (c
[0] == '4' && c
[1] == '.' && c
[2] >= '0' && c
[2] <= '2')
1563 while (safe_read (fd
[0], &c
[0], 1) > 0)
1568 /* Remove zombie process from process list, and retrieve exit
1571 wait_subprocess (child
, "gcj", false, true, true, false, NULL
);
1572 if (exitstatus
!= 0)
1582 /* Test whether gcj >= 4.3 can be used, and whether it needs a -fsource and/or
1584 Return a failure indicator (true upon error). */
1586 is_gcj43_usable (const char *source_version
,
1587 const char *target_version
,
1589 bool *fsource_option_p
, bool *ftarget_option_p
)
1591 /* The cache depends on the source_version and target_version. */
1596 bool fsource_option
;
1597 bool ftarget_option
;
1599 static struct result_t result_cache
[SOURCE_VERSION_BOUND
][TARGET_VERSION_BOUND
];
1600 struct result_t
*resultp
;
1602 resultp
= &result_cache
[source_version_index (source_version
)]
1603 [target_version_index (target_version
)];
1604 if (!resultp
->tested
)
1607 struct temp_dir
*tmpdir
;
1608 char *conftest_file_name
;
1609 char *compiled_file_name
;
1610 const char *java_sources
[1];
1611 struct stat statbuf
;
1613 tmpdir
= create_temp_dir ("java", NULL
, false);
1617 conftest_file_name
=
1618 xconcatenated_filename (tmpdir
->dir_name
, "conftest.java", NULL
);
1619 if (write_temp_file (tmpdir
, conftest_file_name
,
1620 get_goodcode_snippet (source_version
)))
1622 free (conftest_file_name
);
1623 cleanup_temp_dir (tmpdir
);
1627 compiled_file_name
=
1628 xconcatenated_filename (tmpdir
->dir_name
, "conftest.class", NULL
);
1629 register_temp_file (tmpdir
, compiled_file_name
);
1631 java_sources
[0] = conftest_file_name
;
1632 if (!compile_using_gcj (java_sources
, 1, false, false, NULL
, false, NULL
,
1633 tmpdir
->dir_name
, false, false, false, true)
1634 && stat (compiled_file_name
, &statbuf
) >= 0
1635 && get_classfile_version (compiled_file_name
)
1636 <= corresponding_classfile_version (target_version
))
1638 /* gcj compiled conftest.java successfully. */
1639 /* Try adding -fsource option if it is useful. */
1640 unlink (compiled_file_name
);
1642 java_sources
[0] = conftest_file_name
;
1643 if (!compile_using_gcj (java_sources
, 1,
1644 false, true, source_version
, false, NULL
,
1645 tmpdir
->dir_name
, false, false, false, true)
1646 && stat (compiled_file_name
, &statbuf
) >= 0
1647 && get_classfile_version (compiled_file_name
)
1648 <= corresponding_classfile_version (target_version
))
1650 const char *failcode
= get_failcode_snippet (source_version
);
1652 if (failcode
!= NULL
)
1654 free (compiled_file_name
);
1655 free (conftest_file_name
);
1657 conftest_file_name
=
1658 xconcatenated_filename (tmpdir
->dir_name
,
1659 "conftestfail.java",
1661 if (write_temp_file (tmpdir
, conftest_file_name
, failcode
))
1663 free (conftest_file_name
);
1664 cleanup_temp_dir (tmpdir
);
1668 compiled_file_name
=
1669 xconcatenated_filename (tmpdir
->dir_name
,
1670 "conftestfail.class",
1672 register_temp_file (tmpdir
, compiled_file_name
);
1674 java_sources
[0] = conftest_file_name
;
1675 if (!compile_using_gcj (java_sources
, 1,
1676 false, false, NULL
, false, NULL
,
1678 false, false, false, true)
1679 && stat (compiled_file_name
, &statbuf
) >= 0)
1681 unlink (compiled_file_name
);
1683 java_sources
[0] = conftest_file_name
;
1684 if (compile_using_gcj (java_sources
, 1,
1685 false, true, source_version
,
1688 false, false, false, true))
1689 /* gcj compiled conftestfail.java successfully, and
1690 "gcj -fsource=$source_version" rejects it. So
1691 the -fsource option is useful. */
1692 resultp
->fsource_option
= true;
1697 resultp
->usable
= true;
1701 /* Try with -fsource and -ftarget options. */
1702 unlink (compiled_file_name
);
1704 java_sources
[0] = conftest_file_name
;
1705 if (!compile_using_gcj (java_sources
, 1,
1706 false, true, source_version
,
1707 true, target_version
,
1709 false, false, false, true)
1710 && stat (compiled_file_name
, &statbuf
) >= 0
1711 && get_classfile_version (compiled_file_name
)
1712 <= corresponding_classfile_version (target_version
))
1714 /* "gcj -fsource $source_version -ftarget $target_version"
1715 compiled conftest.java successfully. */
1716 resultp
->fsource_option
= true;
1717 resultp
->ftarget_option
= true;
1718 resultp
->usable
= true;
1722 free (compiled_file_name
);
1723 free (conftest_file_name
);
1725 resultp
->tested
= true;
1728 *usablep
= resultp
->usable
;
1729 *fsource_option_p
= resultp
->fsource_option
;
1730 *ftarget_option_p
= resultp
->ftarget_option
;
1734 /* Test whether gcj < 4.3 can be used for compiling with target_version = 1.4
1735 and source_version = 1.4.
1736 Return a failure indicator (true upon error). */
1738 is_oldgcj_14_14_usable (bool *usablep
)
1740 static bool gcj_tested
;
1741 static bool gcj_usable
;
1746 struct temp_dir
*tmpdir
;
1747 char *conftest_file_name
;
1748 char *compiled_file_name
;
1749 const char *java_sources
[1];
1750 struct stat statbuf
;
1752 tmpdir
= create_temp_dir ("java", NULL
, false);
1756 conftest_file_name
=
1757 xconcatenated_filename (tmpdir
->dir_name
, "conftest.java", NULL
);
1758 if (write_temp_file (tmpdir
, conftest_file_name
,
1759 get_goodcode_snippet ("1.4")))
1761 free (conftest_file_name
);
1762 cleanup_temp_dir (tmpdir
);
1766 compiled_file_name
=
1767 xconcatenated_filename (tmpdir
->dir_name
, "conftest.class", NULL
);
1768 register_temp_file (tmpdir
, compiled_file_name
);
1770 java_sources
[0] = conftest_file_name
;
1771 if (!compile_using_gcj (java_sources
, 1, false, false, NULL
, false, NULL
,
1772 tmpdir
->dir_name
, false, false, false, true)
1773 && stat (compiled_file_name
, &statbuf
) >= 0)
1774 /* Compilation succeeded. */
1777 free (compiled_file_name
);
1778 free (conftest_file_name
);
1780 cleanup_temp_dir (tmpdir
);
1785 *usablep
= gcj_usable
;
1789 /* Test whether gcj < 4.3 can be used for compiling with target_version = 1.4
1790 and source_version = 1.3.
1791 Return a failure indicator (true upon error). */
1793 is_oldgcj_14_13_usable (bool *usablep
, bool *need_no_assert_option_p
)
1795 static bool gcj_tested
;
1796 static bool gcj_usable
;
1797 static bool gcj_need_no_assert_option
;
1801 /* Try gcj and "gcj -fno-assert". But add -fno-assert only if
1802 it works (not gcj < 3.3). */
1803 struct temp_dir
*tmpdir
;
1804 char *conftest_file_name
;
1805 char *compiled_file_name
;
1806 const char *java_sources
[1];
1807 struct stat statbuf
;
1809 tmpdir
= create_temp_dir ("java", NULL
, false);
1813 conftest_file_name
=
1814 xconcatenated_filename (tmpdir
->dir_name
, "conftest.java", NULL
);
1815 if (write_temp_file (tmpdir
, conftest_file_name
,
1816 get_goodcode_snippet ("1.3")))
1818 free (conftest_file_name
);
1819 cleanup_temp_dir (tmpdir
);
1823 compiled_file_name
=
1824 xconcatenated_filename (tmpdir
->dir_name
, "conftest.class", NULL
);
1825 register_temp_file (tmpdir
, compiled_file_name
);
1827 java_sources
[0] = conftest_file_name
;
1828 if (!compile_using_gcj (java_sources
, 1, true, false, NULL
, false, NULL
,
1829 tmpdir
->dir_name
, false, false, false, true)
1830 && stat (compiled_file_name
, &statbuf
) >= 0)
1831 /* Compilation succeeded. */
1834 gcj_need_no_assert_option
= true;
1838 unlink (compiled_file_name
);
1840 java_sources
[0] = conftest_file_name
;
1841 if (!compile_using_gcj (java_sources
, 1, false,
1842 false, NULL
, false, NULL
,
1843 tmpdir
->dir_name
, false, false, false, true)
1844 && stat (compiled_file_name
, &statbuf
) >= 0)
1845 /* Compilation succeeded. */
1848 gcj_need_no_assert_option
= false;
1852 free (compiled_file_name
);
1853 free (conftest_file_name
);
1855 cleanup_temp_dir (tmpdir
);
1860 *usablep
= gcj_usable
;
1861 *need_no_assert_option_p
= gcj_need_no_assert_option
;
1866 is_javac_present (void)
1868 static bool javac_tested
;
1869 static bool javac_present
;
1873 /* Test for presence of javac: "javac 2> /dev/null ; test $? -le 2" */
1879 exitstatus
= execute ("javac", "javac", argv
, NULL
,
1880 false, false, true, true,
1882 javac_present
= (exitstatus
== 0 || exitstatus
== 1 || exitstatus
== 2);
1883 javac_tested
= true;
1886 return javac_present
;
1889 /* Test whether javac can be used and whether it needs a -source and/or
1891 Return a failure indicator (true upon error). */
1893 is_javac_usable (const char *source_version
,
1894 const char *source_version_for_javac
,
1895 const char *target_version
,
1896 bool *usablep
, bool *source_option_p
, bool *target_option_p
)
1898 /* The cache depends on the source_version and target_version. */
1906 static struct result_t result_cache
[SOURCE_VERSION_BOUND
][TARGET_VERSION_BOUND
];
1907 struct result_t
*resultp
;
1909 resultp
= &result_cache
[source_version_index (source_version
)]
1910 [target_version_index (target_version
)];
1911 if (!resultp
->tested
)
1914 struct temp_dir
*tmpdir
;
1915 char *conftest_file_name
;
1916 char *compiled_file_name
;
1917 const char *java_sources
[1];
1918 struct stat statbuf
;
1920 tmpdir
= create_temp_dir ("java", NULL
, false);
1924 conftest_file_name
=
1925 xconcatenated_filename (tmpdir
->dir_name
, "conftest.java", NULL
);
1926 if (write_temp_file (tmpdir
, conftest_file_name
,
1927 get_goodcode_snippet (source_version
)))
1929 free (conftest_file_name
);
1930 cleanup_temp_dir (tmpdir
);
1934 compiled_file_name
=
1935 xconcatenated_filename (tmpdir
->dir_name
, "conftest.class", NULL
);
1936 register_temp_file (tmpdir
, compiled_file_name
);
1938 java_sources
[0] = conftest_file_name
;
1939 if (!compile_using_javac (java_sources
, 1,
1940 false, source_version_for_javac
,
1941 false, target_version
,
1942 tmpdir
->dir_name
, false, false, false, true)
1943 && stat (compiled_file_name
, &statbuf
) >= 0
1944 && get_classfile_version (compiled_file_name
)
1945 <= corresponding_classfile_version (target_version
))
1947 /* javac compiled conftest.java successfully. */
1948 /* Try adding -source option if it is useful. */
1949 unlink (compiled_file_name
);
1951 java_sources
[0] = conftest_file_name
;
1952 if (!compile_using_javac (java_sources
, 1,
1953 true, source_version_for_javac
,
1954 false, target_version
,
1955 tmpdir
->dir_name
, false, false, false, true)
1956 && stat (compiled_file_name
, &statbuf
) >= 0
1957 && get_classfile_version (compiled_file_name
)
1958 <= corresponding_classfile_version (target_version
))
1960 const char *failcode
= get_failcode_snippet (source_version
);
1962 if (failcode
!= NULL
)
1964 free (compiled_file_name
);
1965 free (conftest_file_name
);
1967 conftest_file_name
=
1968 xconcatenated_filename (tmpdir
->dir_name
,
1969 "conftestfail.java",
1971 if (write_temp_file (tmpdir
, conftest_file_name
, failcode
))
1973 free (conftest_file_name
);
1974 cleanup_temp_dir (tmpdir
);
1978 compiled_file_name
=
1979 xconcatenated_filename (tmpdir
->dir_name
,
1980 "conftestfail.class",
1982 register_temp_file (tmpdir
, compiled_file_name
);
1984 java_sources
[0] = conftest_file_name
;
1985 if (!compile_using_javac (java_sources
, 1,
1986 false, source_version_for_javac
,
1987 false, target_version
,
1989 false, false, false, true)
1990 && stat (compiled_file_name
, &statbuf
) >= 0)
1992 unlink (compiled_file_name
);
1994 java_sources
[0] = conftest_file_name
;
1995 if (compile_using_javac (java_sources
, 1,
1996 true, source_version_for_javac
,
1997 false, target_version
,
1999 false, false, false, true))
2000 /* javac compiled conftestfail.java successfully, and
2001 "javac -source $source_version_for_javac" rejects it.
2002 So the -source option is useful. */
2003 resultp
->source_option
= true;
2008 resultp
->usable
= true;
2012 /* Try with -target option alone. (Sun javac 1.3.1 has the -target
2013 option but no -source option.) */
2014 unlink (compiled_file_name
);
2016 java_sources
[0] = conftest_file_name
;
2017 if (!compile_using_javac (java_sources
, 1,
2018 false, source_version_for_javac
,
2019 true, target_version
,
2021 false, false, false, true)
2022 && stat (compiled_file_name
, &statbuf
) >= 0
2023 && get_classfile_version (compiled_file_name
)
2024 <= corresponding_classfile_version (target_version
))
2026 /* "javac -target $target_version" compiled conftest.java
2028 /* Try adding -source option if it is useful. */
2029 unlink (compiled_file_name
);
2031 java_sources
[0] = conftest_file_name
;
2032 if (!compile_using_javac (java_sources
, 1,
2033 true, source_version_for_javac
,
2034 true, target_version
,
2036 false, false, false, true)
2037 && stat (compiled_file_name
, &statbuf
) >= 0
2038 && get_classfile_version (compiled_file_name
)
2039 <= corresponding_classfile_version (target_version
))
2041 const char *failcode
= get_failcode_snippet (source_version
);
2043 if (failcode
!= NULL
)
2045 free (compiled_file_name
);
2046 free (conftest_file_name
);
2048 conftest_file_name
=
2049 xconcatenated_filename (tmpdir
->dir_name
,
2050 "conftestfail.java",
2052 if (write_temp_file (tmpdir
, conftest_file_name
,
2055 free (conftest_file_name
);
2056 cleanup_temp_dir (tmpdir
);
2060 compiled_file_name
=
2061 xconcatenated_filename (tmpdir
->dir_name
,
2062 "conftestfail.class",
2064 register_temp_file (tmpdir
, compiled_file_name
);
2066 java_sources
[0] = conftest_file_name
;
2067 if (!compile_using_javac (java_sources
, 1,
2068 false, source_version_for_javac
,
2069 true, target_version
,
2071 false, false, false, true)
2072 && stat (compiled_file_name
, &statbuf
) >= 0)
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 /* "javac -target $target_version" compiled
2083 conftestfail.java successfully, and
2084 "javac -target $target_version -source $source_version_for_javac"
2085 rejects it. So the -source option is useful. */
2086 resultp
->source_option
= true;
2091 resultp
->target_option
= true;
2092 resultp
->usable
= true;
2096 /* Maybe this -target option requires a -source option? Try with
2097 -target and -source options. (Supported by Sun javac 1.4 and
2099 unlink (compiled_file_name
);
2101 java_sources
[0] = conftest_file_name
;
2102 if (!compile_using_javac (java_sources
, 1,
2103 true, source_version_for_javac
,
2104 true, target_version
,
2106 false, false, false, true)
2107 && stat (compiled_file_name
, &statbuf
) >= 0
2108 && get_classfile_version (compiled_file_name
)
2109 <= corresponding_classfile_version (target_version
))
2111 /* "javac -target $target_version -source $source_version_for_javac"
2112 compiled conftest.java successfully. */
2113 resultp
->source_option
= true;
2114 resultp
->target_option
= true;
2115 resultp
->usable
= true;
2120 free (compiled_file_name
);
2121 free (conftest_file_name
);
2123 resultp
->tested
= true;
2126 *usablep
= resultp
->usable
;
2127 *source_option_p
= resultp
->source_option
;
2128 *target_option_p
= resultp
->target_option
;
2133 is_jikes_present (void)
2135 static bool jikes_tested
;
2136 static bool jikes_present
;
2140 /* Test for presence of jikes: "jikes 2> /dev/null ; test $? = 1" */
2146 exitstatus
= execute ("jikes", "jikes", argv
, NULL
,
2147 false, false, true, true,
2149 jikes_present
= (exitstatus
== 0 || exitstatus
== 1);
2150 jikes_tested
= true;
2153 return jikes_present
;
2156 /* ============================= Main function ============================= */
2159 compile_java_class (const char * const *java_sources
,
2160 unsigned int java_sources_count
,
2161 const char * const *classpaths
,
2162 unsigned int classpaths_count
,
2163 const char *source_version
,
2164 const char *target_version
,
2165 const char *directory
,
2166 bool optimize
, bool debug
,
2167 bool use_minimal_classpath
,
2171 char *old_JAVA_HOME
;
2174 const char *javac
= getenv ("JAVAC");
2175 if (javac
!= NULL
&& javac
[0] != '\0')
2177 bool usable
= false;
2178 bool no_assert_option
= false;
2179 bool source_option
= false;
2180 bool target_option
= false;
2181 bool fsource_option
= false;
2182 bool ftarget_option
= false;
2183 const char *source_version_for_javac
;
2185 if (target_version
== NULL
)
2186 target_version
= default_target_version ();
2188 source_version_for_javac
=
2189 get_source_version_for_javac (source_version
, target_version
);
2191 if (is_envjavac_gcj (javac
))
2193 /* It's a version of gcj. */
2194 if (is_envjavac_gcj43 (javac
))
2196 /* It's a version of gcj >= 4.3. Assume the classfile versions
2198 if (is_envjavac_gcj43_usable (javac
,
2199 source_version
, target_version
,
2201 &fsource_option
, &ftarget_option
))
2209 /* It's a version of gcj < 4.3. Ignore the version of the
2210 class files that it creates. */
2211 if (strcmp (target_version
, "1.4") == 0
2212 && strcmp (source_version
, "1.4") == 0)
2214 if (is_envjavac_oldgcj_14_14_usable (javac
, &usable
))
2220 else if (strcmp (target_version
, "1.4") == 0
2221 && strcmp (source_version
, "1.3") == 0)
2223 if (is_envjavac_oldgcj_14_13_usable (javac
,
2235 /* It's not gcj. Assume the classfile versions are correct. */
2236 if (is_envjavac_nongcj_usable (javac
,
2238 source_version_for_javac
,
2241 &source_option
, &target_option
))
2250 char *old_classpath
;
2251 char *javac_with_options
;
2253 /* Set CLASSPATH. */
2255 set_classpath (classpaths
, classpaths_count
, false, verbose
);
2257 javac_with_options
=
2259 ? xasprintf ("%s -fno-assert", javac
)
2260 : xasprintf ("%s%s%s%s%s%s%s%s%s",
2262 source_option
? " -source " : "",
2263 source_option
? source_version_for_javac
: "",
2264 target_option
? " -target " : "",
2265 target_option
? target_version
: "",
2266 fsource_option
? " -fsource=" : "",
2267 fsource_option
? source_version
: "",
2268 ftarget_option
? " -ftarget=" : "",
2269 ftarget_option
? target_version
: ""));
2271 err
= compile_using_envjavac (javac_with_options
,
2272 java_sources
, java_sources_count
,
2273 directory
, optimize
, debug
, verbose
,
2276 free (javac_with_options
);
2278 /* Reset CLASSPATH. */
2279 reset_classpath (old_classpath
);
2286 /* Unset the JAVA_HOME environment variable. */
2287 old_JAVA_HOME
= getenv ("JAVA_HOME");
2288 if (old_JAVA_HOME
!= NULL
)
2290 old_JAVA_HOME
= xstrdup (old_JAVA_HOME
);
2291 unsetenv ("JAVA_HOME");
2294 if (is_gcj_present ())
2296 /* It's a version of gcj. */
2297 bool usable
= false;
2298 bool no_assert_option
= false;
2299 bool fsource_option
= false;
2300 bool ftarget_option
= false;
2302 if (target_version
== NULL
)
2303 target_version
= default_target_version ();
2307 /* It's a version of gcj >= 4.3. Assume the classfile versions
2309 if (is_gcj43_usable (source_version
, target_version
,
2310 &usable
, &fsource_option
, &ftarget_option
))
2318 /* It's a version of gcj < 4.3. Ignore the version of the class
2319 files that it creates.
2320 Test whether it supports the desired target-version and
2322 if (strcmp (target_version
, "1.4") == 0
2323 && strcmp (source_version
, "1.4") == 0)
2325 if (is_oldgcj_14_14_usable (&usable
))
2331 else if (strcmp (target_version
, "1.4") == 0
2332 && strcmp (source_version
, "1.3") == 0)
2334 if (is_oldgcj_14_13_usable (&usable
, &no_assert_option
))
2344 char *old_classpath
;
2346 /* Set CLASSPATH. We could also use the --CLASSPATH=... option
2347 of gcj. Note that --classpath=... option is different: its
2348 argument should also contain gcj's libgcj.jar, but we don't
2349 know its location. */
2351 set_classpath (classpaths
, classpaths_count
, use_minimal_classpath
,
2354 err
= compile_using_gcj (java_sources
, java_sources_count
,
2356 fsource_option
, source_version
,
2357 ftarget_option
, target_version
,
2358 directory
, optimize
, debug
, verbose
, false);
2360 /* Reset CLASSPATH. */
2361 reset_classpath (old_classpath
);
2367 if (is_javac_present ())
2369 bool usable
= false;
2370 bool source_option
= false;
2371 bool target_option
= false;
2372 const char *source_version_for_javac
;
2374 if (target_version
== NULL
)
2375 target_version
= default_target_version ();
2377 source_version_for_javac
=
2378 get_source_version_for_javac (source_version
, target_version
);
2380 if (is_javac_usable (source_version
, source_version_for_javac
,
2382 &usable
, &source_option
, &target_option
))
2390 char *old_classpath
;
2392 /* Set CLASSPATH. We don't use the "-classpath ..." option because
2393 in JDK 1.1.x its argument should also contain the JDK's
2394 classes.zip, but we don't know its location. (In JDK 1.3.0 it
2397 set_classpath (classpaths
, classpaths_count
, use_minimal_classpath
,
2400 err
= compile_using_javac (java_sources
, java_sources_count
,
2401 source_option
, source_version_for_javac
,
2402 target_option
, target_version
,
2403 directory
, optimize
, debug
, verbose
,
2406 /* Reset CLASSPATH. */
2407 reset_classpath (old_classpath
);
2413 if (is_jikes_present ())
2415 /* Test whether it supports the desired target-version and
2417 bool usable
= (strcmp (source_version
, "1.3") == 0);
2421 char *old_classpath
;
2423 /* Set CLASSPATH. We could also use the "-classpath ..." option.
2424 Since jikes doesn't come with its own standard library, it
2425 needs a classes.zip or rt.jar or libgcj.jar in the CLASSPATH.
2426 To increase the chance of success, we reuse the current CLASSPATH
2427 if the user has set it. */
2429 set_classpath (classpaths
, classpaths_count
, false, verbose
);
2431 err
= compile_using_jikes (java_sources
, java_sources_count
,
2432 directory
, optimize
, debug
, verbose
,
2435 /* Reset CLASSPATH. */
2436 reset_classpath (old_classpath
);
2442 error (0, 0, _("Java compiler not found, try installing gcj or set $JAVAC"));
2446 if (old_JAVA_HOME
!= NULL
)
2448 xsetenv ("JAVA_HOME", old_JAVA_HOME
, 1);
2449 free (old_JAVA_HOME
);