Over a million developers have joined DZone.

On the NetBeans Platform Build System (Part 4)

· Java Zone

Discover how AppDynamics steps in to upgrade your performance game and prevent your enterprise from these top 10 Java performance problems, brought to you in partnership with AppDynamics.

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

The Java Zone is brought to you in partnership with AppDynamics. AppDynamics helps you gain the fundamentals behind application performance, and implement best practices so you can proactively analyze and act on performance problems as they arise, and more specifically with your Java applications. Start a Free Trial.

Topics:

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}