LoginSignup
8
5

More than 3 years have passed since last update.

Apache Ant の作りを理解する

Posted at

第3章 Apache Ant を構成する要素

コマンド

コマンドラインからのAntの利用は、全てantコマンドで行います。
書式は以下の通りで、オプションターゲットを指定して実行します。
※ターゲットについては後ほど紹介します。

ant [オプション] [ターゲット1 ターゲット2...]

オプション

Antで使用できるオプション一覧は、ant -helpで確認できますが、
簡単な利用だけなら以下を押さえていれば問題ありません。

  • -buildfile <ファイル>
    参照するビルドファイルをパスで指定します。
    指定しない場合、カレントディレクトリのbuild.xmlというファイルが指定されます。
  • -find <ディレクトリ>
    指定したディレクトリのサブディレクトリを検索し、ビルドファイルを探す。
  • -verbose
    ビルドに関する詳細な情報を出力しながらビルドを実行します。

ビルドファイル

ビルドファイルは、慣例的にbuild.xmlという名前で作成されます。
他の名前を使用することも可能ですが、実行時にファイルを指定する必要があります。

1. プロジェクト(Project)

project要素は、1ビルドファイルに1つと決まっています。
ビルドファイル内に記載される全ての要素はこの要素内に定義する必要があります。
project要素には、以下の3つの属性が設定できます。

name:プロジェクト名
任意のプロジェクト名を設定します。

default:デフォルトターゲット名
ターゲットを指定しない場合に実行されるターゲットを指定します。
Ant1.4以前では必須でしたが、Ant1.5からはdefault属性を省略した場合はmainターゲットが
実行されるように変更されたので省略が可能になりました。

basedir:ベースディレクトリ
ベースディレクトリを指定します。./fooディレクトリをベースディレクトリに指定し、
mkdir要素のdir属性に"sample"と指定すると、./foo/sampleが作成されます。
つまり、ビルド作業を行う際の起点が./fooになるというわけです。

2. ターゲット(Target)

ターゲットとは、目的を達成するための複数のタスクの集まりです。
「EARファイルの作成」を例にとると、目的はEARファイルを作成することであり、
複数のタスクはソースコードのコンパイル、コンパイルしたクラスファイル・リソースの配置
etc...といった、EARファイルの作成に必要な一連の処理です。
target要素は複数定義可能で、以下の属性が設定できます。

name:ターゲット名
target要素の中で、唯一必須の属性です。antコマンドで指定するターゲット名を定義します。

depends:依存関係
このターゲットを実行する前に実行を完了させるターゲットを指定します。
カンマ区切りで複数指定が可能です。

if:必須プロパティ
プロパティ名を指定することができ、実行時に
指定したプロパティが設定されていない場合、このタスクの実行をスキップします。

unless:不要プロパティ
ifとは反対の設定を行う。プロパティ名を指定することができ、実行時に
指定したプロパティが設定されている場合、このタスクの実行をスキップします。

description:処理概要
projecthelpオプションをつけてAntを実行した時に表示される、
ターゲットの処理概要を設定します。

3. タスク(Task)

ターゲットの節でも説明した通り、タスクとは目的(ターゲット)を達成するための処理で、
1つのターゲットは複数のタスクを組み合わせることで達成されます。
1タスクはコンパイル、ファイルのコピーといった個別の処理を1つだけ担当します。

組み込みタスク
Antには、事前に定義されている組み込みタスクというものが用意されています。
組み込みタスクは大まかに、コアタスクオプショナルタスクに分類されます。
コアタスクはコンパイル、タブからスペースへの変換など、ビルドにおいて頻繁に行われる作業
を定義したタスクで、Antさえインストールしていればすぐに利用できるタスクです。
オプショナルタスクは、あまり汎用的ではないタスクです。jarファイルの追加など、
そのタスク用のモジュールをAntに追加しないと利用できない場合もあります。

組み込みタスクにはPropertyタスクやMkdirタスクなどがあり、
それぞれ<property ~ ><mkdir ~ >といった要素を記載して利用します。
他にどんなタスクがあるのかを知りたい場合は、
Antの公式ドキュメント、使用頻度の高いタスクをまとめた記事などを調べてみてください。

