Pull to refresh

Настройка SBCL и среды разработки SLIME под Windows. Пошаговое руководство

Reading time 9 min
Views 20K
В данной статье я подробно опишу как установить и настроить SBCL и окружение для продуктивной разработки под Windows.

Вообще, изначально это была небольшая заметка для коллеги по планируемому мной проекту по анализу и визуализации кода и текстовых данных, но я решил её доработать и превратить в полноценную статью, так как я мало видел руководств подобного рода относительно лиспа, особенно на русском, и особенно касающихся Windows.



SBCL



Для начала нам нужна сама лисп-система.

SBCL для винды следует брать вот тут:
github.com/akovalenko/sbcl-win32-threads

Этот форк SBCL, поддерживаемый и разрабатываемый Антоном Коваленко, добавляет поддержку многопоточности и исправляет огромное количество windows-специфичных багов официальной версии под винду. Кроме того, в него добавлены некоторые очень приятные фичи, которых в основной ветке нет даже в активно поддерживаемых линукс-версиях. Одна из таких фич — stdcall-коллбэки, так необходимые на винде, другая — возможность работы лисповых коллбэков в сторонних тредах(созданных не лиспом, а, например, операционной системой или сторонними сишными, и не только сишными, библиотеками).

Форк постоянно синхронизируется с основным репозиторием, и когда-нибудь в конечном итоге будет смержен с ним.

Хотя лично я регулярно собираю SBCL из исходников, прямо из HEAD ветки mswinmt, с помощью MinGW, но на страничке вики по ссылке также регулярно выкладываются msi-инсталляторы, и поэтому если вам лень ставить и настраивать MinGW, то вы можете скачать бинарники прямо там.
github.com/akovalenko/sbcl-win32-threads/wiki

Оффверсию под Windows использовать не стоит совершенно ни по каким причинам, так она она глючная и сильно недоработанная.

После того, как у вас в руках есть инсталлятор, SBCL следует установить. Я рекомендую ставить его куда-нибудь поближе к корню файловой системы, наподобие как в «D:\SBCL\», а не как предлагается дефолтно(в \program files\), по причинам того, что, во-первых, MAX_PATH не резиновая, а во-вторых, это поможет избежать конфликтов со сторонними библиотеками и утилитами, которым не нравятся пробелы в файловых путях.

ASDF



После установки рантайма лисп-системы, нам следует настроить ASDF.
ASDF это такая система сборки лисповых библиотек, и загрузки их в работающий лисповый процесс, наподобие Make, написанная полностью на CL и не использующая сторонние программы. Больше про нее почитать можно тут, но а я пока опишу ее настройку.

ASDF фактически является де-факто стандартной системой своего рода в среде лисп-разработчиков, и поставляется практически со всеми реализациями CL, в том числе и с SBCL, поэтому я пропущу первый этап, «где ее взять»(если у вас вдруг ее нет, то её можно скачать на ее домашней страничке по ссылке выше, это буквально один файл).

Второй этап заключается в настройке того, где ASDF ищет лисповые библиотеки.
Предположим, у нас есть директория «D:\Lisp», где у нас будут храниться всякие вещи, связанные с CL.
Предположим еще, что у нас в этой директории существует поддиректория «libraries», в которой будут находиться библиотеки, не связанные с quicklisp(про него ниже).

Тогда нам надо будет определить переменную среды CL_SOURCE_REGISTRY, и задать ей следующее значение:
(:source-registry (:tree "D:/Lisp/libraries/") :inherit-configuration)
(переменные среды, в Windows 7, например, настраиваются в панель управления -> система -> дополнительные параметры системы -> переменные среды)

Вторая переменная среды, которую нам надо будет определить, если мы не хотим, чтобы скомпилированные fasl-файлы засоряли директории с исходным кодом — ASDF_OUTPUT_TRANSLATIONS
Она определяет, куда будет складываться кеш компиляции, и откуда загружаться.
Ей нужно задать значение навроде этого:
(:output-translations (T ("D:/Lisp/fasl-cache/" :implementation)) :inherit-configuration)
Таким образом, fasl-файлы будут лежать по путям вроде "D:/Lisp/fasl-cache/sbcl-1.0.52.1.mswinmt.969-6acb698-win-x86/d/Lisp/libraries/my-library/src/package.fasl" и не будут мешаться в директориях с исходниками.

