4. Использование Apache Ant для сборки Java приложений

Здесь я покажу пример использования Apache Ant для сборки Java приложения. Эта статья покажет только знакомство с Ant, более подробную информацию можно найти в документации. Проект будет располагаться в директории ~/ant. Исходники в ~/ant/src. Откомпилированные файлы в ~/ant/build разделенны в несколько директорий в зависимости от назначения: классы в ~/ant/build/classes, jar файлы в ~/ant/build/jar. Создадим необходимые директории сейчас, они нужны только для демонстрации запуска Java приложения из командной строки, ant сам в дальнейшем создаст или удалит все необходимые директории.

roonyk@MacBookPro:~$pwd
/Users/roonyk
roonyk@MacBookPro:~$mkdir ant
roonyk@MacBookPro:~$cd ant
roonyk@MacBookPro:~/ant$
roonyk@MacBookPro:~/ant$mkdir src
roonyk@MacBookPro:~/ant$mkdir src/testant
roonyk@MacBookPro:~/ant$
roonyk@MacBookPro:~/ant$mkdir build
roonyk@MacBookPro:~/ant$mkdir build/classes
roonyk@MacBookPro:~/ant$mkdir build/jar
roonyk@MacBookPro:~/ant$
roonyk@MacBookPro:~/ant$ls -l
total 0
drwxr-xr-x  4 roonyk  staff  136 Sep 16 14:26 build
drwxr-xr-x  3 roonyk  staff  102 Sep 16 14:25 src
roonyk@MacBookPro:~/ant$

ant_6

Создадим простое и самое популярное приложение в мире HelloWorld!

Создадим простой java класс, который будет выводить фиксированное сообщение в STDOUT, ~/ant/src/testant/HelloWorld.java добавив в него следующий код:

package testant;

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}

Скомпилируем и запустим нашу мега программу.

roonyk@MacBookPro:~/ant$pwd
/Users/roonyk/ant
roonyk@MacBookPro:~/ant$
roonyk@MacBookPro:~/ant$javac -sourcepath src -d build/classes/ src/testant/HelloWorld.java 
roonyk@MacBookPro:~/ant$java -classpath build/classes/ testant.HelloWorld
Hello World
roonyk@MacBookPro:~/ant$

ant_7

Теперь создадим исполняемый jar файл.

roonyk@MacBookPro:~/ant$pwd
/Users/roonyk/ant
roonyk@MacBookPro:~/ant$echo Main-Class: testant.HelloWorld>myManifest
roonyk@MacBookPro:~/ant$jar cfm build/jar/HelloWorld.jar myManifest -C build/classes/ .
roonyk@MacBookPro:~/ant$java -jar build/jar/HelloWorld.jar
Hello World
roonyk@MacBookPro:~/ant$

ant_8

После выполнения этих java-only шагов мы можем продумать build процесс:

1. Мы должны скомпилировать исходники.

2. Мы должны упаковать скомпилированные файлы, сейчас у нас только один файл, но обычно серьезное приложение состоит из нескольких файлов(возможно сотни).

3. Мы должны создать запускающийся архив.

4. Хорошая практика прибирать за собой мусор.

По умолчанию в качестве имени build файла ant использует build.xml. Создадим build.xml файл и поместим его в ~/ant директорию. Build.xml файл будет иметь вид:

<project>

    <target name="clean">
        <delete dir="build"/>
    </target>

    <target name="compile">
        <mkdir dir="build/classes"/>
        <javac srcdir="src" destdir="build/classes"/>
    </target>

    <target name="jar">
        <mkdir dir="build/jar"/>
        <jar destfile="build/jar/HelloWorld.jar" basedir="build/classes">
            <manifest>
                <attribute name="Main-Class" value="oata.HelloWorld"/>
            </manifest>
        </jar>
    </target>

    <target name="run">
        <java jar="build/jar/HelloWorld.jar" fork="true"/>
    </target>

</project>
roonyk@MacBookPro:~/ant$pwd
/Users/roonyk/ant
roonyk@MacBookPro:~/ant$ls -l
total 16
drwxr-xr-x  4 roonyk  staff  136 Sep 16 14:26 build
-rw-r--r--  1 roonyk  staff  604 Sep 16 18:16 build.xml
-rw-r--r--  1 roonyk  staff   31 Sep 16 14:50 myManifest
drwxr-xr-x  3 roonyk  staff  102 Sep 16 14:25 src
roonyk@MacBookPro:~/ant$

Сейчас мы можем компилировать, собирать архив и выполнять приложение через запуск таких команд:

ant compile

ant jar

ant run

ant clean

или

ant clean compile jar run

в результате получив такой вывод:

roonyk@MacBookPro:~/ant$ant clean compile jar run
Buildfile: /Users/roonyk/ant/build.xml

clean:
   [delete] Deleting directory /Users/roonyk/ant/build

compile:
    [mkdir] Created dir: /Users/roonyk/ant/build/classes
    [javac] /Users/roonyk/ant/build.xml:9: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
    [javac] Compiling 1 source file to /Users/roonyk/ant/build/classes