独自タスク
Antでは、ユーザが独自タスクを作成することができます。
作成方法は少し煩雑であり、大体のビルド作業は組み込みタスクで対応可能なため、
Antの学習を掘り下げたい場合に調べるくらいでいいと思います。

データ構造

ビルド作業では、リソースの配置、コンパイル対象の指定など、
複数のファイル(集合)に対して処理を行うことがよくあります。
Antでは、これら複数のファイル等の集合をデータ構造として表すことで、
集合に対しての処理を手軽にします。

データ構造はプロジェクト、ターゲット、タスクの子要素として定義できます。
定義する場所によってスコープがあるので、
複数のターゲット、タスクで使用したい、1つのタスク内でしか使用しないなど、
状況に合わせて定義する場所を選びます。

1. パターン

パターンは、Antにおいてフォルダ、ファイル名などを指定する際のワイルドカードです。
パターンでは以下の3種類のワイルドカードが利用できます。

ワイルドカード 説明
? 任意の1文字にマッチします。
* 0文字以上の任意の文字列にマッチします。
** 任意の深さ、ディレクトリ、ファイル名にマッチします。

2. パターンセット

パターンセットは、複数のパターンを組み合わせてより複雑なパターンの指定を可能にします。
指定は、xxxを含む(include)とxxxを除く(exclude)を組み合わせて表現します。

パターンセットは<patternset ~ >要素で定義します。
パターンの指定には、以下の属性が利用できます。

属性 説明
includes 集合に含めたいパターン。コンマ・スペース区切りで複数のパターンを記述できます。
includesfile 集合に含めたいパターンを記述したファイルを指定できます。
excludes 集合から除外したいパターン。コンマ・スペース区切りで複数のパターンを記述できます。
excludesfile 集合から除外したいパターンを記述したファイルを指定できます。
refid 別のパターンセットのid属性に定義された値を指定し、利用できます。

パターンセットの定義には、
属性を属性値として定義する方法と、要素として定義する方法があります。

<!-- 属性値として定義する方法 -->
<patternset includes="Foo*,Bar*" excludes="*.java,*.class" />

<!-- 要素として定義する方法 -->
<patternset>
  <include name="Foo*,Bar*" />
  <exclude name="*.java,*.class" />
</patternset>

<!-- 別のパターンセットを利用する方法 -->
<patternset refid="common-set">
  <include name="Foo*,Bar*" />
</patternset>
<patternset id="common-set">
  <exclude name="*.java,*.class" />
</patternset>

パターンの要素に使用できる属性
パターンセットに設定する属性を要素として定義する場合、以下の属性が使用可能です。

属性 説明
refid 参照する要素のidを指定します。
if 指定したプロパティに値が設定されている場合のみ、パターンを適用します。
unless 指定したプロパティに値が設定されていない場合のみ、パターンを適用します。

3. ファイルセット

パターンセットにベースディレクトリを設定したデータ構造です。
ベースディレクトリを指定することで、
そこを基点にした相対パスでパターンを指定することが可能になります。
上記の特性上、ベースディレクトリの設定は必須です。

ファイルセットは主に、ファイル群を集合として扱うために使用しますが、
ディレクトリ群を指定するためのディレクトリセット(Dirset)という要素も存在します。
指定できる属性、定義できる要素などはファイルセットと同じです。

デフォルト除外集合
Antでは、デフォルト除外集合というものが設定されており、この集合に定義されているものは
除外パターンの指定などを行わなくても除外されます。
例) **/.svn、**/.git etc...

ファイルセットに使用できる属性

属性名 説明 初期値
dir ベースディレクトリを指定します。指定は必須です。
defaultexcludes デフォルト除外集合をファイル集合から除外するかどうかを指定します。 yes
includes FileSetに含めたいファイルのパターンを指定します。
includesfile FileSetに含めたいファイルのパターンを記述したファイルを指定します。
excludes FileSetから除外したいファイルのパターンを指定します。
excludesfile FileSetから除外したいファイルのパターンを記述したファイルを指定します。
casesensitive 英文字の大文字と小文字を区別するかどうかを指定します。 true
followsymlinks シンボリックリンクをたどるかどうかを指定します。 true

