diff options
Diffstat (limited to 'taskdefs')
-rw-r--r-- | taskdefs/src/org/aspectj/tools/ant/taskdefs/Ajc11CompilerAdapter.java | 282 |
1 files changed, 122 insertions, 160 deletions
diff --git a/taskdefs/src/org/aspectj/tools/ant/taskdefs/Ajc11CompilerAdapter.java b/taskdefs/src/org/aspectj/tools/ant/taskdefs/Ajc11CompilerAdapter.java index 15198d957..4e23c962b 100644 --- a/taskdefs/src/org/aspectj/tools/ant/taskdefs/Ajc11CompilerAdapter.java +++ b/taskdefs/src/org/aspectj/tools/ant/taskdefs/Ajc11CompilerAdapter.java @@ -1,190 +1,152 @@ /* ******************************************************************* - * Copyright (c) 2001-2001 Xerox Corporation, - * 2002 Palo Alto Research Center, Incorporated (PARC). - * All rights reserved. - * This program and the accompanying materials are made available - * under the terms of the Common Public License v1.0 - * which accompanies this distribution and is available at - * http://www.eclipse.org/legal/cpl-v10.html - * - * Contributors: - * Xerox/PARC initial implementation + * Copyright (c) 2003 Contributors. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Wes Isberg initial implementation * ******************************************************************/ package org.aspectj.tools.ant.taskdefs; import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.types.Commandline; -import org.apache.tools.ant.taskdefs.compilers.DefaultCompilerAdapter; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.taskdefs.Javac; +import org.apache.tools.ant.taskdefs.compilers.CompilerAdapter; +import org.aspectj.util.FileUtil; import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.ListIterator; - -import org.aspectj.bridge.*; -import org.aspectj.util.LangUtil; - +import java.io.FileFilter; +import java.io.FileWriter; +import java.io.IOException; /** - * EXPERIMENTAL - This adapts the AspectJ compiler as if it were Javac. - * It just passes the arguments through to the compiler. - * Limitations: + * Adapt ajc to javac commands. + * Note that the srcdirs set for javac are NOT passed on to ajc; + * instead, the list of source files generated is passed to ajc. + * <p> + * Javac usually prunes the source file list based on the timestamps + * of corresponding .class files, which is wrong for ajc which + * requires all the files every time. To work around this, + * set the global property CLEAN ("build.compiler.clean") to delete + * all .class files in the destination directory before compiling. + * This clean process only permits one compile process at a time + * for each destination directory because it tracks recursion by + * writing a tag file to the destination directory. + * + * <p><u>Warnings</u>: * <ol> - * <li>Users still must specify all source files to compile.</li> - * <li>No support for non-Javac options</li> - * <li>Javac srcdir are treated as sourceroots unless -DajcAdapterSkipRoots=...</li> - * </ol> + * <li>cleaning will makes stepwise build processes fail + * if they depend on the results of the prior compilation being + * in the same directory, since this deletes <strong>all</strong> + * .class files.</li> + * <li>If no files are out of date, then the adapter is never called + * and thus cannot gain control to clean out the destination dir. + * </li> + * <p> * * @author Wes Isberg <a href="mailto:isberg@aspectj.org">isberg@aspectj.org</a> - * @since AspectJ 1.1, Ant 1.3 + * @since AspectJ 1.1, Ant 1.5.1 */ -public class Ajc11CompilerAdapter extends DefaultCompilerAdapter { - /* - * Not sure how best to implement our functionality -- not documented. - * Desired functionality: - * - ability to run in-line or forked - * - switch based only on fork="[true|false]" - * (so classpath required to fork must be calculated) - * - able to set memory available when forking - * - handles .lst files on command-line by prefixing with @ - * - and/or handles compiler option -XargPrefix=... - * - this means all AspectJ-specific options (injars/outjars...) - * are in the .lst file? - * - * Implementation options: - * - straight CompilerAdapter - * - override DefaultCompilerAdapter methods for template processes - * - create a new FacadeTaskHelper, supply to DefaultCompilerAdaper - */ - public static final String SKIP_ROOTS_NAME = "ajcAdapterSkipRoots"; - - // ------------------------------ setup - /** - * Adds the command line arguments specifc to the current implementation. - */ - protected void addCurrentCompilerArgs(Commandline cmd) { - cmd.addArguments(getJavac().getCurrentCompilerArgs()); +public class Ajc11CompilerAdapter implements CompilerAdapter { + /** + * Define this system/project property to signal that the + * destination directory should be cleaned + * and javac reinvoked + * to get the complete list of files every time. + */ + public static final String CLEAN = "build.compiler.clean"; + + Javac javac; + + public void setJavac(Javac javac) { + this.javac = javac; } - - // ------------------------------ run - /** - * Run the compilation. - * - * @exception BuildException if the compilation has problems. - */ + public boolean execute() throws BuildException { - Commandline cmd = setupModernJavacCommand(); - - try { - String[] args = cmd.getArguments(); - int result = runCompiler(args); - return (0 == result); - } catch (BuildException e) { - throw e; - } catch (AbortException x) { - if (x.isSilent()) { // no message, just return - return false; - } else { - Throwable t = x.getThrown(); - if (null == t) { - t = x; + checkJavac(); + if (recurse()) { + javac.execute(); // re-invokes us after recalculating file list + } else { + try { + AjcTask ajc = new AjcTask(); + String err = AjcTask.setupAjc(ajc, javac, getDestDir()); + if (null != err) { + throw new BuildException(err, javac.getLocation()); } - throw new BuildException("Thrown: ", t, location); + ajc.execute(); // handles BuildException for failonerror, etc. + } finally { + doneRecursing(); } - } catch (Throwable x) { - throw new BuildException("Thrown: ", x, location); + } + return true; + } + + /** @throws IllegalStateException if javac is not defined */ + protected void checkJavac() { + if (null == javac) { + throw new IllegalStateException("null javac"); } } - // run? handle forking? - private int runCompiler(String[] args) { - int result = -1; - IMessageHolder sink = new MessageHandler(); - ICommand compiler = ReflectionFactory.makeCommand(ReflectionFactory.ECLIPSE, sink); - if ((null == compiler) || sink.hasAnyMessage(IMessage.FAIL, true)) { - throwBuildException("loading compiler", sink); - } else { - args = filterArgs(args); - if (!compiler.runCommand(args, sink)) { - System.err.println("runCompiler args: " + Arrays.asList(args)); - throwBuildException("running compiler", sink); - } else { - result = 0; - } + protected File getDestDir() { + checkJavac(); + File destDir = javac.getDestdir(); + if (null == destDir) { + destDir = new File("."); } - return result; + return destDir; } - /** - * Method throwBuildException. - * @param string - * @param sink - */ - private void throwBuildException(String string, IMessageHolder sink) { // XXX nicer - if ((null != sink) && (0 < sink.numMessages(null, true))) { - MessageUtil.print(System.err, sink, null); + protected File getTagFile() { + return new File(getDestDir(), "Ajc11CompilerAdapter.tag"); + } + + /** + * If property CLEAN is set, then this + * cleans out the dest dir of any .class files, + * installs a tag file, and returns true to signal a recursive call. + * That means this returns false if CLEAN is not set + * or if the tag file already exists (i.e., already recursing). + * The result is that javac is re-invoked after the dest dir + * is cleaned, so it picks up all the correct source files. + * (This is a costly hack to work around Javac's forcing the + * pruning of the file list.) + * @return true if javac should be re-invoked. + */ + protected boolean recurse() { + checkJavac(); + String cleanDirs = javac.getProject().getProperty(CLEAN); + if (null == cleanDirs) { + return false; } - throw new BuildException(string + ": " + sink, location); - } - - /** Convert javac argument list to a form acceptable by ajc */ - protected String[] filterArgs(String[] args) { - LinkedList argList = new LinkedList(); - argList.addAll(LangUtil.arrayAsList(args)); - ArrayList roots = new ArrayList(); - for (ListIterator iter = argList.listIterator(); iter.hasNext();) { - String arg = (String) iter.next(); - if ("-sourcepath".equals(arg)) { // similar to -sourceroots? - iter.remove(); - roots.add(iter.next()); // need next after remove? - iter.remove(); - } else if ("-0".equals(arg)) { // unsupported - System.err.println("warning: ignoring -0 argument"); - iter.remove(); - } else if ("-bootclasspath".equals(arg)) { // ajc fakes - } else if ("-extdirs".equals(arg)) { // ajc fakes - } else if ("-target".equals(arg)) { // -1.4 or -1.3 - iter.remove(); - String vers = (String) iter.next(); - if ("1.3".equals(vers)) { - iter.set("-1.3"); - } else if ("1.4".equals(vers)) { - iter.set("-1.4"); - } else { // huh? - String s = "expecting 1.3 or 1.4 at " + vers + " in " + argList; - throwBuildException(s, null); - } - } - } - - if (0 < roots.size()) { - String skipRoots = null; - try { - skipRoots = System.getProperty(SKIP_ROOTS_NAME); - } catch (Throwable t) { - // ignore SecurityException, etc. - } - - if (null == skipRoots) { - StringBuffer sb = new StringBuffer(); - boolean first = true; - for (Iterator iter = roots.iterator(); iter.hasNext();) { - if (!first) { - sb.append(File.pathSeparator); - } else { - first = false; - } - sb.append((String) iter.next()); - } - argList.add(0, "-sourceroots"); - argList.add(1, sb.toString()); - } + File tagFile = getTagFile(); + if (tagFile.exists()) { + return false; } + try { + File destDir = getDestDir(); + javac.log(CLEAN + " cleaning .class files from " + destDir, + Project.MSG_VERBOSE); + FileUtil.deleteContents(destDir, FileUtil.DIRS_AND_WRITABLE_CLASSES, true); + FileWriter fw = new FileWriter(tagFile); + fw.write("Ajc11CompilerAdapter.recursing"); + fw.close(); + return true; + } catch (IOException e) { + return false; + } + } - return (String[]) argList.toArray(new String[0]); + protected void doneRecursing() { + File tagFile = getTagFile(); + if (tagFile.exists()) { + tagFile.delete(); + } } } + |