【超初心者向け】Ant超入門

# はじめに
今回はAntについてご紹介します。
私の記事は基本的に備忘録を兼ねているので、求めていたAntの情報でない場合はご容赦ください。

Antと言えばビルドツールですが、昨今ではMavenやGradleなど、たくさんのハイテクなビルドツールが出てきているので、「今更なんとレガシーな・・・」と思う方もいらっしゃるかもしれませんが、やはりAntを使わねばどうしようもないこともあります。

Mavenを動かす環境が構築できない、ネットワークにつなぐことができず、ローカルリポジトリを構築する方が手間がかかるなど、いろいろなケースがあります。
何を隠そう最近、筆者自身もそのようなケースにぶち当たって、Mavenで構築した環境をAntように作り直す羽目になりました。

なので本記事は、代表的なAntの使い方である、Webプロジェクトのwarファイルを作るものではなく、純粋なJavaのみで動くJarファイルを作る方法を紹介していきます。

# 1. Antとは
まずは、Antとはなんなのかというところですが、その答えは、Javaプログラムをビルドするためのツールです。
この記事のタイトルにもあるように、超初心者の方は、「ビルドなんかEclipseが勝手にやってくれるじゃないか」と思うかもしれません。

その通りです。その通りなのです。
わざわざビルドするためのツールなんか使わなくても、Eclipseにエクスポートさせれば一瞬でJarファイルなど出来てしまうのです。

ですが、いつもEclipseがあり、そのうえでビルドすることができるとも限りません。
そんな場合は、Eclipseのような統合開発環境に依存せずにビルドできる必要があります。
また、ツールを使えば単純にJavaプログラムをビルドする以外のこともツールにやらせることができるので、それなりの手間やミスを減らすことができます。

そこで今回は、次のことをAntにやらせてみたいと思います。

1. JavaプログラムをビルドしてJarファイルの作成
2. 依存するライブラリや設定ファイルなどのリソースを所定のディレクトリにコピー
3. 1と2を合わせてzip形式に圧縮する

それでは次節から、実際にプロジェクトを構築ながら、Antの使い方を紹介していきます。

# 2. プロジェクトの構築
まずは、Antでビルドする対象のプロジェクトを構築します。
ここはやはり、システム開発の世界では伝統のHello Worldを構築して例にとっていきましょう。
開発環境は、筆者の記事ではおなじみですが、Eclipseを使用します。

## 2.1. Javaプロジェクトの新規作成
まず、EclipseでJavaプロジェクトを新規作成します。
筆者の環境では、Eclipse4.4 Lunaを使用しています。

ソースファイルはたった一つで、今回は依存性を持つライブラリと設定ファイルが欲しいので、ロギングライブラリとしてlogbackを使用します。
新規作成したプロジェクトのツリーは次のようになります。
プロジェクト名はHelloWorldAntとし、実行環境はjdk1.8です。
```:ツリー
■プロジェクトルート
├─src
│    └─main
│          Main.java
├─resources			※srcフォルダとして追加
│      logback.xml
└lib				※通常のフォルダとして追加
   logback-classic-1.2.3.jar
   logback-core-1.2.3.jar
   slf4j-api-1.7.25.jar
build.xml
```

デフォルトのプロジェクト設定から、2つフォルダを追加しています。
logback.xmlの配置してあるresourcesフォルダと、使用ライブラリを配置してあるlibフォルダです。
resourcesフォルダは、実行時にクラスパスとして通しておきたいので、srcフォルダとして定義し、libフォルダは、単なるライブラリの置き場ですので、通常のフォルダとして追加しています。
libフォルダ内のライブラリたちは、プロジェクトのビルドパスに追加しています。

また、プロジェクト直下にAntのビルド設定を記載したbuild.xmlを配置しています。

おまけですが、logback.xmlの設定内容も記載しておきます。