ファイルセット要素には、パターンセットで紹介したinclude要素などの要素以外に、
セレクタ要素を定義することが可能です。
セレクタとは、パス以外の条件で対象を指定できる機能で、詳細は後ほど、説明します。

4. パス類似構造

パス類似構造を定義する要素にはpath要素とclasspath要素があり、
違いとしてはclasspath要素はタスクの子要素として使われるのに対し、
path要素はタスクから独立したところに定義され、refid属性によって複数タスクから
共通して使われます。

以下、指定できる属性や子要素として定義できる属性は
path要素とclasspath要素で共通です。

パス類似構造に使用できる属性

属性 説明
path :(コロン)や;(セミコロン)区切りで複数ファイル・ディレクトリのリストを指定します。
location 単一のファイル・ディレクトリを指定します。
refid 事前に定義したパス類似構造を参照します。

パス類似構造に使用できる要素

  • Filelist
  • Fileset
  • Dirset
  • Pathelement
  • リソースコレクション:Ant1.8以降は使用可能

Pathelement要素
Pathelementはパスを表し、パス類似構造の子要素としてのみ用いられます。
パス類似構造と異なり、子要素をもつことはできません。

属性 説明
path パスのリストを「:」や「;」で区切って記述します。
location 単一のファイルまたはディレクトリを記述します。
refid 事前定義したパス類似構造を参照します

パスの指定にはpath属性とlocation属性が使えますが、
複数パスを指定する場合はpath属性を、
単一のパスを指定する場合はlocation属性を使用します。
location属性を使用し、それぞれのパスを独立させて定義する方が視認性が良くなります。

<!-- path属性で複数パスを一箇所に定義した場合 -->
<classpath path="/usr/local/java/junit-3.7/junit.jar:/usr/local/java/log4j-1.2.4/dist/lib/log4j-1.2.4.jar:/usr/local/tomcat-4.0.4/common/lib/mail.jar:/usr/local/tomcat-4.0.4/common/lib/activation.jar"/>
<!-- location属性でパスを個別に定義した場合 -->
<classpath>
  <pathelement location="/usr/local/java/junit-3.7/jnit.jar" />
  <pathelement location="/usr/local/java/log4j-1.2.4/dist/lib/log4j-1.2.4.jar" />
  <pathelement location="/usr/local/tomcat-4.0.4/common/lib/mail.jar" />
  <pathelement location="/usr/local/tomcat-4.0.4/common/lib/activation.jar" />
</classpath>

5. マッパー

マッパーはファイル名の変換規則を定義します。
Copyタスクを例にとると、以下のような使用方法があります。

バックアップファイルを作るタスク
<!-- Copyタスク:コピー先の定義 -->
<copy todir="/target" includeEmptyDirs="no">
  <!-- コピー元の定義 -->
  <fileset dir="/src" defaultexcludes="no" />
  <!-- コピー元 → コピー先にコピーする際、
       どのようにパス、ファイル名を変換するかを定義 -->
  <mapper type="glob" from="*" to="*.bk" />
</copy>

上記のCopyタスクは、以下を実現します。

/srcディレクトリ配下のファイル全て」(コピー元)を
「全てのファイルの末尾に.bkをつけて」(変換のルール)
/targetディレクトリ配下」(コピー先)に配置する

マッパーは、変換する対象のマッチング方法、マッチングした内容の変換ルール
組み合わせて変換処理を定義しています。
また、マッパーには組み込み(type属性で指定)と、独自定義(classname属性で指定)があります。

マッパーに設定できる属性

属性 説明
type 組込みのマッパーを指定します。
classname 独自定義のマッパー(Javaクラス)を指定します。
classpath classnameで指定したクラスを実行するのに必要なクラスパスを指定します。
classpathref classnameで指定したクラスを実行するのに必要なクラスパスを定義したパス類似構造を指定します。
from 変換前のファイル名を正規表現で指定します。
to 変換後のファイル名を正規表現で指定します。
refid 外部に定義したmapper要素を参照します。

組み込みのマッパー
type属性に指定できる値には以下のものがあります。

【identity】
ファイル名、ディレクトリ構造を変換しません。from属性とto属性は設定しても無視されます。

