Monday, April 26, 2010

Calling javac from Ant Inside Maven Using AntRun

We ran into a situation where we needed to call Ant's javac task to compile code generated by a legacy Ant task as part of a larger build.  This exposed a very confusing feature of Maven: it apparently changes the java.home property to point to the JRE home. This is no problem on Macs but is on Linux.

There are several possible workarounds.  The one that I currently prefer is to exploit the fact that Maven only overrides ${java.home} but not the original ${env.JAVA_HOME}.  So your <javac> task inside the antrun plugin should look like this:

<javac fork="true" executable="${env.JAVA_HOME}/bin/javac" srcdir="${final.src.dir}" destdir="${final.class.dir}">
<classpath refid="maven.dependency.classpath"/>
In testing, the fork attribute needed to be set to true, but I don't know why. 

Another workaround is to specify the location of tools.jar in the Antrun plugin's dependencies.  This introduces a second problem: Mac and Linux put the tools.jar classes in different jars.  For Linux, this is just in $JAVA_HOME/lib/tools.jar as you would expect, but Mac embeds these classes in classes.jar, located in $JAVA_HOME/../Classes/classes.jar.  Thus you should use 

 <!-- Remainder of the antrun configuration and execution -->

Set ${tools.jar} depending on your operating system as described in the preceding paragraph.  Obviously this introduces an undesirable need to either set or detect the operating system of the build.

Perhaps there is some deep reason for Maven to internally overwrite java.home, but I can't guess it.  This really should be cleaned up.


Gerald Guo said...

I found this page:
I saw following statement:
${java.home} specifies the path to the current JRE_HOME environment use with relative paths to get for example:

So, java.home does not overwrite JAVA_HOME. It just refers to a different thing (JRE_HOME). tools.jar is included in JDK instead of JRE. So java.home should not be used.
I guess the problem is the name (java.home) is confusing :-( Probably, jre.home is better.

dre said...

Thanks Marlon - that worked for me.