September 26, 2012

OS-specific ANT properties

The ANT build tool for Java does a pretty decent job of abstracting away OS concerns from your build script. E.g., file paths can always be represented using the / separator and there are tasks for all the typical file system and build operations.

However, once in while you may find yourself in a situation where you need ANT to behave differently based on the operating system. In my case, I needed to specify path to the dot executable within graphviz, a graph drawing tool used by the Hibernate tools ANT package. Rather than torture my environment, I figured I would set a property based on the OS:

<target name="schema-doc">
    <property name=""
              value="-Gsplines=true -Edecorate" />
    <condition property="" value="/usr/bin/fdp">
        <os family="unix" />
    <condition property=""
        <os family="windows" />
    <mkdir dir="${}/doc" />
        <fileset dir="${}/doc" />
    <hibernatetool destdir="${}/doc">
        <configuration configurationfile="${basedir}/hibernate-tool.cfg.xml">
            <fileset dir="${src}" includes="**/*.hbm.xml" />
        <classpath refid="hibernate.classpath" />
            <property key="dot.executable"
                      value="${} ${}" />

The key portion here occurs near the top, using the <condition> directive. Here I’ve placed in inside the <target>, but you can use it outside of a <target> as well. The <os> element within the <condition> allows you test based on properties of the underlying operating system. I’ve chosen to base the test on family, but there are also name, version and arch tests as well.

(As a bonus tip here, I’ve also shown you how to pass extra arguments to graphviz when running it within Hibernate Tools.)

Now this is all well and good for one property, which is the situation I was dealing with, but what if you have a whole mess of properties to deal with? Making multiple <condition> tags for each property and OS combination will get old real fast. In that case, we use the built-in properties ANT supplies:

<property file="build-${}-${os.version}-${os.arch}.properties" />
<property file="build-${}-${os.version}.properties" />
<property file="build-${}.properties" />
<property file="" />

Note the order here. Recall that once a property is defined within ANT it cannot be changed. So put the defaults in and then override them in the more specific properties files that are loaded first. Of course, you may not need to go all the way to the OS architecture level, but now you know how.