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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  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", "Ant", 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.Commandline;
  59. import org.apache.tools.ant.types.Path;
  60. import org.apache.tools.ant.types.Reference;
  61. import org.apache.tools.ant.util.GlobPatternMapper;
  62. import org.apache.tools.ant.util.SourceFileScanner;
  63. import org.apache.tools.ant.taskdefs.compilers.CompilerAdapter;
  64. import org.apache.tools.ant.taskdefs.compilers.CompilerAdapterFactory;
  65. import org.apache.tools.ant.taskdefs.condition.Os;
  66. import java.io.File;
  67. import java.util.Enumeration;
  68. import java.util.Vector;
  69. /**
  70. * Task to compile Java source files. This task can take the following
  71. * arguments:
  72. * <ul>
  73. * <li>sourcedir
  74. * <li>destdir
  75. * <li>deprecation
  76. * <li>classpath
  77. * <li>bootclasspath
  78. * <li>extdirs
  79. * <li>optimize
  80. * <li>debug
  81. * <li>encoding
  82. * <li>target
  83. * <li>depend
  84. * <li>vebose
  85. * <li>failonerror
  86. * <li>includeantruntime
  87. * <li>includejavaruntime
  88. * <li>source
  89. * </ul>
  90. * Of these arguments, the <b>sourcedir</b> and <b>destdir</b> are required.
  91. * <p>
  92. * When this task executes, it will recursively scan the sourcedir and
  93. * destdir looking for Java source files to compile. This task makes its
  94. * compile decision based on timestamp.
  95. *
  96. * @author James Davidson <a href="mailto:duncan@x180.com">duncan@x180.com</a>
  97. * @author Robin Green <a href="mailto:greenrd@hotmail.com">greenrd@hotmail.com</a>
  98. * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
  99. * @author <a href="mailto:jayglanville@home.com">J D Glanville</a>
  100. */
  101. public class Javac extends MatchingTask {
  102. private final static String FAIL_MSG
  103. = "Compile failed, messages should have been provided.";
  104. private Path src;
  105. private File destDir;
  106. private Path compileClasspath;
  107. private String encoding;
  108. private boolean debug = false;
  109. private boolean optimize = false;
  110. private boolean deprecation = false;
  111. private boolean depend = false;
  112. private boolean verbose = false;
  113. private String target;
  114. private Path bootclasspath;
  115. private Path extdirs;
  116. private boolean includeAntRuntime = true;
  117. private boolean includeJavaRuntime = false;
  118. private String fork = "false";
  119. private String forkedExecutable = null;
  120. private boolean nowarn = false;
  121. private String memoryInitialSize;
  122. private String memoryMaximumSize;
  123. private Vector implementationSpecificArgs = new Vector();
  124. protected boolean failOnError = true;
  125. protected File[] compileList = new File[0];
  126. private String source;
  127. private String debugLevel;
  128. /**
  129. * Get the value of debugLevel.
  130. * @return value of debugLevel.
  131. */
  132. public String getDebugLevel() {
  133. return debugLevel;
  134. }
  135. /**
  136. * Set the value of debugLevel.
  137. * @param v Value to assign to debugLevel.
  138. */
  139. public void setDebugLevel(String v) {
  140. this.debugLevel = v;
  141. }
  142. /**
  143. * Get the value of source.
  144. * @return value of source.
  145. */
  146. public String getSource() {
  147. return source;
  148. }
  149. /**
  150. * Set the value of source.
  151. * @param v Value to assign to source.
  152. */
  153. public void setSource(String v) {
  154. this.source = v;
  155. }
  156. /**
  157. * Create a nested src element for multiple source path
  158. * support.
  159. *
  160. * @return a nested src element.
  161. */
  162. public Path createSrc() {
  163. if (src == null) {
  164. src = new Path(project);
  165. }
  166. return src.createPath();
  167. }
  168. /**
  169. * Recreate src
  170. *
  171. * @return a nested src element.
  172. */
  173. protected Path recreateSrc() {
  174. src = null;
  175. return createSrc();
  176. }
  177. /**
  178. * Set the source dirs to find the source Java files.
  179. */
  180. public void setSrcdir(Path srcDir) {
  181. if (src == null) {
  182. src = srcDir;
  183. } else {
  184. src.append(srcDir);
  185. }
  186. }
  187. /** Gets the source dirs to find the source java files. */
  188. public Path getSrcdir() {
  189. return src;
  190. }
  191. /**
  192. * Set the destination directory into which the Java source
  193. * files should be compiled.
  194. */
  195. public void setDestdir(File destDir) {
  196. this.destDir = destDir;
  197. }
  198. /**
  199. * Gets the destination directory into which the java source files
  200. * should be compiled.
  201. */
  202. public File getDestdir() {
  203. return destDir;
  204. }
  205. /**
  206. * Set the classpath to be used for this compilation.
  207. */
  208. public void setClasspath(Path classpath) {
  209. if (compileClasspath == null) {
  210. compileClasspath = classpath;
  211. } else {
  212. compileClasspath.append(classpath);
  213. }
  214. }
  215. /** Gets the classpath to be used for this compilation. */
  216. public Path getClasspath() {
  217. return compileClasspath;
  218. }
  219. /**
  220. * Maybe creates a nested classpath element.
  221. */
  222. public Path createClasspath() {
  223. if (compileClasspath == null) {
  224. compileClasspath = new Path(project);
  225. }
  226. return compileClasspath.createPath();
  227. }
  228. /**
  229. * Adds a reference to a CLASSPATH defined elsewhere.
  230. */
  231. public void setClasspathRef(Reference r) {
  232. createClasspath().setRefid(r);
  233. }
  234. /**
  235. * Sets the bootclasspath that will be used to compile the classes
  236. * against.
  237. */
  238. public void setBootclasspath(Path bootclasspath) {
  239. if (this.bootclasspath == null) {
  240. this.bootclasspath = bootclasspath;
  241. } else {
  242. this.bootclasspath.append(bootclasspath);
  243. }
  244. }
  245. /**
  246. * Gets the bootclasspath that will be used to compile the classes
  247. * against.
  248. */
  249. public Path getBootclasspath() {
  250. return bootclasspath;
  251. }
  252. /**
  253. * Maybe creates a nested classpath element.
  254. */
  255. public Path createBootclasspath() {
  256. if (bootclasspath == null) {
  257. bootclasspath = new Path(project);
  258. }
  259. return bootclasspath.createPath();
  260. }
  261. /**
  262. * Adds a reference to a CLASSPATH defined elsewhere.
  263. */
  264. public void setBootClasspathRef(Reference r) {
  265. createBootclasspath().setRefid(r);
  266. }
  267. /**
  268. * Sets the extension directories that will be used during the
  269. * compilation.
  270. */
  271. public void setExtdirs(Path extdirs) {
  272. if (this.extdirs == null) {
  273. this.extdirs = extdirs;
  274. } else {
  275. this.extdirs.append(extdirs);
  276. }
  277. }
  278. /**
  279. * Gets the extension directories that will be used during the
  280. * compilation.
  281. */
  282. public Path getExtdirs() {
  283. return extdirs;
  284. }
  285. /**
  286. * Maybe creates a nested classpath element.
  287. */
  288. public Path createExtdirs() {
  289. if (extdirs == null) {
  290. extdirs = new Path(project);
  291. }
  292. return extdirs.createPath();
  293. }
  294. /**
  295. * Throw a BuildException if compilation fails
  296. */
  297. public void setFailonerror(boolean fail) {
  298. failOnError = fail;
  299. }
  300. /**
  301. * Proceed if compilation fails
  302. */
  303. public void setProceed(boolean proceed) {
  304. failOnError = !proceed;
  305. }
  306. /**
  307. * Gets the failonerror flag.
  308. */
  309. public boolean getFailonerror() {
  310. return failOnError;
  311. }
  312. /**
  313. * Set the deprecation flag.
  314. */
  315. public void setDeprecation(boolean deprecation) {
  316. this.deprecation = deprecation;
  317. }
  318. /** Gets the deprecation flag. */
  319. public boolean getDeprecation() {
  320. return deprecation;
  321. }
  322. /**
  323. * Set the memoryInitialSize flag.
  324. */
  325. public void setMemoryInitialSize(String memoryInitialSize) {
  326. this.memoryInitialSize = memoryInitialSize;
  327. }
  328. /** Gets the memoryInitialSize flag. */
  329. public String getMemoryInitialSize() {
  330. return memoryInitialSize;
  331. }
  332. /**
  333. * Set the memoryMaximumSize flag.
  334. */
  335. public void setMemoryMaximumSize(String memoryMaximumSize) {
  336. this.memoryMaximumSize = memoryMaximumSize;
  337. }
  338. /** Gets the memoryMaximumSize flag. */
  339. public String getMemoryMaximumSize() {
  340. return memoryMaximumSize;
  341. }
  342. /**
  343. * Set the Java source file encoding name.
  344. */
  345. public void setEncoding(String encoding) {
  346. this.encoding = encoding;
  347. }
  348. /** Gets the java source file encoding name. */
  349. public String getEncoding() {
  350. return encoding;
  351. }
  352. /**
  353. * Set the debug flag.
  354. */
  355. public void setDebug(boolean debug) {
  356. this.debug = debug;
  357. }
  358. /** Gets the debug flag. */
  359. public boolean getDebug() {
  360. return debug;
  361. }
  362. /**
  363. * Set the optimize flag.
  364. */
  365. public void setOptimize(boolean optimize) {
  366. this.optimize = optimize;
  367. }
  368. /** Gets the optimize flag. */
  369. public boolean getOptimize() {
  370. return optimize;
  371. }
  372. /**
  373. * Set the depend flag.
  374. */
  375. public void setDepend(boolean depend) {
  376. this.depend = depend;
  377. }
  378. /** Gets the depend flag. */
  379. public boolean getDepend() {
  380. return depend;
  381. }
  382. /**
  383. * Set the verbose flag.
  384. */
  385. public void setVerbose(boolean verbose) {
  386. this.verbose = verbose;
  387. }
  388. /** Gets the verbose flag. */
  389. public boolean getVerbose() {
  390. return verbose;
  391. }
  392. /**
  393. * Sets the target VM that the classes will be compiled for. Valid
  394. * strings are "1.1", "1.2", and "1.3".
  395. */
  396. public void setTarget(String target) {
  397. this.target = target;
  398. }
  399. /** Gets the target VM that the classes will be compiled for. */
  400. public String getTarget() {
  401. return target;
  402. }
  403. /**
  404. * Include ant's own classpath in this task's classpath?
  405. */
  406. public void setIncludeantruntime( boolean include ) {
  407. includeAntRuntime = include;
  408. }
  409. /**
  410. * Gets whether or not the ant classpath is to be included in the
  411. * task's classpath.
  412. */
  413. public boolean getIncludeantruntime() {
  414. return includeAntRuntime;
  415. }
  416. /**
  417. * Sets whether or not to include the java runtime libraries to this
  418. * task's classpath.
  419. */
  420. public void setIncludejavaruntime( boolean include ) {
  421. includeJavaRuntime = include;
  422. }
  423. /**
  424. * Gets whether or not the java runtime should be included in this
  425. * task's classpath.
  426. */
  427. public boolean getIncludejavaruntime() {
  428. return includeJavaRuntime;
  429. }
  430. /**
  431. * Sets whether to fork the javac compiler.
  432. *
  433. * @param f "true|false|on|off|yes|no" or the name of the javac
  434. * executable.
  435. */
  436. public void setFork(String f) {
  437. if (f.equalsIgnoreCase("on")
  438. || f.equalsIgnoreCase("true")
  439. || f.equalsIgnoreCase("yes")) {
  440. fork = "true";
  441. forkedExecutable = getSystemJavac();
  442. } else if (f.equalsIgnoreCase("off")
  443. || f.equalsIgnoreCase("false")
  444. || f.equalsIgnoreCase("no")) {
  445. fork = "false";
  446. forkedExecutable = null;
  447. } else {
  448. fork = "true";
  449. forkedExecutable = f;
  450. }
  451. }
  452. /**
  453. * Is this a forked invocation of JDK's javac?
  454. */
  455. public boolean isForkedJavac() {
  456. return !"false".equals(fork) ||
  457. "extJavac".equals(project.getProperty("build.compiler"));
  458. }
  459. /**
  460. * The name of the javac executable to use in fork-mode.
  461. */
  462. public String getJavacExecutable() {
  463. if (forkedExecutable == null && isForkedJavac()) {
  464. forkedExecutable = getSystemJavac();
  465. } else if (forkedExecutable != null && !isForkedJavac()) {
  466. forkedExecutable = null;
  467. }
  468. return forkedExecutable;
  469. }
  470. /**
  471. * Sets whether the -nowarn option should be used.
  472. */
  473. public void setNowarn(boolean flag) {
  474. this.nowarn = flag;
  475. }
  476. /**
  477. * Should the -nowarn option be used.
  478. */
  479. public boolean getNowarn() {
  480. return nowarn;
  481. }
  482. /**
  483. * Adds an implementation specific command line argument.
  484. */
  485. public ImplementationSpecificArgument createCompilerArg() {
  486. ImplementationSpecificArgument arg =
  487. new ImplementationSpecificArgument();
  488. implementationSpecificArgs.addElement(arg);
  489. return arg;
  490. }
  491. /**
  492. * Get the additional implementation specific command line arguments.
  493. * @return array of command line arguments, guaranteed to be non-null.
  494. */
  495. public String[] getCurrentCompilerArgs() {
  496. Vector args = new Vector();
  497. for (Enumeration enum = implementationSpecificArgs.elements();
  498. enum.hasMoreElements();
  499. ) {
  500. String[] curr =
  501. ((ImplementationSpecificArgument) enum.nextElement()).getParts();
  502. for (int i=0; i<curr.length; i++) {
  503. args.addElement(curr[i]);
  504. }
  505. }
  506. String[] res = new String[args.size()];
  507. args.copyInto(res);
  508. return res;
  509. }
  510. /**
  511. * Executes the task.
  512. */
  513. public void execute() throws BuildException {
  514. // first off, make sure that we've got a srcdir
  515. if (src == null) {
  516. throw new BuildException("srcdir attribute must be set!", location);
  517. }
  518. String [] list = src.list();
  519. if (list.length == 0) {
  520. throw new BuildException("srcdir attribute must be set!", location);
  521. }
  522. if (destDir != null && !destDir.isDirectory()) {
  523. throw new BuildException("destination directory \"" + destDir + "\" does not exist or is not a directory", location);
  524. }
  525. // scan source directories and dest directory to build up
  526. // compile lists
  527. resetFileLists();
  528. for (int i=0; i<list.length; i++) {
  529. File srcDir = (File)project.resolveFile(list[i]);
  530. if (!srcDir.exists()) {
  531. throw new BuildException("srcdir \"" + srcDir.getPath() + "\" does not exist!", location);
  532. }
  533. DirectoryScanner ds = this.getDirectoryScanner(srcDir);
  534. String[] files = ds.getIncludedFiles();
  535. scanDir(srcDir, destDir != null ? destDir : srcDir, files);
  536. }
  537. // compile the source files
  538. String compiler = determineCompiler();
  539. if (compileList.length > 0) {
  540. CompilerAdapter adapter = CompilerAdapterFactory.getCompiler(
  541. compiler, this );
  542. log("Compiling " + compileList.length +
  543. " source file"
  544. + (compileList.length == 1 ? "" : "s")
  545. + (destDir != null ? " to " + destDir : ""));
  546. // now we need to populate the compiler adapter
  547. adapter.setJavac( this );
  548. // finally, lets execute the compiler!!
  549. if (!adapter.execute()) {
  550. if (failOnError) {
  551. throw new BuildException(FAIL_MSG, location);
  552. }
  553. else {
  554. log(FAIL_MSG, Project.MSG_ERR);
  555. }
  556. }
  557. }
  558. }
  559. /**
  560. * Clear the list of files to be compiled and copied..
  561. */
  562. protected void resetFileLists() {
  563. compileList = new File[0];
  564. }
  565. /**
  566. * Scans the directory looking for source files to be compiled.
  567. * The results are returned in the class variable compileList
  568. */
  569. protected void scanDir(File srcDir, File destDir, String files[]) {
  570. GlobPatternMapper m = new GlobPatternMapper();
  571. m.setFrom("*.java");
  572. m.setTo("*.class");
  573. SourceFileScanner sfs = new SourceFileScanner(this);
  574. File[] newFiles = sfs.restrictAsFiles(files, srcDir, destDir, m);
  575. if (newFiles.length > 0) {
  576. File[] newCompileList = new File[compileList.length +
  577. newFiles.length];
  578. System.arraycopy(compileList, 0, newCompileList, 0,
  579. compileList.length);
  580. System.arraycopy(newFiles, 0, newCompileList,
  581. compileList.length, newFiles.length);
  582. compileList = newCompileList;
  583. }
  584. }
  585. /** Gets the list of files to be compiled. */
  586. public File[] getFileList() {
  587. return compileList;
  588. }
  589. protected boolean isJdkCompiler(String compiler) {
  590. return "modern".equals(compiler) ||
  591. "classic".equals(compiler) ||
  592. "javac1.1".equals(compiler) ||
  593. "javac1.2".equals(compiler) ||
  594. "javac1.3".equals(compiler) ||
  595. "javac1.4".equals(compiler);
  596. }
  597. protected String getSystemJavac() {
  598. // This is the most common extension case - exe for windows and OS/2,
  599. // nothing for *nix.
  600. String extension = Os.isFamily("dos") ? ".exe" : "";
  601. // Look for java in the java.home/../bin directory. Unfortunately
  602. // on Windows java.home doesn't always refer to the correct location,
  603. // so we need to fall back to assuming java is somewhere on the
  604. // PATH.
  605. java.io.File jExecutable =
  606. new java.io.File(System.getProperty("java.home") +
  607. "/../bin/javac" + extension );
  608. if (jExecutable.exists() && !Os.isFamily("netware")) {
  609. return jExecutable.getAbsolutePath();
  610. } else {
  611. return "javac";
  612. }
  613. }
  614. private String determineCompiler() {
  615. String compiler = project.getProperty("build.compiler");
  616. if (!"false".equals(fork)) {
  617. if (compiler != null) {
  618. if (isJdkCompiler(compiler)) {
  619. log("Since fork is true, ignoring build.compiler setting.",
  620. Project.MSG_WARN);
  621. compiler = "extJavac";
  622. }
  623. else {
  624. log("Since build.compiler setting isn't classic or modern, ignoring fork setting.", Project.MSG_WARN);
  625. }
  626. }
  627. else {
  628. compiler = "extJavac";
  629. }
  630. }
  631. if (compiler == null) {
  632. if (Project.getJavaVersion() != Project.JAVA_1_1 &&
  633. Project.getJavaVersion() != Project.JAVA_1_2) {
  634. compiler = "modern";
  635. } else {
  636. compiler = "classic";
  637. }
  638. }
  639. return compiler;
  640. }
  641. /**
  642. * Adds an "implementation" attribute to Commandline$Attribute
  643. * used to filter command line attributes based on the current
  644. * implementation.
  645. */
  646. public class ImplementationSpecificArgument
  647. extends Commandline.Argument {
  648. private String impl;
  649. public void setImplementation(String impl) {
  650. this.impl = impl;
  651. }
  652. public String[] getParts() {
  653. if (impl == null || impl.equals(determineCompiler())) {
  654. return super.getParts();
  655. } else {
  656. return new String[0];
  657. }
  658. }
  659. }
  660. }