```xml:logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
	<!-- コンソール出力用appender -->
	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
			<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
		</encoder>
	</appender>

	<!-- ログファイル用appender -->
	<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
			<!-- ファイルは日替わりでローテーション -->
			<fileNamePattern>logs/log%d{yyyy-MM-dd}.log</fileNamePattern>
			<maxHistory>3</maxHistory>
		</rollingPolicy>
		<encoder>
			<!-- ファイル出力形式 -->
			<pattern>%d{yyyy-MM-dd'T'HH:mm:ss'Z'} - %m%n</pattern>
		</encoder>
	</appender>

	<!-- ロガー定義 -->
	<root level="DEBUG">
		<appender-ref ref="STDOUT" />
		<appender-ref ref="FILE" />
	</root>
</configuration>
```
直接関係ありませんが、日替わりでローテーションするログファイル用の追加しています。

## 2.2. 処理の実装
プロジェクトの設定ができたところで、実際に行う処理を実装していきましょう。
実装すると言っても、locbackを使用する以外はただのHello Worldなので、特に難しいことはしません。

```java:main.javaの実装内容
package main;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * AntでHelloWorldのmain処理を持つクラス。<br>
 * <br>
 * @author tarosa0001
 */
public class Main {
	/** ロガー */
	private static Logger logger = LoggerFactory.getLogger(Main.class);

	/**
	 * [main処理]<br>
	 * AntでHelloWorldのmain処理。<br>
	 * <br>
	 * @param args コマンド引数
	 */
	public static void main(String[] args) {
		logger.info("処理開始");

		logger.info("AntでHello World!!");

		logger.info("処理終了");
	}
}
```

## 2.3. Hello Worldの実行
ここまでで、Antでビルドするためのプロジェクトを構築しました。
試しに実行してみましょう。
実行はEclipse上でJavaアプリケーションとして実行してください。

当然ながら、Hello Worldを表示します笑
後程Antでビルドしたモジュールを実行したときに、結果を比較したいので、実行して表示した内容を記載しておきます。

	■コンソール表示内容
	21:36:08.032 [main] INFO  main.Main - 処理開始
	21:36:08.035 [main] INFO  main.Main - AntでHello World!!
	21:36:08.036 [main] INFO  main.Main - 処理終了

# 3. Antビルドの実装
構築したプロジェクトがエラーなく動くことを確認したところで、ここからはAntを使用してJARファイルをビルドする手順に移っていきましょう。

## 3.1. build.xmlの定義
まずは、プロジェクトルートに配置したbuild.xmlにビルドスクリプトを定義します。
今回は、ターゲットを全部で5つ定義します。
定義の内容は後述しますので、まずは定義内容をすべて記載します。