Quicklisp



Теперь нам нужно установить quicklisp.
Quicklisp это пакетный менеджер для CL, в котором собраны наиболее свежие и наиболее популярные библиотеки. Очень удобная штука, и тоже, как и ASDF, фактически является де-факто стандартом.

Установить quicklisp очень просто — надо скачать файл quicklisp.lisp и загрузить его в образ лисп-системы, например набрав (load "quicklisp.lisp") в REPL'е

После загрузки файла, в REPL появится сообщение:
==== quicklisp quickstart loaded ====

To continue, evaluate: (quicklisp-quickstart:install)


Нам, соответственно, надо набрать (quicklisp-quickstart:install) в REPL и нажать «Enter».
Вообще, эта функция принимает необязательный именованный параметр :path, который указывает, куда устанавливать ql, но в принципе, дефолтное ее значение(%users%/%username%/quicklisp/) подойдет многим.

После того, как установщик quicklisp'а скачает, установит и загрузит его в лисповый процесс, необходимо будет набрать в REPL'е (ql:add-to-init-file), чтобы процесс загрузки ql в образ в будущем автоматизировался, и нам не приходилось каждый раз при старте лисп-системы его загружать руками.

Для установки или просто загрузки какой-либо библиотеки, quicklisp предоставляет функцию ql:quickload. Это реально очень удобно — он автоматически скачивает, компилирует и загружает библиотеки совершенно без каких-либо лишних усилий и телодвижений. Как говорит его автор, самое главное достоинство quicklisp в том, что он «просто работает».

В принципе, уже сейчас можно написать первую программу на лиспе под Windows.
Наберите в REPL несколько форм:
(ql:quickload :cffi)

(cffi:load-foreign-library "user32.dll")

(defun main ()
  (cffi:foreign-funcall "MessageBoxW"
    :pointer (cffi:null-pointer)
    (:string :encoding :utf-16le) "SBCL на Windows это просто!"
    (:string :encoding :utf-16le) "Сообщение"
    :int #x40
    :boolean))

