Большая часть библиотек с исходным кодом на языке Коммон Лисп сопровождается файлом определения системы в формате ASDF (Another System Definition Facility). В LispWorks встроен собственный способ определения систем исходных файлов - макрос lw:defsystem и сопутствующие функции. Стоит ли их использовать, несмотря на наличие более универсальной и работающей на разных реализациях Лисп asd:defsystem?
За годы работы сложилось впечатление, что стоит. Ниже приведённые выводы подтверждаются: в дискуссиях эхоконференции comp.lang.lisp высказано немало сомнений в универсальности ASDF.
asd:defsystem рекомендуют помещать в собственный уникальный пакет. В целом, это слегка обременяет пакетную систему реализации Лисп и выглядит не очень элегантно. Можно этого не делать и помещать в пакет cl-user, что грозит конфликтами символов.
lw:defsystem не требует пакета - все будет работать без проблем в пакете cl-user.
lw:defsystem позволяет отдельно хранить бинарники в собственных папках в зависимости от опций, например:
(lw:defsystem my-system (:object-pathname (lw:current-pathname #+debug "bin/debug/" #-debug "bin/")) ...)Значит, отладочная версия проекта всегда будет храниться отдельно от окончательной, причем обе отделены
Напротив, asd:defsystem помещает бинарники в тот же директорий, где и
исходные Лисп-файлы. Разделение разных версий
скомпилированных файлов
невозможно встроенными средствами. Можно, конечно, определить подкласс
asd:system, но это будет уже другая система :-). Пример определения можно найти
в исходных текстах YstokHelp.
Это значит, что если требуется компонент с исходником вне директория системы,
в опции :pathname необхдимо указывать физический
путь.
Это весьма странно, ибо логические пути - весьма гибкий механизм,
почти незаменимый, если Вы отлаживаетесь на разных компьютерах.
Пример задания логического пути:
:pathname #P"LIB:doc;settings;general.html"
Обработку логических путей можно добавить (проверено для ASDF 1.131), определив следующий метод.
;;; Позволяет в качестве аргумента инициализации :pathname ;;; любого компонента указывать логический путь (defmethod reinitialize-instance :after ((component asdf:component) &key pathname) (setf (slot-value component 'asdf::relative-pathname) (translate-logical-pathname pathname)))
Обработка inline-методов довольно неэллегантна ASDF (видимо, в попытке
достичь портативностьи). Функция %remove-component-inline-methods
(см. asdf.lisp)
пытается удалять
метод из обобщённой функции, к которой он явно не относится.
Реализация функции remove-method
в LW 4.4, мягко говоря, нестандартна
и вызывает ошибку при таком обращении.
Поэтому попытка повторно оценить определение системы asd:defsystem, содержащее опции
:perform, :explain
и т.п., выдаёт ошибку.
Определение системы в формате lw:defsystem может быть представлено в виде графа в браузере систем, который встроен в среду разработки LispWorks. Это обеспечивает наглядность и дополнительные удобства.
При желании можно загнать в браузер и ASDF-определение:
утилита из комплекта
lw-add-ons
позволяет транслировать на лету
определение системы: asd:defsystem -> lw:defsystem.
Вдобавок, в версии LW6 браузер может самостоятельно визуализировать ASDF-определение системы.
В целом, для процесса разработки lw:defsystem лучше подходит. Она отработана годами и берёт начало от Лисп-машин.
Для дистрибуции же готового проекта asd:defsystem вполне достаточно. Даже inline-методы допустимы, если определение системы загружается единожды.