```xml:build.xmlの定義内容
<?xml version="1.0" encoding="UTF-8" ?>
<project name="HelloWorldAnt" default="clean" basedir=".">
	<!--
		定数の定義。
		build.xml上で使用する定数を定義する。
	-->
	<!--
		ビルドのベースディレクトリ。
		何もなければ${basedir}を使っても問題ありませんが、
		他プロジェクトのbuild.xmlからこのbuild.xmlのタスクを呼び出したとき、
		basedirがずれてしまうことがあるので、別に定義しておく。
	-->
	<dirname property="base" file="${ant.file}"/>

	<!-- JARファイル名 -->
	<property name="jarname" value="HelloWorldAnt" />

	<!-- ZIPファイル名 -->
	<property name="zipname" value="AntZip" />

	<!-- ビルド成果物ディレクトリ -->
	<property name="dir.target" value="target" />
	<property name="dir.target.classes" value="${dir.target}/classes" />
	<property name="dir.target.resources" value="${dir.target}/resources" />
	<property name="dir.target.dependency" value="${dir.target}/dependency" />

	<!-- srcディレクトリ -->
	<property name="dir.src" value="src" />

	<!-- リソースファイルディレクトリ -->
	<property name="dir.resources" value="resources" />

	<!-- libディレクトリ -->
	<property name="dir.lib" value="lib" />

	<!-- ソースファイルエンコード -->
	<property name="src.enc" value="UTF-8" />

	<!--
		クラスパスの設定。
		必要ライブラリの配置してあるパスをクラスパスに通す。
	-->
	<path id="build.lib">
		<fileset dir="${dir.lib}" >
			<include name="*" />
		</fileset>
	</path>

	<!-- JARファイル作成(開発用) -->
	<target name="makeJar" description="開発用JARファイル作成">
		<!-- 作業用ディレクトリのcleanup -->
		<antcall target="clean"/>
		<antcall target="compile"/>
		<echo message="JARファイルを作成します。" />
		<jar basedir="${dir.target.classes}" destfile="${base}/${dir.target}/${jarname}.jar" />
		<antcall target="filecopy">
			<param name="dir.env" value="${dir.resources}" />
		</antcall>
	</target>

	<!-- クラスファイル以外の必要なファイルのコピー -->
	<target name="filecopy" description="クラスファイル以外の必要なファイルのコピー">
		<echo message="クラスファイル以外の必要なファイルのコピーを行います。" />

		<!-- 古いファイルを削除 -->
		<delete file="${dir.target.resources}/*" />
		<delete file="${dir.target.dependency}/*" />

		<!-- 新しいフォルダを作成 -->
		<mkdir dir="${dir.target.resources}" />
		<mkdir dir="${dir.target.dependency}" />

		<!-- resourceファイルをコピー -->
		<copy todir="${dir.target.resources}">
			<fileset dir="${dir.env}">
				<include name="*" />
			</fileset>
		</copy>

		<!-- 依存性のあるファイルをコピー -->
		<copy todir="${dir.target.dependency}">
			<fileset dir="${dir.lib}">
				<include name="*" />
			</fileset>
		</copy>
	</target>

	<!-- コンパイル -->
	<target name="compile" description="コンパイル">
		<echo message="コンパイルを開始します。" />
		<mkdir dir="${dir.target.classes}"/>
		<javac classpathref="build.lib"
			srcdir="${dir.src}"
			destdir="${dir.target.classes}"
			encoding="${src.enc}"
			source="1.8"
			target="1.8"
			includeAntRuntime="false"
			debug="true"/>
	</target>

	<!-- デプロイ用ZIPファイルの作成 -->
	<target name="makeZip" description="デプロイ用ZIPファイルの作成">
		<echo message="成果物をZIPファイルに梱包します。" />
		<zip destfile="${base}/${dir.target}/${zipname}.zip"
			basedir="${dir.target}"
			excludes="${dir.target.classes}/*"
		/>
	</target>

	<!-- ビルド成果物削除 -->
	<target name="clean" description="ビルド成果物削除">
		<delete dir="${dir.target}" />
	</target>
</project>
```

## 3.2. 定義内容の詳細
先にも記載しましたが、今回のbuild.xmlにはターゲットを5つ定義しています。
プログラムをビルドするために使用するのは、makeJarターゲットだけですが、今回はすべてバラバラに定義しています。

Antで使用するビルドスクリプトは、プログラムを関数に分けるように、やりたいタスクごとに別々に定義することができます。
makeJarターゲットでは、バラバラに定義したビルドスクリプトから、JARアイルをビルドする上で前提条件となるターゲットを呼び出し、それらを利用してJARファイルをビルドします。

前提条件となるターゲットを呼び出すためには、targetタグにdepends属性を定義する方法もあるのですが、今回はスクリプトをできるだけ柔軟にしたかったので、\<antcall\>タグを使って呼び出しています。

ビルド成果物をzipにするためのターゲットは別に「makeZip」と別ターゲットしています。

# 4. ビルドと実行
それでは、Antによるビルドを実行してみましょう。
ビルドとプログラムの実行は次の手順で行います。

1. JARファイルの生成
2. 生成したJARファイルの実行
3. ビルド成果物をZIPファイルにアーカイブ

## 4.1. JARファイルの生成
まずは、makeJarターゲットを使用して、JARファイルを生成します。
Eclipse上でbuild.xmlを右クリック ＞ Antビルド(2)でダイアログを表示し、makeJarにチェック ＞ 実行をクリック
の順で実行します。

