Меню:


В данной заметке рассматривается использование Maven для сборки проектов, написанных на Clojure (или на смеси Clojure, Java и других языков).

Что такое Maven?

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. Стоит отметить, что список задач, запускаемых в рамках какой-то стадии жизненного цикла, не является фиксированным, а может изменяться путем конфигурации плагина. Пример такой конфигурации вы увидите в следующем разделе.

Maven и 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

Имеется несколько репозиториев, которые имеют отношение к 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.

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

 <dependency>
  <groupId>swank-clojure</groupId>
  <artifactId>swank-clojure</artifactId>
  <version>1.4.2</version>
</dependency>
 <dependency>
  <groupId>de.kotka</groupId>
  <artifactId>vimclojure</artifactId>
  <version>X.X.X</version>
 </dependency>
 <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
данная директива (с возможными значениями true или false) определяет, будет ли выполняться тестирование при запуске кода или REPL. Вы также можете переопределить указанное значение, указав нужное значение в командной строке Maven, например, вот так: 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

blog comments powered by Disqus