こちらは「Ant と Maven ① Apache Ivy の導入」の続きです。
目次記事はこちらです。
build.xml を読み解く
前の記事で Ivy のインストールと動作まで確認しました。次に Ivy の中身を深堀していきます。
Ivy の jar ファイルを導入した ant では、必要なライブラリをインターネット上にある Maven リポジトリからインストールしてきます。ant コマンドを実行したらこんなことになったので、とりあえず build.xml を確認します。
<!--
ここにライセンスのコメントがありますが HelloConsole.java の冒頭と同じです。
-->
<project name="hello-ivy" default="run" xmlns:ivy="antlib:org.apache.ivy.ant">
<!-- some variables used -->
<property name="lib.dir" value="lib"/>
<property name="build.dir" value="build"/>
<property name="src.dir" value="src"/>
<!-- paths used for compilation and run -->
<path id="lib.path.id">
<fileset dir="${lib.dir}"/>
</path>
<path id="run.path.id">
<path refid="lib.path.id"/>
<path location="${build.dir}"/>
</path>
<!-- =================================
target: resolve
================================= -->
<target name="resolve" description="--> retreive dependencies with ivy">
<ivy:retrieve/>
</target>
<!-- =================================
target: report
================================= -->
<target name="report" depends="resolve" description="--> generates a report of dependencies">
<ivy:report todir="${build.dir}"/>
</target>
<!-- =================================
target: run
================================= -->
<target name="run" depends="resolve" description="--> compile and run the project">
<mkdir dir="${build.dir}"/>
<javac srcdir="${src.dir}" destdir="${build.dir}" classpathref="lib.path.id" includeAntRuntime="false"/>
<property name="msg" value="hello ivy !"/>
<java classpathref="run.path.id" classname="example.HelloConsole">
<arg value="-message"/>
<arg value="${msg}"/>
</java>
</target>
<!-- =================================
target: clean
================================= -->
<target name="clean" description="--> clean the project">
<delete includeemptydirs="true">
<fileset dir="${basedir}">
<exclude name="src/**"/>
<exclude name="build.xml"/>
<exclude name="ivy.xml"/>
</fileset>
</delete>
</target>
<!-- =================================
target: clean-cache
================================= -->
<target name="clean-cache" description="--> clean the ivy cache">
<ivy:cleancache/>
</target>
</project>
外側のブロック(<project> タグ)から順に読み解いていきます。
<project name="hello-ivy" default="run" xmlns:ivy="antlib:org.apache.ivy.ant">
<!-- ~~~ propertyタグやtargetタグ ~~~ -->
</project>
project タグは build.xml 全体の設定をするタグになります。省略は不可です。
-
name 属性
name 属性はプロジェクトの名前を表します。たいていは今回のようにプロジェクトを保存しているフォルダと同じ名前になります。今回は「hello-ivy」となっています。
-
default 属性
default 属性は ターゲットを指定しないで実行 (=引数なしでantコマンドを実行)したときに実行されるデフォルトのターゲットを決める部分です。
今回はdefault="run"となっているので、引数なしでantコマンドをたたくと 「name 属性が”run”の target タグ(target タグについては後述)」を実行することになります。
-
XML名前空間(XML Name Space)属性
当該 xml ファイル内での名前空間の定義を行うのが xmlns 属性です。今回はxmlns:ivy="antlib:org.apache.ivy.ant"とあるので、「<ivy:XXX>のように ivy という名前空間を指定したタグは"antlib:org.apache.ivy.ant"を見に行くぞ」って意味になります。
ややこしければ、Ivy を使うためのお約束だと思ってください。さらに詳しく知りたい人は下記の折り畳みを参照。
もうちょい詳しく xmlns:ivy を知りたい人!
Ant では XML 形式でビルドファイルを記述します。XML という言語は、「任意のコンテンツをタグでマークアップする」言語です。<タグ> コンテンツ </タグ> みたいな感じ。
そのタグにどんな意味があるのか?は、その XML ファイルを扱うプログラムが決めます。今回使用している Ant では、タグの意味を決めるのに java のクラスを使用します。(Ant の独自タスクでは新しいタグを自分で定義しましたが、組み込みの Ant タスクも同じように作られています。)
実は Ivy と Ant が連携できている理由は、「Ivy が Ant 用の独自タグを作っている」からです。Ivy が作った独自タスクを Ant の build.xml で使用することで連携してるんですね。
ここで重要なのが、「今使っているタグ <XXX> って Ant のタスク? Ivy の独自タスク?」という問題が起きるってことですね。タスク名が被る可能性は十分にあり得ます。
この問題の解決のために XML では名前空間属性(xmlns属性)を使って、そのタグがどの名前空間に属するのかを決めることができます。
今回の xmlns:ivy="antlib:org.apache.ivy.ant" は、「<ivy:XXX> ってタグがでてきたら、"antlib:org.apache.ivy.ant" って名前空間の <XXX> だよ」という意味になります。
この時、xmlns: の後の ivy をプレフィックスといいます。値はURIを指定するのが一般的です。xmlns は名前空間の定義でしかないので、その URI 自体には意味がないことが多いです(ただ一意に識別できればいい)。
ただ、Ivy では名前空間の値に意味を持たせています。
"antlib:org.apache.ivy.ant" は、「PCにインストールされた Ant がある場所のライブラリフォルダ(lib)にある、org.apache.ivy.ant で Ivy 独自タスクを定義してるよ」って意味です。
ついでなので確認しておきます。Ant の下の lib の中にある ivy-2.5.3.jar を右クリックして展開すると、圧縮された jar ファイルの中身が見れます。
展開して現れた ivy-2.5.3 フォルダの中を見に行くと、Ivy の独自タスクが定義されたフォルダ(ant)があることを確認できます。
Ivy の独自タスクのコードを見たい場合は、この記事の序盤にあるダウンロードページでsourceをクリックします。
ダウンロードしたzipファイルを展開するとソースコードが見れます。例えば、org.apache.ivy.ant の中にある IvyTask.java を少しだけ見ると、
//~~~略
import org.apache.tools.ant.Task;
//~~~略
public abstract class IvyTask extends Task {
//~~~略
となっており、確かに独自タスクが作られていることが確認できます。
<!-- some variables used -->
<property name="lib.dir" value="lib"/>
<property name="build.dir" value="build"/>
<property name="src.dir" value="src"/>
property タグは build.xml 内で使用できる変数のようなものを宣言する要素です。name 属性が build.xml 内で使える変数名、value 属性が変数の内容になります。変数の内容にアクセスするには ${xxx} のように書きます。
property が増えたら外部の properties ファイルを参照するのが普通です。
<!-- paths used for compilation and run -->
<path id="lib.path.id">
<fileset dir="${lib.dir}"/>
</path>
<path id="run.path.id">
<path refid="lib.path.id"/>
<path location="${build.dir}"/>
</path>
path タグはクラスパスやリソースのパスを指定するときに使用するタグです。使用するには id 属性の値を使います。
<!-- =================================
target: resolve
================================= -->
<target name="resolve" description="--> retreive dependencies with ivy">
<ivy:retrieve/>
</target>
Ant のタスクは target タグで定義します。target タグの name 属性でタスク名を指定します。コマンドでタスクを呼び出すには ant [タスク名] と書きます。今回は name="resolve" とあるので、このタスクを呼び出すには ant resolde とコマンドをたたきます。
target タスクの中にある <ivy:retrieve/> が resolve タスクを実行したときの動作です。これは Ivy の独自タスクで、依存関係を解決するタグです。
オプションも豊富に用意されています。よく使うものだけ下記の表にまとめました。
| 属性 | 概要 | 指定しない場合のデフォルト値 |
|---|---|---|
pattern |
プロジェクト内の lib フォルダに保存するときの形式 | "lib/[artifact]-[revision].[ext]" |
sync |
もう依存してない古いライブラリを削除するか。"true" にすると不要なライブラリは消える |
"false" |
overwriteMode |
既存ファイルを上書きするかどうか | "newer" |
log |
出力するログのレベル | "default" |
ほかにもありますが詳しくは公式のドキュメントまで!
各属性の詳細!
各属性についてもうちょい掘り下げます。
-
pattern 属性
ローカルのシステムに保存するときの保存形式の指定です。指定には決まったトークンを使用する必要があり、ちょいクセがあります。まずはトークンを一覧で見てみます。
| トークン | 概要 |
|---|---|
[organisation] |
組織名。org.apache とか org.postgresql とか |
[module] |
モジュール名。commons-lang3 とか postgresql とか |
[artifact] |
アーティファクト名。モジュールの中のjarを指す。だいたいは上の [module] と一緒 |
[revision] |
バージョン番号。10.0.1 とか 42.7.7 とか |
[conf] |
Ivy の構成名。 test とか compile とか |
[type] |
アーティファクトの種類。jar とか |
[ext] |
拡張子。jar とか zip とか |
[orgPath] |
組織名をディレクトリ構造に変換したもの。org/apache とか |
例えば次のような保存形式が考えられますな。
・lib の下に組織で振り分けてライブラリバージョン番号なしでを保存
<ivy:retrieve pattern="lib/[organisation]/[artifact].[ext]"/>
・プロジェクトの構成ごとに振り分けてバージョン付きで保存
<ivy:retrieve pattern="lib/[conf]/[artifact]-[revision].[ext]"/>
[conf] の「Ivy の構成名」については後で詳しくやります。
Maven 触れたことある人は下記の対応がわかりやすいかも。
| Ivy のトークン | Maven の <dependency> タグ内の要素 |
|---|---|
[organisation] |
<groupId> |
[module]、[artifact]
|
<artifactId> |
[revision] |
<version> |
[conf] |
<scope> |
sync属性
依存していない古いライブラリを削除するかどうか指定します。synchronize (同期) の略です。古い jar ファイルが原因で不具合が発生するとか防げます。
-
overwriteMode属性
依存ライブラリをコピーしてくるときの上書き保存の動作を決める属性です。4つのモードで動作を決めることができます。
| 指定できるモード名 | 概要 |
|---|---|
newer |
取得元のファイルが保存先より新しい場合のみ上書き(デフォルト) |
different |
タイムスタンプが違うなら上書き |
always |
どんな時も実行の度に上書き |
| 'never' | どんな時も上書きしない |
これらはすでにライブラリがローカルのプロジェクトにあるときの「上書き保存の方法」です。ローカルにないライブラリは無関係なので注意しましょう。
log属性
すべての Ivy タスクで使用できる、「実行時のログ出力の詳細度の設定」を行う属性が log 属性です。下記の4段階があります。
| 詳細度 | 概要 |
|---|---|
"quiet" |
めっちゃ静かになります。エラー以外基本的に何もしゃべりません。 |
"default" |
普通に話します。標準的な情報が出ます。(デフォルト) |
"verbose" |
よくしゃべります。詳細なログを出します。 |
"debug" |
うるさいです。非常に詳細で開発者向けの内容が出力されます。 |
-
targetタグの description 属性
簡単な概要を書く属性です。なるべく1行で簡潔にタスクの内容を書きます。ant -projecthelpとコマンドをたたいた時に表示される内容です。
C:\Users\[ユーザ名]\Desktop\hello-ivy>ant -projecthelp
Buildfile: C:\Users\[ユーザ名]\Desktop\hello-ivy\build.xml
Main targets:
clean --> clean the project
clean-cache --> clean the ivy cache
report --> generates a report of dependencies
resolve --> retreive dependencies with ivy
run --> compile and run the project
Default target: run
<!-- =================================
target: report
================================= -->
<target name="report" depends="resolve" description="--> generates a report of dependencies">
<ivy:report todir="${build.dir}"/>
</target>
中にある <ivy:report todir="${build.dir}"/> は「レポートを出力する」という Ivy タグです。ant report とコマンドをたたくと、build フォルダの中にレポートが生成されます。build フォルダの中の html ファイルをダブルクリックすると、ブラウザでレポートを確認できます。
こちらも様々な属性が指定できますが、詳しくは公式ドキュメントまで!
<!-- =================================
target: run
================================= -->
<target name="run" depends="resolve" description="--> compile and run the project">
<mkdir dir="${build.dir}"/>
<javac srcdir="${src.dir}" destdir="${build.dir}" classpathref="lib.path.id" includeAntRuntime="false"/>
<property name="msg" value="hello ivy !"/>
<java classpathref="run.path.id" classname="example.HelloConsole">
<arg value="-message"/>
<arg value="${msg}"/>
</java>
</target>
<!-- =================================
target: clean
================================= -->
<target name="clean" description="--> clean the project">
<delete includeemptydirs="true">
<fileset dir="${basedir}">
<exclude name="src/**"/>
<exclude name="build.xml"/>
<exclude name="ivy.xml"/>
</fileset>
</delete>
</target>
ここには Ivy タスクが現れません。Ant の公式ドキュメントか、過去の記事を参照してください。
<!-- =================================
target: clean-cache
================================= -->
<target name="clean-cache" description="--> clean the ivy cache">
<ivy:cleancache/>
</target>
キャッシュを削除するタスクです。ant clean-cache とコマンドをたたくと、ivy2 フォルダの下の chace フォルダが削除されます。メモリが圧迫されちゃったときとかにいいですね。
次は Ivy.xml を読み解きます。



