У меня есть простая серверная программа Common Lisp, которая использует библиотеку osicat для взаимодействия с файловой системой posix. Мне нужно сделать это, потому что система создает символические ссылки на файлы и использует метаданные статистики POSIX, а ни одну из этих вещей нельзя сделать в переносимом лиспе.
Я управляю зависимостями с помощью quicklisp, и все это привязано к рабочему дистрибутиву. Приложение переносимо между CCL и SBCL, и я обычно создаю его в первом и развертываю, используя последний. Я объявляю зависимости для приложения с помощью asdf defsystem
и могу использовать quicklisp, чтобы загрузить его для упрощения разработки из локальных проектов.
Для развертывания я просто использовал несколько нестандартных плейбуков, которые копировали среду разработчика на удаленном компьютере (например, настройка quicklisp, загрузка кода в локальные проекты, запуск из домашнего каталога пользователя), что было хакерским, но в основном нормальным. Совсем недавно, когда он стал более стабильным, я компилировал его с помощью sb-ext:save-lisp-and-die
, используя простой скрипт компиляции. Это означает, что я получаю исполняемый файл, который я могу запускать больше как сервер, со сценариями управления службами и анонимной учетной записью пользователя.
Это работает очень хорошо, и поэтому я недавно перевел этот шаг на следующий уровень, и я создаю пакеты .deb с помощью моего сценария компиляции, поэтому я могу собрать все в перемещаемый двоичный файл. Это тоже работает, но результирующие двоичные файлы нельзя перемещать с исходного хоста сборки. Они отказываются запускаться, и, похоже, они пытаются динамически загрузить общую библиотеку для osicat.
Unhandled SIMPLE-ERROR in thread #<SB-THREAD:THREAD "main thread" RUNNING
Mar 15 12:47:14 annie [479]: {10005C05B3}>:
Mar 15 12:47:14 annie [479]: Error opening shared object "libosicat.so":
Mar 15 12:47:14 annie [479]: libosicat.so: cannot open shared object file: No such file or directory.
похоже, что изображение ожидает найти это в архивах quicklisp исходного дерева сборки
(ERROR "Error opening ~:[runtime~;shared object ~:*~S~]:~% ~A." "/home/builder/buil...quicklisp/dists/quicklisp/software/osicat-20180228-git/posix/libosicat.so
(SB-SYS:DLOPEN-OR-LOSE #S(SB-ALIEN::SHARED-OBJECT :PATHNAME #P"
поэтому, копаясь в исходниках, я понимаю, что когда quicklisp извлекает osicat и выполняет свою операцию сборки, он компилирует эту DLL, чтобы обернуть свой интерфейс системными библиотеками, а не просто подключаться к ним напрямую — возможно, потому, что он использует cffi groveller, я не знаю я действительно много знаю о cffi (пока). Это нормально, но вместо того, чтобы ссылаться на .so с помощью системного компоновщика, он пытается dlopen
получить его по фиксированному пути, который не очень переносим и как бы нарушает полезность save-image
На данный момент я немного озадачен, но прежде чем я углублюсь в сборки QL и cffi, я задался вопросом, есть ли какая-то конфигурация сборки или компиляции, которую мне не хватает, что сделало бы ее загрузку более «статичной» или влиять на производство упакованной библиотеки. В идеале мне просто нужен один большой двоичный объект, который я могу обернуть в установщик и связать его с системными библиотеками, но если мне нужно развернуть некоторые дополнительные артефакты, это, вероятно, нормально. Я не знаю, как сделать так, чтобы автоматически сгенерированные общие объекты появлялись на более контролируемом пути.
Однако в этот момент я также могу написать .so для своих вызовов posix и распространить его вместе с приложением и попытаться использовать FFI для него более напрямую. Это было бы немного больно, поэтому я бы предпочел этого не делать.