■構成の編集ダイアログの表示
![picture1.jpg](https://qiita-image-store.s3.amazonaws.com/0/189344/68f40d14-efc4-3357-f5a2-aafd5a515c8a.jpeg)


■ターゲットをチェックして実行
デフォルトでcleanターゲットにチェックが入っていると思いますが、今回そのチェックは外しましょう。
![picture2.jpg](https://qiita-image-store.s3.amazonaws.com/0/189344/4980b014-d656-4790-df26-92631f050dd4.jpeg)

実行ボタンをクリックすると、ビルドスクリプトが動きます。
コンソールに「BUILD SUCCESSFUL」と表示されれば、ビルド終了です。
Eclipse上でプロジェクトをリフレッシュすると、生成したJARファイルが現れます。

■プロジェクトリフレッシュ後のパッケージ・エクスプローラ
targetフォルダを生成し、フォルダ内に次の資材が配置してあると思います。
・ビルド後のクラスファイル
・設定ファイルや依存するJARファイルのコピー
・生成したJARファイル

![picture3.jpg](https://qiita-image-store.s3.amazonaws.com/0/189344/12b6bf52-81b8-4839-591c-72e1582268a2.jpeg)

## 4.2. 生成したJARファイルの実行
では、生成したファイルを実行してみましょう。
コマンドプロンプトを起動し、先ほどプログラムをビルドしたtargetディレクトリに移動しましょう。
次のコマンドでJARファイルを起動します。
今回ビルドしたJARファイルには、エントリポイントを指定せず、依存性のあるファイルも同梱していませんので、実行時にクラスパスを指定します。

■実行コマンド
`java -cp "./dependency/*;./resources;HelloWorldAnt.jar" main.Main`

するといかがでしょう?先ほどEclipse上で実行した時と同じ表示が行われると思います。
これで、プログラムが期待通りビルドできたことが確認できました。

## 4.3. ビルド成果物をZIPファイルにアーカイブ
ここまでで、Antを使用してのビルドから、ビルドした成果物の実行までができました。
最後に、ビルドした成果物をZIPファイルにアーカイブしてしまいましょう。

必要ないと思う方もいらっしゃるかもしれませんが、やはり作ったものをデプロイするときに、持って行ったZIPを解凍しておしまいなのと、個別で持っていくのでは、やはり手間が違うものです。
今回は、完全に別のターゲットとして切り離していますが、\<antcall\>を使用して、ZIPファイルをアーカイブするまでを一つの手続きとすることもできます。

前置きが長くなりましたが、JARファイルを生成した時と同様の手順で、今度はmakeZipターゲットを実行しましょう。
※先ほど実行した際に生成したログファイルも隠れていますので、邪魔な方はlogフォルダを削除してから実行してください。

ビルド後にプロジェクトをリフレッシュすると、targetフォルダにHelloWorldZipが生成されていると思います。

■プロジェクトリフレッシュ後のパッケージ・エクスプローラ
![picture4.jpg](https://qiita-image-store.s3.amazonaws.com/0/189344/5a6ef229-7de1-5542-d6a8-4c281e7d0d79.jpeg)

こちらを解凍すると、targetフォルダに配置していたすべてのファイルがアーカイブされていることがわかるかと思います。
しかしながら、クラスファイルは通常、成果物としてデプロイすることはないかと思いますので、その場合は、ZIPにアーカイブする前に、削除してしまいましょう。
今回は、すべてZIPにアーカイブしています。

ここで一つ注意いただきたいのは、Antを使用したZIPにアーカイブしたファイルは、Lhaplusでは解凍できないということです。
調べると理由はあるようなのですが、Lhaplus以外の解凍ソフトを使用すれば解凍できますので、そちらを使うようにしてください。

最後に
今回は、Antビルドを使用してJavaプログラムのJARファイルを生成する方法を紹介しましたが、いかがでしたでしょうか。

今回の記事も筆者の備忘録的な意味が強い記事でしたが、少しでもこれからAntを使用する方のお役にたてれば幸いです。