Did you know? DZone has great portals for Python, Cloud, NoSQL, and HTML5!

On the NetBeans Platform Build System (Part 4)

March 03, 2010 AT 4:08 PM
  • submit to reddit

In part 1 and part 2 and part 3 of this series, you were introduced to various topics relating to the NetBeans Platform build system by Hermien Pellissier, from Saab Systems Grintek in Johannesburg (read about their NetBeans Platform work for the South African National Defence Force here). In this, the final part, she reveals the custom Java compiler that is part of the NetBeans Platform and how the AspectJ compiler can be incorporated into your NetBeans Platform development work.

7. About the Custom Java Compiler

First it is worthwhile having a look how the source code was built in NetBeans Platform 6.5. The relevant part of the compile target in "common.xml" is shown below:

<target name="compile" depends="init,up-to-date" unless="is.jar.uptodate">
<mkdir dir="${build.classes.dir}"/>
<depend srcdir="${src.dir}" destdir="${build.classes.dir}" cache="build/depcache">
<classpath refid="cp"/>
</depend>
<javac srcdir="${src.dir}" destdir="${build.classes.dir}" debug="${build.compiler.debug}"
debuglevel="${build.compiler.debuglevel}" encoding="UTF-8"
deprecation="${build.compiler.deprecation}" optimize="${build.compiler.optimize}"
source="${javac.source}" target="${javac.target}" includeantruntime="false">
<classpath refid="cp"/>
<compilerarg line="${javac.compilerargs}"/>
</javac>
...
...
...

And how it is built from 6.7.1 onwards:

<target name="compile" depends="init,up-to-date" unless="is.jar.uptodate">
<mkdir dir="${build.classes.dir}"/>
<depend srcdir="${src.dir}" destdir="${build.classes.dir}" cache="build/depcache">
<classpath refid="cp"/>
</depend>
<nb-javac srcdir="${src.dir}" destdir="${build.classes.dir}" debug="${build.compiler.debug}"
debuglevel="${build.compiler.debuglevel}" encoding="UTF-8"
deprecation="${build.compiler.deprecation}"
optimize="${build.compiler.optimize}" source="${javac.source}"
target="${javac.target}" includeantruntime="false">
<classpath refid="cp"/>
<compilerarg line="${javac.compilerargs}"/>
<processorpath refid="processor.cp"/>
</nb-javac>
...
...
...

In short, the "javac" ant task was replaced with something called "nb-javac". This is defined in the "-javac-init" target (again showing only the relevant part below):

<presetdef>
<custom-javac>
<bootclasspath>
<path path="${bootclasspath.mac}"/>
<path path="${nbjdk.bootclasspath}"/>
</bootclasspath>
<javacclasspath refid="javacimpl"/>
</custom-javac>
</presetdef>

The property "nbjdk.bootclasspath" points to the "harness/antlib/openjdk-javac-6-b12.jar" file, which contains the custom NetBeans compiler.

Why does this compiler exist? The answer, as I discovered quite accidentally when integrating the AspectJ compiler (described in the next section), is simple. It exists to process the new annotations introduced in 6.7.1. The @ServiceProvider annotation, for example, is processed at build time by this custom compiler.

8. Integrating the AspectJ Compiler

Many articles can be written on AspectJ alone. However, here the focus is on how to build module code with the AspectJ compiler, instead of the normal Java compiler or the custom NetBeans compiler.

The first step is to put the AspectJ compiler in a folder close to the harness folder in your platform’s folder structure. In my folder structure, it is located at ${harness.dir}/../aspectj1.6. Then simply replace this part of the "common.xml" build script:

<target name="compile" depends="init,up-to-date" unless="is.jar.uptodate">
<mkdir dir="${build.classes.dir}"/>
<depend srcdir="${src.dir}" destdir="${build.classes.dir}" cache="build/depcache">
<classpath refid="cp"/>
</depend>
<nb-javac srcdir="${src.dir}" destdir="${build.classes.dir}" debug="${build.compiler.debug}"
debuglevel="${build.compiler.debuglevel}" encoding="UTF-8"
deprecation="${build.compiler.deprecation}" optimize="${build.compiler.optimize}"
source="${javac.source}" target="${javac.target}" includeantruntime="false">
<classpath refid="cp"/>
<compilerarg line="${javac.compilerargs}"/>
<processorpath refid="processor.cp"/>
</nb-javac>

with this:

<target name="compile-aspectj" if="aspectjcompiler">
<property name="cpProperty" refid="cp"/>
<property name="aspectj.lib.dir" location="${harness.dir}/../aspectj1.6/lib"/>
<property name="aspectjtools.jar" location="${aspectj.lib.dir}/aspectjtools.jar"/>
<property name="aspectjrt.jar" location="${aspectj.lib.dir}/aspectjrt.jar"/>
<taskdef resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties">
<classpath>
<pathelement path="${aspectjtools.jar}"/>
</classpath>
</taskdef>
<iajc destdir="${build.classes.dir}" srcdir="${src.dir}" source="${javac.source}" fork="true"
forkclasspath="${aspectjtools.jar}" classpath="${aspectjrt.jar};${cpProperty}"
failonerror="false"/>
</target>

<target name="compile-nb-javac" unless="aspectjcompiler">
<nb-javac srcdir="${src.dir}" destdir="${build.classes.dir}" debug="${build.compiler.debug}"
debuglevel="${build.compiler.debuglevel}" encoding="UTF-8" deprecation="${build.compiler.deprecation}"
optimize="${build.compiler.optimize}" source="${javac.source}" target="${javac.target}" includeantruntime="false">
<classpath refid="cp"/>
<compilerarg line="${javac.compilerargs}"/>
<processorpath refid="processor.cp"/>
</nb-javac>
</target>

<target name="compile" depends="init,up-to-date" unless="is.jar.uptodate">
<mkdir dir="${build.classes.dir}"/>
<depend srcdir="${src.dir}" destdir="${build.classes.dir}" cache="build/depcache">
<classpath refid="cp"/>
</depend>
<antcall target="compile-aspectj" inheritAll="true" />
<antcall target="compile-nb-javac" inheritAll="true" />

To activate the AspectJ compiler for a specific module, simply define the "aspectjcompiler=required" property in the "project.properties" file of the module.

However, since the NetBeans compiler is now no longer used, the new annotations are no longer processed. A better way would be to compile the Java and Aspect files separately and then weave them.

9. Conclusion

The NetBeans Platform build harness does its job pretty well, and is configurable without even having to modify scripts. Knowing how the harness works enables the developer to resolve issues that may arise when using the build harness in other ways. The scripts are available for modification if weird and wonderful things are required of it, such as switching off auto-update information generation and replacing the Java compiler with a different one.

From http://www.kitt.co.za

0

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Matayo Stanyslas replied on Fri, 2010/04/23 - 4:30am

I very appreciate your article and I want to Include AspectJ in my project for to add at runtime the firePropertyEvent from all of my POJO developed with EclipseLink, can you give me the sample of your application for to see how you include Aspect in your source Code, because you speak about the modification at compilation time but you don't include a usage of compiler in example. Please can you help me? Thank you in advance

Matayo Stanyslas replied on Fri, 2010/04/23 - 4:44am

Please, why do you remove the name of all property and target ?

Hermien Pellissier replied on Sun, 2010/05/30 - 1:33pm in response to: matayo

The names were left out accidentally somehow. This has now been corrected. Thanks for pointing it out!

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.