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 29 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858
  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.*;
  56. import java.lang.reflect.Method;
  57. import java.io.*;
  58. import java.util.*;
  59. /**
  60. * Task to compile Java source files. This task can take the following
  61. * arguments:
  62. * <ul>
  63. * <li>sourcedir
  64. * <li>destdir
  65. * <li>deprecation
  66. * <li>classpath
  67. * <li>bootclasspath
  68. * <li>extdirs
  69. * <li>optimize
  70. * <li>debug
  71. * <li>target
  72. * </ul>
  73. * Of these arguments, the <b>sourcedir</b> and <b>destdir</b> are required.
  74. * <p>
  75. * When this task executes, it will recursively scan the sourcedir and
  76. * destdir looking for Java source files to compile. This task makes its
  77. * compile decision based on timestamp. Any other file in the
  78. * sourcedir will be copied to the destdir allowing support files to be
  79. * located properly in the classpath.
  80. *
  81. * @author James Davidson <a href="mailto:duncan@x180.com">duncan@x180.com</a>
  82. * @author Robin Green <a href="mailto:greenrd@hotmail.com">greenrd@hotmail.com</a>
  83. */
  84. public class Javac extends MatchingTask {
  85. public class SourcePathElement {
  86. private String path;
  87. public void setPath(String path) {
  88. this.path = path;
  89. }
  90. public String getPath() {
  91. return path;
  92. }
  93. };
  94. /**
  95. * Integer returned by the "Modern" jdk1.3 compiler to indicate success.
  96. */
  97. private static final int
  98. MODERN_COMPILER_SUCCESS = 0;
  99. private Vector srcPathElements = new Vector();
  100. private Vector srcDirs= new Vector();
  101. private File destDir;
  102. private Path compileClasspath;
  103. private boolean debug = false;
  104. private boolean optimize = false;
  105. private boolean deprecation = false;
  106. private boolean filtering = false;
  107. private String target;
  108. private Path bootclasspath;
  109. private Path extdirs;
  110. protected Vector compileList = new Vector();
  111. protected Hashtable filecopyList = new Hashtable();
  112. /**
  113. * Create a nested <src ...> element for multiple source path
  114. * support.
  115. *
  116. * @return a nexted src element.
  117. */
  118. public SourcePathElement createSrc() {
  119. SourcePathElement element = new SourcePathElement();
  120. srcPathElements.addElement(element);
  121. return element;
  122. }
  123. /**
  124. * Add a single directory to the collection of directories that
  125. * make up the source path.
  126. *
  127. * @param srcDirName the name of the directory to add to the list of source directories.
  128. */
  129. private void addSrcDir(String srcDirName) {
  130. addSrcDir(project.resolveFile(srcDirName));
  131. }
  132. /**
  133. * Add a single directory to the collection of directories that
  134. * make up the source path.
  135. *
  136. * @param srcDir the directory to add to the list of source directories.
  137. */
  138. private void addSrcDir(File srcDir) {
  139. srcDirs.addElement(srcDir);
  140. }
  141. /**
  142. * Add a set of source directories specified as path.
  143. *
  144. * @param srcPath the list of source directories.
  145. */
  146. private void addSrcPath(String srcPath) {
  147. // use a Path tokenizer to find the paths and add them to
  148. // the vector of source paths.
  149. PathTokenizer tokenizer = new PathTokenizer(srcPath);
  150. while (tokenizer.hasMoreTokens()) {
  151. addSrcDir(tokenizer.nextToken());
  152. }
  153. }
  154. /**
  155. * Set the source dirs to find the source Java files.
  156. */
  157. public void setSrcdir(String srcPath) {
  158. // clean out the list of source dirs
  159. srcDirs = new Vector();
  160. addSrcPath(srcPath);
  161. }
  162. /**
  163. * Set the destination directory into which the Java source
  164. * files should be compiled.
  165. */
  166. public void setDestdir(File destDir) {
  167. this.destDir = destDir;
  168. }
  169. /**
  170. * Set the classpath to be used for this compilation.
  171. */
  172. public void setClasspath(Path classpath) {
  173. if (compileClasspath == null) {
  174. compileClasspath = classpath;
  175. } else {
  176. compileClasspath.append(classpath);
  177. }
  178. }
  179. /**
  180. * Maybe creates a nested classpath element.
  181. */
  182. public Path createClasspath() {
  183. if (compileClasspath == null) {
  184. compileClasspath = new Path();
  185. }
  186. return compileClasspath;
  187. }
  188. /**
  189. * Sets the bootclasspath that will be used to compile the classes
  190. * against.
  191. */
  192. public void setBootclasspath(Path bootclasspath) {
  193. if (this.bootclasspath == null) {
  194. this.bootclasspath = bootclasspath;
  195. } else {
  196. this.bootclasspath.append(bootclasspath);
  197. }
  198. }
  199. /**
  200. * Maybe creates a nested classpath element.
  201. */
  202. public Path createBootclasspath() {
  203. if (bootclasspath == null) {
  204. bootclasspath = new Path();
  205. }
  206. return bootclasspath;
  207. }
  208. /**
  209. * Sets the extension directories that will be used during the
  210. * compilation.
  211. */
  212. public void setExtdirs(Path extdirs) {
  213. if (this.extdirs == null) {
  214. this.extdirs = extdirs;
  215. } else {
  216. this.extdirs.append(extdirs);
  217. }
  218. }
  219. /**
  220. * Maybe creates a nested classpath element.
  221. */
  222. public Path createExtdirs() {
  223. if (extdirs == null) {
  224. extdirs = new Path();
  225. }
  226. return extdirs;
  227. }
  228. /**
  229. * Set the deprecation flag.
  230. */
  231. public void setDeprecation(boolean deprecation) {
  232. this.deprecation = deprecation;
  233. }
  234. /**
  235. * Set the debug flag.
  236. */
  237. public void setDebug(boolean debug) {
  238. this.debug = debug;
  239. }
  240. /**
  241. * Set the optimize flag.
  242. */
  243. public void setOptimize(boolean optimize) {
  244. this.optimize = optimize;
  245. }
  246. /**
  247. * Sets the target VM that the classes will be compiled for. Valid
  248. * strings are "1.1", "1.2", and "1.3".
  249. */
  250. public void setTarget(String target) {
  251. this.target = target;
  252. }
  253. /**
  254. * Set the filtering flag.
  255. */
  256. public void setFiltering(boolean filter) {
  257. filtering = filter;
  258. }
  259. /**
  260. * Executes the task.
  261. */
  262. public void execute() throws BuildException {
  263. // first off, make sure that we've got a srcdir and destdir
  264. // process the source elements into the srcDirs collection
  265. for (Enumeration e = srcPathElements.elements(); e.hasMoreElements(); ) {
  266. SourcePathElement element = (SourcePathElement)e.nextElement();
  267. addSrcPath(element.getPath());
  268. }
  269. if (srcDirs.size() == 0) {
  270. throw new BuildException("srcdir attribute must be set!");
  271. }
  272. for (Enumeration e = srcDirs.elements(); e.hasMoreElements(); ) {
  273. File srcDir = (File)e.nextElement();
  274. if (!srcDir.exists()) {
  275. throw new BuildException("srcdir " + srcDir.getPath() + " does not exist!");
  276. }
  277. }
  278. if (destDir == null) {
  279. throw new BuildException("destdir attribute must be set!");
  280. }
  281. // scan source directories and dest directory to build up both copy lists and
  282. // compile lists
  283. resetFileLists();
  284. for (Enumeration e = srcDirs.elements(); e.hasMoreElements(); ) {
  285. File srcDir = (File)e.nextElement();
  286. DirectoryScanner ds = this.getDirectoryScanner(srcDir);
  287. String[] files = ds.getIncludedFiles();
  288. scanDir(srcDir, destDir, files);
  289. }
  290. // compile the source files
  291. String compiler = project.getProperty("build.compiler");
  292. if (compiler == null) {
  293. if (Project.getJavaVersion().startsWith("1.3")) {
  294. compiler = "modern";
  295. } else {
  296. compiler = "classic";
  297. }
  298. }
  299. if (compileList.size() > 0) {
  300. log("Compiling " + compileList.size() +
  301. " source files to " + destDir);
  302. if (compiler.equalsIgnoreCase("classic")) {
  303. doClassicCompile();
  304. } else if (compiler.equalsIgnoreCase("modern")) {
  305. doModernCompile();
  306. } else if (compiler.equalsIgnoreCase("jikes")) {
  307. doJikesCompile();
  308. } else {
  309. String msg = "Don't know how to use compiler " + compiler;
  310. throw new BuildException(msg);
  311. }
  312. }
  313. // copy the support files
  314. if (filecopyList.size() > 0) {
  315. log("The implicit copying of support files by javac has been deprecated. " +
  316. "Use the copydir task to copy support files explicitly.",
  317. Project.MSG_WARN);
  318. log("Copying " + filecopyList.size() +
  319. " support files to " + destDir.getAbsolutePath());
  320. Enumeration enum = filecopyList.keys();
  321. while (enum.hasMoreElements()) {
  322. String fromFile = (String) enum.nextElement();
  323. String toFile = (String) filecopyList.get(fromFile);
  324. try {
  325. project.copyFile(fromFile, toFile, filtering);
  326. } catch (IOException ioe) {
  327. String msg = "Failed to copy " + fromFile + " to " + toFile
  328. + " due to " + ioe.getMessage();
  329. throw new BuildException(msg);
  330. }
  331. }
  332. }
  333. }
  334. /**
  335. * Clear the list of files to be compiled and copied..
  336. */
  337. protected void resetFileLists() {
  338. compileList.removeAllElements();
  339. filecopyList.clear();
  340. }
  341. /**
  342. * Scans the directory looking for source files to be compiled and
  343. * support files to be copied. The results are returned in the
  344. * class variables compileList and filecopyList.
  345. */
  346. protected void scanDir(File srcDir, File destDir, String files[]) {
  347. long now = (new Date()).getTime();
  348. for (int i = 0; i < files.length; i++) {
  349. File srcFile = new File(srcDir, files[i]);
  350. if (files[i].endsWith(".java")) {
  351. File classFile = new File(destDir, files[i].substring(0,
  352. files[i].indexOf(".java")) + ".class");
  353. if (srcFile.lastModified() > now) {
  354. log("Warning: file modified in the future: " +
  355. files[i], Project.MSG_WARN);
  356. }
  357. if (srcFile.lastModified() > classFile.lastModified()) {
  358. compileList.addElement(srcFile.getAbsolutePath());
  359. }
  360. } else {
  361. File destFile = new File(destDir, files[i]);
  362. if (srcFile.lastModified() > destFile.lastModified()) {
  363. filecopyList.put(srcFile.getAbsolutePath(),
  364. destFile.getAbsolutePath());
  365. }
  366. }
  367. }
  368. }
  369. /**
  370. * Builds the compilation classpath.
  371. */
  372. // XXX
  373. // we need a way to not use the current classpath.
  374. /**
  375. * @param addRuntime Shall <code>rt.jar</code> or
  376. * <code>classes.zip</code> be added to the classpath.
  377. */
  378. private String getCompileClasspath(boolean addRuntime) {
  379. Path classpath = new Path();
  380. // add dest dir to classpath so that previously compiled and
  381. // untouched classes are on classpath
  382. //classpath.append(sourceDir.getAbsolutePath());
  383. //classpath.append(File.pathSeparator);
  384. classpath.setLocation(destDir.getAbsolutePath());
  385. // add our classpath to the mix
  386. if (compileClasspath != null) {
  387. addExistingToClasspath(classpath,compileClasspath);
  388. }
  389. // add the system classpath
  390. addExistingToClasspath(classpath, Path.systemClasspath);
  391. if (addRuntime) {
  392. if (Project.getJavaVersion() == Project.JAVA_1_1) {
  393. addExistingToClasspath(classpath,
  394. new Path(System.getProperty("java.home")
  395. + File.separator + "lib"
  396. + File.separator
  397. + "classes.zip"));
  398. } else {
  399. // JDK > 1.1 seems to set java.home to the JRE directory.
  400. addExistingToClasspath(classpath,
  401. new Path(System.getProperty("java.home")
  402. + File.separator + "lib"
  403. + File.separator + "rt.jar"));
  404. // Just keep the old version as well and let addExistingToPath
  405. // sort it out.
  406. addExistingToClasspath(classpath,
  407. new Path(System.getProperty("java.home")
  408. + File.separator +"jre"
  409. + File.separator + "lib"
  410. + File.separator + "rt.jar"));
  411. }
  412. }
  413. return classpath.toString();
  414. }
  415. /**
  416. * Takes a classpath-like string, and adds each element of
  417. * this string to a new classpath, if the components exist.
  418. * Components that don't exist, aren't added.
  419. * We do this, because jikes issues warnings for non-existant
  420. * files/dirs in his classpath, and these warnings are pretty
  421. * annoying.
  422. * @param target - target classpath
  423. * @param source - source classpath
  424. * to get file objects.
  425. */
  426. private void addExistingToClasspath(Path target, Path source) {
  427. String[] list = source.list();
  428. for (int i=0; i<list.length; i++) {
  429. File f = project.resolveFile(list[i]);
  430. if (f.exists()) {
  431. target.setLocation(f.getAbsolutePath());
  432. } else {
  433. log("Dropping from classpath: "+
  434. f.getAbsolutePath(), Project.MSG_VERBOSE);
  435. }
  436. }
  437. }
  438. /**
  439. * Get the list of source directories separated by a platform specific
  440. * path separator.
  441. *
  442. * @return the current source directories in a single path separated using the
  443. * platform specific path separator.
  444. */
  445. private String getSourcePath() {
  446. String sourcePath = "";
  447. for (Enumeration e = srcDirs.elements(); e.hasMoreElements(); ) {
  448. File srcDir = (File)e.nextElement();
  449. if (sourcePath.length() != 0) {
  450. sourcePath += File.pathSeparator;
  451. }
  452. sourcePath += srcDir.getAbsolutePath();
  453. }
  454. return sourcePath;
  455. }
  456. /**
  457. * Peforms a copmile using the classic compiler that shipped with
  458. * JDK 1.1 and 1.2.
  459. */
  460. private void doClassicCompile() throws BuildException {
  461. log("Using classic compiler", Project.MSG_VERBOSE);
  462. String classpath = getCompileClasspath(false);
  463. Vector argList = new Vector();
  464. if (deprecation == true)
  465. argList.addElement("-deprecation");
  466. argList.addElement("-d");
  467. argList.addElement(destDir.getAbsolutePath());
  468. argList.addElement("-classpath");
  469. // Just add "sourcepath" to classpath ( for JDK1.1 )
  470. if (Project.getJavaVersion().startsWith("1.1")) {
  471. argList.addElement(classpath.toString() + File.pathSeparator +
  472. getSourcePath());
  473. } else {
  474. argList.addElement(classpath.toString());
  475. argList.addElement("-sourcepath");
  476. argList.addElement(getSourcePath());
  477. if (target != null) {
  478. argList.addElement("-target");
  479. argList.addElement(target);
  480. }
  481. }
  482. if (debug) {
  483. argList.addElement("-g");
  484. }
  485. if (optimize) {
  486. argList.addElement("-O");
  487. }
  488. if (bootclasspath != null) {
  489. argList.addElement("-bootclasspath");
  490. argList.addElement(bootclasspath.toString());
  491. }
  492. if (extdirs != null) {
  493. argList.addElement("-extdirs");
  494. argList.addElement(extdirs.toString());
  495. }
  496. log("Compilation args: " + argList.toString(),
  497. Project.MSG_VERBOSE);
  498. String[] args = new String[argList.size() + compileList.size()];
  499. int counter = 0;
  500. for (int i = 0; i < argList.size(); i++) {
  501. args[i] = (String)argList.elementAt(i);
  502. counter++;
  503. }
  504. // XXX
  505. // should be using system independent line feed!
  506. StringBuffer niceSourceList = new StringBuffer("Files to be compiled:"
  507. + "\r\n");
  508. Enumeration enum = compileList.elements();
  509. while (enum.hasMoreElements()) {
  510. args[counter] = (String)enum.nextElement();
  511. niceSourceList.append(" " + args[counter] + "\r\n");
  512. counter++;
  513. }
  514. log(niceSourceList.toString(), Project.MSG_VERBOSE);
  515. // XXX
  516. // provide the compiler a different message sink - namely our own
  517. ByteArrayOutputStream out = new ByteArrayOutputStream();
  518. sun.tools.javac.Main compiler =
  519. new sun.tools.javac.Main(new TaskOutputStream(this, Project.MSG_WARN), "javac");
  520. if (!compiler.compile(args)) {
  521. throw new BuildException("Compile failed");
  522. }
  523. }
  524. /**
  525. * Performs a compile using the newer compiler that ships with JDK 1.3
  526. */
  527. private void doModernCompile() throws BuildException {
  528. try {
  529. Class.forName("com.sun.tools.javac.Main");
  530. } catch (ClassNotFoundException cnfe) {
  531. doClassicCompile();
  532. return;
  533. }
  534. log("Using modern compiler", Project.MSG_VERBOSE);
  535. String classpath = getCompileClasspath(false);
  536. Vector argList = new Vector();
  537. if (deprecation == true)
  538. argList.addElement("-deprecation");
  539. argList.addElement("-d");
  540. argList.addElement(destDir.getAbsolutePath());
  541. argList.addElement("-classpath");
  542. argList.addElement(classpath.toString());
  543. argList.addElement("-sourcepath");
  544. argList.addElement(getSourcePath());
  545. if (target != null) {
  546. argList.addElement("-target");
  547. argList.addElement(target);
  548. }
  549. if (debug) {
  550. argList.addElement("-g");
  551. }
  552. if (optimize) {
  553. argList.addElement("-O");
  554. }
  555. if (bootclasspath != null) {
  556. argList.addElement("-bootclasspath");
  557. argList.addElement(bootclasspath.toString());
  558. }
  559. if (extdirs != null) {
  560. argList.addElement("-extdirs");
  561. argList.addElement(extdirs.toString());
  562. }
  563. log("Compilation args: " + argList.toString(),
  564. Project.MSG_VERBOSE);
  565. String[] args = new String[argList.size() + compileList.size()];
  566. int counter = 0;
  567. for (int i = 0; i < argList.size(); i++) {
  568. args[i] = (String)argList.elementAt(i);
  569. counter++;
  570. }
  571. // XXX
  572. // should be using system independent line feed!
  573. StringBuffer niceSourceList = new StringBuffer("Files to be compiled:"
  574. + "\r\n");
  575. Enumeration enum = compileList.elements();
  576. while (enum.hasMoreElements()) {
  577. args[counter] = (String)enum.nextElement();
  578. niceSourceList.append(" " + args[counter] + "\r\n");
  579. counter++;
  580. }
  581. log(niceSourceList.toString(), Project.MSG_VERBOSE);
  582. // This won't build under JDK1.2.2 because the new compiler
  583. // doesn't exist there.
  584. //com.sun.tools.javac.Main compiler = new com.sun.tools.javac.Main();
  585. //if (compiler.compile(args) != 0) {
  586. // Use reflection to be able to build on all JDKs >= 1.1:
  587. try {
  588. Class c = Class.forName ("com.sun.tools.javac.Main");
  589. Object compiler = c.newInstance ();
  590. Method compile = c.getMethod ("compile",
  591. new Class [] {(new String [] {}).getClass ()});
  592. int result = ((Integer) compile.invoke
  593. (compiler, new Object [] {args})) .intValue ();
  594. if (result != MODERN_COMPILER_SUCCESS) {
  595. String msg =
  596. "Compile failed, messages should have been provided.";
  597. throw new BuildException(msg);
  598. }
  599. } catch (Exception ex) {
  600. throw new BuildException (ex);
  601. }
  602. }
  603. /**
  604. * Performs a compile using the Jikes compiler from IBM..
  605. * Mostly of this code is identical to doClassicCompile()
  606. * However, it does not support all options like
  607. * bootclasspath, extdirs, deprecation and so on, because
  608. * there is no option in jikes and I don't understand
  609. * what they should do.
  610. *
  611. * It has been successfully tested with jikes 1.10
  612. *
  613. * @author skanthak@muehlheim.de
  614. */
  615. private void doJikesCompile() throws BuildException {
  616. log("Using jikes compiler", Project.MSG_VERBOSE);
  617. Path classpath = new Path(getCompileClasspath(true));
  618. // Jikes doesn't support an extension dir (-extdir)
  619. // so we'll emulate it for compatibility and convenience.
  620. addExtdirsToClasspath(classpath);
  621. // Jikes has no option for source-path so we
  622. // will add it to classpath.
  623. classpath.setPath(getSourcePath());
  624. Vector argList = new Vector();
  625. if (deprecation == true)
  626. argList.addElement("-deprecation");
  627. // We want all output on stdout to make
  628. // parsing easier
  629. argList.addElement("-Xstdout");
  630. argList.addElement("-d");
  631. argList.addElement(destDir.getAbsolutePath());
  632. argList.addElement("-classpath");
  633. argList.addElement(classpath.toString());
  634. if (debug) {
  635. argList.addElement("-g");
  636. }
  637. if (optimize) {
  638. argList.addElement("-O");
  639. }
  640. /**
  641. * XXX
  642. * Perhaps we shouldn't use properties for these
  643. * two options (emacs mode and warnings),
  644. * but include it in the javac directive?
  645. */
  646. /**
  647. * Jikes has the nice feature to print error
  648. * messages in a form readable by emacs, so
  649. * that emcas can directly set the cursor
  650. * to the place, where the error occured.
  651. */
  652. boolean emacsMode = false;
  653. String emacsProperty = project.getProperty("build.compiler.emacs");
  654. if (emacsProperty != null &&
  655. (emacsProperty.equalsIgnoreCase("on") ||
  656. emacsProperty.equalsIgnoreCase("true"))
  657. ) {
  658. emacsMode = true;
  659. }
  660. /**
  661. * Jikes issues more warnings that javac, for
  662. * example, when you have files in your classpath
  663. * that don't exist. As this is often the case, these
  664. * warning can be pretty annoying.
  665. */
  666. boolean warnings = true;
  667. String warningsProperty = project.getProperty("build.compiler.warnings");
  668. if (warningsProperty != null &&
  669. (warningsProperty.equalsIgnoreCase("off") ||
  670. warningsProperty.equalsIgnoreCase("false"))
  671. ) {
  672. warnings = false;
  673. }
  674. if (emacsMode)
  675. argList.addElement("+E");
  676. if (!warnings)
  677. argList.addElement("-nowarn");
  678. log("Compilation args: " + argList.toString(),
  679. Project.MSG_VERBOSE);
  680. String[] args = new String[argList.size() + compileList.size()];
  681. int counter = 0;
  682. for (int i = 0; i < argList.size(); i++) {
  683. args[i] = (String)argList.elementAt(i);
  684. counter++;
  685. }
  686. // XXX
  687. // should be using system independent line feed!
  688. StringBuffer niceSourceList = new StringBuffer("Files to be compiled:"
  689. + "\r\n");
  690. Enumeration enum = compileList.elements();
  691. while (enum.hasMoreElements()) {
  692. args[counter] = (String)enum.nextElement();
  693. niceSourceList.append(" " + args[counter] + "\r\n");
  694. counter++;
  695. }
  696. log(niceSourceList.toString(), Project.MSG_VERBOSE);
  697. // XXX
  698. // provide the compiler a different message sink - namely our own
  699. JikesOutputParser jop = new JikesOutputParser(this, emacsMode);
  700. Jikes compiler = new Jikes(jop,"jikes");
  701. compiler.compile(args);
  702. if (jop.getErrorFlag()) {
  703. String msg = "Compile failed, messages should have been provided.";
  704. throw new BuildException(msg);
  705. }
  706. }
  707. class JarFilenameFilter implements FilenameFilter {
  708. public boolean accept(File dir,String name) {
  709. return name.endsWith(".jar");
  710. }
  711. }
  712. /**
  713. * Emulation of extdirs feature in java >= 1.2.
  714. * This method adds all jar archives in the given
  715. * directories (but not in sub-directories!) to the classpath,
  716. * so that you don't have to specify them all one by one.
  717. * @param classpath - stringbuffer to append jar files to
  718. */
  719. private void addExtdirsToClasspath(Path classpath) {
  720. // FIXME
  721. // Should we scan files recursively? How does
  722. // javac handle this?
  723. if (extdirs != null) {
  724. String[] list = extdirs.list();
  725. for (int j=0; j<list.length; j++) {
  726. File dir = project.resolveFile(list[j]);
  727. String[] files = dir.list(new JarFilenameFilter());
  728. for (int i=0 ; i < files.length ; i++) {
  729. File f = new File(dir,files[i]);
  730. if (f.exists() && f.isFile()) {
  731. classpath.setLocation(f.getAbsolutePath());
  732. }
  733. }
  734. }
  735. }
  736. }
  737. }