<!-- 例1 -->
<copy todir="/target" includeEmptyDirs="no">
  <fileset dir="/src" defaultexcludes="no" />
  <!-- from、toの設定が不要 -->
  <mapper type="identity" />
</copy>
<!-- 例2 -->
<copy todir="/target" includeEmptyDirs="no">
  <fileset dir="/src" defaultexcludes="no" />
  <!-- from、toを指定しても全てのファイルが対象となり、.bkも付与されない -->
  <mapper type="identity" from="*.java" to="*.bk" />
</copy>

【flatten】
ファイル名は変わらず、ディレクトリ構造が除外されます。from属性とto属性は無視されます。

<copy todir="/root/copy" includeEmptyDirs="no">
  <fileset dir="/root/original" defaultexcludes="no" />
  <mapper type="flatten" />
</copy>

上記の通りマッパーを定義すると、originalディレクトリ配下の全てのファイル(コピー元)が
copyディレクトリ直下の同じ階層(コピー先)に配置されます。
無題の図形描画.png

【merge】
from属性は無視され、ディレクトリ構成、ファイル名に関係なく
全てのファイルをto属性で指定した固定のファイル名に変換します。

file1.txt → convert.txt
/foo/bar/file2.txt → convert.txt

【glob】
ワイルドカード「*」を一つ用いることができます。
from属性に記述した「*」にマッチした文字列は、to属性で「*」を使い参照できます。

<!-- /src/Sample.java があった場合 -->
<copy todir="/target" includeEmptyDirs="no">
  <fileset dir="/src" defaultexcludes="no" />
  <mapper type="glob" from="*.java" to="*.class" />
</copy>
<!-- /target/Sample.class がコピーされる -->

【package】
Globと同じようにワイルドカード「」を一つ用いることができます。Globとの違いは、「」にマッチした文字列内にディレクトリ区切り文字(Unixなら「/」、Windowsなら「\」)があったとき、そのディレクトリ区切り文字が「.」に置換されます。例えば、from=".java" to=""としたとき、ソースファイル「a/b/c/d.java」に対するターゲットファイルは「a.b.c.d」となります。

【regexp】
from属性で正規表現が使え、( )で囲まれた部分が1つの正規表現となって9個指定できます。
to属性ではfrom属性でマッチした文字列を「\1」〜「\9」という表記で参照できます。

from="(.*)/(.*).java"
to="\1\2.java"
と定義すると、
One/Test.java → OneTest.java
に変換される。

6. セレクタ

データ構造は基本、ファイル名を基準にファイルの集合を指定しますが、
セレクタはファイルの更新日時、サイズ、指定ディレクトリからの深さなど様々な要素から
ファイルの集合を指定することが可能です。

セレクタには、以下の種類があります。

  • コアセレクタ
    Antにあらかじめ組み込まれているセレクタで、単体として機能します。
  • セレクタコンテナ
    コアセレクタのように、単体で機能するセレクタを複数内包するコンテナです。
  • カスタムセレクタ
    ユーザが独自に定義するセレクタです。

コアセレクタ

名称 条件の指定に使用する要素
filename ファイル名
size ファイルのサイズ
date ファイルの更新時間
contains ファイル内に含まれている文字列
depth ベースディレクトリからの階層の深さ
depend 比較対象より更新時間が新しいこと
present 別の場所に同名のファイルが存在すること

● Filename

属性 設定内容 初期値 必須
name 選択するファイル名のパターン
casesensitive 大文字小文字を区別するか true
negate パターンにマッチしないファイルを選択するか false
refid 事前定義したFilenameセレクタのID

● size

属性 設定内容 初期値 必須
value 比較基準となるサイズ(unitsを設定しない場合はbyte単位)
units value属性に記したファイルサイズの単位を指定します。
when 比較の方法(less, more, equal) equal
refid 事前定義したSizeセレクタのID

〜unitsに設定できる値〜

単位 説明
K, k, kilo, KILO 1,000 ( = 10の3乗) バイト
Ki, KI, ki, kibi, KIBI 1,024 ( = 2の10乗) バイト
M, m mega MEGA 1,000,000 ( = 10の6乗) バイト
Mi, MI, mi, mebi, MEBI 1,048,576 ( = 2の20乗) バイト
G, g, giga, GIGA 1,000,000,000 ( = 10の9乗) バイト
Gi, GI, gi, gibi, gibi 1,073,741,824 ( = 2の30乗) バイト
T, t,tera, TERA 1,000,000,000,000 ( = 10の12乗) バイト
Ti, TI, ti, tebi, TEBI 1,099,511,627,776 ( = 2の40乗) バイト

