はじめに
今回は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にやらせてみたいと思います。
- JavaプログラムをビルドしてJarファイルの作成
- 依存するライブラリや設定ファイルなどのリソースを所定のディレクトリにコピー
- 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 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なので、特に難しいことはしません。
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 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によるビルドを実行してみましょう。
ビルドとプログラムの実行は次の手順で行います。
- JARファイルの生成
- 生成したJARファイルの実行
- ビルド成果物をZIPファイルにアーカイブ
4.1. JARファイルの生成
まずは、makeJarターゲットを使用して、JARファイルを生成します。
Eclipse上でbuild.xmlを右クリック > Antビルド(2)でダイアログを表示し、makeJarにチェック > 実行をクリック
の順で実行します。
■ターゲットをチェックして実行
デフォルトでcleanターゲットにチェックが入っていると思いますが、今回そのチェックは外しましょう。
実行ボタンをクリックすると、ビルドスクリプトが動きます。
コンソールに「BUILD SUCCESSFUL」と表示されれば、ビルド終了です。
Eclipse上でプロジェクトをリフレッシュすると、生成したJARファイルが現れます。
■プロジェクトリフレッシュ後のパッケージ・エクスプローラ
targetフォルダを生成し、フォルダ内に次の資材が配置してあると思います。
・ビルド後のクラスファイル
・設定ファイルや依存するJARファイルのコピー
・生成したJARファイル
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が生成されていると思います。
こちらを解凍すると、targetフォルダに配置していたすべてのファイルがアーカイブされていることがわかるかと思います。
しかしながら、クラスファイルは通常、成果物としてデプロイすることはないかと思いますので、その場合は、ZIPにアーカイブする前に、削除してしまいましょう。
今回は、すべてZIPにアーカイブしています。
ここで一つ注意いただきたいのは、Antを使用したZIPにアーカイブしたファイルは、Lhaplusでは解凍できないということです。
調べると理由はあるようなのですが、Lhaplus以外の解凍ソフトを使用すれば解凍できますので、そちらを使うようにしてください。
最後に
今回は、Antビルドを使用してJavaプログラムのJARファイルを生成する方法を紹介しましたが、いかがでしたでしょうか。
今回の記事も筆者の備忘録的な意味が強い記事でしたが、少しでもこれからAntを使用する方のお役にたてれば幸いです。