В данной заметке рассматривается использование Maven для сборки проектов, написанных на Clojure (или на смеси Clojure, Java и других языков).
Maven — утилита для управления жизненным циклом ПО, реализующая разрешение зависимостей (с автоматическим скачиванием их из репозиториев), сборку и тестирование кода, публикацию собранного ПО и т.д. Функциональность данной утилиты может расширяться с помощью плагинов, что делает возможным ее применение не только для работы с кодом на Java, для чего она в первую очередь и создавалась, но и дает возможность работы с кодом на других языках. Подробнее о Maven вы можете прочитать в следующей книге.
В отличии от утилиты Ant, которая описывает как выполнять сборку и тестирование кода, Maven в декларативном стиле описывает что надо сделать, и все задачи выполняются соответствующими плагинами.
Все описание жизненного цикла и информация о проекте хранится в файле pom.xml
, который
находится в корневом каталоге проекта (и в каталогах подпроектов, если проект состоит из
нескольких частей). К информации о проекте относятся имя и идентификатор проекта, его
версия, и достаточно часто — информация о сайте проекта, репозитории с исходным кодом
(тогда можно использовать цель mvn scm:update
для обновления исходного кода, и т.п.) и
многое другое.
Project Object Model (POM) определяет набор стадий жизненного цикла проекта (lifecycle phases). К каждой из стадий привязывается несколько задач (goals), которые определяют что будет выполнено в данной стадии жизненного цикла. К общим фазам относятся компиляция (compile), тестирование (test), упаковка (package) и установка (install). Каждая из стадий имеет набор зависимостей от стадий, которые должны быть выполнены до ее запуска (компиляция должна быть выполнена до тестирование, тестирование до упаковки и т.д.).
Обычно разработчик использует имена стадий для запуска процесса сборки, например, mvn
package
или mvn install
, и т.д. Но кроме этого, разработчик может явно выполнить
конкретную задачу (goal) используя Maven. Для этого он должен указать имя плагина,
который реализует эту задачу, и название задачи, например, mvn clojure:run
запустит
интерпретатор Clojure. Стоит отметить, что список задач, запускаемых в рамках какой-то
стадии жизненного цикла, не является фиксированным, а может изменяться путем конфигурации
плагина. Пример такой конфигурации вы увидите в следующем разделе.
Поддержка Clojure в Maven реализуется с помощью clojure-maven-plugin, который находится в
центральном репозитории Maven, и поэтому сразу доступен для использования1. В качестве
основы для новых проектов вы можете использовать pom.xml
из проекта clojure-maven-example.
Если вы уже создали файл pom.xml
для вашего проекта, то для подключения плагина вам
необходимо добавить следующий код в pom.xml
в раздел <plugins>
:
<plugin> <groupId>com.theoryinpractise</groupId> <artifactId>clojure-maven-plugin</artifactId> <version>1.3.10</version> </plugin>
Внимание: номер версии может меняться по мере продвижения разработки. Для того, чтобы узнать последнюю версию данного плагина обратитесь к сайтам mvnrepository или Jarvana, которые содержат информацию о пакетах, зарегистрированных в репозиториях Maven. Кроме того, вы можете не указывать номер версии — тогда Maven будет автоматически использовать самую последнюю имеющуюся версию
Подключение данного плагина даст вам возможность компиляции, тестирования и запуска кода
на Clojure, однако для этого вам придется использовать явные имена задач (goals), такие
как clojure:compile
, clojure:test
& clojure:run
. Однако вы можете упростить себе жизнь
путем добавления этих задач в список задач, выполняемых для каждой из стадий жизненного
цикла (compile
и test
, соответственно). Для этого, необходимо добавить раздел
<executions>
в описание плагина, например, вот так:
<plugin> <groupId>com.theoryinpractise</groupId> <artifactId>clojure-maven-plugin</artifactId> <version>1.3.10</version> <executions> <execution> <id>compile</id> <phase>compile</phase> <goals> <goal>compile</goal> </goals> </execution> <execution> <id>test</id> <phase>test</phase> <goals> <goal>test</goal> </goals> </execution> </executions> </plugin>
В этом случае исходные коды на Clojure будут откомпилированы, что иногда полезно — при
использовании gen-class
или если вы не хотите поставлять исходные коды. Но иногда лучше
просто упаковать исходные коды в архив, и они будут откомпилированы при загрузке пакета.
Это позволяет избежать несовместимости, если ваш пакет будет использоваться с разными
версиями Clojure. Для того, чтобы поместить исходные тексты в архив, вам необходимо
добавить следующий код в раздел resources
<resource> <directory>src/main/clojure</directory> </resource>
По умолчанию исходные коды на Clojure помещаются в каталог src/main/clojure
, с
подкаталогами, отражающими структуру вашей программы. А исходные тексты для тестов
помещаются в каталог src/test/clojure
. Эти, и другие значения по умолчанию могут быть
изменены путем конфигурации плагина, как это описано ниже, в разделе Настройка плагина.
clojure-maven-plugin
clojure-maven-plugin реализует несколько задач (goals), реализующих разную функциональность. Их можно разбить на 2 группы:
clojure:compile
clojure:test
clojure:test-with-junit
clojure:add-source
...-sources.jar
;clojure:add-testsource
...-testsources.jar
.clojure:run
script
и/или scripts
. Чаще всего используется для запуска проекта со всеми
зависимостями;clojure:repl
replScript
, в который
можно поместить необходимый код для инициализации среды. В том случае, если в
зависимостях была указана библиотека JLine, то она будет подключена автоматически, что
делает работу в REPL более комфортной;clojure:swank
clojure.swank.port
);clojure:nailgun
clojure.nailgun.port
).clojure:marginalia
clojure:autodoc
clojure:gendoc
Имеется несколько репозиториев, которые имеют отношение к Clojure. Релизы Clojure и промежуточные версии публикуются в репозитории Sonatype, который периодически синхронизируется с Maven Central. Среди "сторонних" репозиториев, самым популярным является Clojars, который используется сообществом разработчиков Clojure для публикации своих проектов.
Для подключения "стороннего" репозитория необходимо добавить следующие строки в раздел
repositories
в pom.xml
:
<repository> <id>clojars</id> <url>http://clojars.org/repo/</url> </repository>
Maven автоматически скачивает все необходимые зависимости из репозитория по умолчанию и
репозиториев указанных пользователем (как это показано выше). Скачанные пакеты помещаются
в домашний каталог пользователя и могут использоваться другими проектами без
дополнительного скачивания их из интернета. Пакет однозначно идентифицируется сочетанием
трех параметров — название группы (groupId
), артифакта (artifactId
) и версии.
Для использования Clojure в своем проекте, то вам как минимум надо указать зависимость от
языка. В настоящее время стабильной версией является 1.4.0, которая находится в
release-репозитории Clojure. Для подключения этой зависимости в ваш проект, добавьте
следующие строки в раздел dependencies
в файле pom.xml
:
<dependency> <groupId>org.clojure</groupId> <artifactId>clojure</artifactId> <version>1.4.0</version> </dependency>
Если же вы хотите пользоваться самой последней версией языка, то вы должны подключить
соответствующий репозиторий (sonatype) и использовать версию 1.5.0-SNAPSHOTS
(или другую
текущую на данный момент) вместо версии 1.4.0
.
Для выполнения некоторых задач перечисленных ниже, может понадобиться указать дополнительные зависимости:
clojure:swank
, то вам надо указать зависимость от пакета
swank-clojure
:<dependency> <groupId>swank-clojure</groupId> <artifactId>swank-clojure</artifactId> <version>1.4.2</version> </dependency>
clojure:nailgun
, то вам необходимо скачать дистрибутив
с сайта vimclojure, собрать его как описано в документации и установить в свой
локальный репозиторий Maven. И после этого, вы можете добавить зависимость от
vimclojure
с помощью следующих строк:<dependency> <groupId>de.kotka</groupId> <artifactId>vimclojure</artifactId> <version>X.X.X</version> </dependency>
mvn
clojure:repl
, поэтому ее можно добавить в список зависимостей с помощью следующего
кода:<dependency> <groupId>jline</groupId> <artifactId>jline</artifactId> <version>0.9.94</version> </dependency>
Разработчик имеет возможность управлять настройками плагина, такими как, расположение
исходных кодов, названия скриптов, которые запускаются при тестировании или выполнении и
т.д. Для изменения какого-либо параметра, вам необходимо добавить его в раздел
configuration
в описании плагина. Например, вот так можно задать название скрипта,
который будет запущен для выполнения тестов:
<plugin> <groupId>com.theoryinpractise</groupId> <artifactId>clojure-maven-plugin</artifactId> <version>1.3.10</version> <configuration> <testScript>src/test/clojure/test.clj</testScript> </configuration> ..... </plugin>
Вот список параметров, относящихся к исходному коду и компиляции:
sourceDirectories
sourceDirectory
) с исходным кодом на Clojure, который будет помещен в результирующий
пакет (и откомпилирован, при задании соответствующих опций);
testSourceDirectories
testSourceDirectory
) с тестами, написанными на Clojure;warnOnReflection
true
или false
), который определяет — будут
ли выводиться предупреждения о вызовах функций, вызов которых требует использования
определения типа во время выполнения (reflection).Кроме этого, вы можете ограничить список пространств имен (namespaces) для которых будет
выполняться компиляция и/или тестирование кода. Для этого, вам в директиве namespaces
необходимо перечислить нужные пространства имен (каждое из них должно быть обернуто в
директиву namespace
). Вы можете использовать регулярные выражения для указания всех
пространств имен в нужном пакете, а также с помощью знака !
вы можете указывать названия
пространств имен, которые необходимо исключить из списка. В дополнение к этому имеются
две директивы: compileDeclaredNamespaceOnly
и testDeclaredNamespaceOnly
(со значениями
true
или false
), которые указывают на то, будут ли ограничения по названиям имен
применяться при компиляции или тестировании.
Еще несколько опций конфигурации используются для задания параметров выполнения кода и/или тестов:
script
и scripts
script
) или несколько (scripts
со вложенными
директивами script
) файлов с кодом, которые будут запущены при выполнении задачи
clojure:run
;testScript
clojure:test
. В том случае, если файл не указан, будет сгенерирован временный скрипт,
который выполнит поиск тестов и запустит их на выполнение;replScript
clojure:repl
. Данный код будет выполнен до перехода в REPL, так что в
него можно поместить необходимые инструкции по инициализации вашей рабочей среды;runWithTests
mvn clojure:repl -Dclojure.runwith.test=false
;clojureOptions
java
при любом выполнении кода — REPL, запуске скрипта, тестировании.В принципе, информации изложенной в данной заметке должно хватить для начала использования Maven вместе с Clojure. В том случае, если у вас проект только на Clojure, и вы не собираетесь использовать всю мощь Maven, то может быть стоит обратить внимание на утилиту Leiningen которая написана специально для сборки проектов на Clojure. Еще одним интересным проектом является Polyglot Maven, целью которого является создание DSL (Domain Specificl Languages) на разных языках (Clojure, Scala, Groovy) для описания конфигураций Maven (для Clojure язык практически совпадает с языком, реализованным в Leiningen).
Дополнительные примеры использования Maven с Clojure вы можете найти в проектах Incanter (как пример проекта, состоящего из нескольких модулей), labrepl и clojure-maven-example, а также в следующих заметках (на английском языке):
1. Кроме clojure-maven-plugin
, имеещется еще и плагин под названием Zi, который был
разработан в рамках проекта Pallet. В отличии от clojure-maven-plugin
он написан на
Clojure и более тесно интегрируется с другими Clojure-специфичными подсистемами,
такими как Marginalia, Ritz, и т.п.
Last change: 05.03.2013 16:54