Сборка Java приложения, ant

ant (анг. муравей) - это мощный платформо-независимый скриптовый инструмент, используемый для сборки приложений. Сценарий сборки приложения java оформляется в виде XML-файла подобно скриптам "make" при обработке файлов С/С++. По-умолчанию сценарий сборки извлекается из файла build.xml.

Пример описания сценария сборки :

  • копирование *.jar файлов в каталог релиза, но перед этим необходимо
  • сформировать *.jar файлы, но перед этим необходимо
  • скомпилировать java-файлы в файлы *.class

Сценарий сборки ant'у показывает что надо делать, чтобы превратить из того, что есть (как правило, исходный java-код) в то, что необходимо. Сценарий представляет собой детальный план сборки из частей единого целого, включающий ряд операндов, позволяющих выполнять команды копирования, удаления и перемещения файлов, компиляции java-файлов, формирование документации к коду и исполняемого jar-файла.

Структура сценария сборки - ant project, basedir, target

Корневой элемент сценария project может содержать три необязательных атрибута :

  • name - имя проекта;
  • default - цель проекта по умолчанию;
  • basedir - базовая директория, относительной которой будут вычисляться все пути.

Элемент описывающий цель проекта target может содержать следующие атрибуты :

  • name - имя цели, обязательный атрибут;
  • depends - промежуточные цели, от которых зависит данная цель; имена перечисляются через запятую;
  • if - определяет какие свойства должны быть равны true для запуска цели;
  • unless - определяет какие свойства должны быть равны false для запуска цели;
  • description - краткое описание цели, что она делает.

Параметр property определяет пару имя/значение, которая может многократно использоваться в сценарии подобно переменным. Свойства (настройки) можно определять как внутри build.xml файла, так и в отдельных файлах. При определении внутри xml файла свойства могут включать следующие атрибуты :

  • name - имя свойства;
  • value - значение свойства;
  • location - устанавливает значение свойства в абсолютный путь. Если значение уже абсолютный путь, то ничего не меняется, если относительный то подставляется базовая директория. Символы / и \ меняются автоматически в зависимости от платформы;
  • refid - ссылка на другой объект, определенный где-либо;
  • resource - имя ресурса содержащего настройки в формате настроечного файла;
  • file - путь к файлу настройки (в нем свойства определяются как имя=значение на отдельной строке);
  • url - адрес настройки;
  • environment - префикс используемый для доступа к переменным окружения. Например, если определено myenv, то к переменным обращаются как "myenv.PATH";
  • classpath - путь к ресурсам;
  • prefix - префикс добавляемый к свойствам загруженных из файла, ресурса, или url. По умолчанию префикс ".".

Шаблон простейшего сценария :

<project name="FirstProject" default="clean.jar" basedir=".">

  <target name="path">
      <property name="srcDir" value="D:\Projects\myProject\src" />
      <property name="dstDir" value="D:\Release\myProject"      />
  </target>

  <target name="clean.jar" depends="path">
      <echo>Delete all *.jar files</echo>
      <delete file="$ {dstDir}\*.jar" />
  </target>
</project>

Согласно представленному сценарию ant'у необходимо удалить все *.jar файлы из директории d:\projects\bin.

В примере сценарий сборки содержит тег проект project, включающий несколько заданий target. Первая строка примера содержит общую инфомацию о проекте. Самые важные атрибуты проекта project это элемент наименования задания (значение default) и базовая директория basedir.

Атрибут basedir указывает на базовую директорию, от которой будут вычисляться относительные пути, используемые в сценарии сборки. Каждый проект может иметь только один атрибут basedir, поэтому можно указывать либо полные пути, либо разбивать сценарий на несколько файлов сборки, в каждом из которых указывать свою базовую директорию. Атрибут default указывает на задание target, определенное для выполнения по-умолчанию.

ant работает из командной строки поэтому необходимо определить переменную окружения ANT_HOME, указывающую корневую директорию приложения.Для запуска ant'a на выполнение сценария необходимо правильно описать команду. Примеры вызова Ant'а для выполнения сценария:

  1. ant -buildfile simple.xml clean.jar
  2. ant -buildfile simple.xml
  3. ant compile
  4. ant

В первом и втором примерах сценарии сборки определены параметром -buildfile и представлены в файле simple.xml. В третьем и четвертом примерах сценарии сборки представлены в файле build.xml, наименование которого используется по-умолчанию. В первом примере выполняется сценарий с заданием clean.jar, в третьем сценарии - compile. Во втором и четвертом примерах Ant выполняет сценарии, определенные по умолчанию.

Определение свойств задания, ant property

Свойства в сценарии ant – это аналог переменных в программировании. Каждое свойство имеет два параметра :

  • name – имя свойства;
  • value – значение.

Примеры определения свойств для секций, property :

