ASDLite

ASDlite — это легкая версия ASDF (Another System Definition Facility), широкоизвестного инструмента для разработки программ на языке Коммон Лисп (аналог make). ASDLite поддерживает те же основные функции и классы операций, что и модуль ASDF, и во многих случаях может использоваться вместо последнего.

Основные цели создания ASDlite

  1. Небольшой исходный код.
  2. Легкость использования для систем, не связанных с компиляцией и загрузкой (compile-and-load) файлов Лисп-программ. Примером может служить YstokHelp (http://lisp.ystok.ru/ru/yhelp/).
  3. Совместимость с ASDF по синтаксису и многим параметрам.
  4. Возможность задавать аргументы операции непосредственно в спецификаторе зависимости.

Операции в ASDlite

operation ::= keyword | operation-instance
operation-type ::= keyword | type-symbol
operation-designator ::= keyword | (keyword . plist) | type-symbol | operation-instance

Операции передаются в качестве аргументов функции perform и других методов. Спецификатор operation-designator может встречаться в правых частях правил.

В качестве спецификаторов мы рекомендуем просто задавать ключи, например, :compile или :load. Для них в ASDlite определены методы с eql-уточнителями.

В методы для операции можно лередать ключевые аргументы, указав из в списке свойств plist. В  нормальном режиме ASDlite допускает только спецификаторы с ключами, но с символами типа.

Если Вы считаете, что этого мало, и нуждаетесь в полноценных; классах операций ASDF, переключитесь в режим совместимости с ASDF следующим образом:

  1. добавтьте :asdf-compat в список системных возможностей *features* перед компиляцией asdlite.lisp,
  2. в правилах употребляйте asdf:compile-op, asdf:load-op и т.п.,
  3. определите собственные подклассы класса  operation и т.д.

В режиме совместимости ASDlite допускает все вышеупомянуютые формы операций и спецификаторы.

Зависимости в ASDlite

Действие (action) - это пара операция плюс компонент (component, составная часть проекта, системы в терминологии ASDF). Некоторые действия производят изменения в файловой системе, другие - изменяют текущий Лисп-образ. Они отличаются трактовкой отметок времени (timestamps).

Зависимости между действиями, или правила (rules), хранятся в каждом (целевом) компоненте и представлены в виде двух списков, ассоциирующих целевые операции с другими действиями, называемыми посылками (dependee).

Соответственно, существуют два вида правил.

caused-by (в ASDF называется in-order-to)
Если какое-нибудь действие-посылка уже находится в текущем плане (из-за того что его результат устарел или вследствие успешного выполнения других правил), то данное правило срабатывает и приводит к тому, что целевое действие также помещается в план.
requires (в ASDF называется do-first)
Действия-посылки должны быть выполнены до данной операции над целевым компонентом. Но повторное выполнение посылок не приводит к повторному срабатыванию данного правила.

Синтаксис

rule ::= (target-op (dep-op {dependee}+)+)
target-op ::= operation-type
dep-op ::= operation-designator | :features
dependee ::= name-or-path | (name-or-path . plist)
name-or-path ::= component-name | vector | feature
plist ::= ([:features feature] [:version minimum-version] {property value}*)
feature ::= keyword | feature-expression

Пример

(:component "A" :caused-by ((:compile (:compile "B" "C") (:load "D"))
                            (:load (:load "B" "C")))
 :requires ((:compile (:load "B"))))

Если исходный файл B изменяется, то необходимо перекомпилировать. Правило caused-by приводит к перекомпиляции  A.fasl независимо от того, изменился ли сам файл A или нет..

Если A сам изменился, это не влечёт ни компиляции B, ни компиляции C. Согласно правилу requires, загрузка B.fasl в текущий образ должна предшествовать компиляции A.

ВНИМАНИЕ: Компонент может зависеть только от своих соседей, т.е.е компонентов в того же модуля, независимо от способа определения зависимостей:

Обоснование

  1. Встроенная в ASDF иерархия операций фактически двухуровневая. Исходный код ASDF не особо завязан на наследование операций (экзотический пример наследования можно найти в asdf-ecl.lisp).
  2. Слоты объекта-операции бесполезны:
    original-initargs
    Только упоминается в print-object
    parent
    В принципе, указывает целевую операцию, вызвавшую данную.
    Но поскольку объекты повторно используются в make-sub-operation, это не имеет место.
    Наряду с другими слотами visiting-..., используется для пометки пройденных узлов в функции traverse, но она изрядно переписана в ASDLite и базируется на другом подходе.
  3. Добавление совершенно новых операций, т.е. на уровне один, является яркой идеей. Но куда проще добавить новые слоты к базовым классам операций, поскольку лишь эти свойства передаются в операции-посылки.
    Существует куда более простой способ передачи аргументов из operate в реализующие функции - посредством ключевых аргументов!
  4. Аргумент инициализации :do-first фактически игнорируется ASDF - слот всегда получает значение
     ((compile-op (load-op ,@depends-on))))
  5. Мы исключили inline-методы, которые довольно неэлегантны в ASDF:
    - реализуются через eval,
    - ASDF пытается удалить такие методы из обобщённой функции с другим именем. Из-за нестандартного поведения remove-method в LispWorks 4.4, эта реализация постоянно сигнализирует об удалении метода при переопределении (т.е. повторном оценивании формы defsystem) системы.
  6. Ссылка на системные возможности (features) в определении компонента куда более полезна, чем в определении правил.
  7. Вопреки приверженности к объёктно-ориентированному представлению операций, в исходном коде наблюдается "необобщённый" (non-generic) подход к именованию функций доступа :-)
    Например:
     - component-parent vs. operation-parent
     - component-version vs. missing-version
     - module-components vs. circular-dependency-components

Платформы

Исходный код тестировался на следующих реализациях Коммон Лисп:

Загрузка и установка

Просто выкачайте файл asdlite.lisp, откомпилируйте и загрузите его в Лисп-систему.

Документация

Концепции и функции описаны в полной документации по ASDF.

Изменения и дополнения

См. Changes and additions на англоязычной странице ASDLite.