Friday, September 26, 2008

Custom Compiler Arguments in PDE/Build

[Edit 2010/07/14: As of the Helios release, PDE/Build now supports per bundle custom compiler arguments using "compilerArg" in the bundle's build.propeties file.]

The other day there was a post to the eclipse.platform.pde newsgroup asking how to include debug information for classes compiled with PDE/Build. The answer is to use the compilerArg property.

This property sets compiler arguments to use when compiling all your bundles. This got me wondering: What if I wanted to set custom compiler arguments for just one bundle, or if different bundles needed different arguments?

There is no explicit support in PDE/Build to do this, but a little digging shows the way!

The Generated Compilation Target

First, take a look at the javac task in the generated build.xml for a bundle. For a typical jar shaped bundle, it looks something like this:
<javac destdir="${temp.folder}/@dot.bin" [...]>
<compilerarg line="${compilerArg}" compiler="${build.compiler}"/>
<classpath refid="@dot.classpath" />
<src path="src/" />
<compilerarg value="@${basedir}/javaCompiler...args"
compiler="org.eclipse.jdt.core.JDTCompilerAdapter"/>
<compilerarg line="-log '${temp.folder}/@dot.bin${logExtension}'"
compiler="org.eclipse.jdt.core.JDTCompilerAdapter"/>
</javac>
Notice the first <compilerarg/>, it is passing the ${compilerArg} property that will affect all bundles. More importantly, notice the second <compilerarg/> whose value starts with '@'. A quick peek at the jdt docs reveals that this specifies a file where more command line arguments will be read.

javaCompiler.<library>.args

For each library specified in the bundle's build.properties file, PDE/Build generates a corresponding javaCompiler.<library>.args file. For most jar shaped bundles, this will be "javaCompiler...args".

We use this file to pass access rules (and custom file encodings) to the compiler. Access rules tell the compiler which packages you are allowed to see for each classpath entry; this is what allows PDE/Build to ensure that your compile-time classpath is as close as possible to the OSGi runtime classpath. The actual #ADAPTER#ACCESS# entries in this file are instructions to the JDT compiler adapter to modify the classpath with the given access rules.

The contents of this file are too ugly to bother pasting here, but the point is that this file is just additional compiler arguments. We can append to this file and insert whichever arguments we like.

Appending to the arguments file

We can use custom callbacks to append to the arguments file. For each library being compiled we can specify a target that will be called just before compilation. Here it is simple to append whatever we like to the arguments file:
<target name="pre.@dot">
<concat append="true" destfile="${basedir}/javaCompiler...args">
-g
-preserveAllLocals
</concat>
</target>



I haven't actually tried this for myself, so you may need to twiddle with the details a little. Note also that because the <compilerarg/> entries have
compiler="org.eclipse.jdt.core.JDTCompilerAdapter"
this will only work with the JDT compiler.