В данной заметке рассматривается использование утилиты Leiningen (версии 1.x) для сборки проектов, написанных на Clojure.5
Leiningen — утилита для сборки кода написанного на Clojure. Leiningen намного проще по сравнению с Maven и позволяет описывать конфигурацию проекта и его зависимости используя сам язык Clojure1. Leiningen использует внешние утилиты и библиотеки для работы с зависимостями и сборки кода, поэтому он имеет достаточно небольшой размер исходного кода. В последнее время эта система становится все более популярной — она имеет возможности расширения с помощью дополнительных модулей, например, для компиляции кода на Java и т.п.
Из коробки Leiningen позволяет выполнять базовые задачи — компиляцию кода, тестирование, упаковку кода в jar-архив, сборку jar-архива со всеми зависимостями и т.д. Кроме того, имеется базовая поддержка работы с Maven, что позволяет использовать собранный код в других проектах.
Установка Leiningen на Unix-подобные ОС и на MS Windows немного различаются. Установка
Leiningen на Unix достаточно проста — вам нужно скачать скрипт lein. После этого,
поместите скрипт в каталог, перечисленный в путях поиска программ, сделайте его
выполняемым, и выполните команду lein self-install
для завершения процедуры установки. В
процессе этой процедуры, Leiningen скачает и установит все компоненты, необходимые для его
работы.
Для установки на MS Windows необходимо скачать файл lein-win32.zip со страницы проекта,
который содержит все необходимые для работы утилиты, распаковать его в нужный каталог, и
добавить этот каталог в пути поиска, и выполните команду lein self-install
. После этого
вы можете начать использовать Leiningen.
Для своей работы Leiningen предполагает использование проекта определенной структуры — в
корне проекта должен находиться файл project.clj
, который содержит определение проекта.
Единственной обязательной конструкцией является defproject
— макрос Clojure, который
раскрывается в набор инструкций по сборке. project.clj
также может содержать произвольный
код на Clojure, который будет выполнен в процессе сборки.
Исходный код проекта должен находиться в каталоге src
, тесты — в каталоге test
, а
дополнительные ресурсы — в каталоге resources/
. Каталог lib
содержит библиотеки, нужные
для работы проекта — они копируются туда с помощью команды lein deps
, используя
информацию о зависимостях, определенных в описании проекта. В том случае, если какая-то
из библиотек отсутствует в репозиториях, то вы можете просто скопировать ее в каталог lib
,
и она станет доступна при работе с проектом.
Однако названия каталогов не являются неизменяемыми — вы можете использовать опции
defproject
для изменения этих значений:
:source-path
src
);:compile-path
classes/
);:resources-path
resources/
);:test-path
test/
);:library-path
lib/
).Вы также можете добавить в определение проекта его описание (опция :description
) и ссылку
на домашнюю страницу (опция :url
).
Самым простым способом создать новый проект является использование команды lein new
,
которая принимает один обязательный аргумент — название проекта. Данная команда создаст
новый каталог, чье имя совпадает с именем проекта, и внутри него создаст файл project.clj
с зависимостями от Clojure и clojure-contrib
, файл README
с описанием проекта, а также два
каталога —
src
и test
для исходного кода и тестов, соответственно. После этого вы можете
начать работать с данным проектом.
Рассмотрим простой проект, описанный в файле project.clj
следующим кодом (полный код для
данного проекта вы можете найти тут):
(defproject test-project "1.0-SNAPSHOT" :description "A test project." :url "http://my-cool-project.com" :dependencies [[org.clojure/clojure "1.1.0"] [org.clojure/clojure-contrib "1.1.0"]] :dev-dependencies [ [swank-clojure "1.2.0"] ] )
который определяет новый проект test-project
с зависимостями от Clojure и набора библиотек
clojure-contrib
, а также зависимостью, которая используется в процессе разработки —
swank-clojure
.
В каталоге src
находится один файл —
simple.clj
, определяющий модуль simple
и внутри
него, одну функцию следующего вида:
(ns simple) (defn hello ([] "Hello world!") ([name] (str "Hello " name "!")))
В каталоге test
находится файл simple_test.clj
, содержащий тест для модуля simple
. Для
тестирования используется стандартный модуль clojure.test
. Исходный код теста выглядит
следующим образом:
(ns simple-test (:use clojure.test) (:use simple)) (deftest simple-test (is (= (hello) "Hello world!")) (is (= (hello "test") "Hello test!")))
Это полный проект для которого можно выполнять все команды поддерживаемые Leiningen.
Одной из важных и наиболее часто используемых частей defproject
является определение
зависимостей от других библиотек, находящихся во внешних репозиториях. Для проектов
написанных на Clojure это в первую очередь зависимость от самого языка, как это показано в
примере.
Различают разные виды зависимостей для которых используются разные опции проекта:
:dependencies
:dev-dependencies
swank-clojure
и т.п. библиотек.Кроме этого, имеется плагин native-deps, который реализует поддержку зависимостей от непереносимых библиотек (специфических для конкретных платформ). Вот пример использования этого плагина.
Каждая из перечисленных опций является вектором, каждый элемент которого является вектором с описанием библиотеки. Это описание состоит из (вы уже видели эти определения в примере проекта):
org.clojure/clojure
;"1.1.0"
или "1.2.0-master-SNAPSHOT"
. Но также можно указать
несколько версий, записав их в виде вектора версий, перечисленных через запятую,
например, "[1.1,1.2-SNAPSHOT]"
;:exclusions
. Вот пример исключения лишних зависимостей для библиотеки log4j
:[log4j "1.2.15" :exclusions [javax.mail/mail javax.jms/jms com.sun.jdmk/jmxtools com.sun.jmx/jmxri]]
Leiningen по умолчанию подключает три репозитория:
Помимо этого, пользователь может указать дополнительные репозитории с помощью опции
:repositories
. В качестве параметров для этой опции указывается отображение (map)
состоящее из имени репозитория и его адреса (URL). Например, вот так подключается
репозиторий проекта Apache:
(defproject test2 "1.0.0-SNAPSHOT" :dependencies [....] :repositories {"apache-releases" "http://repository.apache.org/content/repositories/releases/"} )
Типичное использование Leiningen выглядит следующим образом:
lein new
), определяете зависимости от внешних библиотек и
загружаете их к себе с помощью lein deps
(эту команду надо выполнять после каждого
изменения списка зависимостей);lein compile
, lein test
, а также пользуясь при
необходимости lein repl
, lein swank
или lein nailgun
(в зависимости от предпочтений)
для интерактивной разработки;lein install
или залить на
Clojars (с помощью scp
, как предлагается на сайте, или при помощи плагина lein-clojars
);lein jar
— только ваш код, без зависимостей, или с помощью команды
lein uberjar
создаете архив с вашим кодом и всеми зависимостями — такой архив намного
проще распространять.Этот процесс достаточно прост и повторяется до полной готовности вашего кода :-)
Список команд, которые могут быть выполнены Leiningen не является фиксированным —
дополнительные плагины могут добавлять новые команды. В минимальной конфигурации
Leiningen реализует следующие команды, которые запускаются как lein имя_команды [опции]
:
help [имя_команды]
repl
) , если ее имя указано в командной строкеnew имя проекта [опции]
deps
lib/
. Эта команда должна выполняться после
каждого изменения зависимостей, чтобы остальные команды имели доступ к правильным
пакетам;compile
classes/
. Пользователь может управлять тем, какие
пространства имен будут откомпилированы — для этого имеется опция :namespaces
, в
которой надо указать список пространств имен для которых будет производиться компиляция;test [список пространств имен]
jar
uberjar
java -jar ...
точкой входа является пространство имен, указанное в опции :main
в
defproject
;pom
pom.xml
, содержащий описание проекта. Этот файл нужен если вы хотите
использовать ваш пакет в другом проекте;install
clean
lib/
);repl
lib/
, а также каталоги
src/
и classes/
. При запуске lein
2 автоматически определяет наличие библиотеки jline,
так что вам становится доступна история введенных команд.Дополнительные команды реализуются плагинами, расширяющими возможности Leiningen. Существует некоторое количество популярных плагинов доступных для Leiningen, обзор которых вы можете найти в следующем постинге. Сюда можно отнести и плагины для запуска серверов Swank и Nailgun, которые реализуют интерактивную работу из привычной среды Emacs или Vim. При этом происходит автоматическое подключение всех указанных зависимостей, так что вы работаете в том же окружении, как и ваша программа.
Для работы с сервером Swank вам необходимо указать в модуль swank-clojure3 в списке
зависимостей используемых при разработке (:dev-dependencies
)4. После этого вам станет
доступна команда lein swank
, выполнив которую на порту 4005 будет запущен сервер Swank, к
которому вы можете подключиться используя команду Emacs slime-connect
. Если же вы
пользователь Vim, то вам необходимо указать в зависимостях модуль lein-nailgun, о работе с
которым вы можете прочитать на странице проекта vimclojure.
Leiningen является расширяемой системой. В случае необходимости вы можете реализовывать
свои команды — для этого необходимо создать проект, определяющий пространство имен
leiningen.имя_команды
и содержащий реализацию в виде функции имя_команды
, принимающей
описание проекта в качестве аргумента. Подробнее про написание плагинов вы можете
прочитать в следующем постинге. Одним из примеров расширения функциональности Leiningen
является плагин lein-swank
, который реализует поддержку сервера Swank, и
находится прямо в репозитории Leiningen.
В репозитории Clojars имеется достаточное количество плагинов, которые были написаны для
расширения базовой функциональности Leiningen — автоматической заливки кода в репозиторий
Clojars, сборки кода написанного на Java, и т.д. Обычно их имя начинается со слова lein-
,
которое вы можете использовать в поиске. Для использования этих плагинов вы должны
указать их в качестве зависимостей, используемых при разработке (опция :dev-dependencies
).
Я очень надеюсь, что данный рассказ поможет вам в работе с Leiningen при разработке на Clojure. Если у вас имеются вопросы, то вы можете оставить комментарии на сайте или написать мне по электронной почте — я постараюсь на них ответить.
1. стоит также отметить, что существует проект Polyglot Maven, целью которого является предоставление возможностей описания конфигураций Maven на разных языках — Clojure, Scala, Groovy и др.
2. в отличии от других команд repl
реализована напрямую в скрипте lein
, а не написана на
Clojure
3. пример подключения swank-clojure
вы можете увидеть в нашем тестовом примере.
4. и не забудьте выполнить команду lein deps
после добавления этой зависимости!
5. в составе Leiningen также имеется небольшой документ, описывающий начала работы с lein
.
Last change: 05.03.2013 16:54