You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Javac.java 32 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914
  1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. * Copyright (c) 1999 The Apache Software Foundation. All rights
  5. * reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the
  17. * distribution.
  18. *
  19. * 3. The end-user documentation included with the redistribution, if
  20. * any, must include the following acknowlegement:
  21. * "This product includes software developed by the
  22. * Apache Software Foundation (http://www.apache.org/)."
  23. * Alternately, this acknowlegement may appear in the software itself,
  24. * if and wherever such third-party acknowlegements normally appear.
  25. *
  26. * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
  27. * Foundation" must not be used to endorse or promote products derived
  28. * from this software without prior written permission. For written
  29. * permission, please contact apache@apache.org.
  30. *
  31. * 5. Products derived from this software may not be called "Apache"
  32. * nor may "Apache" appear in their names without prior written
  33. * permission of the Apache Group.
  34. *
  35. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46. * SUCH DAMAGE.
  47. * ====================================================================
  48. *
  49. * This software consists of voluntary contributions made by many
  50. * individuals on behalf of the Apache Software Foundation. For more
  51. * information on the Apache Software Foundation, please see
  52. * <http://www.apache.org/>.
  53. */
  54. package org.apache.tools.ant.taskdefs;
  55. import org.apache.tools.ant.BuildException;
  56. import org.apache.tools.ant.DirectoryScanner;
  57. import org.apache.tools.ant.Project;
  58. import org.apache.tools.ant.types.*;
  59. import org.apache.tools.ant.util.*;
  60. import java.lang.reflect.Method;
  61. import java.lang.reflect.Constructor;
  62. import java.io.*;
  63. import java.util.*;
  64. /**
  65. * Task to compile Java source files. This task can take the following
  66. * arguments:
  67. * <ul>
  68. * <li>sourcedir
  69. * <li>destdir
  70. * <li>deprecation
  71. * <li>classpath
  72. * <li>bootclasspath
  73. * <li>extdirs
  74. * <li>optimize
  75. * <li>debug
  76. * <li>encoding
  77. * <li>target
  78. * <li>depend
  79. * <li>vebose
  80. * </ul>
  81. * Of these arguments, the <b>sourcedir</b> and <b>destdir</b> are required.
  82. * <p>
  83. * When this task executes, it will recursively scan the sourcedir and
  84. * destdir looking for Java source files to compile. This task makes its
  85. * compile decision based on timestamp.
  86. *
  87. * @author James Davidson <a href="mailto:duncan@x180.com">duncan@x180.com</a>
  88. * @author Robin Green <a href="mailto:greenrd@hotmail.com">greenrd@hotmail.com</a>
  89. * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
  90. */
  91. public class Javac extends MatchingTask {
  92. /**
  93. * Integer returned by the "Modern" jdk1.3 compiler to indicate success.
  94. */
  95. private static final int
  96. MODERN_COMPILER_SUCCESS = 0;
  97. private static final String FAIL_MSG = "Compile failed, messages should have been provided.";
  98. private Path src;
  99. private File destDir;
  100. private Path compileClasspath;
  101. private String encoding;
  102. private boolean debug = false;
  103. private boolean optimize = false;
  104. private boolean deprecation = false;
  105. private boolean depend = false;
  106. private boolean verbose = false;
  107. private String target;
  108. private Path bootclasspath;
  109. private Path extdirs;
  110. private static String lSep = System.getProperty("line.separator");
  111. protected File[] compileList = new File[0];
  112. /**
  113. * Create a nested <src ...> element for multiple source path
  114. * support.
  115. *
  116. * @return a nexted src element.
  117. */
  118. public Path createSrc() {
  119. if (src == null) {
  120. src = new Path(project);
  121. }
  122. return src.createPath();
  123. }
  124. /**
  125. * Set the source dirs to find the source Java files.
  126. */
  127. public void setSrcdir(Path srcDir) {
  128. if (src == null) {
  129. src = srcDir;
  130. } else {
  131. src.append(srcDir);
  132. }
  133. }
  134. /**
  135. * Set the destination directory into which the Java source
  136. * files should be compiled.
  137. */
  138. public void setDestdir(File destDir) {
  139. this.destDir = destDir;
  140. }
  141. /**
  142. * Set the classpath to be used for this compilation.
  143. */
  144. public void setClasspath(Path classpath) {
  145. if (compileClasspath == null) {
  146. compileClasspath = classpath;
  147. } else {
  148. compileClasspath.append(classpath);
  149. }
  150. }
  151. /**
  152. * Maybe creates a nested classpath element.
  153. */
  154. public Path createClasspath() {
  155. if (compileClasspath == null) {
  156. compileClasspath = new Path(project);
  157. }
  158. return compileClasspath.createPath();
  159. }
  160. /**
  161. * Adds a reference to a CLASSPATH defined elsewhere.
  162. */
  163. public void setClasspathRef(Reference r) {
  164. createClasspath().setRefid(r);
  165. }
  166. /**
  167. * Sets the bootclasspath that will be used to compile the classes
  168. * against.
  169. */
  170. public void setBootclasspath(Path bootclasspath) {
  171. if (this.bootclasspath == null) {
  172. this.bootclasspath = bootclasspath;
  173. } else {
  174. this.bootclasspath.append(bootclasspath);
  175. }
  176. }
  177. /**
  178. * Maybe creates a nested classpath element.
  179. */
  180. public Path createBootclasspath() {
  181. if (bootclasspath == null) {
  182. bootclasspath = new Path(project);
  183. }
  184. return bootclasspath.createPath();
  185. }
  186. /**
  187. * Adds a reference to a CLASSPATH defined elsewhere.
  188. */
  189. public void setBootClasspathRef(Reference r) {
  190. createBootclasspath().setRefid(r);
  191. }
  192. /**
  193. * Sets the extension directories that will be used during the
  194. * compilation.
  195. */
  196. public void setExtdirs(Path extdirs) {
  197. if (this.extdirs == null) {
  198. this.extdirs = extdirs;
  199. } else {
  200. this.extdirs.append(extdirs);
  201. }
  202. }
  203. /**
  204. * Maybe creates a nested classpath element.
  205. */
  206. public Path createExtdirs() {
  207. if (extdirs == null) {
  208. extdirs = new Path(project);
  209. }
  210. return extdirs.createPath();
  211. }
  212. /**
  213. * Set the deprecation flag.
  214. */
  215. public void setDeprecation(boolean deprecation) {
  216. this.deprecation = deprecation;
  217. }
  218. /**
  219. * Set the Java source file encoding name.
  220. */
  221. public void setEncoding(String encoding) {
  222. this.encoding = encoding;
  223. }
  224. /**
  225. * Set the debug flag.
  226. */
  227. public void setDebug(boolean debug) {
  228. this.debug = debug;
  229. }
  230. /**
  231. * Set the optimize flag.
  232. */
  233. public void setOptimize(boolean optimize) {
  234. this.optimize = optimize;
  235. }
  236. /**
  237. * Set the depend flag.
  238. */
  239. public void setDepend(boolean depend) {
  240. this.depend = depend;
  241. }
  242. /**
  243. * Set the verbose flag.
  244. */
  245. public void setVerbose(boolean verbose) {
  246. this.verbose = verbose;
  247. }
  248. /**
  249. * Sets the target VM that the classes will be compiled for. Valid
  250. * strings are "1.1", "1.2", and "1.3".
  251. */
  252. public void setTarget(String target) {
  253. this.target = target;
  254. }
  255. /**
  256. * Executes the task.
  257. */
  258. public void execute() throws BuildException {
  259. // first off, make sure that we've got a srcdir
  260. if (src == null) {
  261. throw new BuildException("srcdir attribute must be set!", location);
  262. }
  263. String [] list = src.list();
  264. if (list.length == 0) {
  265. throw new BuildException("srcdir attribute must be set!", location);
  266. }
  267. if (destDir != null && !destDir.isDirectory()) {
  268. throw new BuildException("destination directory \"" + destDir + "\" does not exist or is not a directory", location);
  269. }
  270. // scan source directories and dest directory to build up both copy lists and
  271. // compile lists
  272. resetFileLists();
  273. for (int i=0; i<list.length; i++) {
  274. File srcDir = (File)project.resolveFile(list[i]);
  275. if (!srcDir.exists()) {
  276. throw new BuildException("srcdir \"" + srcDir.getPath() + "\" does not exist!", location);
  277. }
  278. DirectoryScanner ds = this.getDirectoryScanner(srcDir);
  279. String[] files = ds.getIncludedFiles();
  280. scanDir(srcDir, destDir != null ? destDir : srcDir, files);
  281. }
  282. // compile the source files
  283. String compiler = project.getProperty("build.compiler");
  284. if (compiler == null) {
  285. if (Project.getJavaVersion().startsWith("1.3")) {
  286. compiler = "modern";
  287. } else {
  288. compiler = "classic";
  289. }
  290. }
  291. if (compileList.length > 0) {
  292. log("Compiling " + compileList.length +
  293. " source file"
  294. + (compileList.length == 1 ? "" : "s")
  295. + (destDir != null ? " to " + destDir : ""));
  296. if (compiler.equalsIgnoreCase("classic")) {
  297. doClassicCompile();
  298. } else if (compiler.equalsIgnoreCase("modern")) {
  299. doModernCompile();
  300. } else if (compiler.equalsIgnoreCase("jikes")) {
  301. doJikesCompile();
  302. } else if (compiler.equalsIgnoreCase("jvc")) {
  303. doJvcCompile();
  304. } else {
  305. String msg = "Don't know how to use compiler " + compiler;
  306. throw new BuildException(msg, location);
  307. }
  308. }
  309. }
  310. /**
  311. * Clear the list of files to be compiled and copied..
  312. */
  313. protected void resetFileLists() {
  314. compileList = new File[0];
  315. }
  316. /**
  317. * Scans the directory looking for source files to be compiled.
  318. * The results are returned in the class variable compileList
  319. */
  320. protected void scanDir(File srcDir, File destDir, String files[]) {
  321. GlobPatternMapper m = new GlobPatternMapper();
  322. m.setFrom("*.java");
  323. m.setTo("*.class");
  324. SourceFileScanner sfs = new SourceFileScanner(this);
  325. File[] newFiles = sfs.restrictAsFiles(files, srcDir, destDir, m);
  326. if (newFiles.length > 0) {
  327. File[] newCompileList = new File[compileList.length + newFiles.length];
  328. System.arraycopy(compileList, 0, newCompileList, 0, compileList.length);
  329. System.arraycopy(newFiles, 0, newCompileList, compileList.length, newFiles.length);
  330. compileList = newCompileList;
  331. }
  332. }
  333. /**
  334. * Builds the compilation classpath.
  335. *
  336. * @param addRuntime Shall <code>rt.jar</code> or
  337. * <code>classes.zip</code> be added to the classpath.
  338. */
  339. protected Path getCompileClasspath(boolean addRuntime) {
  340. Path classpath = new Path(project);
  341. // add dest dir to classpath so that previously compiled and
  342. // untouched classes are on classpath
  343. if (destDir != null) {
  344. classpath.setLocation(destDir);
  345. }
  346. // Compine the build classpath with the system classpath, in an
  347. // order determined by the value of build.classpath
  348. if (compileClasspath == null) {
  349. classpath.addExisting(Path.systemClasspath);
  350. } else {
  351. String order = project.getProperty("build.sysclasspath");
  352. if (order == null) order="first";
  353. if (order.equals("only")) {
  354. // only: the developer knows what (s)he is doing
  355. classpath.addExisting(Path.systemClasspath);
  356. } else if (order.equals("last")) {
  357. // last: don't trust the developer
  358. classpath.addExisting(compileClasspath);
  359. classpath.addExisting(Path.systemClasspath);
  360. } else if (order.equals("ignore")) {
  361. // ignore: don't trust anyone
  362. classpath.addExisting(compileClasspath);
  363. addRuntime = true;
  364. } else {
  365. // first: developer could use a little help
  366. classpath.addExisting(Path.systemClasspath);
  367. classpath.addExisting(compileClasspath);
  368. }
  369. }
  370. // optionally add the runtime classes
  371. if (addRuntime) {
  372. if (System.getProperty("java.vendor").toLowerCase().indexOf("microsoft") >= 0) {
  373. // Pull in *.zip from packages directory
  374. FileSet msZipFiles = new FileSet();
  375. msZipFiles.setDir(new File(System.getProperty("java.home") + File.separator + "Packages"));
  376. msZipFiles.setIncludes("*.ZIP");
  377. classpath.addFileset(msZipFiles);
  378. }
  379. else if (Project.getJavaVersion() == Project.JAVA_1_1) {
  380. classpath.addExisting(new Path(null,
  381. System.getProperty("java.home")
  382. + File.separator + "lib"
  383. + File.separator
  384. + "classes.zip"));
  385. } else {
  386. // JDK > 1.1 seems to set java.home to the JRE directory.
  387. classpath.addExisting(new Path(null,
  388. System.getProperty("java.home")
  389. + File.separator + "lib"
  390. + File.separator + "rt.jar"));
  391. // Just keep the old version as well and let addExistingToPath
  392. // sort it out.
  393. classpath.addExisting(new Path(null,
  394. System.getProperty("java.home")
  395. + File.separator +"jre"
  396. + File.separator + "lib"
  397. + File.separator + "rt.jar"));
  398. }
  399. }
  400. return classpath;
  401. }
  402. /**
  403. * Peforms a compile using the classic compiler that shipped with
  404. * JDK 1.1 and 1.2.
  405. */
  406. private void doClassicCompile() throws BuildException {
  407. log("Using classic compiler", Project.MSG_VERBOSE);
  408. Commandline cmd = setupJavacCommand();
  409. // Use reflection to be able to build on all JDKs
  410. /*
  411. // provide the compiler a different message sink - namely our own
  412. sun.tools.javac.Main compiler =
  413. new sun.tools.javac.Main(new LogOutputStream(this, Project.MSG_WARN), "javac");
  414. if (!compiler.compile(cmd.getArguments())) {
  415. throw new BuildException("Compile failed");
  416. }
  417. */
  418. try {
  419. // Create an instance of the compiler, redirecting output to
  420. // the project log
  421. OutputStream logstr = new LogOutputStream(this, Project.MSG_WARN);
  422. Class c = Class.forName("sun.tools.javac.Main");
  423. Constructor cons = c.getConstructor(new Class[] { OutputStream.class, String.class });
  424. Object compiler = cons.newInstance(new Object[] { logstr, "javac" });
  425. // Call the compile() method
  426. Method compile = c.getMethod("compile", new Class [] { String[].class });
  427. Boolean ok = (Boolean)compile.invoke(compiler, new Object[] {cmd.getArguments()});
  428. if (!ok.booleanValue()) {
  429. throw new BuildException(FAIL_MSG, location);
  430. }
  431. }
  432. catch (ClassNotFoundException ex) {
  433. throw new BuildException("Cannot use classic compiler, as it is not available"+
  434. " A common solution is to set the environment variable"+
  435. " JAVA_HOME to your jdk directory.", location);
  436. }
  437. catch (Exception ex) {
  438. if (ex instanceof BuildException) {
  439. throw (BuildException) ex;
  440. } else {
  441. throw new BuildException("Error starting classic compiler: ", ex, location);
  442. }
  443. }
  444. }
  445. /**
  446. * Performs a compile using the newer compiler that ships with JDK 1.3
  447. */
  448. private void doModernCompile() throws BuildException {
  449. try {
  450. Class.forName("com.sun.tools.javac.Main");
  451. } catch (ClassNotFoundException cnfe) {
  452. log("Modern compiler is not available - using classic compiler", Project.MSG_WARN);
  453. doClassicCompile();
  454. return;
  455. }
  456. log("Using modern compiler", Project.MSG_VERBOSE);
  457. Commandline cmd = setupJavacCommand();
  458. PrintStream err = System.err;
  459. PrintStream out = System.out;
  460. // Use reflection to be able to build on all JDKs >= 1.1:
  461. try {
  462. PrintStream logstr =
  463. new PrintStream(new LogOutputStream(this, Project.MSG_WARN));
  464. System.setOut(logstr);
  465. System.setErr(logstr);
  466. Class c = Class.forName ("com.sun.tools.javac.Main");
  467. Object compiler = c.newInstance ();
  468. Method compile = c.getMethod ("compile",
  469. new Class [] {(new String [] {}).getClass ()});
  470. int result = ((Integer) compile.invoke
  471. (compiler, new Object[] {cmd.getArguments()})) .intValue ();
  472. if (result != MODERN_COMPILER_SUCCESS) {
  473. throw new BuildException(FAIL_MSG, location);
  474. }
  475. } catch (Exception ex) {
  476. if (ex instanceof BuildException) {
  477. throw (BuildException) ex;
  478. } else {
  479. throw new BuildException("Error starting modern compiler", ex, location);
  480. }
  481. } finally {
  482. System.setErr(err);
  483. System.setOut(out);
  484. }
  485. }
  486. /**
  487. * Does the command line argument processing common to classic and
  488. * modern.
  489. */
  490. private Commandline setupJavacCommand() {
  491. Commandline cmd = new Commandline();
  492. Path classpath = getCompileClasspath(false);
  493. if (deprecation == true) {
  494. cmd.createArgument().setValue("-deprecation");
  495. }
  496. if (destDir != null) {
  497. cmd.createArgument().setValue("-d");
  498. cmd.createArgument().setFile(destDir);
  499. }
  500. cmd.createArgument().setValue("-classpath");
  501. // Just add "sourcepath" to classpath ( for JDK1.1 )
  502. if (Project.getJavaVersion().startsWith("1.1")) {
  503. cmd.createArgument().setValue(classpath.toString()
  504. + File.pathSeparator
  505. + src.toString());
  506. } else {
  507. cmd.createArgument().setPath(classpath);
  508. cmd.createArgument().setValue("-sourcepath");
  509. cmd.createArgument().setPath(src);
  510. if (target != null) {
  511. cmd.createArgument().setValue("-target");
  512. cmd.createArgument().setValue(target);
  513. }
  514. }
  515. if (encoding != null) {
  516. cmd.createArgument().setValue("-encoding");
  517. cmd.createArgument().setValue(encoding);
  518. }
  519. if (debug) {
  520. cmd.createArgument().setValue("-g");
  521. }
  522. if (optimize) {
  523. cmd.createArgument().setValue("-O");
  524. }
  525. if (bootclasspath != null) {
  526. cmd.createArgument().setValue("-bootclasspath");
  527. cmd.createArgument().setPath(bootclasspath);
  528. }
  529. if (extdirs != null) {
  530. cmd.createArgument().setValue("-extdirs");
  531. cmd.createArgument().setPath(extdirs);
  532. }
  533. if (depend) {
  534. if (Project.getJavaVersion().startsWith("1.1")) {
  535. cmd.createArgument().setValue("-depend");
  536. } else if (Project.getJavaVersion().startsWith("1.2")) {
  537. cmd.createArgument().setValue("-Xdepend");
  538. } else {
  539. log("depend attribute is not supported by the modern compiler",
  540. Project.MSG_WARN);
  541. }
  542. }
  543. if (verbose) {
  544. cmd.createArgument().setValue("-verbose");
  545. }
  546. logAndAddFilesToCompile(cmd);
  547. return cmd;
  548. }
  549. /**
  550. * Logs the compilation parameters, adds the files to compile and logs the
  551. * &qout;niceSourceList&quot;
  552. */
  553. protected void logAndAddFilesToCompile(Commandline cmd) {
  554. log("Compilation args: " + cmd.toString(),
  555. Project.MSG_VERBOSE);
  556. StringBuffer niceSourceList = new StringBuffer("File");
  557. if (compileList.length != 1) {
  558. niceSourceList.append("s");
  559. }
  560. niceSourceList.append(" to be compiled:");
  561. niceSourceList.append(lSep);
  562. for (int i=0; i < compileList.length; i++) {
  563. String arg = compileList[i].getAbsolutePath();
  564. cmd.createArgument().setValue(arg);
  565. niceSourceList.append(" " + arg + lSep);
  566. }
  567. log(niceSourceList.toString(), Project.MSG_VERBOSE);
  568. }
  569. /**
  570. * Performs a compile using the Jikes compiler from IBM..
  571. * Mostly of this code is identical to doClassicCompile()
  572. * However, it does not support all options like
  573. * bootclasspath, extdirs, deprecation and so on, because
  574. * there is no option in jikes and I don't understand
  575. * what they should do.
  576. *
  577. * It has been successfully tested with jikes >1.10
  578. *
  579. * @author skanthak@muehlheim.de
  580. */
  581. private void doJikesCompile() throws BuildException {
  582. log("Using jikes compiler", Project.MSG_VERBOSE);
  583. Path classpath = new Path(project);
  584. // Jikes doesn't support bootclasspath dir (-bootclasspath)
  585. // so we'll emulate it for compatibility and convenience.
  586. if (bootclasspath != null) {
  587. classpath.append(bootclasspath);
  588. }
  589. // Jikes doesn't support an extension dir (-extdir)
  590. // so we'll emulate it for compatibility and convenience.
  591. addExtdirsToClasspath(classpath);
  592. classpath.append(getCompileClasspath(true));
  593. // Jikes has no option for source-path so we
  594. // will add it to classpath.
  595. classpath.append(src);
  596. // if the user has set JIKESPATH we should add the contents as well
  597. String jikesPath = System.getProperty("jikes.class.path");
  598. if (jikesPath != null) {
  599. classpath.append(new Path(project, jikesPath));
  600. }
  601. Commandline cmd = new Commandline();
  602. cmd.setExecutable("jikes");
  603. if (deprecation == true)
  604. cmd.createArgument().setValue("-deprecation");
  605. if (destDir != null) {
  606. cmd.createArgument().setValue("-d");
  607. cmd.createArgument().setFile(destDir);
  608. }
  609. cmd.createArgument().setValue("-classpath");
  610. cmd.createArgument().setPath(classpath);
  611. if (encoding != null) {
  612. cmd.createArgument().setValue("-encoding");
  613. cmd.createArgument().setValue(encoding);
  614. }
  615. if (debug) {
  616. cmd.createArgument().setValue("-g");
  617. }
  618. if (optimize) {
  619. cmd.createArgument().setValue("-O");
  620. }
  621. if (verbose) {
  622. cmd.createArgument().setValue("-verbose");
  623. }
  624. if (depend) {
  625. cmd.createArgument().setValue("-depend");
  626. }
  627. /**
  628. * XXX
  629. * Perhaps we shouldn't use properties for these
  630. * three options (emacs mode, warnings and pedantic),
  631. * but include it in the javac directive?
  632. */
  633. /**
  634. * Jikes has the nice feature to print error
  635. * messages in a form readable by emacs, so
  636. * that emacs can directly set the cursor
  637. * to the place, where the error occured.
  638. */
  639. String emacsProperty = project.getProperty("build.compiler.emacs");
  640. if (emacsProperty != null && Project.toBoolean(emacsProperty)) {
  641. cmd.createArgument().setValue("+E");
  642. }
  643. /**
  644. * Jikes issues more warnings that javac, for
  645. * example, when you have files in your classpath
  646. * that don't exist. As this is often the case, these
  647. * warning can be pretty annoying.
  648. */
  649. String warningsProperty = project.getProperty("build.compiler.warnings");
  650. if (warningsProperty != null && !Project.toBoolean(warningsProperty)) {
  651. cmd.createArgument().setValue("-nowarn");
  652. }
  653. /**
  654. * Jikes can issue pedantic warnings.
  655. */
  656. String pedanticProperty = project.getProperty("build.compiler.pedantic");
  657. if (pedanticProperty != null && Project.toBoolean(pedanticProperty)) {
  658. cmd.createArgument().setValue("+P");
  659. }
  660. /**
  661. * Jikes supports something it calls "full dependency
  662. * checking", see the jikes documentation for differences
  663. * between -depend and +F.
  664. */
  665. String fullDependProperty = project.getProperty("build.compiler.fulldepend");
  666. if (fullDependProperty != null && Project.toBoolean(fullDependProperty)) {
  667. cmd.createArgument().setValue("+F");
  668. }
  669. int firstFileName = cmd.size();
  670. logAndAddFilesToCompile(cmd);
  671. if (executeJikesCompile(cmd.getCommandline(), firstFileName) != 0) {
  672. throw new BuildException(FAIL_MSG, location);
  673. }
  674. }
  675. /**
  676. * Do the compile with the specified arguments.
  677. * @param args - arguments to pass to process on command line
  678. * @param firstFileName - index of the first source file in args
  679. */
  680. protected int executeJikesCompile(String[] args, int firstFileName) {
  681. String[] commandArray = null;
  682. File tmpFile = null;
  683. try {
  684. /*
  685. * Many system have been reported to get into trouble with
  686. * long command lines - no, not only Windows ;-).
  687. *
  688. * POSIX seems to define a lower limit of 4k, so use a temporary
  689. * file if the total length of the command line exceeds this limit.
  690. */
  691. if (Commandline.toString(args).length() > 4096) {
  692. PrintWriter out = null;
  693. try {
  694. tmpFile = new File("jikes"+(new Random(System.currentTimeMillis())).nextLong());
  695. out = new PrintWriter(new FileWriter(tmpFile));
  696. for (int i = firstFileName; i < args.length; i++) {
  697. out.println(args[i]);
  698. }
  699. out.flush();
  700. commandArray = new String[firstFileName+1];
  701. System.arraycopy(args, 0, commandArray, 0, firstFileName);
  702. commandArray[firstFileName] = "@" + tmpFile.getAbsolutePath();
  703. } catch (IOException e) {
  704. throw new BuildException("Error creating temporary file", e, location);
  705. } finally {
  706. if (out != null) {
  707. try {out.close();} catch (Throwable t) {}
  708. }
  709. }
  710. } else {
  711. commandArray = args;
  712. }
  713. try {
  714. Execute exe = new Execute(new LogStreamHandler(this,
  715. Project.MSG_INFO,
  716. Project.MSG_WARN));
  717. exe.setAntRun(project);
  718. exe.setWorkingDirectory(project.getBaseDir());
  719. exe.setCommandline(commandArray);
  720. exe.execute();
  721. return exe.getExitValue();
  722. } catch (IOException e) {
  723. throw new BuildException("Error running Jikes compiler", e, location);
  724. }
  725. } finally {
  726. if (tmpFile != null) {
  727. tmpFile.delete();
  728. }
  729. }
  730. }
  731. /**
  732. * Emulation of extdirs feature in java >= 1.2.
  733. * This method adds all files in the given
  734. * directories (but not in sub-directories!) to the classpath,
  735. * so that you don't have to specify them all one by one.
  736. * @param classpath - Path to append files to
  737. */
  738. protected void addExtdirsToClasspath(Path classpath) {
  739. if (extdirs == null) {
  740. String extProp = System.getProperty("java.ext.dirs");
  741. if (extProp != null) {
  742. extdirs = new Path(project, extProp);
  743. } else {
  744. return;
  745. }
  746. }
  747. String[] dirs = extdirs.list();
  748. for (int i=0; i<dirs.length; i++) {
  749. if (!dirs[i].endsWith(File.separator)) {
  750. dirs[i] += File.separator;
  751. }
  752. File dir = project.resolveFile(dirs[i]);
  753. FileSet fs = new FileSet();
  754. fs.setDir(dir);
  755. fs.setIncludes("*");
  756. classpath.addFileset(fs);
  757. }
  758. }
  759. private void doJvcCompile() throws BuildException {
  760. log("Using jvc compiler", Project.MSG_VERBOSE);
  761. Path classpath = new Path(project);
  762. // jvc doesn't support bootclasspath dir (-bootclasspath)
  763. // so we'll emulate it for compatibility and convenience.
  764. if (bootclasspath != null) {
  765. classpath.append(bootclasspath);
  766. }
  767. // jvc doesn't support an extension dir (-extdir)
  768. // so we'll emulate it for compatibility and convenience.
  769. addExtdirsToClasspath(classpath);
  770. classpath.append(getCompileClasspath(true));
  771. // jvc has no option for source-path so we
  772. // will add it to classpath.
  773. classpath.append(src);
  774. Commandline cmd = new Commandline();
  775. cmd.setExecutable("jvc");
  776. if (destDir != null) {
  777. cmd.createArgument().setValue("/d");
  778. cmd.createArgument().setFile(destDir);
  779. }
  780. // Add the Classpath before the "internal" one.
  781. cmd.createArgument().setValue("/cp:p");
  782. cmd.createArgument().setPath(classpath);
  783. // Enable MS-Extensions and ...
  784. cmd.createArgument().setValue("/x-");
  785. // ... do not display a Message about this.
  786. cmd.createArgument().setValue("/nomessage");
  787. // Do not display Logo
  788. cmd.createArgument().setValue("/nologo");
  789. if (debug) {
  790. cmd.createArgument().setValue("/g");
  791. }
  792. if (optimize) {
  793. cmd.createArgument().setValue("/O");
  794. }
  795. int firstFileName = cmd.size();
  796. logAndAddFilesToCompile(cmd);
  797. if (executeJikesCompile(cmd.getCommandline(), firstFileName) != 0) {
  798. throw new BuildException(FAIL_MSG, location);
  799. }
  800. }
  801. }