Игра в снапкрафтера очень увлекательна, поскольку прокачивает твой скилл в знаниях Linux систем. Поэтому после упаковки менеджера сессий PAC, шило снова заиграло в /dev/ass и решено было найти нового подопытного кролика. Вначале глянул в список Debian Orphaned, который неизменно наводит на уныние. Это брошенные сироты, в описании которых неизменно одно и тоже - потерян интерес сопровождающего. Очень хотелось впервые упаковать какой-либо русский проект, чтобы своим маленьким вкладом немного помочь ему. Почти случайно обнаружил на просторах Интернета сайт про ДРАКОНа - Дружелюбный русский алгоритмический язык, который обеспечивает наглядность. Но, прочитав пару статей про него, был немного ошарашен. Кратко говоря, Дракон - это средство создания различных диаграмм, в частности, диаграмм деятельности (activity diagram), диаграмм состояний (UML state machine), диаграмм синхронизации (timing diagram). В довершение, с помощью Дракона можно через Экспорт получить готовую программу на языках программирования: C и C++, Java, C#, Python, Tcl, Javascript, Erlang, D, Lua и Go. А теперь добавьте, что Дракон был создан в рамках космической программы Буран и активно используется в российской космической отрасли.
Здесь и далее речь пойдёт о DRAKON Editor, так как существует ещё "ИС Дракон" для MS Windows платформы. Начитавшись про Дракона, реально струхнул, честно говоря. Программа на глазах стала не просто программой, а программищей, пародируя Дмитрия Нагиева. Но первое знакомство подвергло в ступор. Как-то морально готовишься к тому, что если программа сложная, то должно +100500 кнопок и пунктов меню и всё должно быть похоже на пульт управления звездолётом.
Но Дракон, написанный с помощью Tool Command Language (Tcl) и графической библиотеки Tk, производил, мягко говоря, аскетичный вид. По первости я лишь недоумённо разводил руками и выдавал нечленораздельное мычание - э-э-э, что это? Снова перечитал статьи в Интернете и, навсякий случай, поискал мнение англоязычного населения планеты. Просто опасался, что это может оказаться детищем очередного Дениски Попова, аля Болгенос! Будучи админом, давно умер как программист, поэтому решил, что не мне судить программы. Привлекло, что это 1) русский проект и 2) используется язык/тулкит Tcl/Tk, с которыми до этого времени не сталкивался. Ок, подумал, давай сделаем это!
Сборочный сервак обзавёлся новой пустой папкой и прототипом snapcraft.yaml. На сайте разработчиков drakon.su для Drakon Editor'а указаны нужные пакеты для Ubuntu - tcl8.5, tk8.5, tcllib, libsqlite3-tcl, libtk-img. Заносим их всех в stage-packages кусочка integration. Правлю свой уже вылизанный скрипт-обёртку run.sh под нужды Дракона и пробую первую итерацию по сборке. Уже было понятно сразу, что закончится всё печально. Первый блин в мире снапкрафтинга всегда комом! Так как сборка программы в snap пакет довольно таки ресурсоёмкий и времязатратный процесс, то делаю ход конём, который всегда выручал при анализе программы. Программу располагаю на своём ПК в /opt/drakon/ с владельцем root:root (имитация будущего пути $SNAP с доступом только-чтение), ставлю нужные пакеты в свою систему и пытаюсь добиться работоспособности программы. Программа стартует и работает нормально. Конечно нормально! Tcl/Tk лежат со своими модулями там где нужно, а внутри snap пакета они будут лежать по своим путям, сдвинутые относительно хост системы на величину $SNAP. Чтобы в своей системе без утомительной сборки добиться работы Дракона, просто нашёл все папки tcltk и переименовал в tcltk_, имитируя изменение пути в будущем пакете снап. Программа предсказуемо "сломалась". Теперь осталось дело за малым . Нужно запустить Дракона, указав каким-либо способом (желательно самым простым и элегантным), где лежат нужные вещи у Tcl/Tk.
Самые главные помощники - это переменные окружения (environment variables). Чтение документации знакомит с переменными TCL_LIBRARY, TK_LIBRARY, TCLLIBPATH. Их говорящие названия обнадёживают. Пробуем!? В запускающем скрипте переопределяем пути с помощью данных переменных.
#!/bin/bash export TCL_LIBRARY="/usr/share/tcltk_/tcl8.6" export TK_LIBRARY="/usr/share/tcltk_/tk8.6" /opt/drakon/drakon_editor.tcl
Программа упорно пишет что не видит нужные ей snit, Tk, msgcat, Img. Добавил всё что можно и не можно в переменную TCLLIBPATH, но толку ноль. К этому времени начитался чуток про Tcl/Tk и понял, что нужно пока отстать от программы Дракон и сосредоточиться на оболочке tclsh. Если её запуск и команды внутри неё типа
package require msgcat package require Tk package require snit
перестанут вызывать ошибку и начнут показывать номер версии пакета, тогда и Дракон заработает. msgcat с расширением tm обнаружил в моём правленом пути /usr/share/tcltk_/tcl8.6/tcl8/, а в родительской папке /usr/share/tcltk_/tcl8.6/ нашёл файл tm.tcl со строкой, которая всегда наводит уныние.
variable paths {/usr/share/tcltk/tcl8.6/tcl8}
Вечно эти жёстковшитые пути! Твоютоматьдивизию! Прочитал tm.tcl целиком и набрёл на кусок кода
foreach ev [::list \ TCL${major}.${n}_TM_PATH \
EV - это скорее всего Environment Variables. А TCL${major}.${n}_TM_PATH это переменная, которая зависит от версии языка и тулкита Tcl/Tk. В данный момент доступна версия 8.6, поэтому tcl ждёт от меня переменной TCL8.6_TM_PATH="/usr/share/tcltk_/tcl8.6/tcl8/", которая может переопределить дефолтный путь. Ринулся было указывать export TCL8.6_TM_PATH, но bash мне выдал что точку нельзя использовать в имени-идентификаторе переменной. Разрабы Tcl/Tk, ну как так-то? Ну что вам стоило ожидать переменную TCL_8_6_TM_PATH или TCL86TM_PATH?! Нашёл обходной манёвр. Запуск tclsh нужно делать так
#!/bin/bash export TCL_LIBRARY="/usr/share/tcltk_/tcl8.6" export TK_LIBRARY="/usr/share/tcltk_/tk8.6" env "TCL8.6_TM_PATH=/usr/share/tcltk_/tcl8.6/tcl8" tclsh
Бинго! Теперь можно было узнать версии нужных модулей через tclsh и package require, кроме Tk. Но Tk - это не пакет Tcl, а отдельная сущность в лице графического тулкита. Мысль работала так. Где-то есть файл, в котором указан путь, как он был до моего грубого переименования. Файл нашёлся по пути /usr/lib/tcltk_/x86_64-linux-gnu/tk8.6/pkgIndex.tcl, в котором опять эти жёстковшитые пути.
if {[catch {package present Tcl 8.6.0}]} return package ifneeded Tk 8.6.6 [list load [file normalize [file join /usr/lib/x86_64-linux-gnu libtk8.6.so]] Tk]
Формируется путь /usr/lib/x86_64-linux-gnu/libtk8.6.so и нет в этой паре строк возможности это как-то переопределить. Да что это такое!? Особенно стало обидно, что рядом находятся папки с sqlite и Img, чьи pkgIndex.tcl используют относительные пути и легко подключают нужные библиотеки .so в этой же папке. И только Tk хочет загрузить свою библиотеку через указание абсолютного адреса.
В такие моменты, когда видишь hardcoded path, то понимаешь что стройность и элегантность сейчас рухнет и придётся делать костыль для обходного манёвра. Не владею Tcl/Tk, но придётся править код. По аналогии с PkgIndex.tcl у sqlite, изменил в /usr/lib/tcltk_/x86_64-linux-gnu/tk8.6/pkgIndex.tcl строки на
if {[catch {package present Tcl 8.6.0}]} return package ifneeded Tk 8.6.5 [list load [file normalize [file join $dir libtk8.6.so]] Tk]
Но рядом с PkgIndex.tcl нет libtk8.6.so! Сделал ссылку libtk8.6.so -> ../../../x86_64-linux-gnu/libtk8.6.so
Всё заработало! tclsh и Дракон не ругаются и работают исправно. Ну а теперь нужно костыль как-то внедрить в сборочный процесс. Красоты уже не будет, но выхода нет. В snapcraft.yaml в кусочек project-files, который занимается размещением нужного, добавляем важные строки.
project-files: plugin: copy files: run.sh : usr/bin/run.sh files/* : / libtk8.6.so : usr/lib/tcltk/x86_64-linux-gnu/tk8.6/libtk8.6.so after: [integration]
Строка after: [integration] попросит сначала обработать кусочек integration и сначала будут распакованы нужные пакеты из раздела stage-packages и автоматически создадутся нужные пути. Символическую ссылку libtk8.6.so прошу разместить внутри снап пакета по адресу usr/lib/tcltk/x86_64-linux-gnu/tk8.6/libtk8.6.so
Snapcraft не обладает функционалом править какие-либо не ваши файлы, которые он разместил по вашему приказу из пакетов, перечисленных в stage-packages. Теперь собирать итоговый пакет snap придётся так. Сначала сделать этап Prime и подкинуть правленную версию файла, чтобы snapcraft "не заметил". Затем уже попросить итоговый этап упаковки по имени snap.
snapcraft prime
cp -f pkgIndex.tcl prime/usr/lib/tcltk/x86_64-linux-gnu/tk8.6/
snapcraft snap
Не успел залить протестированный snap пакет Дракона в Ubuntu Store, как глазастый разработчик Майкл Холл в Гугл+ уже пишет о нём. Действительно, множество программ никогда не были представлены в официальных репозиториях и доступны пользователями для установки "в один щелчок". Через GUI в Software или в Терминале - sudo snap install drakon
Теперь если вам нужно накидать алгоритм для любого случая жизни, то вспомните про Дракошу и порекомендуйте друзьям.
Первый snap пакет. Java программа LanguageTool. sudo snap install languagetool
Второй 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. sudo snap install pac-vs