● date
日時の指定は必須で、「MM/DD/YYYY HH:MM AM[or PM]」というフォーマットか
1970年1月1日からのミリ秒で指定できる。

属性 設定内容 初期値
datetime 比較基準となる日時
millis 比較基準となる時間(1970年からのミリ秒)
guranularity 許容する誤差(単位:ミリ秒) 0
when 比較の方法(before, after, equal) equal
refid 事前定義したDateセレクタのID

● contains

属性 設定内容 初期値 必須
text ファイルの内容に含まれる文字列
casesensitive 大文字小文字を区別するか true
refid 事前定義したContainsセレクタのID

● depth
ベースディレクトリの深さを0として、検索対象をファイルの深さで指定する。

属性 設定内容
min ファイルの最小の深さ
max ファイルの最大の深さ
refid 事前定義したDepthセレクタのID

以下の例では、{$src}/a/b/c/d/eというフォルダ構成があった場合、
b、c、dディレクトリにあるファイルは対象になりますが、a、eディレクトリにあるファイルは
対象外となります。

<fileset dir="{$src}">
  <depth min="2" />
  <depth max="4" />
</fileset>

● depend
比較対象ディレクトリ(targetdir)を検証し、
比較対象より更新時間が新しい、比較対象にファイルが存在しないのいずれかに該当する
ファイルが処理対象として指定される。
デフォルトでは比較を同名のファイルで行うが、独自の比較パターンを使用したい場合は
mapper子要素を定義します。(Foo.javaとFooDevelop.javaを比較したいなど)

属性 設定内容 初期値 必須
targetdir 比較対象のベースディレクトリ
guranularity 更新時間の粒度※ 0(Windows:2000)
refid 事前定義したDependセレクタのID

※全てのファイルシステムが更新日時をミリ秒で管理しているわけではないため

● present
更新日時の比較は行わず、ファイルの存在チェックのみ行うDependセレクタと言えます。
デフォルトでは比較を同名のファイルで行うが、独自の比較パターンを使用したい場合は
mapper子要素を定義します。(Foo.javaとFooDevelop.javaを比較したいなど)

属性 設定内容 初期値 必須
targetdir 比較対象のベースディレクトリ
refid 事前定義したPresentセレクタのID

セレクタコンテナ
セレクタコンテナは、複数のセレクタを組み合わせ、複雑な条件指定を可能にします。
使用例は以下のようになり、以下のソースコードでは
「更新日時が2002年8月20日午前6時より後」もしくは「ファイルサイズが100KB以上」の
ファイルが選択されます。

<fileset dir="{$log}" includes="**/*.log">
  <or>
    <date datetime="08/20/2002 6:00 AM" when="after" />
    <size value="100" units="Ki" when="more" />
  </or>
</fileset>

上記の例では<or>がセレクタコンテナにあたり、
セレクタコンテナに設定できる共通の属性には以下のものがあります。

属性 説明
id refidで指定するID
refid 事前定義した同種のセレクタコンテナのID
description このセレクタに関する説明

セレクタコンテナには以下のものがあります。

セレクタ 説明
And 複数セレクタを内包。すべてのセレクタに当てはまるファイルを選択する。
Or 複数セレクタを内包。少なくとも一つのセレクタに当てはまるファイルを選択する。
None 複数セレクタを内包。全てのセレクタに当てはまらないファイルを選択する。
Not 一つだけセレクタを内包。そのセレクタに当てはまらないファイルを選択する。
Majority 複数セレクタを内包。過半数のセレクタに当てはまるファイルを選択する。
Selector 事前定義した他のセレクタを再利用する場合に用います。

● Selector
Selectorはセレクターを内包する箱(他のSelectorからrefidで参照するセレクタを保持する箱)、
もしくは、事前適宜されたSelectorを参照するためのタグとして使用できます。

