Ajc11CompilerAdapter (javac)

This CompilerAdapter can be used in javac task calls by setting the build.compiler property. This enables users to to easily switch between the Javac and AspectJ compilers. However, because there are differences in source file handling between the Javac task and the ajc compiler, not all Javac task invocations can be turned over to iajc. However, ajc can compile anything that Javac can, so it should be possible for any given compile job to restate the Javac task in a way that can be handled by iajc/ajc.

Sample of compiler adapter

To build using the adapter, put the aspectjtools.jar on the system/ant classpath (e.g., in ${ANT_HOME}/lib) and define the build.compiler property as the fully-qualified name of the class, org.aspectj.tools.ant.taskdefs.Ajc11CompilerAdapter.

The AspectJ compiler should run for any compile using the Javac task (for options, see the Ant documentation for the Javac task). For example, the call below passes all out-of-date source files in the src/org/aspectj subdirectories to the ajc command along with the destination directory:

		
-- command:

    cp aspectj1.1/lib/aspectjtools.jar ant/lib
    ant/bin/ant -Dbuild.compiler=org.aspectj.tools.ant.taskdefs.Ajc11CompilerAdapter ...

-- task invocation in the build script:

  <javac srcdir="src" includes="org/aspectj/**/*.java" destdir="dest" />

		

To pass ajc-specific arguments, use a compilerarg entry.

		
-- command

  Ant -Dbuild.compiler=org.aspectj.tools.ant.taskdefs.Ajc11CompilerAdapter

-- build script

  <property name="ajc" 
              value="org.aspectj.tools.ant.taskdefs.Ajc11CompilerAdapter"/>

  <javac srcdir="src" includes="org/aspectj/**/*.java" destdir="dest" >
    <compilerarg compiler="${ajc}" line="-argfile src/args.lst"/>
  <javac/>

		

The Javac task does special handling of source files that can interfere with ajc. It removes any files that are not out-of-date with respect to the corresponding .class files. But ajc requires all source files, since an aspect may affect a source file that is not out of date. (For a solution to this, see the build.compiler.clean property described below.) Conversely, developers sometimes specify a source directory to javac, and let it search for files for types it cannot find. AspectJ will not do this kind of searching under the source directory (since the programmer needs to control which sources are affected). (Don't confuse the source directory used by Javac with the source root used by ajc; if you specify a source root to ajc, it will compile any source file under that source root (without exception or filtering).) To replace source dir searching in Javac, use an Ant filter to specify the source files.

Compiler adapter compilerarg options

The adapter supports any ajc command-line option passed using compilerarg, as well as the following options available only in AjcTask. Find more details on the following options in AjcTask (iajc).

  • -Xmaxmem: set maximum memory for forking (also settable in javac).

  • -Xlistfileargs: list file arguments (also settable in javac).

  • -Xfailonerror: throw BuildException on compiler error (also settable in javac).

  • -Xmessageholderclass: specify fully-qualified name of class to use as the message holder.

  • -Xcopyinjars: copy resources from any input jars to output (default behavior since 1.1.1)

  • -Xsourcerootcopyfilter {filter}: copy resources from source directories to output (minus files specified in filter)

  • -Xtagfile {file}: use file to control incremental compilation

  • -Xsrcdir {dir}: add to list of ajc source roots (all source files will be included).

Special considerations when using Javac and compilerarg:

  • The names above may differ slightly from what you might expect from AjcTask; use these forms when specifying compilerarg.

  • By default the adapter will mimic the Javac task's copying of resource files by specifying "**/CVS/*,**/*.java,**/*.aj" for the sourceroot copy filter. To change this behavior, supply your own value (e.g., "**/*" to copy nothing).

  • Warning - define the system property build.compiler.clean to compile all files, when available. Javac prunes the source file list of "up-to-date" source files based on the timestamps of corresponding .class files, and will not compile if no sources are out of date. This is wrong for ajc which requires all the files for each compile and which may refer indirectly to sources using argument files.

    To work around this, set the global property build.compiler.clean. This tells the compiler adapter to delete all .class files in the destination directory and re-execute the javac task so javac can recalculate the list of source files. e.g.,

    		
      Ant -Dbuild.compiler=org.aspectj.tools.ant.taskdefs.Ajc11CompilerAdapter
          -Dbuild.compiler.clean=anything ...
    
    		

    Caveats to consider when using this global build.compiler.clean property:

    1. If javac believes there are no out-of-date source files, then the adapter is never called and cannot clean up, and the "compile" will appear to complete successfully though it did nothing.

    2. Cleaning will makes stepwise build processes fail if they depend on the results of the prior compilation being in the same directory, since cleaning deletes all .class files.

    3. 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.

    4. When running incrementally, the clean happens only before the initial compile.