3.8 Defining a Classpath

3.8.1 Problem

You want to define a classpath and reuse it throughout a buildfile.

3.8.2 Solution

Use the <path> element to define the classpath along with a unique ID. Then refer to the classpath using the ID.

3.8.3 Discussion

Example 3-5 shows how to define a classpath and refer to it later from the javac task.

Example 3-5. Reusing a classpath
<?xml version="1.0" encoding="UTF-8"?>
<project name="Classpath Sample" default="compile" basedir=".">
  <!-- get an environment variable -->
  <property environment="env"/>
  <property name="tomcatHome" value="${env.TOMCAT_HOME}"/>

  <!-- define some directories -->
  <property name="dir.src" value="src"/>
  <property name="dir.build" value="build"/>
  <property name="dir.lib" value="lib"/>
  
  <!-- Define a classpath for use throughout the buildfile -->
  <path id="project.classpath">
    <pathelement location="${dir.src}"/>
    <!-- include Tomcat libraries -->
    <fileset dir="${tomcatHome}/common/lib">
      <include name="*.jar"/>
    </fileset>    
    <!-- include our own libraries -->
    <fileset dir="${dir.lib}">
      <include name="*.jar"/>
    </fileset>
  </path>
  
  <target name="clean">
    <delete dir="${dir.build}"/>
  </target>
  
  <target name="prepare">
    <mkdir dir="${dir.build}"/>
  </target>
  
  <target name="compile" depends="prepare">
    <!-- use <pathconvert> to convert the path into a property -->
    <pathconvert targetos="windows" property="windowsPath"
                 refid="project.classpath"/>
    <!-- now echo the path to the console -->
    <echo>Windows path = ${windowsPath}</echo>
        
    <!-- Here is how to use the classpath for compiling -->
    <javac destdir="${dir.build}">
      <src path="${dir.src}"/>
      <classpath refid="project.classpath"/>
    </javac>
  </target>
</project>

Several aspects of this buildfile are worthy of discussion. We define our classpath using the <path> element, giving it a unique ID so it can be referenced and reused more than once:

<path id="project.classpath">

You can construct a path consisting of many different files using a combination of nested <pathelement> and <fileset> elements. The first nested <pathelement> in our example adds the source directory to our path:

  <pathelement location="${dir.src}"/>

We then use two <fileset>s to add numerous JAR files to our path:

  <fileset dir="${tomcatHome}/common/lib">
    <include name="*.jar"/>
  </fileset>    
  <!-- include our own libraries -->
  <fileset dir="${dir.lib}">
    <include name="*.jar"/>
  </fileset>

All of these items are added in the order listed in the buildfile. Later, we use <pathconvert> to store our path in a property named windowsPath:

<pathconvert targetos="windows" property="windowsPath"
             refid="project.classpath"/>

This does not affect the path in any way. Instead, it creates the windowsPath property, which might contain something like:

C:\myproj\src;C:\tomcat\common\lib\servlet.jar;etc...

This property is useful for debugging purposes because you can echo it to the console for inspection.

Our buildfile concludes by using the classpath with the javac task:

<javac destdir="${dir.build}">
  <src path="${dir.src}"/>
  <classpath refid="project.classpath"/>
</javac>

Since the classpath has an ID, you can refer to it from other targets throughout the buildfile as shown.

We almost always create a lib directory in source control and put all the JARs we depend on there. This makes it easy to find the JAR files and update them in a controlled manner.

3.8.4 See Also

The next two recipes provide additional information about setting up paths.