Antは、Javaのプログラムのコンパイルや実行を手助けをしてくれるツールです。Antを使うことによって、コンパイルや実行のときに必要なJarファイルやオプションの指定が楽にできます。
こうしたツールは「ビルドツール」と呼ばれます。AntはJavaでできているビルドツールです。UNIXの世界では、代表的なビルドツールとしてmakeがあり、Antも同様の機能を持っています。
makeのようなビルドツールは、そもそもOSなどの環境に依存しているところがあります。makeはUNIXのシェルがベースとなっているので、なおさらです。「Write Once, Run Anywhere」を標榜するJavaとしては、こうした環境依存のツールを使うと、不便な点が多く出てきます。
Antは、Javaで書かれているので、こうした心配はありません。またmakeでのMakefileのような、処理内容を記述するファイルはXMLで書かれていますので、わかりやすくなっています。Makefileを編集した経験がある人なら、Makefileのタブや空白に悩まされた経験を持つ人も多いでしょう。
その反面、makeのようにシェルをベースとしていないので、できる処理に限りがあるという欠点もあります。
Antは、Tomcatを作っているJakarta Projectによって作成されています。(http://ant.apache.org/)
Antでは、処理内容を記述したファイルをXMLで記述します。デフォルトでは"build.xml"というファイル名になります。
ここでは、jp.ac.wakhok.tomoharu.csvパッケージに属するCSVLine.javaとCSVTokenizer.javaという2つのファイルについて、次のような処理をAntで実行してみます。
まずは準備として、src/jp/ac/wakhok/tomoharu/csvディレクトリに2つのソースファイルを置いておきます。build.xmlを見てみましょう。
<?xml version="1.0"?> <project name="csv" default="all" basedir="."> <property name="srcDir" value="src" /> <property name="classDir" value="classes" /> <property name="packageName" value="jp.ac.wakhok.tomoharu.csv" /> <property name="apiDocsDir" value="docs/api" /> <target name="init"> <tstamp/> </target> <target name="compile" depends="init"> <mkdir dir="${classDir}" /> <javac srcdir="${srcDir}" destdir="${classDir}" /> </target> <target name="jar" depends="compile"> <jar jarfile="csv.jar" basedir="${classDir}" /> </target> <target name="javadoc" depends="init"> <mkdir dir="${apiDocsDir}" /> <javadoc packagenames="jp.ac.wakhok.tomoharu.csv" sourcepath="${srcDir}" destdir="${apiDocsDir}" /> </target> <target name="all" depends="jar, javadoc"> <zip zipfile="../csv.zip" basedir=".." includes="csv/**" excludes="**/classes/**" /> </target> </project>
build.xmlの中には、要素projectが1つだけ含まれています。要素projectの中には複数の要素targetが含まれています。targetの中には、処理の最小単位である要素taskが複数含まれています。
project要素の直下に、要素propertyが設定されています。propertyは名前と値のペアになっており、"srcDir"という名前のpropertyは、
${srcDir}
と記述することで名前を参照できます。
taskは、処理の最小単位です。Antでは、さまざまな種類のtaskが標準で組みこまれています。この例では、次のtaskが実行されています。
いずれも、Javaプログラマにとっては馴染み深いものですね。最後のtstampは、現在の日時の情報をDSTAMP, TSTAMP, TODAYといったプロパティに設定するためのタスクです。他にも、CVSリポジトリにアクセスしたり、メールを送信したりするようなtaskもあります。
例えば、javacというtaskは次のような構成になっています。
<javac srcdir="${srcDir}" destdir="${classDir}" />
javacはソースファイルのコンパイルを行うタスクです。srcdir属性がソースファイルのありかを示し、destdir属性がクラスファイルの生成先のディレクトリを示しています。
targetは複数のtaskをまとめてグループにしています。この例では、"compile"というname属性を持つtargetには、ディレクトリを作成するmkdirというtaskと、コンパイルを実行するjavacというtaskが含まれています。
targetは他のtargetに依存できます。ここでは、"compile"は"init"に依存しています。この場合、先に"init"の処理をしてから"compile"のtaskが実行されます。Antでは、targetを明示的に指定して実行できます。この場合、そのtargetの依存関係を順にたどり、もっとも優先される処理から実行されます。
Antでは、ファイルやディレクトリを指定するときに、WindowsやUnixでお馴染みのスタイルのパターンを利用できます。
*.java .java や a.java にマッチ。a.xml にはマッチしない。 ?.java b.java にマッチ。
"*"は、0個以上の文字にマッチします。また、"?"は、1個の文字にマッチします。
またこのサンプルには、次のような記述があります。
includes="csv/**"
"**"はすべての階層のファイル・ディレクトリにマッチします。この例では、csv以下のすべてのファイル・ディレクトリにマッチします。
Antを動かすためには、適当なディレクトリにインストールした後に、次の手順が必要です。
AntをWindows上のc:\antにインストールするとします。その場合、次のように設定をする必要があります。
set ANT_HOME=c:\ant set JAVA_HOME=c:\j2sdk1.4.2 set PATH=%PATH%;%ANT_HOME%\bin
antを実行するには、build.xml (もしくは他の設定ファイル)があるディレクトリに移動して
C:\> ant
と実行するだけです。引数を指定せずにantコマンドを実行した場合、デフォルトのtargetが実行されます。デフォルトのtargetは、project要素のdefault属性で指定できます。この場合は、"all"というtargetになります。
<project name="csv" default="all" basedir="."> ... </project>
特定のtargetのみ処理したい場合は
C:\> ant javadoc
のように、targetの名前を引数に取ります。
build.xmlの例をもう一つ紹介しましょう。このbuild.xmlでは、環境変数で指定されたディレクトリにあるたくさんのjarファイルをクラスパスに設定し、プログラムのコンパイルと実行を行っています。
<?xml version="1.0"?> <project name="Google Web API Sample" default="compile" basedir="."> <property environment="env"/> <property name="jaxrpc.home" value="${env.JWSDP_HOME}/jaxrpc"/> <property name="jaxp.home" value="${env.JWSDP_HOME}/jaxp"/> <property name="jaxr.home" value="${env.JWSDP_HOME}/jaxr"/> <property name="saaj.home" value="${env.JWSDP_HOME}/saaj"/> <property name="jaxb.home" value="${env.JWSDP_HOME}/jaxb"/> <property name="shared.lib" value="${env.JWSDP_HOME}/jwsdp-shared/lib"/> <property name="common.lib" value="${env.JWSDP_HOME}/common/lib"/> <property name="common.endorsed" \ value="${env.JWSDP_HOME}/common/endorsed"/> <path id="wspack.classpath"> <!-- JAXRPC jars --> <pathelement location="${jaxrpc.home}/lib/jaxrpc-api.jar"/> <pathelement location="${jaxrpc.home}/lib/jaxrpc-impl.jar"/> <pathelement location="${jaxrpc.home}/lib/jaxrpc-spi.jar"/> <!-- JAXP jars --> <pathelement location="${jaxp.home}/lib/jaxp-api.jar"/> <pathelement location="${jaxp.home}/lib/endorsed/xercesImpl.jar"/> <pathelement location="${jaxp.home}/lib/endorsed/sax.jar"/> <pathelement location="${jaxp.home}/lib/endorsed/dom.jar"/> <pathelement location="${jaxp.home}/lib/endorsed/xalan.jar"/> <!-- JAXR jars --> <pathelement location="${jaxr.home}/lib/jaxr-api.jar"/> <pathelement location="${jaxr.home}/lib/jaxr-impl.jar"/> <!-- SAAJ jars --> <pathelement location="${saaj.home}/lib/saaj-api.jar"/> <pathelement location="${saaj.home}/lib/saaj-impl.jar"/> <!-- JAXB jars --> <pathelement location="${jaxb.home}/lib/jaxb-api.jar"/> <pathelement location="${jaxb.home}/lib/jaxb-impl.jar"/> <pathelement location="${jaxb.home}/lib/jaxb-xjc.jar"/> <pathelement location="${jaxb.home}/lib/jaxb-libs.jar"/> <!-- Common jars --> <pathelement location="${shared.lib}/activation.jar"/> <pathelement location="${shared.lib}/mail.jar"/> <pathelement location="${shared.lib}/commons-logging.jar"/> <pathelement location="${shared.lib}/jax-qname.jar"/> <pathelement location="${shared.lib}/xsdlib.jar"/> <pathelement location="${shared.lib}/relaxngDatatype.jar"/> <pathelement location="${shared.lib}/namespace.jar"/> <!-- Servlet jar --> <pathelement location="${jwsdp.home}/common/lib/servlet-api.jar"/> <!-- current directory --> <pathelement location="."/> </path> <target name="init"> <tstamp/> </target> <target name="compile" depends="init"> <javac srcdir="."> <include name="*.java" /> <classpath> <path refid="wspack.classpath"/> </classpath> </javac> </target> <target name="run" depends="compile"> <java classname="GoogleSearch" > <arg value="wakhok"/> <classpath> <path refid="wspack.classpath"/> </classpath> </java> </target> </project>
まず、次のproperty要素で、環境変数を読み込み、envという変数に格納しています。
<property environment="env"/>
次のproperty要素のvalue属性で、${env.JWSDP_HOME}という記述があります。これは、先に環境変数を読み込んだenvという変数を通じて、環境変数JWSDP_HOMEの値を取得しています。ここでは、JWSDP_HOMEの値に"/jaxrpc"という文字列をつけたものを、jaxrpc.homeプロパティの値として設定しています。
<property name="jaxrpc.home" value="${env.JWSDP_HOME}/jaxrpc"/>
次の部分では、たくさんのjarファイルをクラスパスに追加しています。このクラスパスには"wspack.classpath"というidが付けられています。
<path id="wspack.classpath"> <!-- JAXRPC jars --> <pathelement location="${jaxrpc.home}/lib/jaxrpc-api.jar"/> <pathelement location="${jaxrpc.home}/lib/jaxrpc-impl.jar"/> ...... </path>
コンパイルや実行のときには、path要素を用いて、クラスパスにwspack.classpathを指定しています。
<target name="compile" depends="init"> <javac srcdir="."> <include name="*.java" /> <classpath> <path refid="wspack.classpath"/> </classpath> </javac> </target>