Вечно мне хочется написать слово snapcraft в виде StarCraft, уж так похожи слова. В англонете даже появились слова снапкрафтер (кто делает пакеты snap) и глагол снапкрафтить (процесс упаковки софта). Нет ничего лучше для понимания сути процесса, как погрузиться в него. Решил создать пакет snap и посмотреть весь процесс от создания до заливки в Ubuntu Store.
Первым делом нужно определиться с подопытным кроликом, которого мы будем мучать. Хотелось не просто для себя что-то поделать, но и принести пользу сообществу, если всё получится. Осмотрелся вокруг и решил взяться за LanguageTool. Прекрасный инструмент, который позволяет исправить не только орфографические, но и грамматические ошибки, давая советы по стилистическому оформлению текста. Но его Java природа меня чуток пугала, так как программист во мне умер довольно давно и с джавой никогда не работал. Но подкупало то, что LanguageTool не представлен в репозиториях и оформить его в виде snap для людей - это круто.
С чего начать? Лезем на официальный сайт languagetool.org в раздел development. Итак, у нас есть исходники на github.com/languagetool-org/languagetool. Wiki проекта пишет, что используется система сборки Maven.
Теперь знакомимся с инструментом сборки и упаковки snapcraft. Он умеет собирать различный софт, написанный на различных языках программирования. Расширяется это через систему плагинов и команда snapcraft list-plugins
выводит на данный момент:
ant catkin copy jdk kernel maven nodejs python3 tar-content autotools cmake go kbuild make nil python2 scons
Maven есть и это обнадёживает. Создаю черновой вариант snapcraft.yaml и знакомлюсь с первым понятием - Parts. Это кусочек того, что будет обрабатывать снапкрафт. Кусочков можно делать несколько и они, обычно, независимы друг от друга. Помимо основной информации, создал кусочек languagetool и приказал обрабатывать его плагином maven, указав адрес исходного кода. В идеале, снапкрафт скачает, соберёт и упакует одной командой, но жизнь суровее.
parts: languagetool: plugin: maven source: https://github.com/languagetool-org/languagetool.git source-type: git
Каждый кусочек проходит следующие этапы при вызове из снапкрафт:
Данные этапы parts проходит как они описаны выше. Если просто вызвать snapcraft в каталоге где лежит одинокий snapcraft.yaml, то вы неявно вызываете snapcraft snap
, а этап snap вызовет все этапы перед ним. Этапы можно вызвать и явно - snapcraft build
.
И что мы имеем? Оказалось, что имеют нас.
... [INFO] LanguageTool common GUI classes .................... SUCCESS [ 1.303 s] [INFO] LanguageTool command-line version .................. SUCCESS [ 17.175 s] [INFO] LanguageTool embedded HTTP server .................. SUCCESS [ 30.993 s] [INFO] LanguageTool tools for building dictionaries ....... SUCCESS [ 31.072 s] [INFO] LanguageTool stand-alone GUI ....................... SUCCESS [01:19 min] [INFO] LanguageTool LibreOffice/OpenOffice extension ...... SUCCESS [ 23.636 s] [INFO] Hunspell native libs for LanguageTool .............. SUCCESS [ 0.306 s] [INFO] LanguageTool Wikipedia tools ....................... SUCCESS [01:19 min] [INFO] LanguageTool HTTP API client ....................... SUCCESS [ 13.500 s] [INFO] LanguageTool development tools ..................... SUCCESS [ 40.936 s] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 14:19 min [INFO] Finished at: 2016-06-14T16:03:17+03:00 [INFO] Final Memory: 46M/141M [INFO] ------------------------------------------------------------------------ could not find any built jar files for part
Очень долгая из-за тестов сборка Maven завершилась успешно, но общий итог плачевен. Строка could not find any built jar files for part принадлежит коду плагина maven у snapcraft и косяк где-то там - он не может найти итоговые jar файлы. Тут решил взять таймаут и разрешить часть проблем:
cat /etc/apt/apt.conf.d/01proxy
Меня смущала проблема с плагином maven и не знал как поступить правильно. Добавьте сюда что мне нужна была лишь часть проекта в лице languagetool-standalone, а там ещё:
hunspell-native-libs
languagetool-client-example
languagetool-commandline
languagetool-core
languagetool-dev
languagetool-gui-commons
languagetool-http-client
languagetool-language-modules
languagetool-office-extension
languagetool-server
languagetool-tools
languagetool-wikipedia
Сначала позанимался форменным садо-мазо и, не зная ни Java, ни как собираются её проекты с помощью Maven, решил подправить в parts/languagetool/src/pom.xml строки. Стало ещё хуже. Теперь и Maven начал справедливо ругаться на меня матом. Почти случайно обнаружил, что maven свою работу сделал на все 100% и даже подготовил в parts/languagetool/build/languagetool-standalone/target/ готовый архив LanguageTool-3.4-SNAPSHOT.zip с откомпилированной в jar версией отдельного инструмента LanguageTool.
Тогда вспыхнула надежда, что не всё потеряно. Мысль заработала так. Не могу сейчас починить плагин maven, тогда создам новый пустой каталог и сделаю другой snapcraft.yaml. Мне нужно готовый проект в виде jar скрепить с Java в виде snap пакета, поэтому в новом файле snapcraft.yaml пишу следующее:
parts: jdkfiles: plugin: jdk source: lt-snapshot lt: plugin: tar-content source: lt-snapshot.tar.gz destination: usr/bin
LanguageTool-3.4-SNAPSHOT.zip перепаковал в lt-snapshot.tar.gz и создал ДВА кусочка: jdkfiles и lt (сократил имя). Кусочек jdkfiles использует плагин jdk и мой неправильный путь в source. Не знаю как правильно, но фигня работает. Кусочек lt использует deprecated плагин tar-content (его советуют заменить на copy) и разворачивает весь lt-snapshot.tar.gz в usr/bin. Тут я нарушил все известные стандарты иерархии файловой системы (Filesystem Hierarchy Standard - FHS), накакав в папку для бинарников всем чем можно, но в оправдание скажу, что программа всё равно будет изолирована и её usr/bin это не наш системный /usr/bin/ и мне хотелось чтобы хоть что-то заработало.
Результат? Программа LanguageTool корректно ставилась на моём рабочем компьютере из snap пакета, но не запускалась, выводя Bad system call. В логах AppArmor действительно ругался на системный вызов под номером 45, который утилита scmp_sys_resolver 45 расшифровала в recvfrom. Что-то не так с разрешением мной сокетов. Дело в том, что в разделе apps дал добро на стыковку с сетью, домом, X11 и Unity7.
apps: languagetool: command: java -jar usr/bin/languagetool.jar plugs: [network, network-bind, x11, home, unity7]
Но все эти plugs в декларативной форме будут развёрнуты в правила AppArmor, а там помимо его ещё трудится фильтр seccomp. В данном моменте чуть не ушёл не туда. Начал начитываться про системные вызовы и как их нужно оформлять декларативно в snapcraft.yaml, но тестовые примеры от разрабов на все случаи жизни не содержали подобного и значит мыслю я неверно.
Тут гуглёж вывел на такие темы, что руки опустились и стало грустно. Snapcraft сам готовит враппер-обёртку, но переменных там не достаточно для корректного запуска именно Java программ. Люди пишут, что необходимы как минимум строки
# Not good, needed for fontconfig export XDG_DATA_HOME=$SNAP/usr/share # Font Config export FONTCONFIG_PATH=$SNAP/etc/fonts/config.d export FONTCONFIG_FILE=$SNAP/etc/fonts/fonts.conf export HOME=$SNAP_USER_DATA
И тогда решил сделать ход конём. Запускать будем шелл скрипт, который дополнит нужное и уже сам запустит джава программу. Меняем строку command: java -jar usr/bin/languagetool.jar на command: usr/bin/run.sh. Создаём скрипт lt-snapshot/run.sh с содержимым
#!/bin/sh # Not good, needed for fontconfig export XDG_DATA_HOME=$SNAP/usr/share # Font Config export FONTCONFIG_PATH=$SNAP/etc/fonts/config.d export FONTCONFIG_FILE=$SNAP/etc/fonts/fonts.conf export HOME=$SNAP_USER_DATA java -jar $SNAP/usr/bin/languagetool.jar
И снова пакуем lt-snapshot/ в lt-snapshot.tar.gz .... ииииииииии? Запуск программы! Аллилуйя, запрыгал как горный козёл в шаманской пляске. Неужели сделал? На тебе под дых, чтобы жизнь мёдом не казалась. Софт при закрытии ругается и ругается если сползать в Опции. Просто в этой новой версии LanguageTool 3.4, которая выйдет в свет только 27 июня 2016 года, реализовали сохранение настроек внешнего вида и файл настроек лежит там куда нельзя писать софту из snap пакетов.
Финальный аккорд - переопределяем джава программе её домашнюю папку и меняем последнюю строку в run.sh на
java -jar -Duser.home=$SNAP_USER_DATA $SNAP/usr/bin/languagetool.jar
И всё! Реально всё. LanguageTool корректно сохраняет всё что ему нужно в вашей-и-его домашней папке ~/snap/languagetool/.
Побежал заливать snap пакет и тут проверка выдала 1 помарку, которую я проигнорировал от snapcraft. Затесалась ссылка на несуществующий файл - usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/cacerts вердикт lint-snap-v2_external_symlinks
Автоматическое одобрение прервалось. Нужно было или исправлять, но моё удаление тупой ссылки вызвало ругань от snapcraft - дескать не ты делал, чего ручонки пихаешь? Я выбрал - запрос на проверку специалистом.
Прошло немного времени и LanguageTool-3.4 для 64 битных систем стал доступен в Ubuntu Store.
snap find language
languagetool 3.4 - LanguageTool
Впереди работа над ошибками, так как специалист вынес мне вердикт - разрешу сейчас, но исправьте ситуацию. If your app is java and needs to use ssl, it will fail due to this. You'll need to resolve this in the snap. One way is to ship usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/cacerts as an actual file and not a symlink. I suggest talking to the snapcraft developers and/or filing a bug. I'm going to approve this for now, but please get this resolved in your next upload. — Jamie Strandboge
Нужно подумать над единым пакетом для 32 и 64 битных платформ. Сердце бьётся от такого факта, что мои кривые ручки смогли преодолеть все проблемы, не разбираясь ни в джаве ни в maven. Это ли не показатель крутости Snapcraft?
Второй snap пакет. GTK программа DeaDBeeF. sudo snap install deadbeef-vs
Третий snap пакет. Java программа TuxGuitar. sudo snap install tuxguitar-vs
Четвёртый snap пакет. Java программа Vuze. sudo snap install vuze-vs
Пятый snap пакет. Java программа osddm. sudo snap install osddm
Шестой snap пакет. PAC (Perl Auto Connector). sudo snap install pac-vs