jar:
    [mkdir] Created dir: /Users/roonyk/ant/build/jar
      [jar] Building jar: /Users/roonyk/ant/build/jar/HelloWorld.jar

run:
     [java] Hello World

BUILD SUCCESSFUL
Total time: 0 seconds
roonyk@MacBookPro:~/ant$

 

ant_9

Красоту портит строка:

[javac] /Users/roonyk/ant/build.xml:9: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds

Решение - необходимо установить атрибут includeantruntime="false".

<project>

    <target name="clean">
        <delete dir="build"/>
    </target>

    <target name="compile">
        <mkdir dir="build/classes"/>
        <javac srcdir="src" destdir="build/classes" includeantruntime="false"/>
    </target>

    <target name="jar">
        <mkdir dir="build/jar"/>
        <jar destfile="build/jar/HelloWorld.jar" basedir="build/classes">
            <manifest>
                <attribute name="Main-Class" value="testant.HelloWorld"/>
            </manifest>
        </jar>
    </target>

    <target name="run">
        <java jar="build/jar/HelloWorld.jar" fork="true"/>
    </target>

</project>

Вывод стал более красивый:

roonyk@MacBookPro:~/ant$ant clean compile jar run
Buildfile: /Users/roonyk/ant/build.xml

clean:
   [delete] Deleting directory /Users/roonyk/ant/build

compile:
    [mkdir] Created dir: /Users/roonyk/ant/build/classes
    [javac] Compiling 1 source file to /Users/roonyk/ant/build/classes

jar:
    [mkdir] Created dir: /Users/roonyk/ant/build/jar
      [jar] Building jar: /Users/roonyk/ant/build/jar/HelloWorld.jar

run:
     [java] Hello World

BUILD SUCCESSFUL
Total time: 0 seconds
roonyk@MacBookPro:~/ant$

Взглянув на build файл мы можем отметить схожесть между Ant and java-only командами:

java-only

Ant

mkdir build\classes

javac

    -sourcepath src

    -d build\classes

    src\testant\HelloWorld.java

echo Main-Class: testant.HelloWorld>mf

mkdir build\jar

jar cfm

    build\jar\HelloWorld.jar

    mf

    -C build\classes

    .

 

 

 

java -jar build\jar\HelloWorld.jar

 

<mkdir dir="build/classes"/>

<javac

    srcdir="src"

    destdir="build/classes"/>

<!-- automatically detected -->

<!-- obsolete; done via manifest tag -->

<mkdir dir="build/jar"/>

<jar

    destfile="build/jar/HelloWorld.jar"

 

    basedir="build/classes">

    <manifest>

        <attribute name="Main-Class" value="testant.HelloWorld"/>

    </manifest>

</jar>

<java jar="build/jar/HelloWorld.jar" fork="true"/>

 

Теперь у нас есть рабочий build файл, который мы можем немного улучшить, а именно зададим в виде переменных директории и имя main-class, а также порядок шагов сборки зависящих один от другого.

<project name="HelloWorld" basedir="." default="main">

    <property name="src.dir"     value="src"/>
    <property name="build.dir"   value="build"/>
    <property name="classes.dir" value="${build.dir}/classes"/>
    <property name="jar.dir"     value="${build.dir}/jar"/>

    <property name="main-class"  value="testant.HelloWorld"/>

    <target name="clean">
        <delete dir="${build.dir}"/>
    </target>

    <target name="compile">
        <mkdir dir="${classes.dir}"/>
        <javac srcdir="${src.dir}" destdir="${classes.dir}" includeantruntime="false"/>
    </target>

    <target name="jar" depends="compile">
        <mkdir dir="${jar.dir}"/>
        <jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}">
            <manifest>
                <attribute name="Main-Class" value="${main-class}"/>
            </manifest>
        </jar>
    </target>

    <target name="run" depends="jar">
        <java jar="${jar.dir}/${ant.project.name}.jar" fork="true"/>
    </target>

    <target name="clean-build" depends="clean,jar"/>

    <target name="main" depends="clean,run"/>

</project>

Теперь просто выполнив команду ant получим:

roonyk@MacBookPro:~/ant$ant
Buildfile: /Users/roonyk/ant/build.xml

clean:
   [delete] Deleting directory /Users/roonyk/ant/build

compile:
    [mkdir] Created dir: /Users/roonyk/ant/build/classes
    [javac] Compiling 1 source file to /Users/roonyk/ant/build/classes

jar:
    [mkdir] Created dir: /Users/roonyk/ant/build/jar
      [jar] Building jar: /Users/roonyk/ant/build/jar/HelloWorld.jar

run:
     [java] Hello World

main:

BUILD SUCCESSFUL
Total time: 0 seconds
roonyk@MacBookPro:~/ant$

Вот таким образом осуществляется простейшая сборка простейшего Java приложения с помощью Apache Ant.

Комментарии

Чтобы оставить комментарий, необходимо Войти или Зарегистрироваться.