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

    В данной статье я подробно опишу как установить и настроить 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

    • +29
    • 13,2k
    • 4
    Поделиться публикацией
    Похожие публикации
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 4
    • +2
      Спасибо, хорошая статья.

      quicklisp, если бы с ним было знакомо большее число людей, мог бы стать образцом как надо писать менеджеры пакетов для языков и софт вообще. Прошёл месяц-два после релиза beta (ещё даже RC нет) и эта штука стала не только стандартом де-факто взамен хромавшего несколько лет asdf-install, но и ИМХО самым удобным менеджером пакетов вообще, в сравнении со всякими CPAN и Gems.
      • 0
        Я не знаю, типичная это проблема или нет, но у меня после установки sbcl и emacs значение user-homedir-pathname было различным при запуске sbcl из коммандной строки или как inferior-lisp из emacs.

        Из коммандной строки user-homedir-pathname было c:/users/me (под Windows 7), а из emacs — c:/users/me/appdata/roaming.

        В результате чего .sbclrc не загружался из emacs. Если же его передавать явно как (setq inferior-lisp-program «sbcl --userinit c:/users/me/.sbclrc»), то тогда не загружался quicklisp по той же причине. Пришлось еще пофиксить загрузку quicklisp.
        • +1
          Причина, кажется, понятна, потому как я почему-то забыл один момент в статье описать.

          Вобщем, нужно обязательно установить переменную среды HOME в %users%/%username%
          www.gnu.org/s/libtool/manual/emacs/Windows-HOME.html
        • 0
          > SBCL для винды следует брать вот тут: github.com/akovalenko/sbcl-win32-threads
          > Этот форк SBCL, поддерживаемый и разрабатываемый Антоном Коваленко,
          > добавляет поддержку многопоточности и исправляет огромное количество windows-
          > специфичных багов официальной версии под винду.
          >
          > Форк постоянно синхронизируется с основным репозиторием, и когда-нибудь в
          > конечном итоге будет смержен с ним.

          Если кто знает — исправились ли проблемы в текущих версиях SBCL для Windows? 1.2.13
          Многопоточность?

          Произошел ли мердж?

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

          Интегрировались ли эти фичи в текущие версии SBCL?

          Вообще этот гайд для найстройки ли надо использовать или актуальнее новый:
          "(to-customize (to-install Common-Lisp-IDE))" habrahabr.ru/post/259737
          ?

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.