How to make a conditional decision in an Ant build script based on operating system

Background

I was writing with a former co-worker the other day about how to do some things that are specific to Mac OS X in his Java Swing applications (see How to make a Java/Swing application look like a native Mac OS X application), but also keep his Ant build script working on a Windows computer.

During our email conversation, one approach that came to mind was to create an Ant build script that conditionally performed operations (tasks, or targets) on Mac OS X that it wouldn't perform if the same build script was run on a Windows system.

Solution

I do all of my development exclusively on Mac OS X these days, so I haven't been able to test the following Ant build script on other platforms (like Windows, Linux, or Unix systems), but I think it will work as shown.

The basic idea of the script is that you create certain properties in your Ant build script (isMac, isWindows, isUnix) using the Ant condition task, and then use those properties to later determine whether a specific target should or should not be run. This decision is made with the if clause of the target tag.

The source code for my Ant build script

Here's the complete source code for an Ant build script I just created to demonstrate this process of creating an operating system specific conditional build process.

<?xml version="1.0"?>

<!--
  build.xml

  A test Ant script to demonstrate how to conditionally run Ant
  tasks depending on the operating system (OS) the Ant build script
  is currently running on. Tests for Mac, Windows, or Unix systems.
  Created by Alvin Alexander, http://alvinalexander.com
-->

<project default="GO" name="Ant Operating System Conditional Test" >

  <!-- first create our properties -->
  <condition property="isMac">
    <os family="mac" />
  </condition>

  <condition property="isWindows">
    <os family="windows" />
  </condition>

  <condition property="isUnix">
    <os family="unix" />
  </condition>

  <!-- now create our operating system specific targets -->
  <target name="doMac" if="isMac">
    <echo message="Came into the Mac target" />
    <!-- do whatever you want to do here for Mac systems -->
  </target>

  <target name="doWindows" if="isWindows">
    <echo message="Came into the Windows target" />
  </target>

  <target name="doUnix" if="isUnix">
    <echo message="Came into the Unix target" />
  </target>

  <!-- run everything from our main target -->
  <!-- the other targets will only be run when their properties are true -->
  <target name="GO" depends="doMac, doWindows, doUnix">
    <echo message="Running GO target" />
    <echo message="os.name = ${os.name}" />
    <echo message="os.arch = ${os.arch}" />
    <echo message="os.version = ${os.version}" />
  </target>

</project>

The output from this Ant build script

When I save this Ant build script (naming it build.xml) and run it on my Mac OS X 10.5.7 system using Ant version 1.7.0, I get the following output:

Buildfile: build.xml

doMac:
     [echo] Came into the Mac target

doWindows:

doUnix:
     [echo] Came into the Unix target

GO:
     [echo] Running GO target
     [echo] os.name = Mac OS X
     [echo] os.arch = i386
     [echo] os.version = 10.5.7

BUILD SUCCESSFUL
Total time: 0 seconds

I'm a little concerned that this script sets both isMac and isUnix to true, but that doesn't affect my current desire to find an approach that works on both Mac OS X and Windows. That being said, I'll look into this some more and see what I can find out. (Mac OS X is build on top of a BSD/Mach base, so I'm assuming that's the answer, but I don't know for sure.)