ASDF является фактически единственным на данный момент сборщиком Common Lisp програм. Более того он играет свою роль в различных менеджерах дистрибутивов, хотя и не является самим по себе полноценным решением. И, я бы сказал, что со своей ролью инструмента сборки он справляется довольно неплохо, а вот в сфере описания дистрибутивов есть проблемы, которые пока что не решены на практике. Это заставляет многих людей, в том числе и меня, вообще не пользоваться подобными инструментами и произвоить установку дистрибутивов вручную (благо в Common Lisp среде, в том числе и благоаря ASDF это очень просто1), а других (в том числе и меня) задумыватся о создании собственного средства: примеры тому — Mudballs, Lispy, CL-Librarian, LibCL...
В недавней статье в журнале ПФП я написал, что
развитие средства управления пакетами должно идти именно с учетом децентрализованной структуры Лисп-среды, а не вопреки ей.
К такому же заключению мы пришли и в процессе обсуждения темы на форуме lisper.ru, которое также заставило меня немного заглянуть под капот ASDF, чтобы узнать, насколько реально и легко создать на его основе пакетный менеджер. Этот "быстрый взгляд" в итоге вылился в растянутое на целый месяц неспешное ковыряние кода и его доработку для полноценной поддержки версионирования. Свое решение я направил в список рассылки asdf-devel, однако оно вряд ли будет интегрированно. В любом случае, этой теме я собираюсь посвятить отдельную запись в этой серии.
А начнем мы с того, что нового нам несет ASDF 2, релиз которого состоялся 31 мая, и который уже скоро войдет в вашу любимую Лисп реализацию.
Целая новая версия системы претерпела существенный рефакторинг и доработку силами Фарэ и Роберта Голдмана. С точки зрения пользователей она включает в себя следующие улучшения (разумеется, накопленные и отлаженные за посление ряд релизов):
- версионность самой библиотеки, возможность обновления ASDF
- добавление более простого пользовательского интерфейса
- добавление нового способа конфигурации
- сохранение FASL-файлов отдельно (в других директориях) от исходного кода
- улучшение работы c путями и соответствующее расширение классов
component
иsystem
- исправление некоторых багов
Вот lightning talk Роберта на встрече TwinCity лисперов, посвященный ASDF 2. Нужно заметить, что ценность этого релиза не только практическая, но и символическая, знаменующая переход проекта на новую стадию разработки: более структурированную и прогнозируемую.
Итак, кратко о новых фичах.
1. Возможность обновления ASDF.
Сейчас любой пользователь может воспользоваться самой новой версией ASDF, просто загрузив ее через
(asdf:oos 'asdf:load-op 'asdf)
(но не через require
!) Подробнее об этом в мануале, который, также улучшается.2. Более простой пользовательский интерфейс — это функции
load-system
, compile-system
и test-system
. Вроде бы как, тривиальное изменение, но избавляющее новичков от необхоимости думать, почему это операции load-op
и т.п. являются объектами, а не функциями, и других схожих волнений. Это важно в борьбе с кажущейся сложностью ASDF. При этом методы на test-op
, как и раньше — и это понятно — нужно описывать разработчикам систем.3. Системный реестр (
source-registry
) — новый способ конфигурации :)Именно таким является новый, и по замыслу авторов основной способ задания места расположения исходников систем у пользователя. В то же время старый вариант через
*central-registry*
остается полностью функциональным и поддерживаемым. Более того, он был дополнен проверкой на самую неприятную и, наверно, частую ошибку при использовании ASDF — отсутствие слеша в конце пути к директориям — теперь этой неразберихи больше не будет.Что же такое системный реестр? Это набор конфигурационных файлов в предопределенной структуре директорий для каждого пользователя, смоделированных по принципу *.conf.d директорий в Unix. А также собственно DSL для конфигурации. Простой пример того, как это работает из мануала:
В директории~/.config/common-lisp/
находится файлsource-registry.conf
со следующей конфигурацией:
(:source-registry
(:tree "/home/fare/cl/")
:inherit-configuration)
В данном случае поиск установленных систем производится рекурсивно в поддиректориях в/home/fare/cl/
.
Однако это объяснение и пример далеко не исчерпывающи, поэтому лучше читать соответствующий раздел руководства и проверить все собственноручно.
Честно говоря, как по мне, то новый подход для индивидуального разработчика менее удобен, чем использование
*central-registry*
. Однако он лучше подойдет для средств автоматического конфигурирования (и, я думаю, что как раз опыт в рамках ITA, где используется много Lisp серверов приложений, послужил отправной точкой для разработки этого способа), а также для использования в пакетных менеджерах. И хорошо, что теперь есть альтернативы для каждого из случаев.4. Cохранение FASL-файлов теперь происходит в компилятор-специфичных директориях, по умолчанию спрятанных в домашней диретории пользователя. Благодаря этому устраняются проблемы как конфликта прав в случае использования одних и тех же исходников библиотек разными пользователями, так и stale FASLs, которые возникают при апгрейде реализации (в частности для SBCL).
5. В общем, исправлены основные недочеты, которые присутствовали в ASDF при работе с путями в разных операционках, а в классы компонент и система добавлены слоты, указывающие абсолютное положение их в файловой системе. Также исправлены и некоторые другие баги, о чем можно почитать в Changelog'е.
Какие проблемы остались? Из существенных для меня — две: нечеткая семантика форсированных операций (параметр
:force t
), а также недостатки работы с версиями (этой теме будет посвящена отдельная запись, поэтому не буду касаться ее здесь).В завершение скажу, что, очевидно, ASDF будет развиваться, как минимум, в сторону устранения явных проблем и упрощения работы с ним, а также, возможно, и поддержки большего количества сценариев использования и перехода к еще более декларативной модели описания систем.
В следующей записи — немного о внутренностях ASDF...
1 Мой алгоритм установки Lisp библиотеки:
- Загрузить tar.gz файл
- Развернуть в
~/lib/lisp/
- Создать символическую ссылку на ASD-файл в
~/.lisp/
- (И вариация для случая работы с разными версиями одного пакета): ссылка на ASD-файл основной версии в
~/.lisp/
, а при необходимости использования альтернативной версии, скажем hunchentoot-0.15.7 вместо hunchentoot-1.1.0 (push "~/lib/lisp/hunchentoot-0.15.7/" asdf:*central-registry*)
(аналог PATH
).