Archive

Posts Tagged ‘ant’

Running javadoc Ant task from Eclipse

December 9th, 2008 25 comments

All things being equal, I like projects that build out-of-the-box. That is, given a clean checkout from revision control, a project should just build without requiring too much customization: setting environment variables, installing third party software, modifying the system path. I’m especially sensitive to this at the moment because I’ve just finished up five days (actually maybe 30 hours all together) getting one particularly horrible system to build.

Along these lines, I added a javadoc task to an Ant build script today and tried running it from Eclipse. Just for the record, that procedure is as follows:

  • Open build.xml
  • Right-click the task in the Outline View
  • Select Run As->Ant build.

Interestingly enough, this failed with the following error:

build.xml:208: Javadoc failed: java.io.IOException: Cannot run program
"javadoc.exe": CreateProcess error=2, The system cannot find the file
specified

A quick Google search reveals several suggestions that the solution is to make sure that javadoc.exe is on the system path.  First, it’s a little ridiculous that Ant can’t find javadoc from JAVA_HOME when it clearly uses the same mechanism to track down javac. Oh well. Bygones. Second, returning to the idea of builds that “just work”, I don’t want to modify my system path. What if I have several JDKs installed, used with several different projects simultaneously?

So, how do we get javadoc onto the system path without modifying it? Simple, modify the path in Eclipse. This time, run the Ant task with the following procedure:

  • Open build.xml
  • Right-click the task in the Outline View
  • Select Run As->Ant Build …

That elipsis at the end is important. This will bring up the Eclipse launch configuration dialog. Give your new launch configuration a name, like “Build <Project Name>” or something and switch to the Environment tab. Here you can specify the environment for Ant. But we don’t want to kill the whole system path, just prepend the location of javadoc.exe to it. So click New… and enter Path for the name and the following for the value:

   ${env_var:JAVA_HOME}/bin;${env_var:Path}

This prepends JAVA_HOME/bin to the current system path. Now click Run and everything should work fine. Yay.

Now, when someone else checks out the project you don’t want them to have to go through the same hassle. It’s still a hassle, just inside Eclipse instead somewhere else on the machine. The solution to this problem is to save the launch configuration!  Return to the launch configuration screen and open the Common tab. There you can select to save the configuration as a shared file. I usually save it in tools/launches. The resulting file will have a .launch extension. Commit the launch file to version control. Now anyone who checks out the project will have a properly configured launch configuration to build the project. No fuss, no muss.

Also note that this is a much more general purpose solution. It applies to any launch configuration where you need to modify the path, or set any kind of environment variables.

Possible Issues

There are a few potential issues I can think of:

  • That semi-colon in the path string may not work on non-Windows systems. I’m not sure if Eclipse is smart enough to fix that.
  • In the past, I’ve had trouble with the case of environment variables and Ant.

Also, I believe that an alternate solution to this problem is to register the JDK in Eclipse. This is ok, but it’s nice to not require it.

Categories: eclipse, java Tags: , ,

Beware of Case-Sensitive Environment Variables in ANT

December 2nd, 2008 No comments

Today I was bitten by a kind of annoying feature of ANT. Sadly, a project I’m working relies on a Swig-generated wrapper for a C++ library, in particular the SML client libraries for Soar. So, it’s important to have all the DLLs in the right spot to avoid link exceptions. The usual, and I think most straightforward, solution is to ensure that the DLLs are on the system path. To this end, I can make a simple bat scripts (or shell script) that sets up the environment and then invokes Java.

However, I try to be good and write unit tests for this stuff too which means that the environment has to be set up correctly for JUnit too, even when invoked from ANT. So, in ANT, how do I extend the system path for the JUnit task while not clobbering the path that’s already there? I did a little hunting around and found the nice <env> tag which is documented in the exec task. Lo and behold, the second example is exactly what I want to do. Here is what I did, translated for junit:

<property environment="env"/>
<junit fork="true" ... >
  <env key="PATH" path="${env.PATH}:${basedir}/vendor/soar-8.6.3/bin"/>
</exec>

Pretty straightforward, right. But, of course it didn’t work right away. After a little more hunting, I figure out the problem is with that <property environment … > tag. It turns out there are a few things going on here:

  • On Windows, environment variable names are case insensitive
  • Properties in ANT are case sensitive
  • The case of the PATH environment variable in Windows appears to be totally random

These factors conspired against me. In my case, my path environment variable was spelled “Path” with a capital Pee. Changing the ANT file to use this spelling fixed everything. And yes, this limitation is documented in the documentation for the property task.

The really sad thing is that I got bit by this less than an hour later when I set up the project on Hudson (really cool by the way). In this case, it appears that Hudson (or something else) changes the PATH environment variable to all lower case when invoking ANT. So, now I have a build script that runs great on my machine, but fails on the build machine. I’m sure there’s a better solution, but for expediency, I went with this monstrosity:

<property environment="env"/>
<junit fork="true" ... >
  <env key="PATH" path="${env.path}:${env.Path}:${basedir}/vendor/soar-8.6.3/bin"/>
</exec>

I wonder if this will ever come back to haunt me… Yet another reason for me to eliminate this C++ dependency.

Categories: java, software engineering Tags: , ,