1/* Compile a Java program. 2 Copyright (C) 2001-2003, 2006-2007 Free Software Foundation, Inc. 3 Written by Bruno Haible <haible@clisp.cons.org>, 2001. 4 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. 9 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. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 18#include <config.h> 19#include <alloca.h> 20 21/* Specification. */ 22#include "javacomp.h" 23 24#include <errno.h> 25#include <limits.h> 26#include <stdio.h> 27#include <stdlib.h> 28#include <string.h> 29#include <unistd.h> 30#include <sys/types.h> 31#include <sys/stat.h> 32 33#include "javaversion.h" 34#include "execute.h" 35#include "pipe.h" 36#include "wait-process.h" 37#include "classpath.h" 38#include "xsetenv.h" 39#include "sh-quote.h" 40#include "binary-io.h" 41#include "safe-read.h" 42#include "xalloc.h" 43#include "xmalloca.h" 44#include "filename.h" 45#include "fwriteerror.h" 46#include "clean-temp.h" 47#include "error.h" 48#include "xvasprintf.h" 49#include "c-strstr.h" 50#include "gettext.h" 51 52#define _(str) gettext (str) 53 54/* The results of open() in this file are not used with fchdir, 55 therefore save some unnecessary work in fchdir.c. */ 56#undef open 57#undef close 58 59 60/* Survey of Java compilers. 61 62 A = does it work without CLASSPATH being set 63 C = option to set CLASSPATH, other than setting it in the environment 64 O = option for optimizing 65 g = option for debugging 66 T = test for presence 67 68 Program from A C O g T 69 70 $JAVAC unknown N n/a -O -g true 71 gcj -C GCC 3.2 Y --classpath=P -O -g gcj --version | sed -e 's,^[^0-9]*,,' -e 1q | sed -e '/^3\.[01]/d' | grep '^[3-9]' >/dev/null 72 javac JDK 1.1.8 Y -classpath P -O -g javac 2>/dev/null; test $? = 1 73 javac JDK 1.3.0 Y -classpath P -O -g javac 2>/dev/null; test $? -le 2 74 jikes Jikes 1.14 N -classpath P -O -g jikes 2>/dev/null; test $? = 1 75 76 All compilers support the option "-d DIRECTORY" for the base directory 77 of the classes to be written. 78 79 The CLASSPATH is a colon separated list of pathnames. (On Windows: a 80 semicolon separated list of pathnames.) 81 82 We try the Java compilers in the following order: 83 1. getenv ("JAVAC"), because the user must be able to override our 84 preferences, 85 2. "gcj -C", because it is a completely free compiler, 86 3. "javac", because it is a standard compiler, 87 4. "jikes", comes last because it has some deviating interpretation 88 of the Java Language Specification and because it requires a 89 CLASSPATH environment variable. 90 91 We unset the JAVA_HOME environment variable, because a wrong setting of 92 this variable can confuse the JDK's javac. 93 */ 94 95/* Return the default target_version. */ 96static const char * 97default_target_version (void) 98{ 99 /* Use a cache. Assumes that the PATH environment variable doesn't change 100 during the lifetime of the program. */ 101 static const char *java_version_cache; 102 if (java_version_cache == NULL) 103 { 104 /* Determine the version from the found JVM. */ 105 java_version_cache = javaexec_version (); 106 if (java_version_cache == NULL 107 || !(java_version_cache[0] == '1' && java_version_cache[1] == '.' 108 && (java_version_cache[2] >= '1' && java_version_cache[2] <= '6') 109 && java_version_cache[3] == '\0')) 110 java_version_cache = "1.1"; 111 } 112 return java_version_cache; 113} 114 115/* ======================= Source version dependent ======================= */ 116 117/* Convert a source version to an index. */ 118#define SOURCE_VERSION_BOUND 3 /* exclusive upper bound */ 119static unsigned int 120source_version_index (const char *source_version) 121{ 122 if (source_version[0] == '1' && source_version[1] == '.' 123 && (source_version[2] >= '3' && source_version[2] <= '5') 124 && source_version[3] == '\0') 125 return source_version[2] - '3'; 126 error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class")); 127 return 0; 128} 129 130/* Return a snippet of code that should compile in the given source version. */ 131static const char * 132get_goodcode_snippet (const char *source_version) 133{ 134 if (strcmp (source_version, "1.3") == 0) 135 return "class conftest {}\n"; 136 if (strcmp (source_version, "1.4") == 0) 137 return "class conftest { static { assert(true); } }\n"; 138 if (strcmp (source_version, "1.5") == 0) 139 return "class conftest<T> { T foo() { return null; } }\n"; 140 error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class")); 141 return NULL; 142} 143 144/* Return a snippet of code that should fail to compile in the given source 145 version, or NULL (standing for a snippet that would fail to compile with 146 any compiler). */ 147static const char * 148get_failcode_snippet (const char *source_version) 149{ 150 if (strcmp (source_version, "1.3") == 0) 151 return "class conftestfail { static { assert(true); } }\n"; 152 if (strcmp (source_version, "1.4") == 0) 153 return "class conftestfail<T> { T foo() { return null; } }\n"; 154 if (strcmp (source_version, "1.5") == 0) 155 return NULL; 156 error (EXIT_FAILURE, 0, _("invalid source_version argument to compile_java_class")); 157 return NULL; 158} 159 160/* ======================= Target version dependent ======================= */ 161 162/* Convert a target version to an index. */ 163#define TARGET_VERSION_BOUND 6 /* exclusive upper bound */ 164static unsigned int 165target_version_index (const char *target_version) 166{ 167 if (target_version[0] == '1' && target_version[1] == '.' 168 && (target_version[2] >= '1' && target_version[2] <= '6') 169 && target_version[3] == '\0') 170 return target_version[2] - '1'; 171 error (EXIT_FAILURE, 0, _("invalid target_version argument to compile_java_class")); 172 return 0; 173} 174 175/* Return the class file version number corresponding to a given target 176 version. */ 177static int 178corresponding_classfile_version (const char *target_version) 179{ 180 if (strcmp (target_version, "1.1") == 0) 181 return 45; 182 if (strcmp (target_version, "1.2") == 0) 183 return 46; 184 if (strcmp (target_version, "1.3") == 0) 185 return 47; 186 if (strcmp (target_version, "1.4") == 0) 187 return 48; 188 if (strcmp (target_version, "1.5") == 0) 189 return 49; 190 if (strcmp (target_version, "1.6") == 0) 191 return 50; 192 error (EXIT_FAILURE, 0, _("invalid target_version argument to compile_java_class")); 193 return 0; 194} 195 196/* ======================== Compilation subroutines ======================== */ 197 198/* Try to compile a set of Java sources with $JAVAC. 199 Return a failure indicator (true upon error). */ 200static bool 201compile_using_envjavac (const char *javac, 202 const char * const *java_sources, 203 unsigned int java_sources_count, 204 const char *directory, 205 bool optimize, bool debug, 206 bool verbose, bool null_stderr) 207{ 208 /* Because $JAVAC may consist of a command and options, we use the 209 shell. Because $JAVAC has been set by the user, we leave all 210 environment variables in place, including JAVA_HOME, and we don't 211 erase the user's CLASSPATH. */ 212 bool err; 213 unsigned int command_length; 214 char *command; 215 char *argv[4]; 216 int exitstatus; 217 unsigned int i; 218 char *p; 219 220 command_length = strlen (javac); 221 if (optimize) 222 command_length += 3; 223 if (debug) 224 command_length += 3; 225 if (directory != NULL) 226 command_length += 4 + shell_quote_length (directory); 227 for (i = 0; i < java_sources_count; i++) 228 command_length += 1 + shell_quote_length (java_sources[i]); 229 command_length += 1; 230 231 command = (char *) xmalloca (command_length); 232 p = command; 233 /* Don't shell_quote $JAVAC, because it may consist of a command 234 and options. */ 235 memcpy (p, javac, strlen (javac)); 236 p += strlen (javac); 237 if (optimize) 238 { 239 memcpy (p, " -O", 3); 240 p += 3; 241 } 242 if (debug) 243 { 244 memcpy (p, " -g", 3); 245 p += 3; 246 } 247 if (directory != NULL) 248 { 249 memcpy (p, " -d ", 4); 250 p += 4; 251 p = shell_quote_copy (p, directory); 252 } 253 for (i = 0; i < java_sources_count; i++) 254 { 255 *p++ = ' '; 256 p = shell_quote_copy (p, java_sources[i]); 257 } 258 *p++ = '\0'; 259 /* Ensure command_length was correctly calculated. */ 260 if (p - command > command_length) 261 abort (); 262 263 if (verbose) 264 printf ("%s\n", command); 265 266 argv[0] = "/bin/sh"; 267 argv[1] = "-c"; 268 argv[2] = command; 269 argv[3] = NULL; 270 exitstatus = execute (javac, "/bin/sh", argv, false, false, false, 271 null_stderr, true, true); 272 err = (exitstatus != 0); 273 274 freea (command); 275 276 return err; 277} 278 279/* Try to compile a set of Java sources with gcj. 280 Return a failure indicator (true upon error). */ 281static bool 282compile_using_gcj (const char * const *java_sources, 283 unsigned int java_sources_count, 284 bool no_assert_option, 285 bool fsource_option, const char *source_version, 286 bool ftarget_option, const char *target_version, 287 const char *directory, 288 bool optimize, bool debug, 289 bool verbose, bool null_stderr) 290{ 291 bool err; 292 unsigned int argc; 293 char **argv; 294 char **argp; 295 char *fsource_arg; 296 char *ftarget_arg; 297 int exitstatus; 298 unsigned int i; 299 300 argc = 301 2 + (no_assert_option ? 1 : 0) + (fsource_option ? 1 : 0) 302 + (ftarget_option ? 1 : 0) + (optimize ? 1 : 0) + (debug ? 1 : 0) 303 + (directory != NULL ? 2 : 0) + java_sources_count; 304 argv = (char **) xmalloca ((argc + 1) * sizeof (char *)); 305 306 argp = argv; 307 *argp++ = "gcj"; 308 *argp++ = "-C"; 309 if (no_assert_option) 310 *argp++ = "-fno-assert"; 311 if (fsource_option) 312 { 313 fsource_arg = (char *) xmalloca (9 + strlen (source_version) + 1); 314 memcpy (fsource_arg, "-fsource=", 9); 315 strcpy (fsource_arg + 9, source_version); 316 *argp++ = fsource_arg; 317 } 318 else 319 fsource_arg = NULL; 320 if (ftarget_option) 321 { 322 ftarget_arg = (char *) xmalloca (9 + strlen (target_version) + 1); 323 memcpy (ftarget_arg, "-ftarget=", 9); 324 strcpy (ftarget_arg + 9, target_version); 325 *argp++ = ftarget_arg; 326 } 327 else 328 ftarget_arg = NULL; 329 if (optimize) 330 *argp++ = "-O"; 331 if (debug) 332 *argp++ = "-g"; 333 if (directory != NULL) 334 { 335 *argp++ = "-d"; 336 *argp++ = (char *) directory; 337 } 338 for (i = 0; i < java_sources_count; i++) 339 *argp++ = (char *) java_sources[i]; 340 *argp = NULL; 341 /* Ensure argv length was correctly calculated. */ 342 if (argp - argv != argc) 343 abort (); 344 345 if (verbose) 346 { 347 char *command = shell_quote_argv (argv); 348 printf ("%s\n", command); 349 free (command); 350 } 351 352 exitstatus = execute ("gcj", "gcj", argv, false, false, false, null_stderr, 353 true, true); 354 err = (exitstatus != 0); 355 356 if (ftarget_arg != NULL) 357 freea (ftarget_arg); 358 if (fsource_arg != NULL) 359 freea (fsource_arg); 360 freea (argv); 361 362 return err; 363} 364 365/* Try to compile a set of Java sources with javac. 366 Return a failure indicator (true upon error). */ 367static bool 368compile_using_javac (const char * const *java_sources, 369 unsigned int java_sources_count, 370 bool source_option, const char *source_version, 371 bool target_option, const char *target_version, 372 const char *directory, 373 bool optimize, bool debug, 374 bool verbose, bool null_stderr) 375{ 376 bool err; 377 unsigned int argc; 378 char **argv; 379 char **argp; 380 int exitstatus; 381 unsigned int i; 382 383 argc = 384 1 + (source_option ? 2 : 0) + (target_option ? 2 : 0) + (optimize ? 1 : 0) 385 + (debug ? 1 : 0) + (directory != NULL ? 2 : 0) + java_sources_count; 386 argv = (char **) xmalloca ((argc + 1) * sizeof (char *)); 387 388 argp = argv; 389 *argp++ = "javac"; 390 if (source_option) 391 { 392 *argp++ = "-source"; 393 *argp++ = (char *) source_version; 394 } 395 if (target_option) 396 { 397 *argp++ = "-target"; 398 *argp++ = (char *) target_version; 399 } 400 if (optimize) 401 *argp++ = "-O"; 402 if (debug) 403 *argp++ = "-g"; 404 if (directory != NULL) 405 { 406 *argp++ = "-d"; 407 *argp++ = (char *) directory; 408 } 409 for (i = 0; i < java_sources_count; i++) 410 *argp++ = (char *) java_sources[i]; 411 *argp = NULL; 412 /* Ensure argv length was correctly calculated. */ 413 if (argp - argv != argc) 414 abort (); 415 416 if (verbose) 417 { 418 char *command = shell_quote_argv (argv); 419 printf ("%s\n", command); 420 free (command); 421 } 422 423 exitstatus = execute ("javac", "javac", argv, false, false, false, 424 null_stderr, true, true); 425 err = (exitstatus != 0); 426 427 freea (argv); 428 429 return err; 430} 431 432/* Try to compile a set of Java sources with jikes. 433 Return a failure indicator (true upon error). */ 434static bool 435compile_using_jikes (const char * const *java_sources, 436 unsigned int java_sources_count, 437 const char *directory, 438 bool optimize, bool debug, 439 bool verbose, bool null_stderr) 440{ 441 bool err; 442 unsigned int argc; 443 char **argv; 444 char **argp; 445 int exitstatus; 446 unsigned int i; 447 448 argc = 449 1 + (optimize ? 1 : 0) + (debug ? 1 : 0) + (directory != NULL ? 2 : 0) 450 + java_sources_count; 451 argv = (char **) xmalloca ((argc + 1) * sizeof (char *)); 452 453 argp = argv; 454 *argp++ = "jikes"; 455 if (optimize) 456 *argp++ = "-O"; 457 if (debug) 458 *argp++ = "-g"; 459 if (directory != NULL) 460 { 461 *argp++ = "-d"; 462 *argp++ = (char *) directory; 463 } 464 for (i = 0; i < java_sources_count; i++) 465 *argp++ = (char *) java_sources[i]; 466 *argp = NULL; 467 /* Ensure argv length was correctly calculated. */ 468 if (argp - argv != argc) 469 abort (); 470 471 if (verbose) 472 { 473 char *command = shell_quote_argv (argv); 474 printf ("%s\n", command); 475 free (command); 476 } 477 478 exitstatus = execute ("jikes", "jikes", argv, false, false, false, 479 null_stderr, true, true); 480 err = (exitstatus != 0); 481 482 freea (argv); 483 484 return err; 485} 486 487/* ====================== Usability test subroutines ====================== */ 488 489/* Write a given contents to a temporary file. 490 FILE_NAME is the name of a file inside TMPDIR that is known not to exist 491 yet. 492 Return a failure indicator (true upon error). */ 493static bool 494write_temp_file (struct temp_dir *tmpdir, const char *file_name, 495 const char *contents) 496{ 497 FILE *fp; 498 499 register_temp_file (tmpdir, file_name); 500 fp = fopen_temp (file_name, "w"); 501 if (fp == NULL) 502 { 503 error (0, errno, _("failed to create \"%s\""), file_name); 504 unregister_temp_file (tmpdir, file_name); 505 return true; 506 } 507 fputs (contents, fp); 508 if (fwriteerror_temp (fp)) 509 { 510 error (0, errno, _("error while writing \"%s\" file"), file_name); 511 return true; 512 } 513 return false; 514} 515 516/* Return the class file version number of a class file on disk. */ 517static int 518get_classfile_version (const char *compiled_file_name) 519{ 520 unsigned char header[8]; 521 int fd; 522 523 /* Open the class file. */ 524 fd = open (compiled_file_name, O_RDONLY | O_BINARY, 0); 525 if (fd >= 0) 526 { 527 /* Read its first 8 bytes. */ 528 if (safe_read (fd, header, 8) == 8) 529 { 530 /* Verify the class file signature. */ 531 if (header[0] == 0xCA && header[1] == 0xFE 532 && header[2] == 0xBA && header[3] == 0xBE) 533 return header[7]; 534 } 535 close (fd); 536 } 537 538 /* Could not get the class file version. Return a very large one. */ 539 return INT_MAX; 540} 541 542/* Return true if $JAVAC is a version of gcj. */ 543static bool 544is_envjavac_gcj (const char *javac) 545{ 546 static bool envjavac_tested; 547 static bool envjavac_gcj; 548 549 if (!envjavac_tested) 550 { 551 /* Test whether $JAVAC is gcj: 552 "$JAVAC --version 2>/dev/null | sed -e 1q | grep gcj > /dev/null" */ 553 unsigned int command_length; 554 char *command; 555 char *argv[4]; 556 pid_t child; 557 int fd[1]; 558 FILE *fp; 559 char *line; 560 size_t linesize; 561 size_t linelen; 562 int exitstatus; 563 char *p; 564 565 /* Setup the command "$JAVAC --version". */ 566 command_length = strlen (javac) + 1 + 9 + 1; 567 command = (char *) xmalloca (command_length); 568 p = command; 569 /* Don't shell_quote $JAVAC, because it may consist of a command 570 and options. */ 571 memcpy (p, javac, strlen (javac)); 572 p += strlen (javac); 573 memcpy (p, " --version", 1 + 9 + 1); 574 p += 1 + 9 + 1; 575 /* Ensure command_length was correctly calculated. */ 576 if (p - command > command_length) 577 abort (); 578 579 /* Call $JAVAC --version 2>/dev/null. */ 580 argv[0] = "/bin/sh"; 581 argv[1] = "-c"; 582 argv[2] = command; 583 argv[3] = NULL; 584 child = create_pipe_in (javac, "/bin/sh", argv, DEV_NULL, true, true, 585 false, fd); 586 if (child == -1) 587 goto failed; 588 589 /* Retrieve its result. */ 590 fp = fdopen (fd[0], "r"); 591 if (fp == NULL) 592 goto failed; 593 594 line = NULL; linesize = 0; 595 linelen = getline (&line, &linesize, fp); 596 if (linelen == (size_t)(-1)) 597 { 598 fclose (fp); 599 goto failed; 600 } 601 /* It is safe to call c_strstr() instead of strstr() here; see the 602 comments in c-strstr.h. */ 603 envjavac_gcj = (c_strstr (line, "gcj") != NULL); 604 605 fclose (fp); 606 607 /* Remove zombie process from process list, and retrieve exit status. */ 608 exitstatus = wait_subprocess (child, javac, true, true, true, false); 609 if (exitstatus != 0) 610 envjavac_gcj = false; 611 612 failed: 613 freea (command); 614 615 envjavac_tested = true; 616 } 617 618 return envjavac_gcj; 619} 620 621/* Return true if $JAVAC, known to be a version of gcj, is a version >= 4.3 622 of gcj. */ 623static bool 624is_envjavac_gcj43 (const char *javac) 625{ 626 static bool envjavac_tested; 627 static bool envjavac_gcj43; 628 629 if (!envjavac_tested) 630 { 631 /* Test whether $JAVAC is gcj: 632 "$JAVAC --version 2>/dev/null | sed -e 's,^[^0-9]*,,' -e 1q \ 633 | sed -e '/^4\.[012]/d' | grep '^[4-9]' >/dev/null" */ 634 unsigned int command_length; 635 char *command; 636 char *argv[4]; 637 pid_t child; 638 int fd[1]; 639 FILE *fp; 640 char *line; 641 size_t linesize; 642 size_t linelen; 643 int exitstatus; 644 char *p; 645 646 /* Setup the command "$JAVAC --version". */ 647 command_length = strlen (javac) + 1 + 9 + 1; 648 command = (char *) xmalloca (command_length); 649 p = command; 650 /* Don't shell_quote $JAVAC, because it may consist of a command 651 and options. */ 652 memcpy (p, javac, strlen (javac)); 653 p += strlen (javac); 654 memcpy (p, " --version", 1 + 9 + 1); 655 p += 1 + 9 + 1; 656 /* Ensure command_length was correctly calculated. */ 657 if (p - command > command_length) 658 abort (); 659 660 /* Call $JAVAC --version 2>/dev/null. */ 661 argv[0] = "/bin/sh"; 662 argv[1] = "-c"; 663 argv[2] = command; 664 argv[3] = NULL; 665 child = create_pipe_in (javac, "/bin/sh", argv, DEV_NULL, true, true, 666 false, fd); 667 if (child == -1) 668 goto failed; 669 670 /* Retrieve its result. */ 671 fp = fdopen (fd[0], "r"); 672 if (fp == NULL) 673 goto failed; 674 675 line = NULL; linesize = 0; 676 linelen = getline (&line, &linesize, fp); 677 if (linelen == (size_t)(-1)) 678 { 679 fclose (fp); 680 goto failed; 681 } 682 p = line; 683 while (*p != '\0' && !(*p >= '0' && *p <= '9')) 684 p++; 685 envjavac_gcj43 = 686 !(*p == '4' && p[1] == '.' && p[2] >= '0' && p[2] <= '2') 687 && (*p >= '4' && *p <= '9'); 688 689 fclose (fp); 690 691 /* Remove zombie process from process list, and retrieve exit status. */ 692 exitstatus = wait_subprocess (child, javac, true, true, true, false); 693 if (exitstatus != 0) 694 envjavac_gcj43 = false; 695 696 failed: 697 freea (command); 698 699 envjavac_tested = true; 700 } 701 702 return envjavac_gcj43; 703} 704 705/* Test whether $JAVAC, known to be a version of gcj >= 4.3, can be used, and 706 whether it needs a -fsource and/or -ftarget option. 707 Return a failure indicator (true upon error). */ 708static bool 709is_envjavac_gcj43_usable (const char *javac, 710 const char *source_version, 711 const char *target_version, 712 bool *usablep, 713 bool *fsource_option_p, bool *ftarget_option_p) 714{ 715 /* The cache depends on the source_version and target_version. */ 716 struct result_t 717 { 718 bool tested; 719 bool usable; 720 bool fsource_option; 721 bool ftarget_option; 722 }; 723 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND]; 724 struct result_t *resultp; 725 726 resultp = &result_cache[source_version_index (source_version)] 727 [target_version_index (target_version)]; 728 if (!resultp->tested) 729 { 730 /* Try $JAVAC. */ 731 struct temp_dir *tmpdir; 732 char *conftest_file_name; 733 char *compiled_file_name; 734 const char *java_sources[1]; 735 struct stat statbuf; 736 737 tmpdir = create_temp_dir ("java", NULL, false); 738 if (tmpdir == NULL) 739 return true; 740 741 conftest_file_name = 742 concatenated_filename (tmpdir->dir_name, "conftest.java", NULL); 743 if (write_temp_file (tmpdir, conftest_file_name, 744 get_goodcode_snippet (source_version))) 745 { 746 free (conftest_file_name); 747 cleanup_temp_dir (tmpdir); 748 return true; 749 } 750 751 compiled_file_name = 752 concatenated_filename (tmpdir->dir_name, "conftest.class", NULL); 753 register_temp_file (tmpdir, compiled_file_name); 754 755 java_sources[0] = conftest_file_name; 756 if (!compile_using_envjavac (javac, 757 java_sources, 1, tmpdir->dir_name, 758 false, false, false, true) 759 && stat (compiled_file_name, &statbuf) >= 0 760 && get_classfile_version (compiled_file_name) 761 <= corresponding_classfile_version (target_version)) 762 { 763 /* $JAVAC compiled conftest.java successfully. */ 764 /* Try adding -fsource option if it is useful. */ 765 char *javac_source = 766 xasprintf ("%s -fsource=%s", javac, source_version); 767 768 unlink (compiled_file_name); 769 770 java_sources[0] = conftest_file_name; 771 if (!compile_using_envjavac (javac_source, 772 java_sources, 1, tmpdir->dir_name, 773 false, false, false, true) 774 && stat (compiled_file_name, &statbuf) >= 0 775 && get_classfile_version (compiled_file_name) 776 <= corresponding_classfile_version (target_version)) 777 { 778 const char *failcode = get_failcode_snippet (source_version); 779 780 if (failcode != NULL) 781 { 782 free (compiled_file_name); 783 free (conftest_file_name); 784 785 conftest_file_name = 786 concatenated_filename (tmpdir->dir_name, 787 "conftestfail.java", 788 NULL); 789 if (write_temp_file (tmpdir, conftest_file_name, failcode)) 790 { 791 free (conftest_file_name); 792 free (javac_source); 793 cleanup_temp_dir (tmpdir); 794 return true; 795 } 796 797 compiled_file_name = 798 concatenated_filename (tmpdir->dir_name, 799 "conftestfail.class", 800 NULL); 801 register_temp_file (tmpdir, compiled_file_name); 802 803 java_sources[0] = conftest_file_name; 804 if (!compile_using_envjavac (javac, 805 java_sources, 1, 806 tmpdir->dir_name, 807 false, false, false, true) 808 && stat (compiled_file_name, &statbuf) >= 0) 809 { 810 unlink (compiled_file_name); 811 812 java_sources[0] = conftest_file_name; 813 if (compile_using_envjavac (javac_source, 814 java_sources, 1, 815 tmpdir->dir_name, 816 false, false, false, true)) 817 /* $JAVAC compiled conftestfail.java successfully, and 818 "$JAVAC -fsource=$source_version" rejects it. So 819 the -fsource option is useful. */ 820 resultp->fsource_option = true; 821 } 822 } 823 } 824 825 free (javac_source); 826 827 resultp->usable = true; 828 } 829 else 830 { 831 /* Try with -fsource and -ftarget options. */ 832 char *javac_target = 833 xasprintf ("%s -fsource=%s -ftarget=%s", 834 javac, source_version, target_version); 835 836 unlink (compiled_file_name); 837 838 java_sources[0] = conftest_file_name; 839 if (!compile_using_envjavac (javac_target, 840 java_sources, 1, tmpdir->dir_name, 841 false, false, false, true) 842 && stat (compiled_file_name, &statbuf) >= 0 843 && get_classfile_version (compiled_file_name) 844 <= corresponding_classfile_version (target_version)) 845 { 846 /* "$JAVAC -fsource $source_version -ftarget $target_version" 847 compiled conftest.java successfully. */ 848 resultp->fsource_option = true; 849 resultp->ftarget_option = true; 850 resultp->usable = true; 851 } 852 853 free (javac_target); 854 } 855 856 free (compiled_file_name); 857 free (conftest_file_name); 858 859 resultp->tested = true; 860 } 861 862 *usablep = resultp->usable; 863 *fsource_option_p = resultp->fsource_option; 864 *ftarget_option_p = resultp->ftarget_option; 865 return false; 866} 867 868/* Test whether $JAVAC, known to be a version of gcj < 4.3, can be used for 869 compiling with target_version = 1.4 and source_version = 1.4. 870 Return a failure indicator (true upon error). */ 871static bool 872is_envjavac_oldgcj_14_14_usable (const char *javac, bool *usablep) 873{ 874 static bool envjavac_tested; 875 static bool envjavac_usable; 876 877 if (!envjavac_tested) 878 { 879 /* Try $JAVAC. */ 880 struct temp_dir *tmpdir; 881 char *conftest_file_name; 882 char *compiled_file_name; 883 const char *java_sources[1]; 884 struct stat statbuf; 885 886 tmpdir = create_temp_dir ("java", NULL, false); 887 if (tmpdir == NULL) 888 return true; 889 890 conftest_file_name = 891 concatenated_filename (tmpdir->dir_name, "conftest.java", NULL); 892 if (write_temp_file (tmpdir, conftest_file_name, 893 get_goodcode_snippet ("1.4"))) 894 { 895 free (conftest_file_name); 896 cleanup_temp_dir (tmpdir); 897 return true; 898 } 899 900 compiled_file_name = 901 concatenated_filename (tmpdir->dir_name, "conftest.class", NULL); 902 register_temp_file (tmpdir, compiled_file_name); 903 904 java_sources[0] = conftest_file_name; 905 if (!compile_using_envjavac (javac, java_sources, 1, tmpdir->dir_name, 906 false, false, false, true) 907 && stat (compiled_file_name, &statbuf) >= 0) 908 /* Compilation succeeded. */ 909 envjavac_usable = true; 910 911 free (compiled_file_name); 912 free (conftest_file_name); 913 914 cleanup_temp_dir (tmpdir); 915 916 envjavac_tested = true; 917 } 918 919 *usablep = envjavac_usable; 920 return false; 921} 922 923/* Test whether $JAVAC, known to be a version of gcj < 4.3, can be used for 924 compiling with target_version = 1.4 and source_version = 1.3. 925 Return a failure indicator (true upon error). */ 926static bool 927is_envjavac_oldgcj_14_13_usable (const char *javac, 928 bool *usablep, bool *need_no_assert_option_p) 929{ 930 static bool envjavac_tested; 931 static bool envjavac_usable; 932 static bool envjavac_need_no_assert_option; 933 934 if (!envjavac_tested) 935 { 936 /* Try $JAVAC and "$JAVAC -fno-assert". But add -fno-assert only if 937 it makes a difference. (It could already be part of $JAVAC.) */ 938 struct temp_dir *tmpdir; 939 char *conftest_file_name; 940 char *compiled_file_name; 941 const char *java_sources[1]; 942 struct stat statbuf; 943 bool javac_works; 944 char *javac_noassert; 945 bool javac_noassert_works; 946 947 tmpdir = create_temp_dir ("java", NULL, false); 948 if (tmpdir == NULL) 949 return true; 950 951 conftest_file_name = 952 concatenated_filename (tmpdir->dir_name, "conftest.java", NULL); 953 if (write_temp_file (tmpdir, conftest_file_name, 954 get_goodcode_snippet ("1.3"))) 955 { 956 free (conftest_file_name); 957 cleanup_temp_dir (tmpdir); 958 return true; 959 } 960 961 compiled_file_name = 962 concatenated_filename (tmpdir->dir_name, "conftest.class", NULL); 963 register_temp_file (tmpdir, compiled_file_name); 964 965 java_sources[0] = conftest_file_name; 966 if (!compile_using_envjavac (javac, 967 java_sources, 1, tmpdir->dir_name, 968 false, false, false, true) 969 && stat (compiled_file_name, &statbuf) >= 0) 970 /* Compilation succeeded. */ 971 javac_works = true; 972 else 973 javac_works = false; 974 975 unlink (compiled_file_name); 976 977 javac_noassert = xasprintf ("%s -fno-assert", javac); 978 979 java_sources[0] = conftest_file_name; 980 if (!compile_using_envjavac (javac_noassert, 981 java_sources, 1, tmpdir->dir_name, 982 false, false, false, true) 983 && stat (compiled_file_name, &statbuf) >= 0) 984 /* Compilation succeeded. */ 985 javac_noassert_works = true; 986 else 987 javac_noassert_works = false; 988 989 free (compiled_file_name); 990 free (conftest_file_name); 991 992 if (javac_works && javac_noassert_works) 993 { 994 conftest_file_name = 995 concatenated_filename (tmpdir->dir_name, "conftestfail.java", 996 NULL); 997 if (write_temp_file (tmpdir, conftest_file_name, 998 get_failcode_snippet ("1.3"))) 999 { 1000 free (conftest_file_name); 1001 free (javac_noassert); 1002 cleanup_temp_dir (tmpdir); 1003 return true; 1004 } 1005 1006 compiled_file_name = 1007 concatenated_filename (tmpdir->dir_name, "conftestfail.class", 1008 NULL); 1009 register_temp_file (tmpdir, compiled_file_name); 1010 1011 java_sources[0] = conftest_file_name; 1012 if (!compile_using_envjavac (javac, 1013 java_sources, 1, tmpdir->dir_name, 1014 false, false, false, true) 1015 && stat (compiled_file_name, &statbuf) >= 0) 1016 { 1017 /* Compilation succeeded. */ 1018 unlink (compiled_file_name); 1019 1020 java_sources[0] = conftest_file_name; 1021 if (!(!compile_using_envjavac (javac_noassert, 1022 java_sources, 1, tmpdir->dir_name, 1023 false, false, false, true) 1024 && stat (compiled_file_name, &statbuf) >= 0)) 1025 /* Compilation failed. */ 1026 /* "$JAVAC -fno-assert" works better than $JAVAC. */ 1027 javac_works = true; 1028 } 1029 1030 free (compiled_file_name); 1031 free (conftest_file_name); 1032 } 1033 1034 cleanup_temp_dir (tmpdir); 1035 1036 if (javac_works) 1037 { 1038 envjavac_usable = true; 1039 envjavac_need_no_assert_option = false; 1040 } 1041 else if (javac_noassert_works) 1042 { 1043 envjavac_usable = true; 1044 envjavac_need_no_assert_option = true; 1045 } 1046 1047 envjavac_tested = true; 1048 } 1049 1050 *usablep = envjavac_usable; 1051 *need_no_assert_option_p = envjavac_need_no_assert_option; 1052 return false; 1053} 1054 1055/* Test whether $JAVAC, known to be not a version of gcj, can be used, and 1056 whether it needs a -source and/or -target option. 1057 Return a failure indicator (true upon error). */ 1058static bool 1059is_envjavac_nongcj_usable (const char *javac, 1060 const char *source_version, 1061 const char *target_version, 1062 bool *usablep, 1063 bool *source_option_p, bool *target_option_p) 1064{ 1065 /* The cache depends on the source_version and target_version. */ 1066 struct result_t 1067 { 1068 bool tested; 1069 bool usable; 1070 bool source_option; 1071 bool target_option; 1072 }; 1073 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND]; 1074 struct result_t *resultp; 1075 1076 resultp = &result_cache[source_version_index (source_version)] 1077 [target_version_index (target_version)]; 1078 if (!resultp->tested) 1079 { 1080 /* Try $JAVAC. */ 1081 struct temp_dir *tmpdir; 1082 char *conftest_file_name; 1083 char *compiled_file_name; 1084 const char *java_sources[1]; 1085 struct stat statbuf; 1086 1087 tmpdir = create_temp_dir ("java", NULL, false); 1088 if (tmpdir == NULL) 1089 return true; 1090 1091 conftest_file_name = 1092 concatenated_filename (tmpdir->dir_name, "conftest.java", NULL); 1093 if (write_temp_file (tmpdir, conftest_file_name, 1094 get_goodcode_snippet (source_version))) 1095 { 1096 free (conftest_file_name); 1097 cleanup_temp_dir (tmpdir); 1098 return true; 1099 } 1100 1101 compiled_file_name = 1102 concatenated_filename (tmpdir->dir_name, "conftest.class", NULL); 1103 register_temp_file (tmpdir, compiled_file_name); 1104 1105 java_sources[0] = conftest_file_name; 1106 if (!compile_using_envjavac (javac, 1107 java_sources, 1, tmpdir->dir_name, 1108 false, false, false, true) 1109 && stat (compiled_file_name, &statbuf) >= 0 1110 && get_classfile_version (compiled_file_name) 1111 <= corresponding_classfile_version (target_version)) 1112 { 1113 /* $JAVAC compiled conftest.java successfully. */ 1114 /* Try adding -source option if it is useful. */ 1115 char *javac_source = 1116 xasprintf ("%s -source %s", javac, source_version); 1117 1118 unlink (compiled_file_name); 1119 1120 java_sources[0] = conftest_file_name; 1121 if (!compile_using_envjavac (javac_source, 1122 java_sources, 1, tmpdir->dir_name, 1123 false, false, false, true) 1124 && stat (compiled_file_name, &statbuf) >= 0 1125 && get_classfile_version (compiled_file_name) 1126 <= corresponding_classfile_version (target_version)) 1127 { 1128 const char *failcode = get_failcode_snippet (source_version); 1129 1130 if (failcode != NULL) 1131 { 1132 free (compiled_file_name); 1133 free (conftest_file_name); 1134 1135 conftest_file_name = 1136 concatenated_filename (tmpdir->dir_name, 1137 "conftestfail.java", 1138 NULL); 1139 if (write_temp_file (tmpdir, conftest_file_name, failcode)) 1140 { 1141 free (conftest_file_name); 1142 free (javac_source); 1143 cleanup_temp_dir (tmpdir); 1144 return true; 1145 } 1146 1147 compiled_file_name = 1148 concatenated_filename (tmpdir->dir_name, 1149 "conftestfail.class", 1150 NULL); 1151 register_temp_file (tmpdir, compiled_file_name); 1152 1153 java_sources[0] = conftest_file_name; 1154 if (!compile_using_envjavac (javac, 1155 java_sources, 1, 1156 tmpdir->dir_name, 1157 false, false, false, true) 1158 && stat (compiled_file_name, &statbuf) >= 0) 1159 { 1160 unlink (compiled_file_name); 1161 1162 java_sources[0] = conftest_file_name; 1163 if (compile_using_envjavac (javac_source, 1164 java_sources, 1, 1165 tmpdir->dir_name, 1166 false, false, false, true)) 1167 /* $JAVAC compiled conftestfail.java successfully, and 1168 "$JAVAC -source $source_version" rejects it. So the 1169 -source option is useful. */ 1170 resultp->source_option = true; 1171 } 1172 } 1173 } 1174 1175 free (javac_source); 1176 1177 resultp->usable = true; 1178 } 1179 else 1180 { 1181 /* Try with -target option alone. (Sun javac 1.3.1 has the -target 1182 option but no -source option.) */ 1183 char *javac_target = 1184 xasprintf ("%s -target %s", javac, target_version); 1185 1186 unlink (compiled_file_name); 1187 1188 java_sources[0] = conftest_file_name; 1189 if (!compile_using_envjavac (javac_target, 1190 java_sources, 1, tmpdir->dir_name, 1191 false, false, false, true) 1192 && stat (compiled_file_name, &statbuf) >= 0 1193 && get_classfile_version (compiled_file_name) 1194 <= corresponding_classfile_version (target_version)) 1195 { 1196 /* "$JAVAC -target $target_version" compiled conftest.java 1197 successfully. */ 1198 /* Try adding -source option if it is useful. */ 1199 char *javac_target_source = 1200 xasprintf ("%s -source %s", javac_target, source_version); 1201 1202 unlink (compiled_file_name); 1203 1204 java_sources[0] = conftest_file_name; 1205 if (!compile_using_envjavac (javac_target_source, 1206 java_sources, 1, tmpdir->dir_name, 1207 false, false, false, true) 1208 && stat (compiled_file_name, &statbuf) >= 0 1209 && get_classfile_version (compiled_file_name) 1210 <= corresponding_classfile_version (target_version)) 1211 { 1212 const char *failcode = get_failcode_snippet (source_version); 1213 1214 if (failcode != NULL) 1215 { 1216 free (compiled_file_name); 1217 free (conftest_file_name); 1218 1219 conftest_file_name = 1220 concatenated_filename (tmpdir->dir_name, 1221 "conftestfail.java", 1222 NULL); 1223 if (write_temp_file (tmpdir, conftest_file_name, 1224 failcode)) 1225 { 1226 free (conftest_file_name); 1227 free (javac_target_source); 1228 free (javac_target); 1229 cleanup_temp_dir (tmpdir); 1230 return true; 1231 } 1232 1233 compiled_file_name = 1234 concatenated_filename (tmpdir->dir_name, 1235 "conftestfail.class", 1236 NULL); 1237 register_temp_file (tmpdir, compiled_file_name); 1238 1239 java_sources[0] = conftest_file_name; 1240 if (!compile_using_envjavac (javac_target, 1241 java_sources, 1, 1242 tmpdir->dir_name, 1243 false, false, false, true) 1244 && stat (compiled_file_name, &statbuf) >= 0) 1245 { 1246 unlink (compiled_file_name); 1247 1248 java_sources[0] = conftest_file_name; 1249 if (compile_using_envjavac (javac_target_source, 1250 java_sources, 1, 1251 tmpdir->dir_name, 1252 false, false, false, 1253 true)) 1254 /* "$JAVAC -target $target_version" compiled 1255 conftestfail.java successfully, and 1256 "$JAVAC -target $target_version -source $source_version" 1257 rejects it. So the -source option is useful. */ 1258 resultp->source_option = true; 1259 } 1260 } 1261 } 1262 1263 free (javac_target_source); 1264 1265 resultp->target_option = true; 1266 resultp->usable = true; 1267 } 1268 else 1269 { 1270 /* Maybe this -target option requires a -source option? Try with 1271 -target and -source options. (Supported by Sun javac 1.4 and 1272 higher.) */ 1273 char *javac_target_source = 1274 xasprintf ("%s -source %s", javac_target, source_version); 1275 1276 unlink (compiled_file_name); 1277 1278 java_sources[0] = conftest_file_name; 1279 if (!compile_using_envjavac (javac_target_source, 1280 java_sources, 1, tmpdir->dir_name, 1281 false, false, false, true) 1282 && stat (compiled_file_name, &statbuf) >= 0 1283 && get_classfile_version (compiled_file_name) 1284 <= corresponding_classfile_version (target_version)) 1285 { 1286 /* "$JAVAC -target $target_version -source $source_version" 1287 compiled conftest.java successfully. */ 1288 resultp->source_option = true; 1289 resultp->target_option = true; 1290 resultp->usable = true; 1291 } 1292 1293 free (javac_target_source); 1294 } 1295 1296 free (javac_target); 1297 } 1298 1299 free (compiled_file_name); 1300 free (conftest_file_name); 1301 1302 resultp->tested = true; 1303 } 1304 1305 *usablep = resultp->usable; 1306 *source_option_p = resultp->source_option; 1307 *target_option_p = resultp->target_option; 1308 return false; 1309} 1310 1311static bool 1312is_gcj_present (void) 1313{ 1314 static bool gcj_tested; 1315 static bool gcj_present; 1316 1317 if (!gcj_tested) 1318 { 1319 /* Test for presence of gcj: 1320 "gcj --version 2> /dev/null | \ 1321 sed -e 's,^[^0-9]*,,' -e 1q | \ 1322 sed -e '/^3\.[01]/d' | grep '^[3-9]' > /dev/null" */ 1323 char *argv[3]; 1324 pid_t child; 1325 int fd[1]; 1326 int exitstatus; 1327 1328 argv[0] = "gcj"; 1329 argv[1] = "--version"; 1330 argv[2] = NULL; 1331 child = create_pipe_in ("gcj", "gcj", argv, DEV_NULL, true, true, 1332 false, fd); 1333 gcj_present = false; 1334 if (child != -1) 1335 { 1336 /* Read the subprocess output, drop all lines except the first, 1337 drop all characters before the first digit, and test whether 1338 the remaining string starts with a digit >= 3, but not with 1339 "3.0" or "3.1". */ 1340 char c[3]; 1341 size_t count = 0; 1342 1343 while (safe_read (fd[0], &c[count], 1) > 0) 1344 { 1345 if (c[count] == '\n') 1346 break; 1347 if (count == 0) 1348 { 1349 if (!(c[0] >= '0' && c[0] <= '9')) 1350 continue; 1351 gcj_present = (c[0] >= '3'); 1352 } 1353 count++; 1354 if (count == 3) 1355 { 1356 if (c[0] == '3' && c[1] == '.' 1357 && (c[2] == '0' || c[2] == '1')) 1358 gcj_present = false; 1359 break; 1360 } 1361 } 1362 while (safe_read (fd[0], &c[0], 1) > 0) 1363 ; 1364 1365 close (fd[0]); 1366 1367 /* Remove zombie process from process list, and retrieve exit 1368 status. */ 1369 exitstatus = 1370 wait_subprocess (child, "gcj", false, true, true, false); 1371 if (exitstatus != 0) 1372 gcj_present = false; 1373 } 1374 1375 if (gcj_present) 1376 { 1377 /* See if libgcj.jar is well installed. */ 1378 struct temp_dir *tmpdir; 1379 1380 tmpdir = create_temp_dir ("java", NULL, false); 1381 if (tmpdir == NULL) 1382 gcj_present = false; 1383 else 1384 { 1385 char *conftest_file_name; 1386 1387 conftest_file_name = 1388 concatenated_filename (tmpdir->dir_name, "conftestlib.java", 1389 NULL); 1390 if (write_temp_file (tmpdir, conftest_file_name, 1391"public class conftestlib {\n" 1392" public static void main (String[] args) {\n" 1393" }\n" 1394"}\n")) 1395 gcj_present = false; 1396 else 1397 { 1398 char *compiled_file_name; 1399 const char *java_sources[1]; 1400 1401 compiled_file_name = 1402 concatenated_filename (tmpdir->dir_name, 1403 "conftestlib.class", 1404 NULL); 1405 register_temp_file (tmpdir, compiled_file_name); 1406 1407 java_sources[0] = conftest_file_name; 1408 if (compile_using_gcj (java_sources, 1, false, 1409 false, NULL, false, NULL, 1410 tmpdir->dir_name, 1411 false, false, false, true)) 1412 gcj_present = false; 1413 1414 free (compiled_file_name); 1415 } 1416 free (conftest_file_name); 1417 } 1418 cleanup_temp_dir (tmpdir); 1419 } 1420 1421 gcj_tested = true; 1422 } 1423 1424 return gcj_present; 1425} 1426 1427static bool 1428is_gcj_43 (void) 1429{ 1430 static bool gcj_tested; 1431 static bool gcj_43; 1432 1433 if (!gcj_tested) 1434 { 1435 /* Test for presence of gcj: 1436 "gcj --version 2> /dev/null | \ 1437 sed -e 's,^[^0-9]*,,' -e 1q | \ 1438 sed -e '/^4\.[012]/d' | grep '^[4-9]'" */ 1439 char *argv[3]; 1440 pid_t child; 1441 int fd[1]; 1442 int exitstatus; 1443 1444 argv[0] = "gcj"; 1445 argv[1] = "--version"; 1446 argv[2] = NULL; 1447 child = create_pipe_in ("gcj", "gcj", argv, DEV_NULL, true, true, 1448 false, fd); 1449 gcj_43 = false; 1450 if (child != -1) 1451 { 1452 /* Read the subprocess output, drop all lines except the first, 1453 drop all characters before the first digit, and test whether 1454 the remaining string starts with a digit >= 4, but not with 1455 "4.0" or "4.1" or "4.2". */ 1456 char c[3]; 1457 size_t count = 0; 1458 1459 while (safe_read (fd[0], &c[count], 1) > 0) 1460 { 1461 if (c[count] == '\n') 1462 break; 1463 if (count == 0) 1464 { 1465 if (!(c[0] >= '0' && c[0] <= '9')) 1466 continue; 1467 gcj_43 = (c[0] >= '4'); 1468 } 1469 count++; 1470 if (count == 3) 1471 { 1472 if (c[0] == '4' && c[1] == '.' && c[2] >= '0' && c[2] <= '2') 1473 gcj_43 = false; 1474 break; 1475 } 1476 } 1477 while (safe_read (fd[0], &c[0], 1) > 0) 1478 ; 1479 1480 close (fd[0]); 1481 1482 /* Remove zombie process from process list, and retrieve exit 1483 status. */ 1484 exitstatus = 1485 wait_subprocess (child, "gcj", false, true, true, false); 1486 if (exitstatus != 0) 1487 gcj_43 = false; 1488 } 1489 1490 gcj_tested = true; 1491 } 1492 1493 return gcj_43; 1494} 1495 1496/* Test whether gcj >= 4.3 can be used, and whether it needs a -fsource and/or 1497 -ftarget option. 1498 Return a failure indicator (true upon error). */ 1499static bool 1500is_gcj43_usable (const char *source_version, 1501 const char *target_version, 1502 bool *usablep, 1503 bool *fsource_option_p, bool *ftarget_option_p) 1504{ 1505 /* The cache depends on the source_version and target_version. */ 1506 struct result_t 1507 { 1508 bool tested; 1509 bool usable; 1510 bool fsource_option; 1511 bool ftarget_option; 1512 }; 1513 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND]; 1514 struct result_t *resultp; 1515 1516 resultp = &result_cache[source_version_index (source_version)] 1517 [target_version_index (target_version)]; 1518 if (!resultp->tested) 1519 { 1520 /* Try gcj. */ 1521 struct temp_dir *tmpdir; 1522 char *conftest_file_name; 1523 char *compiled_file_name; 1524 const char *java_sources[1]; 1525 struct stat statbuf; 1526 1527 tmpdir = create_temp_dir ("java", NULL, false); 1528 if (tmpdir == NULL) 1529 return true; 1530 1531 conftest_file_name = 1532 concatenated_filename (tmpdir->dir_name, "conftest.java", NULL); 1533 if (write_temp_file (tmpdir, conftest_file_name, 1534 get_goodcode_snippet (source_version))) 1535 { 1536 free (conftest_file_name); 1537 cleanup_temp_dir (tmpdir); 1538 return true; 1539 } 1540 1541 compiled_file_name = 1542 concatenated_filename (tmpdir->dir_name, "conftest.class", NULL); 1543 register_temp_file (tmpdir, compiled_file_name); 1544 1545 java_sources[0] = conftest_file_name; 1546 if (!compile_using_gcj (java_sources, 1, false, false, NULL, false, NULL, 1547 tmpdir->dir_name, false, false, false, true) 1548 && stat (compiled_file_name, &statbuf) >= 0 1549 && get_classfile_version (compiled_file_name) 1550 <= corresponding_classfile_version (target_version)) 1551 { 1552 /* gcj compiled conftest.java successfully. */ 1553 /* Try adding -fsource option if it is useful. */ 1554 unlink (compiled_file_name); 1555 1556 java_sources[0] = conftest_file_name; 1557 if (!compile_using_gcj (java_sources, 1, 1558 false, true, source_version, false, NULL, 1559 tmpdir->dir_name, false, false, false, true) 1560 && stat (compiled_file_name, &statbuf) >= 0 1561 && get_classfile_version (compiled_file_name) 1562 <= corresponding_classfile_version (target_version)) 1563 { 1564 const char *failcode = get_failcode_snippet (source_version); 1565 1566 if (failcode != NULL) 1567 { 1568 free (compiled_file_name); 1569 free (conftest_file_name); 1570 1571 conftest_file_name = 1572 concatenated_filename (tmpdir->dir_name, 1573 "conftestfail.java", 1574 NULL); 1575 if (write_temp_file (tmpdir, conftest_file_name, failcode)) 1576 { 1577 free (conftest_file_name); 1578 cleanup_temp_dir (tmpdir); 1579 return true; 1580 } 1581 1582 compiled_file_name = 1583 concatenated_filename (tmpdir->dir_name, 1584 "conftestfail.class", 1585 NULL); 1586 register_temp_file (tmpdir, compiled_file_name); 1587 1588 java_sources[0] = conftest_file_name; 1589 if (!compile_using_gcj (java_sources, 1, 1590 false, false, NULL, false, NULL, 1591 tmpdir->dir_name, 1592 false, false, false, true) 1593 && stat (compiled_file_name, &statbuf) >= 0) 1594 { 1595 unlink (compiled_file_name); 1596 1597 java_sources[0] = conftest_file_name; 1598 if (compile_using_gcj (java_sources, 1, 1599 false, true, source_version, 1600 false, NULL, 1601 tmpdir->dir_name, 1602 false, false, false, true)) 1603 /* gcj compiled conftestfail.java successfully, and 1604 "gcj -fsource=$source_version" rejects it. So 1605 the -fsource option is useful. */ 1606 resultp->fsource_option = true; 1607 } 1608 } 1609 } 1610 1611 resultp->usable = true; 1612 } 1613 else 1614 { 1615 /* Try with -fsource and -ftarget options. */ 1616 unlink (compiled_file_name); 1617 1618 java_sources[0] = conftest_file_name; 1619 if (!compile_using_gcj (java_sources, 1, 1620 false, true, source_version, 1621 true, target_version, 1622 tmpdir->dir_name, 1623 false, false, false, true) 1624 && stat (compiled_file_name, &statbuf) >= 0 1625 && get_classfile_version (compiled_file_name) 1626 <= corresponding_classfile_version (target_version)) 1627 { 1628 /* "gcj -fsource $source_version -ftarget $target_version" 1629 compiled conftest.java successfully. */ 1630 resultp->fsource_option = true; 1631 resultp->ftarget_option = true; 1632 resultp->usable = true; 1633 } 1634 } 1635 1636 free (compiled_file_name); 1637 free (conftest_file_name); 1638 1639 resultp->tested = true; 1640 } 1641 1642 *usablep = resultp->usable; 1643 *fsource_option_p = resultp->fsource_option; 1644 *ftarget_option_p = resultp->ftarget_option; 1645 return false; 1646} 1647 1648/* Test whether gcj < 4.3 can be used for compiling with target_version = 1.4 1649 and source_version = 1.4. 1650 Return a failure indicator (true upon error). */ 1651static bool 1652is_oldgcj_14_14_usable (bool *usablep) 1653{ 1654 static bool gcj_tested; 1655 static bool gcj_usable; 1656 1657 if (!gcj_tested) 1658 { 1659 /* Try gcj. */ 1660 struct temp_dir *tmpdir; 1661 char *conftest_file_name; 1662 char *compiled_file_name; 1663 const char *java_sources[1]; 1664 struct stat statbuf; 1665 1666 tmpdir = create_temp_dir ("java", NULL, false); 1667 if (tmpdir == NULL) 1668 return true; 1669 1670 conftest_file_name = 1671 concatenated_filename (tmpdir->dir_name, "conftest.java", NULL); 1672 if (write_temp_file (tmpdir, conftest_file_name, 1673 get_goodcode_snippet ("1.4"))) 1674 { 1675 free (conftest_file_name); 1676 cleanup_temp_dir (tmpdir); 1677 return true; 1678 } 1679 1680 compiled_file_name = 1681 concatenated_filename (tmpdir->dir_name, "conftest.class", NULL); 1682 register_temp_file (tmpdir, compiled_file_name); 1683 1684 java_sources[0] = conftest_file_name; 1685 if (!compile_using_gcj (java_sources, 1, false, false, NULL, false, NULL, 1686 tmpdir->dir_name, false, false, false, true) 1687 && stat (compiled_file_name, &statbuf) >= 0) 1688 /* Compilation succeeded. */ 1689 gcj_usable = true; 1690 1691 free (compiled_file_name); 1692 free (conftest_file_name); 1693 1694 cleanup_temp_dir (tmpdir); 1695 1696 gcj_tested = true; 1697 } 1698 1699 *usablep = gcj_usable; 1700 return false; 1701} 1702 1703/* Test whether gcj < 4.3 can be used for compiling with target_version = 1.4 1704 and source_version = 1.3. 1705 Return a failure indicator (true upon error). */ 1706static bool 1707is_oldgcj_14_13_usable (bool *usablep, bool *need_no_assert_option_p) 1708{ 1709 static bool gcj_tested; 1710 static bool gcj_usable; 1711 static bool gcj_need_no_assert_option; 1712 1713 if (!gcj_tested) 1714 { 1715 /* Try gcj and "gcj -fno-assert". But add -fno-assert only if 1716 it works (not gcj < 3.3). */ 1717 struct temp_dir *tmpdir; 1718 char *conftest_file_name; 1719 char *compiled_file_name; 1720 const char *java_sources[1]; 1721 struct stat statbuf; 1722 1723 tmpdir = create_temp_dir ("java", NULL, false); 1724 if (tmpdir == NULL) 1725 return true; 1726 1727 conftest_file_name = 1728 concatenated_filename (tmpdir->dir_name, "conftest.java", NULL); 1729 if (write_temp_file (tmpdir, conftest_file_name, 1730 get_goodcode_snippet ("1.3"))) 1731 { 1732 free (conftest_file_name); 1733 cleanup_temp_dir (tmpdir); 1734 return true; 1735 } 1736 1737 compiled_file_name = 1738 concatenated_filename (tmpdir->dir_name, "conftest.class", NULL); 1739 register_temp_file (tmpdir, compiled_file_name); 1740 1741 java_sources[0] = conftest_file_name; 1742 if (!compile_using_gcj (java_sources, 1, true, false, NULL, false, NULL, 1743 tmpdir->dir_name, false, false, false, true) 1744 && stat (compiled_file_name, &statbuf) >= 0) 1745 /* Compilation succeeded. */ 1746 { 1747 gcj_usable = true; 1748 gcj_need_no_assert_option = true; 1749 } 1750 else 1751 { 1752 unlink (compiled_file_name); 1753 1754 java_sources[0] = conftest_file_name; 1755 if (!compile_using_gcj (java_sources, 1, false, 1756 false, NULL, false, NULL, 1757 tmpdir->dir_name, false, false, false, true) 1758 && stat (compiled_file_name, &statbuf) >= 0) 1759 /* Compilation succeeded. */ 1760 { 1761 gcj_usable = true; 1762 gcj_need_no_assert_option = false; 1763 } 1764 } 1765 1766 free (compiled_file_name); 1767 free (conftest_file_name); 1768 1769 cleanup_temp_dir (tmpdir); 1770 1771 gcj_tested = true; 1772 } 1773 1774 *usablep = gcj_usable; 1775 *need_no_assert_option_p = gcj_need_no_assert_option; 1776 return false; 1777} 1778 1779static bool 1780is_javac_present (void) 1781{ 1782 static bool javac_tested; 1783 static bool javac_present; 1784 1785 if (!javac_tested) 1786 { 1787 /* Test for presence of javac: "javac 2> /dev/null ; test $? -le 2" */ 1788 char *argv[2]; 1789 int exitstatus; 1790 1791 argv[0] = "javac"; 1792 argv[1] = NULL; 1793 exitstatus = execute ("javac", "javac", argv, false, false, true, true, 1794 true, false); 1795 javac_present = (exitstatus == 0 || exitstatus == 1 || exitstatus == 2); 1796 javac_tested = true; 1797 } 1798 1799 return javac_present; 1800} 1801 1802/* Test whether javac can be used and whether it needs a -source and/or 1803 -target option. 1804 Return a failure indicator (true upon error). */ 1805static bool 1806is_javac_usable (const char *source_version, const char *target_version, 1807 bool *usablep, bool *source_option_p, bool *target_option_p) 1808{ 1809 /* The cache depends on the source_version and target_version. */ 1810 struct result_t 1811 { 1812 bool tested; 1813 bool usable; 1814 bool source_option; 1815 bool target_option; 1816 }; 1817 static struct result_t result_cache[SOURCE_VERSION_BOUND][TARGET_VERSION_BOUND]; 1818 struct result_t *resultp; 1819 1820 resultp = &result_cache[source_version_index (source_version)] 1821 [target_version_index (target_version)]; 1822 if (!resultp->tested) 1823 { 1824 /* Try javac. */ 1825 struct temp_dir *tmpdir; 1826 char *conftest_file_name; 1827 char *compiled_file_name; 1828 const char *java_sources[1]; 1829 struct stat statbuf; 1830 1831 tmpdir = create_temp_dir ("java", NULL, false); 1832 if (tmpdir == NULL) 1833 return true; 1834 1835 conftest_file_name = 1836 concatenated_filename (tmpdir->dir_name, "conftest.java", NULL); 1837 if (write_temp_file (tmpdir, conftest_file_name, 1838 get_goodcode_snippet (source_version))) 1839 { 1840 free (conftest_file_name); 1841 cleanup_temp_dir (tmpdir); 1842 return true; 1843 } 1844 1845 compiled_file_name = 1846 concatenated_filename (tmpdir->dir_name, "conftest.class", NULL); 1847 register_temp_file (tmpdir, compiled_file_name); 1848 1849 java_sources[0] = conftest_file_name; 1850 if (!compile_using_javac (java_sources, 1, 1851 false, source_version, 1852 false, target_version, 1853 tmpdir->dir_name, false, false, false, true) 1854 && stat (compiled_file_name, &statbuf) >= 0 1855 && get_classfile_version (compiled_file_name) 1856 <= corresponding_classfile_version (target_version)) 1857 { 1858 /* javac compiled conftest.java successfully. */ 1859 /* Try adding -source option if it is useful. */ 1860 unlink (compiled_file_name); 1861 1862 java_sources[0] = conftest_file_name; 1863 if (!compile_using_javac (java_sources, 1, 1864 true, source_version, 1865 false, target_version, 1866 tmpdir->dir_name, false, false, false, true) 1867 && stat (compiled_file_name, &statbuf) >= 0 1868 && get_classfile_version (compiled_file_name) 1869 <= corresponding_classfile_version (target_version)) 1870 { 1871 const char *failcode = get_failcode_snippet (source_version); 1872 1873 if (failcode != NULL) 1874 { 1875 free (compiled_file_name); 1876 free (conftest_file_name); 1877 1878 conftest_file_name = 1879 concatenated_filename (tmpdir->dir_name, 1880 "conftestfail.java", 1881 NULL); 1882 if (write_temp_file (tmpdir, conftest_file_name, failcode)) 1883 { 1884 free (conftest_file_name); 1885 cleanup_temp_dir (tmpdir); 1886 return true; 1887 } 1888 1889 compiled_file_name = 1890 concatenated_filename (tmpdir->dir_name, 1891 "conftestfail.class", 1892 NULL); 1893 register_temp_file (tmpdir, compiled_file_name); 1894 1895 java_sources[0] = conftest_file_name; 1896 if (!compile_using_javac (java_sources, 1, 1897 false, source_version, 1898 false, target_version, 1899 tmpdir->dir_name, 1900 false, false, false, true) 1901 && stat (compiled_file_name, &statbuf) >= 0) 1902 { 1903 unlink (compiled_file_name); 1904 1905 java_sources[0] = conftest_file_name; 1906 if (compile_using_javac (java_sources, 1, 1907 true, source_version, 1908 false, target_version, 1909 tmpdir->dir_name, 1910 false, false, false, true)) 1911 /* javac compiled conftestfail.java successfully, and 1912 "javac -source $source_version" rejects it. So the 1913 -source option is useful. */ 1914 resultp->source_option = true; 1915 } 1916 } 1917 } 1918 1919 resultp->usable = true; 1920 } 1921 else 1922 { 1923 /* Try with -target option alone. (Sun javac 1.3.1 has the -target 1924 option but no -source option.) */ 1925 unlink (compiled_file_name); 1926 1927 java_sources[0] = conftest_file_name; 1928 if (!compile_using_javac (java_sources, 1, 1929 false, source_version, 1930 true, target_version, 1931 tmpdir->dir_name, 1932 false, false, false, true) 1933 && stat (compiled_file_name, &statbuf) >= 0 1934 && get_classfile_version (compiled_file_name) 1935 <= corresponding_classfile_version (target_version)) 1936 { 1937 /* "javac -target $target_version" compiled conftest.java 1938 successfully. */ 1939 /* Try adding -source option if it is useful. */ 1940 unlink (compiled_file_name); 1941 1942 java_sources[0] = conftest_file_name; 1943 if (!compile_using_javac (java_sources, 1, 1944 true, source_version, 1945 true, target_version, 1946 tmpdir->dir_name, 1947 false, false, false, true) 1948 && stat (compiled_file_name, &statbuf) >= 0 1949 && get_classfile_version (compiled_file_name) 1950 <= corresponding_classfile_version (target_version)) 1951 { 1952 const char *failcode = get_failcode_snippet (source_version); 1953 1954 if (failcode != NULL) 1955 { 1956 free (compiled_file_name); 1957 free (conftest_file_name); 1958 1959 conftest_file_name = 1960 concatenated_filename (tmpdir->dir_name, 1961 "conftestfail.java", 1962 NULL); 1963 if (write_temp_file (tmpdir, conftest_file_name, 1964 failcode)) 1965 { 1966 free (conftest_file_name); 1967 cleanup_temp_dir (tmpdir); 1968 return true; 1969 } 1970 1971 compiled_file_name = 1972 concatenated_filename (tmpdir->dir_name, 1973 "conftestfail.class", 1974 NULL); 1975 register_temp_file (tmpdir, compiled_file_name); 1976 1977 java_sources[0] = conftest_file_name; 1978 if (!compile_using_javac (java_sources, 1, 1979 false, source_version, 1980 true, target_version, 1981 tmpdir->dir_name, 1982 false, false, false, true) 1983 && stat (compiled_file_name, &statbuf) >= 0) 1984 { 1985 unlink (compiled_file_name); 1986 1987 java_sources[0] = conftest_file_name; 1988 if (compile_using_javac (java_sources, 1, 1989 true, source_version, 1990 true, target_version, 1991 tmpdir->dir_name, 1992 false, false, false, true)) 1993 /* "javac -target $target_version" compiled 1994 conftestfail.java successfully, and 1995 "javac -target $target_version -source $source_version" 1996 rejects it. So the -source option is useful. */ 1997 resultp->source_option = true; 1998 } 1999 } 2000 } 2001 2002 resultp->target_option = true; 2003 resultp->usable = true; 2004 } 2005 else 2006 { 2007 /* Maybe this -target option requires a -source option? Try with 2008 -target and -source options. (Supported by Sun javac 1.4 and 2009 higher.) */ 2010 unlink (compiled_file_name); 2011 2012 java_sources[0] = conftest_file_name; 2013 if (!compile_using_javac (java_sources, 1, 2014 true, source_version, 2015 true, target_version, 2016 tmpdir->dir_name, 2017 false, false, false, true) 2018 && stat (compiled_file_name, &statbuf) >= 0 2019 && get_classfile_version (compiled_file_name) 2020 <= corresponding_classfile_version (target_version)) 2021 { 2022 /* "javac -target $target_version -source $source_version" 2023 compiled conftest.java successfully. */ 2024 resultp->source_option = true; 2025 resultp->target_option = true; 2026 resultp->usable = true; 2027 } 2028 } 2029 } 2030 2031 free (compiled_file_name); 2032 free (conftest_file_name); 2033 2034 resultp->tested = true; 2035 } 2036 2037 *usablep = resultp->usable; 2038 *source_option_p = resultp->source_option; 2039 *target_option_p = resultp->target_option; 2040 return false; 2041} 2042 2043static bool 2044is_jikes_present (void) 2045{ 2046 static bool jikes_tested; 2047 static bool jikes_present; 2048 2049 if (!jikes_tested) 2050 { 2051 /* Test for presence of jikes: "jikes 2> /dev/null ; test $? = 1" */ 2052 char *argv[2]; 2053 int exitstatus; 2054 2055 argv[0] = "jikes"; 2056 argv[1] = NULL; 2057 exitstatus = execute ("jikes", "jikes", argv, false, false, true, true, 2058 true, false); 2059 jikes_present = (exitstatus == 0 || exitstatus == 1); 2060 jikes_tested = true; 2061 } 2062 2063 return jikes_present; 2064} 2065 2066/* ============================= Main function ============================= */ 2067 2068bool 2069compile_java_class (const char * const *java_sources, 2070 unsigned int java_sources_count, 2071 const char * const *classpaths, 2072 unsigned int classpaths_count, 2073 const char *source_version, 2074 const char *target_version, 2075 const char *directory, 2076 bool optimize, bool debug, 2077 bool use_minimal_classpath, 2078 bool verbose) 2079{ 2080 bool err = false; 2081 char *old_JAVA_HOME; 2082 2083 { 2084 const char *javac = getenv ("JAVAC"); 2085 if (javac != NULL && javac[0] != '\0') 2086 { 2087 bool usable = false; 2088 bool no_assert_option = false; 2089 bool source_option = false; 2090 bool target_option = false; 2091 bool fsource_option = false; 2092 bool ftarget_option = false; 2093 2094 if (target_version == NULL) 2095 target_version = default_target_version (); 2096 2097 if (is_envjavac_gcj (javac)) 2098 { 2099 /* It's a version of gcj. */ 2100 if (is_envjavac_gcj43 (javac)) 2101 { 2102 /* It's a version of gcj >= 4.3. Assume the classfile versions 2103 are correct. */ 2104 if (is_envjavac_gcj43_usable (javac, 2105 source_version, target_version, 2106 &usable, 2107 &fsource_option, &ftarget_option)) 2108 { 2109 err = true; 2110 goto done1; 2111 } 2112 } 2113 else 2114 { 2115 /* It's a version of gcj < 4.3. Ignore the version of the 2116 class files that it creates. */ 2117 if (strcmp (target_version, "1.4") == 0 2118 && strcmp (source_version, "1.4") == 0) 2119 { 2120 if (is_envjavac_oldgcj_14_14_usable (javac, &usable)) 2121 { 2122 err = true; 2123 goto done1; 2124 } 2125 } 2126 else if (strcmp (target_version, "1.4") == 0 2127 && strcmp (source_version, "1.3") == 0) 2128 { 2129 if (is_envjavac_oldgcj_14_13_usable (javac, 2130 &usable, 2131 &no_assert_option)) 2132 { 2133 err = true; 2134 goto done1; 2135 } 2136 } 2137 } 2138 } 2139 else 2140 { 2141 /* It's not gcj. Assume the classfile versions are correct. */ 2142 if (is_envjavac_nongcj_usable (javac, 2143 source_version, target_version, 2144 &usable, 2145 &source_option, &target_option)) 2146 { 2147 err = true; 2148 goto done1; 2149 } 2150 } 2151 2152 if (usable) 2153 { 2154 char *old_classpath; 2155 char *javac_with_options; 2156 2157 /* Set CLASSPATH. */ 2158 old_classpath = 2159 set_classpath (classpaths, classpaths_count, false, verbose); 2160 2161 javac_with_options = 2162 (no_assert_option 2163 ? xasprintf ("%s -fno-assert", javac) 2164 : xasprintf ("%s%s%s%s%s%s%s%s%s", 2165 javac, 2166 source_option ? " -source " : "", 2167 source_option ? source_version : "", 2168 target_option ? " -target " : "", 2169 target_option ? target_version : "", 2170 fsource_option ? " -fsource=" : "", 2171 fsource_option ? source_version : "", 2172 ftarget_option ? " -ftarget=" : "", 2173 ftarget_option ? target_version : "")); 2174 2175 err = compile_using_envjavac (javac_with_options, 2176 java_sources, java_sources_count, 2177 directory, optimize, debug, verbose, 2178 false); 2179 2180 free (javac_with_options); 2181 2182 /* Reset CLASSPATH. */ 2183 reset_classpath (old_classpath); 2184 2185 goto done1; 2186 } 2187 } 2188 } 2189 2190 /* Unset the JAVA_HOME environment variable. */ 2191 old_JAVA_HOME = getenv ("JAVA_HOME"); 2192 if (old_JAVA_HOME != NULL) 2193 { 2194 old_JAVA_HOME = xstrdup (old_JAVA_HOME); 2195 unsetenv ("JAVA_HOME"); 2196 } 2197 2198 if (is_gcj_present ()) 2199 { 2200 /* It's a version of gcj. */ 2201 bool usable = false; 2202 bool no_assert_option = false; 2203 bool fsource_option = false; 2204 bool ftarget_option = false; 2205 2206 if (target_version == NULL) 2207 target_version = default_target_version (); 2208 2209 if (is_gcj_43 ()) 2210 { 2211 /* It's a version of gcj >= 4.3. Assume the classfile versions 2212 are correct. */ 2213 if (is_gcj43_usable (source_version, target_version, 2214 &usable, &fsource_option, &ftarget_option)) 2215 { 2216 err = true; 2217 goto done1; 2218 } 2219 } 2220 else 2221 { 2222 /* It's a version of gcj < 4.3. Ignore the version of the class 2223 files that it creates. 2224 Test whether it supports the desired target-version and 2225 source-version. */ 2226 if (strcmp (target_version, "1.4") == 0 2227 && strcmp (source_version, "1.4") == 0) 2228 { 2229 if (is_oldgcj_14_14_usable (&usable)) 2230 { 2231 err = true; 2232 goto done1; 2233 } 2234 } 2235 else if (strcmp (target_version, "1.4") == 0 2236 && strcmp (source_version, "1.3") == 0) 2237 { 2238 if (is_oldgcj_14_13_usable (&usable, &no_assert_option)) 2239 { 2240 err = true; 2241 goto done1; 2242 } 2243 } 2244 } 2245 2246 if (usable) 2247 { 2248 char *old_classpath; 2249 2250 /* Set CLASSPATH. We could also use the --CLASSPATH=... option 2251 of gcj. Note that --classpath=... option is different: its 2252 argument should also contain gcj's libgcj.jar, but we don't 2253 know its location. */ 2254 old_classpath = 2255 set_classpath (classpaths, classpaths_count, use_minimal_classpath, 2256 verbose); 2257 2258 err = compile_using_gcj (java_sources, java_sources_count, 2259 no_assert_option, 2260 fsource_option, source_version, 2261 ftarget_option, target_version, 2262 directory, optimize, debug, verbose, false); 2263 2264 /* Reset CLASSPATH. */ 2265 reset_classpath (old_classpath); 2266 2267 goto done2; 2268 } 2269 } 2270 2271 if (is_javac_present ()) 2272 { 2273 bool usable = false; 2274 bool source_option = false; 2275 bool target_option = false; 2276 2277 if (target_version == NULL) 2278 target_version = default_target_version (); 2279 2280 if (is_javac_usable (source_version, target_version, 2281 &usable, &source_option, &target_option)) 2282 { 2283 err = true; 2284 goto done1; 2285 } 2286 2287 if (usable) 2288 { 2289 char *old_classpath; 2290 2291 /* Set CLASSPATH. We don't use the "-classpath ..." option because 2292 in JDK 1.1.x its argument should also contain the JDK's 2293 classes.zip, but we don't know its location. (In JDK 1.3.0 it 2294 would work.) */ 2295 old_classpath = 2296 set_classpath (classpaths, classpaths_count, use_minimal_classpath, 2297 verbose); 2298 2299 err = compile_using_javac (java_sources, java_sources_count, 2300 source_option, source_version, 2301 target_option, target_version, 2302 directory, optimize, debug, verbose, 2303 false); 2304 2305 /* Reset CLASSPATH. */ 2306 reset_classpath (old_classpath); 2307 2308 goto done2; 2309 } 2310 } 2311 2312 if (is_jikes_present ()) 2313 { 2314 /* Test whether it supports the desired target-version and 2315 source-version. */ 2316 bool usable = (strcmp (source_version, "1.3") == 0); 2317 2318 if (usable) 2319 { 2320 char *old_classpath; 2321 2322 /* Set CLASSPATH. We could also use the "-classpath ..." option. 2323 Since jikes doesn't come with its own standard library, it 2324 needs a classes.zip or rt.jar or libgcj.jar in the CLASSPATH. 2325 To increase the chance of success, we reuse the current CLASSPATH 2326 if the user has set it. */ 2327 old_classpath = 2328 set_classpath (classpaths, classpaths_count, false, verbose); 2329 2330 err = compile_using_jikes (java_sources, java_sources_count, 2331 directory, optimize, debug, verbose, 2332 false); 2333 2334 /* Reset CLASSPATH. */ 2335 reset_classpath (old_classpath); 2336 2337 goto done2; 2338 } 2339 } 2340 2341 error (0, 0, _("Java compiler not found, try installing gcj or set $JAVAC")); 2342 err = true; 2343 2344 done2: 2345 if (old_JAVA_HOME != NULL) 2346 { 2347 xsetenv ("JAVA_HOME", old_JAVA_HOME, 1); 2348 free (old_JAVA_HOME); 2349 } 2350 2351 done1: 2352 return err; 2353} 2354