Apache Ant должен быть знаком каждому Java-программисту: это популярный инструмент сборки ПО (build tool), полностью написанный на Java. Сценарий представляет собой простой XML-файл. Несмотря на Java-направленность, этим инструментом пользуются и другие разработчики.
Мы пройдём пять простых шагов, чтобы начать использовать Ant:
- Скачаем, установим и настроим.
- Разберёмся с принципами работы и форматом XML-сценария сборки.
- Узнаем минимально необходимый список заданий.
- Напишем простейший Ant-сценарий.
- Напишем сценарий для полного цикла сборки и тестирования простого проекта.
Нам потребуется Java SE Development Kit (JDK, скачиваем тут), ваш любимый текстовый редактор (для Windows рекомендую Notepad++) и минимальные навыки работы в командной строке. Сценарии сборки и пример на Java протестированы и в Windows (XP/7), и в Linux (Xubuntu 12.04, CentOS 6.8). Однако в дальнейшем мы будем предполагать что работаем в Windows.
1. Скачиваем, устанавливаем, настраиваем
Посещаем веб-сайт ant.apache.org заходим в раздел Download/Binary Distributions и скачиваем файл apache-ant-1.10.1-bin.zip (возможно сейчас есть уже более свежая версия). Содержимое архива копируем в любой каталог, например «C:Program FilesAnt» (Windows). Затем добавляем путь к каталогу bin (C:Program FilesAntbin) в системную переменную Path.
Проверяем работоспособность Ant, вызвав командную строку:
C:>ant -version
Apache Ant(TM) version 1.10.1 compiled on February 2 2017
Если аналогичное сообщение получено — всё в порядке.
2. Основные принципы работы
Сценарий сборки — обычный XML-файл. Он содержит определение целей (target), зависимостей (depends) и свойств (property). Простейший сценарий должен иметь хотя бы одну цель. Цель описывает вызов одной или нескольких команд или заданий (tasks). Мы можем задать имя цели с помощью атрибута «name» (name=«command»). Заданное имя становится командой для нашего сценария и может быть вызвана так:
C:>ant command
В теге target также можно (но необязательно) указать зависимость с помощью атрибута «depends». Зависимости связывают цели между собой. Например, есть цель «compile», a есть «run», зависимая от «compile». И если мы выполняем «run», сначала выполняется «compile».
3. Минимально необходимый список заданий (tasks)
Стандартная версия Ant содержит более 150 заданий (https://ant.apache.org/manual/tasklist.html). Нам пока потребуются только семь:
- echo — вывод сообщения в консоль
- mkdir — создание директорий
- delete — удаление файлов и директорий
- javac — компиляция Java-кода
- java — запуск class и jar файлов
- jar — создание jar файла
- junit — запуск тестов
4. Простейший Ant-сценарий
<?xml version="1.0"?>
<project name="HelloWorld" default="hello">
<target name="hello">
<echo>Hello, World!</echo>
</target>
</project>
В этом сценарии у нас единственная цель с именем hello — вывести строку в консоль. Обратите внимание: в теге project мы задали имя проекта, с помощью атрибута name и цель по умолчанию, с помощью атрибута default.
Создадим каталог D:Hello в корне диска D: (можно выбрать другой диск) и сохраним туда файл build.xml, содержащий предложенный выше сценарий. Запустим интерпретатор командной строки (Пуск/Выполнить/cmd), перейдём в наш каталог и вызовем ant:
D:Hello>ant
Buildfile: D:Hellobuild.xmlhello:
[echo] Hello, World!
BUILD SUCCESSFULLTotal time: 0 seconds
Ant нашел файл сценария по умолчанию (build.xml), прочитал его и выполнил задание, заданное по умолчанию в теге project — hello. Мы получим такой же результат, если при вызове ant укажем в качестве параметра команду hello:
D:Hello>ant hello
5. Пишем сценарий для сборки и тестирования Java проекта
Ant предоставляет полную свободу в формировании структуры каталогов. Мы создадим подкаталог src для исходных текстов на java. Это можно сделать в командной строке:
D:Hello>md src
Там (D:Hellosrc) мы сохраним файл HelloWorld.java следующего содержания:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
Затем изменим текст сценария, получив следующее:
<?xml version="1.0"?>
<project name="HelloWorld" default="run">
<target name="mkdir">
<mkdir dir="build/classes"/>
</target>
<target name="compile" depends="mkdir">
<javac destdir="build/classes" includeantruntime="false">
<src path="src"/>
</javac>
</target>
<target name="run" depends="compile">
<java classname="HelloWorld" classpath="build/classes"/>
</target>
<target name="clean">
<delete dir="build"/>
</target>
</project>
Теперь сценарий содержит четыре цели (команды): mkdir (создание папок для классов), compile (компиляция файла(ов) .java), run (запуск файла(ов) .class), clean (удаление результатов компиляции).
Запустим сценарий без параметров и увидим результат выполнения Java программы. Обратим внимание, что в сценарии есть цель clean, которая удаляет каталоги с результатами компиляции.
Прямое указание имен каталогов не говорит о хорошем стиле. Особенно если имена в сценарии повторяются. Модифицируем build.xml, используя property:
<?xml version="1.0"?>
<project name="HelloWorld" default="run">
<property name="src" location="src"/>
<property name="build" location="build"/>
<property name="classes" location="${build}/classes"/>
<target name="mkdir">
<mkdir dir="${classes}"/>
</target>
<target name="compile" depends="mkdir">
<javac srcdir="${src}" destdir="${classes}" includeAntRuntime="false"/>
</target>
<target name="run" depends="compile">
<java classname="${ant.project.name}" classpath="${classes}"/>
</target>
<target name="clean">
<delete dir="${build}"/>
</target>
</project>
Затем добавим в сценарий цель/команду, которая формирует jar файл:
<target name="package" depends="compile">
<jar destfile="${build}/${ant.project.name}.jar" basedir="${classes}">
<manifest>
<attribute name="Main-Class" value="${ant.project.name}"/>
</manifest>
</jar>
</target>
И убедимся что она работает:
D:Hello>ant package
D:Hello>java -jar buildHelloWorld.jar
Hello, World!
Перейдём к тестированию. Изменим код проекта (чтобы было что тестировать):
public class HelloWorld {
public static void main(String[] args) {
HelloWorld hello = new HelloWorld();
System.out.println(hello.sayHello());
}
String sayHello() {
return "Hello, World!";
}
}
и добавим в каталог src файл/класс (TestHello.java) с простым тестом:
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class TestHello {
@Test
public void testHello() {
HelloWorld hello = new HelloWorld();
assertEquals("Hello, World!", hello.sayHello());
}
}
Используя информацию со страницы github.com/junit-team/junit4/wiki/getting-started загрузим два файла, junit-4.12.jar и hamcrest-core-1.3.jar и скопируем их в каталог нашего jrelibext. Теперь можно проверить как работает тест в командной строке:
D:Hello>java -cp buildclasses org.junit.runner.JUnitCore TestHello
JUnit version 4.12
.
Time: 0,281
OK (1 test)
Дополним наш сценарий следующими строчками:
<target name="test" depends="compile">
<junit>
<classpath>
<pathelement location="${classes}"/>
</classpath>
<test name="TestHello"/>
</junit>
</target>
и дополним строку с заданием package (jar):
<jar destfile="${build}/${ant.project.name}.jar" basedir="${classes}" excludes="Test*.class">
Теперь к списку команд нашего build файла (mkdir, compile, run, package) добавилась команда test. Проверим как она работает.
В заключение мы изменим код нашего проекта так, чтобы приветствие выводилось в отдельном графическом окне. Затем сформируем jar файл и запустим его двойным кликом мыши (у вас должно быть настроено выполнение jar по клику).
Третья версия кода проекта:
import javax.swing.*;
import java.awt.*;
public class HelloWorld extends JFrame {
public static void main(String[] args) {
new HelloWorld();
}
HelloWorld() {
setTitle(sayHello());
setDefaultCloseOperation(EXIT_ON_CLOSE);
setBounds(200, 200, 300, 200);
JLabel label = new JLabel(sayHello(), SwingConstants.CENTER);
label.setFont(new Font("", Font.BOLD, 24));
add(label);
setVisible(true);
}
String sayHello() {
return "Hello, World!";
}
}
Вносим незначительные дополнение в сценарий (в команде run), добавив fork=«true» (запуск выполнения класса в другой виртуальной машине). В противном случае run не сработает (проверено экспериментально):
<java classname="${ant.project.name}" classpath="${classes}" fork="true"/>
Выполняем команду формирования jar (D:Hello>ant package), открываем в проводнике каталог D:Hellobuild находим там файл HelloWorld.jar, дважды кликаем по нему мышкой и получаем удовольствие от созерцания графического окошка с приветствием.
Автор: biblelamp