<target name="path">
    <property name="srcDir"    value="D:\Projects\myProject\src" />
    <property name="dstDir"    value="D:\Release\myProject" />
    <property name="classpath" 
                       value="C:\oracle\ora92\jdbc\lib\ojdbc14.jar" />
</target>

Использовать свойства очень просто, для этого нужно имя свойства написать между символами $ { 'property.name' }. Например, выражение: $ {dstDir}/src будет преобразовано в "D:\Release\myProject\src".

Создание директории, ant mkdir

<target name="make.dir" description="Make a dir" depends="path">
    <echo>Make a directory</echo>
    <mkdir dir="$ {dstDir}" />
</target>

В представленном задании "make.dir" ant должен создать директорию "D:\Release\myProject", определенную атрибутом "dstDir".

Копирование файлов, ant copy todir

Представленный сценарий решает задачу копирования файла myProject.ini из директории проекта prjDir в директорию сборки проекта basedir.

<target name="copy" description="Copy ini file" depends="path">
    <echo>Copy *.ini files</echo>
    <copy todir="$ {basedir}">
        <fileset dir="$ {prjDir}">
            <include name="**/myProject.ini">
        </fileset">
    </copy">
</target>

Команда "copy" включает вложенный элемент <fileset>, который определяет группу файлов. Файлы, которые включаются в эти группы, располагаются в поддиректориях относительно базовой, определенной атрибутом basedir корневого элемента project.

Для файлов может быть указан набор масок patternset, по которым будут отбираться файлы. Шаблон patternset может быть включен как вложенный элемент <patternset> в элемент fileset и иметь атрибут id, по которому можно ссылаться на данный набор из других мест сборки. Например:

<patternset id="sources">
    <include name="**/*.java>
    <exclude name="**/*test*>
</patternset>

Элементы include и exclude указывают на маски (фильтры), результат применения которых следует включать и не включать в набор.

Компиляция java-файлов, ant javac

Следующие задания сценария сборки решают задачу компиляции java-файлов. Элемент srcDir определяет директорию с файлами исходных кодов. Если java-файлы располагаются в поддиректории, то после фигурных скобок и "слеша" необходимо указать поддиректорию.

<target name="common" depends="path">
    <echo>Compile common java files</echo>
    <javac srcdir="$ {srcDir}\common">
        <destdir="$ {dstDir}">
        <deprecation="off">
        <include name="*.java" />
    </javac>
</target>

<target name="compile" depends="path,common">
    <echo>Compile sql files</echo>
    <javac srcdir="$ {srcDir}\sql">
        <destdir="$ {dstDir}">
        <deprecation="off">
        <classpath="$ {classpath}">
    </javac>
</target>

Элемент destDir определяет директорию назначения. Если в исходных java-файлах указан пакет package, то откомпилированные class-файлы будут располагаться в соответствующих поддиректориях.

Второе задание compile зависит от первого задания common согласно значения атрибута depends, в связи с чем при вызове ant'а с флагом compile первоначально будет выполнено первое задание.

Для выполнения второго задания, т.е. для компиляции файлов, необходимо использовать дополнительные библиотеки, упакованные в .jar файлы, в связи с чем путь к этим библиотекам указывается в элементе classpath.

Существует 2 особенности задачи компиляции java-файлов javac. Во-первых, можно не указывать непосредственно имена java файлов - достаточно просто указать каталог. Во-вторых, если ant определит, что class файл существует и новее, чем java файл, то компиляция будет проигнорирована. Эти две особенности являются примерами приемов сборки приложения.

Формирование .jar файла, ant jar

Java приложения, как правило, поставляются упакованными в jar файлы. ant использует команду "jar" для создания архивов :

<target name="jar" depends="compile">
    <echo>Make jar file</echo>
    <jar destfile="myProject.jar">
    <fileset dir="$ {dstDir}">
        <include name="**/*.class">
        <exclude name="**/CVS">
    </fileset>
    </jar>
</target>

В представленном задании сценарий формирования файла jar зависит от задания компиляции compile. Упакованный архив в виде файла myProject.jar будет включать все поддиректории с файлами, расположенными в директории dstDir.

Определение манифеста приложения

ant позволяет вставить в сборку готовый файл манифеста manifest.mf.

<target name="dist" depends="compile" description="Create jar-file">
    <jar jarfile="$ {dist}/myProject.jar" basedir="$ {buildSrc}"
        manifest="$ {src}/manifest.mf"/>
</target>

Но можно также определить содержимое манифеста:

<target name="jar" depends="compile" 
                      description="Generates executable jar file">
    <jar jarfile="myTest.jar">
        <manifest>
            <attribute name="Main-Class" value="soft.test.MainForm"/>
            <attribute name="Class-Path" value="."/>
            <attribute name="Rsrc-Class-Path"
                          value="./ commons-beanutils.jar
                                    derby.jar json-lib.jar ..."/>
        </manifest>
        <fileset dir="build" includes="**/*.class"/>
        <fileset dir="src" includes="**/*.properties"/>
    </jar>
</target>

Запуск приложения, ant fork

Ант позволяет запускать приложение. Для этого необходимо определить параметры приложения и свойству fork присвоить значение "true". Определим задание для запуска создаваемого jar-файла.

<target name="run" depends="dist" description="Run program">
    <java jar="$ {dist}/myProject.jar" fork="true"/>
</target>

Следует обратить внимание, что параметр depends имеет значение dist. Поэтому, пока архив не создан, запускать нечего. Запуск программы осуществляет тег "java". Его параметр jar указывает, что мы хотим запустить программу из jar-архива. Параметр fork имеет значение true, это означает, что для запуска программы мы используем отдельную виртуальную машину (обязательное требование при запуске из jar-файла).

Задание с тестами, JUnit

Следующая задача запускает тесты (если они были созданы прежде).

<target name="test" depends="compile">
    <junit fork="yes" haltonfailure="yes">
        <classpath>
            <pathelement location="$ {buildTest}"/>
            <pathelement location="$ {buildSrc}"/>
        </classpath>
    <formatter type="plain" usefile="false" />
    <test name="tools.utils.Class1Test"/>
    <test name="tools.utils.Class2Test"/>
    </junit>
</target>

Внимание. Для того, чтобы работала эта задача нам нужно рассказать ant где находится библиотека junit.jar. В документации к ant описывается три различных способа, которые позволяют это сделать. Самый простой способ - это копирование файла junit.jar в папку ANT_HOME/lib.

Тестирование выполняется в теге junit, который имеет два параметра:

  • fork – запускает тесты в отдельной виртуальной машине;
  • haltonfailure – останавливает выполнение, в случае если тест не проходит.

Содержимое тега classpath определяет размещение скомпилированных тестов и классов, которые они трестируют.
Тег formatter задает параметры отображения результатов тестирования. Параметр type="plain" указывает, что результаты тестирования должны отображаться в виде обычного текста, а параметр usefile="false" обеспечивает вывод результатов на экран, а не в файл.

С помощью тега test запускается тест. В параметре name указывается наименование теста.

Архивирование файлов, ant zip

Для архивирования файлов необходимо использовать в задании тег zip.
<target name="packSrc">
    <zip destfile="myProject_Src.zip">
        <fileset dir="." includes="**/*.java, **/*.mf, **/*.xml"/>
    </zip>
</target>

С помощью параметра destfile задаем имя архива. А вложенный тег fileset позволяет указать перечень файлов, которые войдут в архив.

Согласно заданию в архив включаем только исходные коды java и файлы с расширениями mf, xml. Атрибут dir задает стартовую папку, includes – указывает шаблоны выбора файлов в архив ("**" - означают любую папку, "*" - любое количество любых символов в имени файла).

Очистка временных директорий, ant delete

Для очистки временных директории и удаления файлов необходимо использовать тег delete. С её помощью можно удалить результаты работы всех предыдущих задач и оставить только исходники.

<target name="clean">
    <!-- удалить директорию -->
    <delete dir="build"/>
    <delete dir="$ {dist}"/>
	<!-- удалить файл -->
    <delete file="test.zip"/>
	<!-- удалить файлы и поддиректории, но не саму директорию build -->
    <delete includeemptydirs="true">
        <fileset dir="build" includes="**/*"/>
    </delete>
	<!-- удалить *.bak файлы в текущей директории и поддиректориях -->
    <delete>
        <fileset dir="." includes="**/*.bak"/>
    </delete>
</target>

Тег delete удаляет папку и её содержимое. Параметр dir задает имя папки. В последнем теге параметр file определяет имя файла.

Обратите внимание, что в первом теге delete имя папки указывается явно (не используя параметры), что позволяет за один раз удалить папки build/classes и build/tests.

Перемещение и переименование файлов/директорий, ant move

Для переименования и перемещения файлов или директорий необходимо использовать move.

<!-- переименование файла -->
<move file="file.orig" tofile="file.moved"/>

<!-- переместить файл в другую директорию -->
<move file="file.orig" todir="dir/to/move/to"/>

<!-- перемещение директории -->
<move file="src/dir" tofile="new/dir/to/move/to"/>

<!-- перемещение группы файлов -->
<move todir="some/new/dir">
    <fileset dir="my/src/dir">
        <include name="**/*.jar"/>
        <exclude name="**/ant.jar"/>
    </fileset>
</move>

<!-- добавление .bak к именам файлов в директории -->
<move todir="my/src/dir" includeemptydirs="false">
    <fileset dir="my/src/dir">
        <exclude name="**/*.bak"/>
    </fileset>
    <mapper type="glob" from="*" to="*.bak"/>
</move>

Создание документации, ant javadoc

ant можно использовать для создания документации java-приложения. Пример задания приведен на странице javadoc.

Подробная информация формирования документации представлена на странице Javadoc/Javadoc2

Наверх
  Рейтинг@Mail.ru