<project default="all" basedir="./root">
    <!-- セレクタを保持する箱 -->
    <selector id="completed">
        <none>
            <depend targetdir="build/classes">
                <mapper type="glob" from="*.java" to="*.class"/>
            </depend>
            <depend targetdir="docs/manual/api">
                <mapper type="glob" from="*.java" to="*.html"/>
            </depend>
        </none>
    </selector>

    <target>
        <zip>
            <fileset dir="src/main" includes="**/*.java">
                <!-- 上記で作成したSelectorを参照するタグ -->
                <selector refid="completed"/>
            </fileset>
        </zip>
    </target>
</project>

Selectorにはif属性とunless属性を設定することができ、if="プロパティ値"の形で使用する。
ifで指定したプロパティが設定されている場合は有効に、
unlessで指定したプロパティが設定されていない場合はそのSelectorが有効になります。

<fileset dir="${working.copy}">
    <or>
        <selector if="include.tests">
            <filename name="**/*Test.class">
        </selector>
        <selector if="include.source">
            <and>
                <filename name="**/*.java">
                <not>
                    <selector unless="include.tests">
                        <filename name="**/*Test.java">
                    </selector>
                </not>
            </and>
        </selector>
    </or>
</fileset>

7. フィルター

フィルターはcopyやmoveタスクを実行するときにファイルの内容を置換するための機能です。
Antではデフォルトの場合、@で囲まれた文字列をトークンとして認識し、置換対象とします。

フィルター
タグは以下の属性を設定可能です。

属性 説明 必須
token 置換の対象となるトークン
value 置換後の文字列

以下の例では、テキストファイル中の@srcFolder@という文字列を
/project/main/srcに変換します。

<filter token="srcFolder" value="/project/main/src" />

フィルタセット
通常、フィルタは単体ではなく、複数のフィルタをフィルタセットにまとめて使用します。
フィルタセットはフィルタとフィルタセットを子要素として持つことができ、
以下の属性を設定することができます。

属性 説明 初期値
begintoken トークンの開始区切り文字 @
endtoken トークンの終了区切り文字 @
refid 事前定義されたフィルタセットのID

フィルタチェーンとフィルタリーダー
フィルタリーダはフィルタよりも高度な置換を行う機能で、
Javaクラスにより定義し、クラスを指定するととで処理を呼び出します。
フィルタチェーンは複数のフィルタリーダを子要素に持ち、その実行順序を制御します。

フィルタチェーンは以下の形で利用します。フィルタリーダーは上から順に実行されます。

<filterchain>
  <filterreader classname="org.apache.tools.ant.filters.HeadFilter">
    <param name="lines" value="30"/>
  </filterreader>
  <filterreader>
    ...
  </filterreader>
</filterchain>

フィルタリーダーには以下の属性を使用することができます。

属性値 説明 必須
classname フィルタリーダーの実装クラス
classpath 実装クラスの実行に必要なクラスパス
classpathref classpathの値を参照で指定する  

フィルタリーダーには<param>要素を子要素として定義することで実行クラスに
パラメータを渡すことが可能で、以下の属性が指定できる。

説明 初期値
name パラメータの名前
type パラメータのタイプ
value パラメータの値

● 事前定義されたフィルタリーダー

Antには事前定義されたフィルタリーダーが存在し、
事前定義されたフィルタリーダーは略記することができる。

<filterreader classname="org.apache.tools.ant.filters.HeadFilter">
  <param name="lines" value="30"/>
</filterreader>
<!-- 略記の場合 -->
<headfilter lines="30" />

使用頻度の高いフィルタリーダーについては、別途記事を作成していますので、
Antの代表的なフィルタリーダー」を参照してください。

以下、各種のデータ構造について再度まとめます。

データ構造 説明
Filelist ファイル名を列挙してファイルの集合を表します。
Fileset パターンやセレクタ等でファイルの集合を表します。
Patternset パターンの集合を表します。
パス類似構造 PATHやCLASSPATHを表します。
リソース ファイルまたはファイルに似たものを抽象化します。
リソースコレクション リソースの集合です。Ant1.8以降、FileListなど従来のデータ構造はリソースコレクションの一種という扱いになりました
セレクタ Filesetにおいて、ファイル名以外の基準でファイルの集合を表します。

メインページへ戻る

8
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
5