Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

はじめに

今回は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の設定内容も記載しておきます。

■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なので、特に難しいことはしません。

■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つ定義します。
定義の内容は後述しますので、まずは定義内容をすべて記載します。

■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

■ターゲットをチェックして実行
デフォルトでcleanターゲットにチェックが入っていると思いますが、今回そのチェックは外しましょう。
picture2.jpg

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

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

picture3.jpg

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

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

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

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

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

tarosa0001
tarosa0001です。 いろんなところに散らばっている技術的ノウハウを、勉強したついでに集めて記載していきます。 よろしくお願いいたします。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした