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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881
  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 java.lang.reflect.Method;
  60. import java.lang.reflect.Constructor;
  61. import java.io.*;
  62. import java.util.*;
  63. /**
  64. * Task to compile Java source files. This task can take the following
  65. * arguments:
  66. * <ul>
  67. * <li>sourcedir
  68. * <li>destdir
  69. * <li>deprecation
  70. * <li>classpath
  71. * <li>bootclasspath
  72. * <li>extdirs
  73. * <li>optimize
  74. * <li>debug
  75. * <li>encoding
  76. * <li>target
  77. * <li>depend
  78. * <li>vebose
  79. * </ul>
  80. * Of these arguments, the <b>sourcedir</b> and <b>destdir</b> are required.
  81. * <p>
  82. * When this task executes, it will recursively scan the sourcedir and
  83. * destdir looking for Java source files to compile. This task makes its
  84. * compile decision based on timestamp.
  85. *
  86. * @author James Davidson <a href="mailto:duncan@x180.com">duncan@x180.com</a>
  87. * @author Robin Green <a href="mailto:greenrd@hotmail.com">greenrd@hotmail.com</a>
  88. */
  89. public class Javac extends MatchingTask {
  90. /**
  91. * Integer returned by the "Modern" jdk1.3 compiler to indicate success.
  92. */
  93. private static final int
  94. MODERN_COMPILER_SUCCESS = 0;
  95. private static final String FAIL_MSG = "Compile failed, messages should have been provided.";
  96. private Path src;
  97. private File destDir;
  98. private Path compileClasspath;
  99. private String encoding;
  100. private boolean debug = false;
  101. private boolean optimize = false;
  102. private boolean deprecation = false;
  103. private boolean depend = false;
  104. private boolean verbose = false;
  105. private String target;
  106. private Path bootclasspath;
  107. private Path extdirs;
  108. private static String lSep = System.getProperty("line.separator");
  109. protected Vector compileList = new Vector();
  110. /**
  111. * Create a nested <src ...> element for multiple source path
  112. * support.
  113. *
  114. * @return a nexted src element.
  115. */
  116. public Path createSrc() {
  117. if (src == null) {
  118. src = new Path(project);
  119. }
  120. return src.createPath();
  121. }
  122. /**
  123. * Set the source dirs to find the source Java files.
  124. */
  125. public void setSrcdir(Path srcDir) {
  126. if (src == null) {
  127. src = srcDir;
  128. } else {
  129. src.append(srcDir);
  130. }
  131. }
  132. /**
  133. * Set the destination directory into which the Java source
  134. * files should be compiled.
  135. */
  136. public void setDestdir(File destDir) {
  137. this.destDir = destDir;
  138. }
  139. /**
  140. * Set the classpath to be used for this compilation.
  141. */
  142. public void setClasspath(Path classpath) {
  143. if (compileClasspath == null) {
  144. compileClasspath = classpath;
  145. } else {
  146. compileClasspath.append(classpath);
  147. }
  148. }
  149. /**
  150. * Maybe creates a nested classpath element.
  151. */
  152. public Path createClasspath() {
  153. if (compileClasspath == null) {
  154. compileClasspath = new Path(project);
  155. }
  156. return compileClasspath.createPath();
  157. }
  158. /**
  159. * Adds a reference to a CLASSPATH defined elsewhere.
  160. */
  161. public void setClasspathRef(Reference r) {
  162. createClasspath().setRefid(r);
  163. }
  164. /**
  165. * Sets the bootclasspath that will be used to compile the classes
  166. * against.
  167. */
  168. public void setBootclasspath(Path bootclasspath) {
  169. if (this.bootclasspath == null) {
  170. this.bootclasspath = bootclasspath;
  171. } else {
  172. this.bootclasspath.append(bootclasspath);
  173. }
  174. }
  175. /**
  176. * Maybe creates a nested classpath element.
  177. */
  178. public Path createBootclasspath() {
  179. if (bootclasspath == null) {
  180. bootclasspath = new Path(project);
  181. }
  182. return bootclasspath.createPath();
  183. }
  184. /**
  185. * Adds a reference to a CLASSPATH defined elsewhere.
  186. */
  187. public void setBootClasspathRef(Reference r) {
  188. createBootclasspath().setRefid(r);
  189. }
  190. /**
  191. * Sets the extension directories that will be used during the
  192. * compilation.
  193. */
  194. public void setExtdirs(Path extdirs) {
  195. if (this.extdirs == null) {
  196. this.extdirs = extdirs;
  197. } else {
  198. this.extdirs.append(extdirs);
  199. }
  200. }
  201. /**
  202. * Maybe creates a nested classpath element.
  203. */
  204. public Path createExtdirs() {
  205. if (extdirs == null) {
  206. extdirs = new Path(project);
  207. }
  208. return extdirs.createPath();
  209. }
  210. /**
  211. * Set the deprecation flag.
  212. */
  213. public void setDeprecation(boolean deprecation) {
  214. this.deprecation = deprecation;
  215. }
  216. /**
  217. * Set the Java source file encoding name.
  218. */
  219. public void setEncoding(String encoding) {
  220. this.encoding = encoding;
  221. }
  222. /**
  223. * Set the debug flag.
  224. */
  225. public void setDebug(boolean debug) {
  226. this.debug = debug;
  227. }
  228. /**
  229. * Set the optimize flag.
  230. */
  231. public void setOptimize(boolean optimize) {
  232. this.optimize = optimize;
  233. }
  234. /**
  235. * Set the depend flag.
  236. */
  237. public void setDepend(boolean depend) {
  238. this.depend = depend;
  239. }
  240. /**
  241. * Set the verbose flag.
  242. */
  243. public void setVerbose(boolean verbose) {
  244. this.verbose = verbose;
  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. * Executes the task.
  255. */
  256. public void execute() throws BuildException {
  257. // first off, make sure that we've got a srcdir and destdir
  258. if (src == null) {
  259. throw new BuildException("srcdir attribute must be set!", location);
  260. }
  261. String [] list = src.list();
  262. if (list.length == 0) {
  263. throw new BuildException("srcdir attribute must be set!", location);
  264. }
  265. if (destDir == null) {
  266. throw new BuildException("destdir attribute must be set!", location);
  267. }
  268. if (!destDir.isDirectory()) {
  269. throw new BuildException("destination directory \"" + destDir + "\" does not exist or is not a directory", location);
  270. }
  271. // scan source directories and dest directory to build up both copy lists and
  272. // compile lists
  273. resetFileLists();
  274. for (int i=0; i<list.length; i++) {
  275. File srcDir = (File)project.resolveFile(list[i]);
  276. if (!srcDir.exists()) {
  277. throw new BuildException("srcdir \"" + srcDir.getPath() + "\" does not exist!", location);
  278. }
  279. DirectoryScanner ds = this.getDirectoryScanner(srcDir);
  280. String[] files = ds.getIncludedFiles();
  281. scanDir(srcDir, destDir, files);
  282. }
  283. // compile the source files
  284. String compiler = project.getProperty("build.compiler");
  285. if (compiler == null) {
  286. if (Project.getJavaVersion().startsWith("1.3")) {
  287. compiler = "modern";
  288. } else {
  289. compiler = "classic";
  290. }
  291. }
  292. if (compileList.size() > 0) {
  293. log("Compiling " + compileList.size() +
  294. " source file"
  295. + (compileList.size() == 1 ? "" : "s")
  296. + " to " + destDir);
  297. if (compiler.equalsIgnoreCase("classic")) {
  298. doClassicCompile();
  299. } else if (compiler.equalsIgnoreCase("modern")) {
  300. doModernCompile();
  301. } else if (compiler.equalsIgnoreCase("jikes")) {
  302. doJikesCompile();
  303. } else if (compiler.equalsIgnoreCase("jvc")) {
  304. doJvcCompile();
  305. } else {
  306. String msg = "Don't know how to use compiler " + compiler;
  307. throw new BuildException(msg, location);
  308. }
  309. }
  310. }
  311. /**
  312. * Clear the list of files to be compiled and copied..
  313. */
  314. protected void resetFileLists() {
  315. compileList.removeAllElements();
  316. }
  317. /**
  318. * Scans the directory looking for source files to be compiled.
  319. * The results are returned in the class variable compileList
  320. */
  321. protected void scanDir(File srcDir, File destDir, String files[]) {
  322. long now = (new Date()).getTime();
  323. for (int i = 0; i < files.length; i++) {
  324. File srcFile = new File(srcDir, files[i]);
  325. if (files[i].endsWith(".java")) {
  326. File classFile = new File(destDir, files[i].substring(0,
  327. files[i].indexOf(".java")) + ".class");
  328. if (srcFile.lastModified() > now) {
  329. log("Warning: file modified in the future: " +
  330. files[i], Project.MSG_WARN);
  331. }
  332. if (!classFile.exists() || srcFile.lastModified() > classFile.lastModified()) {
  333. if (!classFile.exists()) {
  334. log("Compiling " + srcFile.getPath() + " because class file "
  335. + classFile.getPath() + " does not exist", Project.MSG_DEBUG);
  336. }
  337. else {
  338. log("Compiling " + srcFile.getPath() + " because it is out of date with respect to "
  339. + classFile.getPath(), Project.MSG_DEBUG);
  340. }
  341. compileList.addElement(srcFile.getAbsolutePath());
  342. }
  343. }
  344. }
  345. }
  346. // XXX
  347. // we need a way to not use the current classpath.
  348. /**
  349. * Builds the compilation classpath.
  350. *
  351. * @param addRuntime Shall <code>rt.jar</code> or
  352. * <code>classes.zip</code> be added to the classpath.
  353. */
  354. protected Path getCompileClasspath(boolean addRuntime) {
  355. Path classpath = new Path(project);
  356. // add dest dir to classpath so that previously compiled and
  357. // untouched classes are on classpath
  358. classpath.setLocation(destDir);
  359. // add our classpath to the mix
  360. if (compileClasspath != null) {
  361. classpath.addExisting(compileClasspath);
  362. }
  363. // add the system classpath
  364. classpath.addExisting(Path.systemClasspath);
  365. if (addRuntime) {
  366. if (System.getProperty("java.vendor").toLowerCase().indexOf("microsoft") >= 0) {
  367. // Pull in *.zip from packages directory
  368. FileSet msZipFiles = new FileSet();
  369. msZipFiles.setDir(new File(System.getProperty("java.home") + File.separator + "Packages"));
  370. msZipFiles.setIncludes("*.ZIP");
  371. classpath.addFileset(msZipFiles);
  372. }
  373. else if (Project.getJavaVersion() == Project.JAVA_1_1) {
  374. classpath.addExisting(new Path(null,
  375. System.getProperty("java.home")
  376. + File.separator + "lib"
  377. + File.separator
  378. + "classes.zip"));
  379. } else {
  380. // JDK > 1.1 seems to set java.home to the JRE directory.
  381. classpath.addExisting(new Path(null,
  382. System.getProperty("java.home")
  383. + File.separator + "lib"
  384. + File.separator + "rt.jar"));
  385. // Just keep the old version as well and let addExistingToPath
  386. // sort it out.
  387. classpath.addExisting(new Path(null,
  388. System.getProperty("java.home")
  389. + File.separator +"jre"
  390. + File.separator + "lib"
  391. + File.separator + "rt.jar"));
  392. }
  393. }
  394. return classpath;
  395. }
  396. /**
  397. * Peforms a compile using the classic compiler that shipped with
  398. * JDK 1.1 and 1.2.
  399. */
  400. private void doClassicCompile() throws BuildException {
  401. log("Using classic compiler", Project.MSG_VERBOSE);
  402. Commandline cmd = setupJavacCommand();
  403. // Use reflection to be able to build on all JDKs
  404. /*
  405. // provide the compiler a different message sink - namely our own
  406. sun.tools.javac.Main compiler =
  407. new sun.tools.javac.Main(new LogOutputStream(this, Project.MSG_WARN), "javac");
  408. if (!compiler.compile(cmd.getArguments())) {
  409. throw new BuildException("Compile failed");
  410. }
  411. */
  412. try {
  413. // Create an instance of the compiler, redirecting output to
  414. // the project log
  415. OutputStream logstr = new LogOutputStream(this, Project.MSG_WARN);
  416. Class c = Class.forName("sun.tools.javac.Main");
  417. Constructor cons = c.getConstructor(new Class[] { OutputStream.class, String.class });
  418. Object compiler = cons.newInstance(new Object[] { logstr, "javac" });
  419. // Call the compile() method
  420. Method compile = c.getMethod("compile", new Class [] { String[].class });
  421. Boolean ok = (Boolean)compile.invoke(compiler, new Object[] {cmd.getArguments()});
  422. if (!ok.booleanValue()) {
  423. throw new BuildException(FAIL_MSG, location);
  424. }
  425. }
  426. catch (ClassNotFoundException ex) {
  427. throw new BuildException("Cannot use classic compiler, as it is not available", location);
  428. }
  429. catch (Exception ex) {
  430. throw new BuildException("Error starting classic compiler: ", ex, location);
  431. }
  432. }
  433. /**
  434. * Performs a compile using the newer compiler that ships with JDK 1.3
  435. */
  436. private void doModernCompile() throws BuildException {
  437. try {
  438. Class.forName("com.sun.tools.javac.Main");
  439. } catch (ClassNotFoundException cnfe) {
  440. log("Modern compiler is not available - using classic compiler", Project.MSG_WARN);
  441. doClassicCompile();
  442. return;
  443. }
  444. log("Using modern compiler", Project.MSG_VERBOSE);
  445. Commandline cmd = setupJavacCommand();
  446. // This won't build under JDK1.2.2 because the new compiler
  447. // doesn't exist there.
  448. //com.sun.tools.javac.Main compiler = new com.sun.tools.javac.Main();
  449. //if (compiler.compile(args) != 0) {
  450. // Use reflection to be able to build on all JDKs >= 1.1:
  451. try {
  452. Class c = Class.forName ("com.sun.tools.javac.Main");
  453. Object compiler = c.newInstance ();
  454. Method compile = c.getMethod ("compile",
  455. new Class [] {(new String [] {}).getClass ()});
  456. int result = ((Integer) compile.invoke
  457. (compiler, new Object[] {cmd.getArguments()})) .intValue ();
  458. if (result != MODERN_COMPILER_SUCCESS) {
  459. throw new BuildException(FAIL_MSG, location);
  460. }
  461. } catch (Exception ex) {
  462. throw new BuildException("Error starting modern compiler", ex, location);
  463. }
  464. }
  465. /**
  466. * Does the command line argument processing common to classic and
  467. * modern.
  468. */
  469. private Commandline setupJavacCommand() {
  470. Commandline cmd = new Commandline();
  471. Path classpath = getCompileClasspath(false);
  472. if (deprecation == true) {
  473. cmd.createArgument().setValue("-deprecation");
  474. }
  475. cmd.createArgument().setValue("-d");
  476. cmd.createArgument().setFile(destDir);
  477. cmd.createArgument().setValue("-classpath");
  478. // Just add "sourcepath" to classpath ( for JDK1.1 )
  479. if (Project.getJavaVersion().startsWith("1.1")) {
  480. cmd.createArgument().setValue(classpath.toString()
  481. + File.pathSeparator
  482. + src.toString());
  483. } else {
  484. cmd.createArgument().setPath(classpath);
  485. cmd.createArgument().setValue("-sourcepath");
  486. cmd.createArgument().setPath(src);
  487. if (target != null) {
  488. cmd.createArgument().setValue("-target");
  489. cmd.createArgument().setValue(target);
  490. }
  491. }
  492. if (encoding != null) {
  493. cmd.createArgument().setValue("-encoding");
  494. cmd.createArgument().setValue(encoding);
  495. }
  496. if (debug) {
  497. cmd.createArgument().setValue("-g");
  498. }
  499. if (optimize) {
  500. cmd.createArgument().setValue("-O");
  501. }
  502. if (bootclasspath != null) {
  503. cmd.createArgument().setValue("-bootclasspath");
  504. cmd.createArgument().setPath(bootclasspath);
  505. }
  506. if (extdirs != null) {
  507. cmd.createArgument().setValue("-extdirs");
  508. cmd.createArgument().setPath(extdirs);
  509. }
  510. if (depend) {
  511. if (Project.getJavaVersion().startsWith("1.1")) {
  512. cmd.createArgument().setValue("-depend");
  513. } else if (Project.getJavaVersion().startsWith("1.2")) {
  514. cmd.createArgument().setValue("-Xdepend");
  515. } else {
  516. log("depend attribute is not supported by the modern compiler",
  517. Project.MSG_WARN);
  518. }
  519. }
  520. if (verbose) {
  521. cmd.createArgument().setValue("-verbose");
  522. }
  523. logAndAddFilesToCompile(cmd);
  524. return cmd;
  525. }
  526. /**
  527. * Logs the compilation parameters, adds the files to compile and logs the
  528. * &qout;niceSourceList&quot;
  529. */
  530. protected void logAndAddFilesToCompile(Commandline cmd) {
  531. log("Compilation args: " + cmd.toString(),
  532. Project.MSG_VERBOSE);
  533. StringBuffer niceSourceList = new StringBuffer("File");
  534. if (compileList.size() != 1) {
  535. niceSourceList.append("s");
  536. }
  537. niceSourceList.append(" to be compiled:");
  538. niceSourceList.append(lSep);
  539. Enumeration enum = compileList.elements();
  540. while (enum.hasMoreElements()) {
  541. String arg = (String)enum.nextElement();
  542. cmd.createArgument().setValue(arg);
  543. niceSourceList.append(" " + arg + lSep);
  544. }
  545. log(niceSourceList.toString(), Project.MSG_VERBOSE);
  546. }
  547. /**
  548. * Performs a compile using the Jikes compiler from IBM..
  549. * Mostly of this code is identical to doClassicCompile()
  550. * However, it does not support all options like
  551. * bootclasspath, extdirs, deprecation and so on, because
  552. * there is no option in jikes and I don't understand
  553. * what they should do.
  554. *
  555. * It has been successfully tested with jikes >1.10
  556. *
  557. * @author skanthak@muehlheim.de
  558. */
  559. private void doJikesCompile() throws BuildException {
  560. log("Using jikes compiler", Project.MSG_VERBOSE);
  561. Path classpath = new Path(project);
  562. // Jikes doesn't support bootclasspath dir (-bootclasspath)
  563. // so we'll emulate it for compatibility and convenience.
  564. if (bootclasspath != null) {
  565. classpath.append(bootclasspath);
  566. }
  567. // Jikes doesn't support an extension dir (-extdir)
  568. // so we'll emulate it for compatibility and convenience.
  569. addExtdirsToClasspath(classpath);
  570. classpath.append(getCompileClasspath(true));
  571. // Jikes has no option for source-path so we
  572. // will add it to classpath.
  573. classpath.append(src);
  574. // if the user has set JIKESPATH we should add the contents as well
  575. String jikesPath = System.getProperty("jikes.class.path");
  576. if (jikesPath != null) {
  577. classpath.append(new Path(project, jikesPath));
  578. }
  579. Commandline cmd = new Commandline();
  580. cmd.setExecutable("jikes");
  581. if (deprecation == true)
  582. cmd.createArgument().setValue("-deprecation");
  583. cmd.createArgument().setValue("-d");
  584. cmd.createArgument().setFile(destDir);
  585. cmd.createArgument().setValue("-classpath");
  586. cmd.createArgument().setPath(classpath);
  587. if (encoding != null) {
  588. cmd.createArgument().setValue("-encoding");
  589. cmd.createArgument().setValue(encoding);
  590. }
  591. if (debug) {
  592. cmd.createArgument().setValue("-g");
  593. }
  594. if (optimize) {
  595. cmd.createArgument().setValue("-O");
  596. }
  597. if (verbose) {
  598. cmd.createArgument().setValue("-verbose");
  599. }
  600. if (depend) {
  601. cmd.createArgument().setValue("-depend");
  602. String fullDependProperty = project.getProperty("build.compiler.fulldepend");
  603. if (fullDependProperty != null
  604. && Project.toBoolean(fullDependProperty)) {
  605. cmd.createArgument().setValue("+F");
  606. }
  607. }
  608. /**
  609. * XXX
  610. * Perhaps we shouldn't use properties for these
  611. * three options (emacs mode, warnings and pedantic),
  612. * but include it in the javac directive?
  613. */
  614. /**
  615. * Jikes has the nice feature to print error
  616. * messages in a form readable by emacs, so
  617. * that emacs can directly set the cursor
  618. * to the place, where the error occured.
  619. */
  620. String emacsProperty = project.getProperty("build.compiler.emacs");
  621. if (emacsProperty != null && Project.toBoolean(emacsProperty)) {
  622. cmd.createArgument().setValue("+E");
  623. }
  624. /**
  625. * Jikes issues more warnings that javac, for
  626. * example, when you have files in your classpath
  627. * that don't exist. As this is often the case, these
  628. * warning can be pretty annoying.
  629. */
  630. String warningsProperty = project.getProperty("build.compiler.warnings");
  631. if (warningsProperty != null && !Project.toBoolean(warningsProperty)) {
  632. cmd.createArgument().setValue("-nowarn");
  633. }
  634. /**
  635. * Jikes can issue pedantic warnings.
  636. */
  637. String pedanticProperty = project.getProperty("build.compiler.pedantic");
  638. if (pedanticProperty != null && Project.toBoolean(pedanticProperty)) {
  639. cmd.createArgument().setValue("+P");
  640. }
  641. int firstFileName = cmd.size();
  642. logAndAddFilesToCompile(cmd);
  643. if (executeJikesCompile(cmd.getCommandline(), firstFileName) != 0) {
  644. throw new BuildException(FAIL_MSG, location);
  645. }
  646. }
  647. /**
  648. * Do the compile with the specified arguments.
  649. * @param args - arguments to pass to process on command line
  650. * @param firstFileName - index of the first source file in args
  651. */
  652. protected int executeJikesCompile(String[] args, int firstFileName) {
  653. String[] commandArray = null;
  654. File tmpFile = null;
  655. try {
  656. /*
  657. * Many system have been reported to get into trouble with
  658. * long command lines - no, not only Windows ;-).
  659. *
  660. * POSIX seems to define a lower limit of 4k, so use a temporary
  661. * file if the total length of the command line exceeds this limit.
  662. */
  663. if (Commandline.toString(args).length() > 4096) {
  664. PrintWriter out = null;
  665. try {
  666. tmpFile = new File("jikes"+(new Random(System.currentTimeMillis())).nextLong());
  667. out = new PrintWriter(new FileWriter(tmpFile));
  668. for (int i = firstFileName; i < args.length; i++) {
  669. out.println(args[i]);
  670. }
  671. out.flush();
  672. commandArray = new String[firstFileName+1];
  673. System.arraycopy(args, 0, commandArray, 0, firstFileName);
  674. commandArray[firstFileName] = "@" + tmpFile.getAbsolutePath();
  675. } catch (IOException e) {
  676. throw new BuildException("Error creating temporary file", e, location);
  677. } finally {
  678. if (out != null) {
  679. try {out.close();} catch (Throwable t) {}
  680. }
  681. }
  682. } else {
  683. commandArray = args;
  684. }
  685. try {
  686. Execute exe = new Execute(new LogStreamHandler(this,
  687. Project.MSG_INFO,
  688. Project.MSG_WARN));
  689. exe.setAntRun(project);
  690. exe.setWorkingDirectory(project.getBaseDir());
  691. exe.setCommandline(commandArray);
  692. exe.execute();
  693. return exe.getExitValue();
  694. } catch (IOException e) {
  695. throw new BuildException("Error running Jikes compiler", e, location);
  696. }
  697. } finally {
  698. if (tmpFile != null) {
  699. tmpFile.delete();
  700. }
  701. }
  702. }
  703. /**
  704. * Emulation of extdirs feature in java >= 1.2.
  705. * This method adds all files in the given
  706. * directories (but not in sub-directories!) to the classpath,
  707. * so that you don't have to specify them all one by one.
  708. * @param classpath - Path to append files to
  709. */
  710. protected void addExtdirsToClasspath(Path classpath) {
  711. if (extdirs == null) {
  712. String extProp = System.getProperty("java.ext.dirs");
  713. if (extProp != null) {
  714. extdirs = new Path(project, extProp);
  715. } else {
  716. return;
  717. }
  718. }
  719. String[] dirs = extdirs.list();
  720. for (int i=0; i<dirs.length; i++) {
  721. if (!dirs[i].endsWith(File.separator)) {
  722. dirs[i] += File.separator;
  723. }
  724. File dir = project.resolveFile(dirs[i]);
  725. FileSet fs = new FileSet();
  726. fs.setDir(dir);
  727. fs.setIncludes("*");
  728. classpath.addFileset(fs);
  729. }
  730. }
  731. private void doJvcCompile() throws BuildException {
  732. log("Using jvc compiler", Project.MSG_VERBOSE);
  733. Path classpath = new Path(project);
  734. // jvc doesn't support bootclasspath dir (-bootclasspath)
  735. // so we'll emulate it for compatibility and convenience.
  736. if (bootclasspath != null) {
  737. classpath.append(bootclasspath);
  738. }
  739. // jvc doesn't support an extension dir (-extdir)
  740. // so we'll emulate it for compatibility and convenience.
  741. addExtdirsToClasspath(classpath);
  742. classpath.append(getCompileClasspath(true));
  743. // jvc has no option for source-path so we
  744. // will add it to classpath.
  745. classpath.append(src);
  746. Commandline cmd = new Commandline();
  747. cmd.setExecutable("jvc");
  748. cmd.createArgument().setValue("/d");
  749. cmd.createArgument().setFile(destDir);
  750. // Add the Classpath before the "internal" one.
  751. cmd.createArgument().setValue("/cp:p");
  752. cmd.createArgument().setPath(classpath);
  753. // Enable MS-Extensions and ...
  754. cmd.createArgument().setValue("/x-");
  755. // ... do not display a Message about this.
  756. cmd.createArgument().setValue("/nomessage");
  757. // Do not display Logo
  758. cmd.createArgument().setValue("/nologo");
  759. if (debug) {
  760. cmd.createArgument().setValue("/g");
  761. }
  762. if (optimize) {
  763. cmd.createArgument().setValue("/O");
  764. }
  765. int firstFileName = cmd.size();
  766. logAndAddFilesToCompile(cmd);
  767. if (executeJikesCompile(cmd.getCommandline(), firstFileName) != 0) {
  768. throw new BuildException(FAIL_MSG, location);
  769. }
  770. }
  771. }