こちらは「makeの応用(Java)」の続きです。
目次記事はこちらです。
Ant とは
Ant は Java の自動ビルドツールの一つです。正式名称はApache Antですが、まぁ Ant で伝わります。Apache Tomcat をビルドするための便利ツールとして開発されました。
すでに make を知っている人は、Ant = make の Java 版 といえばわかりやすいかもしれないですね。make はシェルスクリプトを使ってタスクを構築していたので非常に柔軟なタスクを記述することができました。しかしそれゆえ、Makefile の内容はガッツリ OS に依存していました。
Ant ではタスクを XML で記述します。Antタスクと呼ばれる特殊なXMLタグ(空要素タグも含む)を使用してタスクを記述していきます。Ant タスクを記述した XML ファイルは build.xml というファイル名で作成する必要があります。
Ant の誕生は2000年7月で、2004年に Maven、2008年に Gradle が誕生しました。Java の自動ビルドツールの長男みたいなもんですね。現在も現場によっては Ant が使われていたりします。新規のプロジェクトで自動ビルドツールに Ant を採用することはないでしょうが、知っておいて損はありません。
環境構築
下記のサイトにアクセスします。
少しスクロールして、apache-ant-1.10.15-bin.zipをクリックしてダウンロードします。
ダウンロードした zip ファイルを任意の場所に展開してPathを通します。
make の記事から読み進めている人はCドライブの下の tools フォルダにzipファイルを展開して、環境変数の Path に C:\tools\apache-ant-1.10.15\bin
を追加してください。
Pathを通したらコマンドプロンプトを起動して下記のコマンドを入力します。
ant -version
Apache Ant(TM) version 1.10.15 compiled on August 25 2024
正しくバージョンが表示されない場合、環境変数の設定を見直してください。
Ant プロジェクトの作成
任意の場所に「AntTestProject」というフォルダを作成します。本記事ではデスクトップに作成します。Ant プロジェクトでは Java のソースファイルを置く場所を src という名前にするのが一般的です。src フォルダを AntTestProject フォルダの下に新規作成します。
src フォルダの下に make の記事で作成した Human.java と HumanTester.java をコピーします。参考までに下にソースコードを折りたたんでいます。(実際、どんな Java ファイルでも問題ありません。自分で過去に作った Java ファイルとかあればそれを使ってください。)
Humanクラス、HumanTesterクラス
public class Human{
private String name;
private int age;
public Human(String name, int age){
this.name = name;
this.age = age;
}
public String getName(){
return this.name;
}
public int getAge(){
return this.age;
}
public void grow(){
this.age++;
}
}
public class HumanTester{
public static void main(String[] args){
// インスタンス化テスト
instantiateHuman();
// growメソッドのテスト
testGrowMethod();
}
// インスタンス化テスト
public static void instantiateHuman(){
Human h = new Human("山田太郎", 20);
boolean isEqualName = (h.getName().equals("山田太郎"));
boolean isSameAge = (h.getAge() == 20);
if(isEqualName && isSameAge){
System.out.println("インスタンス化テスト成功!");
}else{
System.out.println("インスタンス化テスト失敗!");
}
}
// growメソッドのテスト
public static void testGrowMethod(){
Human h = new Human("大海めぐみ", 22);
h.grow();
boolean isGrewAge = (h.getAge() == 23);
if(isGrewAge){
System.out.println("growメソッドのテスト成功!");
}else{
System.out.println("growメソッドのテスト失敗!");
}
}
}
次に AntTestProject の直下に build.xml を新規作成します。build.xml の中身を下記のように編集してください。
<project name="AntTestProject" default="compile" basedir=".">
<!-- プロパティの設定 -->
<property name="src.dir" value="src"/>
<property name="target.dir" value="target"/>
<!-- ディレクトリの初期化 -->
<target name="init">
<mkdir dir="${target.dir}"/>
</target>
<!-- コンパイルタスク -->
<target name="compile" depends="init">
<javac srcdir="${src.dir}" destdir="${target.dir}" encoding="utf-8"/>
</target>
<!-- クリーンアップタスク -->
<target name="clean">
<delete dir="${target.dir}"/>
</target>
</project>
build.xml の詳細は次の節で見ていきます。現状のフォルダのツリーは次のようになっています。
AntTestProject
├── src
│ ├── Human.java
│ └── HumanTester.java
└── build.xml
build.xml を作成したらコマンドプロンプトを立ち上げ、cd
コマンドでカレントディレクトリを AntTestProject に変更します。変更したら ant
コマンドを入力して実行結果を確認します。
Buildfile: C:\Users\oka\Desktop\AntTestProject\build.xml
init:
[mkdir] Created dir: C:\Users\oka\Desktop\AntTestProject\target
compile:
[javac] C:\Users\oka\Desktop\AntTestProject\build.xml:13: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
[javac] Compiling 2 source files to C:\Users\oka\Desktop\AntTestProject\target
BUILD SUCCESSFUL
Total time: 1 second
ant
コマンドによって新しく target ディレクトリが作成され、その中に javac
コマンドによって生成された .class ファイルが保存されます。
build.xml の中身の説明
build.xml の各タグについて
<project name="AntTestProject" default="compile" basedir=".">
<!-- ~~~ propertyタグやtargetタグ ~~~ -->
</project>
project タグは build.xml 全体の設定をするタグになります。省略は不可です。
-
name 属性
name 属性はプロジェクトの名前を表します。たいていは今回のようにプロジェクトを保存しているフォルダと同じ名前になります。 -
default 属性
default 属性は ターゲットを指定しないで実行 (=引数なしでant
コマンドを実行)したときに実行されるデフォルトのターゲットを決める部分です。
今回はdefault="compile"
としているので、引数なしでant
コマンドをたたくと 「name 属性が”compile”
の target タグ(target タグについては後述)」を実行することになります。 -
basedir 属性
basedir 属性はビルド作業を行う起点となるディレクトリを指定する属性です。今回はbasedir="."
としているので、今後 target によって作成されるファイルやディレクトリは、 build.xml があるフォルダを起点とすることになります。
例えばあるターゲットで「XXXというファイルを作成する」という操作がある場合、build.xml と同じ階層にXXXというファイルが作成されます。
<property name="xxx" value="yyy" />
property タグは build.xml 内で使用できる変数のようなものを宣言する要素です。name 属性が build.xml 内で使える変数名、value 属性が変数の内容になります。変数の内容にアクセスするには ${xxx}
のように書きます。
例えば、<property name="src.dir" value="src"/>
という宣言では ${src.dir}
で、src
という値が使用できるという意味になります。
<target name="ppp" depends="qqq">
<!-- Antタスクのタグが並ぶ -->
</target>
target タグは目的達成のために必要となるタスクを書いていくタグです。makeにおけるタスクと同じものと考えて問題ありません。
-
name 属性
target タグの属性には name 属性が必須です。name 属性に指定した名前を使ってタスクを呼び出します。例えば、<target name="init">
と書かれた target の場合、ant init
でそのタスクを実行することができます。
ant
コマンドの引数には target タグの name 属性を指定しますが、これを省略した場合には project タグの default 属性で指定したタスクが呼び出されます。 -
depends 属性
今回は name 属性が"compile"
となっているタスクに depends 属性というものが入っています。(<target name="compile" depends="init">
)
depends 属性は「このタスクの実行は depends 属性で指定したタスクに依存しているので、先にそちらを実行してください」という意味で使う属性になります。複数のタスクに依存している場合、カンマ区切りでタスクを列挙します。(e.g.depends="foo, bar, baz"
)
今回の<target name="compile" depends="init">
という target タグの場合、ant compile
と実行すると先に init タスクが実行されてから compile タスクが実行されます。これはコマンドプロンプトの実行結果から読み取ることができます。
ant compile
Buildfile: C:\Users\oka\Desktop\AntTestProject\build.xml
init: <- 先に init タスクが動いている!
compile:
[javac] C:\Users\oka\Desktop\AntTestProject\build.xml:13: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
BUILD SUCCESSFUL
Total time: 0 seconds
(上の実行結果はすでに target ディレクトリがある場合の表示です。target ディレクトリがない場合には init タスクで target ディレクトリを作成するコマンドが実行されます。)
< Antタスク名 タスクに準ずる属性="VVV" >
target タグの中には Ant タスクを書きます。複数書くことも可能です。標準で使える Ant タスクのうち、比較的よく使うものを下の表にまとめます。
- ファイル・ディレクトリ操作系
Antタスク名 | 役割 |
---|---|
move | ファイルの移動、ファイルの名前変更 |
copy | ファイルのコピー |
mkdir | ディレクトリ作成 |
delete | ディレクトリ削除 |
- java 関連
Antタスク名 | 役割 |
---|---|
javac | Java ファイルをコンパイルする |
java | java を実行する |
jar | jar ファイルを作成する |
javadoc | javadoc を生成する |
- その他
Antタスク名 | 役割 |
---|---|
echo | (基本的には)標準出力にメッセージを表示する |
ant | 別の build.xml のターゲットを呼び出す |
では今回の build.xml で使用したAntタスクを見ていきます(上の表で太字にしてます)。
<mkdir dir="作成したいディレクトリの名前"/>
mkdir
はディレクトリを新規作成するタスクです。指定する属性は dir 属性のみで、dir 属性に指定した名前のディレクトリを作成します。
今回は init タスクの中で <mkdir dir="${target.dir}"/>
と書いているので target という名前のディレクトリを、このファイル(build.xml)があるのと同じ階層に作成する という意味になります。
(project タグの basedir="."
と、property タグの <property name="target.dir" value="target"/>
も併せてみておきましょう)
<delete dir="削除したいディレクトリの名前"/>
delete
はファイルやディレクトリを削除するタスクです。ファイルを削除したい場合は file 属性で、ディレクトリを削除したい場合は dir 属性で名前を指定します。
今回は clean タスクの中で <delete dir="${target.dir}"/>
と書いているので build.xml と同じ階層にある target という名前のディレクトリを削除する という意味になります。
file 属性で指定する名前に *
(ワイルドカード) は使えません。ワイルドカードを使用する場合は fileset タグ(タスクじゃないです)を使用して次のように書きます。
<delete>
<fileset dir="${target.dir}" includes="*.class"/>
</delete>
これで target ディレクトリの中の拡張子が .class のファイルを殲滅できます
<javac> ~各種設定項目~ </javac> (今回は <javac /> で空要素)
javac
は Java ファイルのコンパイルを行うタスクです。これに関しては属性を一つずつ説明するよりも javac
コマンドとの対応を見た方が早い気がします。
javac タスクの属性 |
javac コマンドのオプション |
---|---|
destdir="XXX" | -d XXX |
encoding="utf-8" | -encoding UTF-8 |
srcdir="YYY" | オプションではないですがYYY下の Java ファイルを見るって意味 |
javac
コマンドはタグのボディ部で各種の設定をすることが可能です。
よく使うものとして、<classpath refid="CLASSPATH">
があります。クラスパスの指定です。詳しくはこの先の未来で。
今回は <javac srcdir="${src.dir}" destdir="${target.dir}" encoding="utf-8"/>
とあるので、src ディレクトリの下の Java ファイルを UTF-8 の文字コードでコンパイルして、できた .class ファイルを target ディレクトリに入れる という意味になります。
java タスクの実装
作成した AntTestProject に今度は実行タスクを追加してみます。build.xml に下記を追記してください。
<!-- 実行タスク -->
<target name="run" depends="compile">
<java classname="HumanTester" classpath="${target.dir}"/>
</target>
Java タグは Java ファイルの実行を行うタスクです。たくさんの属性がありますが、(自分的に)よく使うものだけ以下に列挙します。
- classname 属性
実行したいクラス名を指定します。java
コマンドの主引数に当たります。なのでパッケージ構成をとっている場合は完全限定名(FQCN)で記述します。 - jar 属性
java
コマンドの-jar
オプションに相当します。次の記事で利用します。 - classpath 属性
java
コマンドの-classpath
オプションに相当します。実行したいクラスの .class ファイルがある場所を指定します。今回は target ディレクトリにコンパイル済みの .class ファイルが転がってるのでそこを指定しています。 - output 属性
出力先をリダイレクトする属性です。標準出力に出てくる文字をログに残したい場合などにoutput="log.txt"
みたいな指定をします。
ほかにも多様な属性があるのですが、出てきたらその都度紹介する感じにします。
Java ファイルの実行にはコマンドライン引数を与えたい場合があります。その場合、以下のように java タグにボディ部を持たせて arg タグを使用します。
<java classname="HumanTester">
<arg value="与えたい引数" />
<!-- ちなクラスパスもボディ部に持たせられる -->
<classpath refid="${target.dir}" />
</java>
build.xmlに実行タスクを追記したら、コマンドプロンプトで ant run
を入力してみましょう。
Buildfile: C:\Users\oka\Desktop\AntTestProject\build.xml
init:
compile:
[javac] C:\Users\oka\Desktop\AntTestProject\build.xml:13: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
run:
WARNING: A terminally deprecated method in java.lang.System has been called
WARNING: System::setSecurityManager has been called by org.apache.tools.ant.types.Permissions (file:/C:/tools_oka/apache-ant-1.10.15/lib/ant.jar)
WARNING: Please consider reporting this to the maintainers of org.apache.tools.ant.types.Permissions
WARNING: System::setSecurityManager will be removed in a future release
[java] 名前:名無しの権兵衛
[java] 年齢:20
[java] -----歳をとりました-----
[java] 1年後...
[java] 名前:名無しの権兵衛
[java] 年齢:21
BUILD SUCCESSFUL
Total time: 0 seconds
確かに実行されることが確認できます。ついでに Human.java を編集して再度 ant run
してみてください。まるで IDE(統合開発環境) の実行ボタンみたいに動いてくれますね。
次の記事