(sb-ext:save-lisp-and-die "my-program.exe" :executable t :toplevel #'main)


Запустим my-program.exe и проверим:


Среда разработки



Про Emacs, наверное, слышали все.
Мнения о нем расходятся — кому-то он, возможно, представляется бесполезной игрушкой для гиков, для кого-то это заумный, но устаревший консольный редактор из 70х, а для кого-то — ежедневный инструмент.

Какое бы у вас мнение о Emacs'е не было, один факт на текущий момент остается фактом — расширение SLIME для Emacs — единственная, на текущий момент, полноценная и удобная среда разработки на Common Lisp.

Вообще, я лично имею достаточный опыт работы с продвинутыми IDE вроде Visual Studio, и могу заверить — по удобству SLIME от них ушел недалеко, а может даже, благодаря гибкости Emacs, и вырвался вперед.

Вообще, Emacs по своей сути это рантайм одного старого диалекта лиспа, Emacs Lisp, и своей расширяемости и гибкости, а может даже и выживаемости, он обязан именно этому факту.

Ну ладно, это я отвлекся.

Сначала — «где взять сам Emacs?». Вот здесь: ftp.gnu.org/pub/gnu/emacs/windows
Качайте самый новый (на данный момент это emacs-23.3-bin-i386.zip) и распаковывайте контент директории emacs-23.3 куда-нибудь навроде "D:\Emacs\"(кстати, ввиду изначальной юникс-ориентированности Емакса, возможны некоторые проблемы с путями с пробелами, поэтому тут совет такой же как и при установке SBCL).

Как только распаковали — запускаем программу addpm.exe, находящуюся в %Путь_к_Emacs%/bin — это опциональный шаг, он добавляет иконку в меню «Пуск» и тому подобное, но я все же рекомендую его пройти.

Теперь нам надо скачать SLIME.

Брать его вот тут: common-lisp.net/project/slime
Я лично предпочитаю обновлять через CVS, но, в принципе, там по ссылке всегда есть и простой архив с более-менее свежей версией.

Директорию SLIME нужно положить в директорию библиотек, для которой мы настроили ASDF(в случае, если вы прямо следовали написанному выше, это будет D:\Lisp\libraries\)

Теперь про настройку.

Для подключения SLIME и приведения Emacs'а к более-менее привычному для пользователя Windows виду, нам надо написать некоторые вещи в его файле инициализации.

Как я уже выше сказал, Emacs это по сути интерпретатор Emacs Lisp'а, а это значит, среди прочего, что его файл инициализации это просто файл с кодом на этом самом Emacs Lisp.

Находится файл, если говорить о Windows, обычно в директории %users%\%username%\.emacs.d\, и называется init.el(собственно расширение указывает, что это код на упомянутом диалекте лиспа). У меня, например, это C:\Users\Lovesan\.emacs.d\init.el. Если директории .emacs.d в директории пользователя нету — создайте её и, соответственно, файл.

Далее я приведу часть своего init.el с некоторыми комментариями и объяснениями.

;; Настройка кодировок и окружения.
;; Мы хотим чтобы наши файлы с кодом сохранялись в UTF-8,
;;   пока прямо не укажем другое.
(set-language-environment 'UTF-8)
(setq default-buffer-file-coding-system 'utf-8-unix)

;; Если не отменить make-backup-files, Emacs будет засорять
;;   файловую систему бэкапами.
(setq-default make-backup-files nil)

;; Это включает автосохранение - пока вы работаете с файлом,
;;   Emacs время от времени автоматически создает копию, и удаляет её
;;     как только вы сохрание файл с которым работаете.
(setq-default auto-save-defaults t)

;; Это отключает табы. Как бы вы не относились к табам
;;   в контексте кода других языков программирования,
;;     в лиспе с ними работать совершенно невозможно.
(setq-default indent-tabs-mode nil)

;; Это делает Emacs немного более дружелюбным к пользователям Windows.
;; Конкретно, первая строка включает обычный виндовый курсор для
;;   текстовых редакторов, а вторая - биндит хоткеи вставки/вырезки и
;;     копирования на стандартные Ctrl+V, Ctrl+X и Ctrl+C    
(setq w32-use-visible-system-caret t)
(cua-mode)

;; Это настраивает подсветку парных скобок, очень полезная штука
;;  чтобы в них не заблудиться, и чтобы видеть где скобки лишние.
(show-paren-mode)

;; Это настраивает дополнительный модуль highlight-parentheses
;;  Полезная штука, подсвечивает вложенные скобки в несколько уровней.
;; Скачать его можно тут: http://www.emacswiki.org/emacs/HighlightParentheses
(byte-compile-file "d:/Emacs/lisp/highlight-parentheses.el")
(require 'highlight-parentheses)
(define-globalized-minor-mode global-highlight-parentheses-mode
    highlight-parentheses-mode
  (lambda ()
    (highlight-parentheses-mode t)))
(global-highlight-parentheses-mode t)


;; Дальше собственно настройка SLIME.
;; Первое, что нужно сделать, это указать путь к рантайму реализации лиспа,
;;  с которой мы будем работать.
(setq inferior-lisp-program "D:/SBCL/sbcl.exe")

;; Далее нужно указать, где у нас находится SLIME.
(add-to-list 'load-path "D:/Lisp/libraries/slime-2011-10-27/")

;; Загружаем SLIME
(require 'slime)

;; Устанавливаем, с помощью какой кодировки SLIME будет
;;   общаться с лисп-системой
(setq slime-net-coding-system 'utf-8-unix)

;; Модули SLIME, которые мы подключаем
;;  Тут указанные - это, по моему мнению, базовый минимум.
;;  В дальнейшем можете сами подробнее почитать о них
;;    в мануале SLIME.
(slime-setup '(slime-repl
               slime-fuzzy
               slime-fancy-inspector
               slime-indentation))

;; Настроим хоткеи для автодополнения и выравнивания отступов
(define-key slime-mode-map (kbd "TAB")
  'slime-indent-and-complete-symbol)
(define-key slime-mode-map (kbd "C-c TAB")
  'slime-complete-symbol)

;; Это включает алгоритмы выравнивания лиспового кода из SLIME,
;;   в противоположность стандартным из Emacs
(setq lisp-indent-function 'common-lisp-indent-function)

;; Немного настроим выравнивание отступов под себя
;; Более подробно о кастомизации этого дела можно почитать
;;   в сорцах SLIME, а именно
;;     в %путь_к_slime%/contrib/slime-cl-indent.el
(define-common-lisp-style "my-indent-style"
  "My custom indent style."
  (:inherit "modern")
  (:variables
    (lisp-loop-indent-subclauses t))    
  (:indentation
    (if (4 2 2))
    (define (&lambda 2))
    (with-gensyms ((&whole 4 &rest 1) &body))
    (once-only (as with-gensyms))))

(setq common-lisp-style-default "my-indent-style")


В принципе, можно начинать работать.
Запускаем Emacs (через меню пуск, или runemacs.exe в %путь_к_emacs%/bin/).
Набираем Alt+X и печатаем slime.
Как только SBCL откомпилирует и загрузит лисповую сторону SLIME(т.н. swank-сервер), появится REPL SLIME.

Можно, естественно, работать полностью в нем, но лучше, конечно, в основном работать с файлами.

Тут надо описать некоторые хоткеи Emacs и SLIME, чтобы хоть с чего-то начать(по себе знаю, как просто в этом редакторе потеряться, не зная биндинги основных команд).

M-x — вызов команды(то есть к-либо функции Emacs Lisp) по имени.

(Вообще, C- означает, что во время набора должен быть нажат Ctrl, а M- соответственно Alt. Почему «M»? Потому что «Meta key», но т.к. этой клавиши на стандартных клавиатурах нет, вместо нее используется Alt.)

C-x C-c — выход из Emacs.

С-x b — смена буфера (буфер это что-то вроде файла, который открыт в Emacs, за исключением того, что некоторый буфер не обязательно с каким-то файлом в файловой системе связан).

C-x k — закрыть буфер.

C-c C-f — открывает файл, существующий или новый

C-x s — сохранить файл.

C-x C-s — сохранить файл не спрашивая о перезаписи.

C-x 0 — закрыть текущее окно.

C-x 1 — закрыть все окна кроме текущего.

C-x 2 — разделить окно на два, вертикально (в емаксе встроенный тайлинговый оконный менеджер. Пользователям современных версий винды он может показаться необычным.)

C-x 3 — разделить окно на два, горизонтально.

C-x o — перейти в другое окно

M-: — считывание и вычисление какого-либо выражения Emacs Lisp в минибуфере.

В SLIME REPL:

, — ввод специфичной для SLIME REPL команды.

В буфере файла, с которым работает SLIME(как правило, файлы с расширением .lisp и подобными):

M-. — прыгнуть к определению какого-либо символа/функции/etc.

M-, — прыгнуть назад.

C-x C-e — вычислить выражение

C-c C-k — скомпилировать и сразу загрузить файл.

TAB — автодополнение и выравнивание (мы это настроили в init.el) (кстати, также работает и в REPL)

C-c TAB — просто автодополнение

Автодополнение и прочие подобные функции в SLIME работают основываясь на состоянии подключенной лисп системы, а не просто на основе анализа файлов с кодом. Это значит, что для того чтобы SLIME мог нам что-то конкретное о символе/функции/типе/etc. сказать, нам нужно загрузить файл или библиотеку, содержащую их, в лисп-систему, через REPL или еще как-нибудь.

C-c C-d C-d — описать символ и все с ним связанное (работает наподобие стандартного describe)

C-c C-d h — посмотреть описание символа на CLHS

C-c C-d a — найти и описать символы по их части(работает наподобие стандартного apropos)

По лисповым выражениям удобно перемещаться стрелочками, зажав при этом Ctrl — курсор перемещается через слова и блоки текста, а не по буквам, и с помощью C-M-b и C-M-f — курсор перемещается по S-выражениям.

Вот, в принципе, и всё. Можно начинать писать код.



Upd. Для корректной работы SLIME очень желательно установить переменную среды HOME в значение, соответствующее пути домашней директории пользователя. У меня, на Windows 7, например, это C:\Users\Lovesan

Tags:
Hubs:
+29
Comments 4
Comments Comments 4

Articles