前時代的なプロジェクト構成に強いAnt。

いまだMavenやGradleを利用せず、かといってそれらを使おうとしても既存の構成がクソで置き換えがままならず、しかもAntなどのビルドツールを一切使っていないというプロジェクトに出くわした。ウェブアプリなんだけど、デプロイの方法がEclipseでRefreshを行ってビルドして、できあがったclassファイルたちを「webapps/myproj/WEB-INF/classes」にコピペするという・・・。

さすがに、デプロイする度にEclipseを開いて、できたclassをコピペなんていうめんどくさいことはしたくないので、すごい久しぶりにAntを使うことにした。いや、Antの存在を思い出すのに時間がかかった。
今回対象とする言語はScala。環境周りの構成は下記の通り。

  • Scala 2.10.4
  • Java 1.7.0_13
  • OS X 10.9.3
  • Ant 1.9.4
  • Tomcat 7.0.50(ここは今回の話とはそれほど関係ない)

ビルド対象の全体的な構成は下記の通り。

## 説明のため、不要なディレクトリや階層は省略
tomcat
├── webapps
    └── myproj
        ├── WEB-INF
        │   ├── classes
        │   ├── lib
        │   ├── html
        │   ├── src_myproj1 <-- eclipse project
        │   │   ├── bin
        │   │   └── src
        │   ├── src_myproj2 <-- eclipse project
        │   │   ├── bin
        │   │   └── src
        │   └── web.xml
        ├── index.jsp
        ├── img
        ├── css
        └── js

最初は、Antを使ってwarファイルを作成して、そいつをwebapps配下にコピーしてデプロイ完了っていうふうにしようと思ったけど、そもそもこの構成自体がまるまるリポジトリ管理対象となっているので、うかつに変更できないと思って断念。
そんなわけで、至極単純にビルドしてあとはclasses配下にコピーという結論に落ち着いた。以下、作ったビルドファイル。配置先は、上の図でいうところの「src_myproj1」。

まずはbuild.propertiesファイル。

# Change the tomcat directory to your path
tomcat.home=/path/to/tomcat

# Change the tomcat library setting to your path
tomcat.libdir=${tomcat.home}/lib

# Change the project home to your path
homedir=${tomcat.home}/webapps/myproj

# Change the webapp library setting to your path
libdir=${homedir}/WEB-INF/lib

# Change the scala setting to your path
scala.home=/path/to/scala

# Change the scala library setting to your path
scala.libdir=${scala.home}/lib

# Deploy directory
deploydir=${homedir}/WEB-INF/classes

続いてbuild.xmlファイル。

<?xml version="1.0" encoding="UTF-8"?>
<project name="myproj" basedir="." default="build">
    <property file="build.properties"/>
    <property name="srcdir" value="${basedir}" />
    <property name="bindir" value="${basedir}/bin" />

    <target name="init">
        <path id="build.classpath">
            <fileset dir="${scala.libdir}">
                <include name="*.jar" />
            </fileset>
            <fileset dir="${libdir}">
                <include name="*.jar" />
            </fileset>
            <fileset dir="${tomcat.libdir}">
                <include name="*.jar" />
            </fileset>
            <pathelement location="${bindir}" />
        </path>
        <taskdef resource="scala/tools/ant/antlib.xml">
            <classpath>
                <fileset dir="${scala.libdir}">
                    <include name="*.jar" />
                </fileset>
            </classpath>
        </taskdef>
    </target>
    <target name="build" depends="init">
        <delete verbose="true" failonerror="false">
            <fileset dir="${basedir}/bin" erroronmissingdir="false"/>
            <fileset dir="${deploydir}/yourpackage" erroronmissingdir="false"/>
        </delete>
        <mkdir dir="${bindir}" />
        <scalac srcdir="${srcdir}"
            destdir="${bindir}"
            encoding="UTF-8"
            classpathref="build.classpath">
            <include name="**/*.scala" />
        </scalac>
        <copy todir="${deploydir}">
            <fileset dir="${basedir}/bin"
                includes="yourpackage/**/*.class" />
        </copy>
    </target>
</project>

流れとしては簡単で、

  1. build targetを実行する
  2. 依存しているinit targetを先に実行して、「build.classpath」っていうpathに、ビルドに必要な各ライブラリ群のディレクトリパスを格納する
  3. 改めてbuild targetを実行して、
    1. ${basedir}/binと${deploydir}/yourpackageを削除
    2. ${bindir}作成
    3. ビルド
    4. ${deploydir}に、${basedir}/bin/yourpackage/**/*.classに一致するファイルをコピー

となっている。

ひとまずこれで、antコマンド一発で更新が可能になったので、開発は楽になった。