it-history
June 20, 2023

Забытые технологии прошлого: Tclkit, Starkit и Starpack

Снова обучаю плохому: как у «дидов» совсем недавно получалось делать быстрый портабельный софт, работающий везде, с UI, с сетевым стеком и без кучи внешних библиотек.

Возможно данная статья заставит задуматься о вечном — что на Java/C#, «typescript hydration» и микросервисах ПО не заканчивается. А крутых результатов можно достичь и без вездесущего докера.

Все такое красивое, в стиле начала 90х.

Вступление

На текущем этапе ИТ-эволюции, существенная часть софта завязана на интернет и работу онлайн, настолько существенная что даже вы, читатель, практически 100% занимаетесь именно таким ПО, если конечно имеете отношение к ИТ.

Так вот, когда бОльшая часть времени запуска программы тратится на установление связи с сервером и передачу обновлений (и контролировать это фактически нельзя) — все рассуждения о скорости можно считать юмористическими:

You’re offline — так шутит Youtube при медленной скорости подключения

Но были и другие времена, когда скорость подключения не измерялась мегабитами, а память — гигабайтами. Да и сейчас, вне сферы «социальных погремушек для вечных детей из больших городов» ИТ не сильно поменялось:

если надо создать софт для пожарных, полярников или военных, который должен работать в экстремальных условиях при ограниченных ресурсах — вы все также будете упрощать и считать байты.

И алгоритмы внезапно понадобятся, вместе со структурами данных — зуб даю. Вообщем несмотря на название, статья про полезное и важное.

Проблема портируемости

Допустим, вы создали некую программу. Технически и фактически это калькулятор, но очень сложный и дюже специфичный:

считает по сложной формуле траекторию полета очередной летающей «Кузькиной матери» или расчитывает усталость металла и возможность разрушения конструкции.

Оператор (в погонах или в каске и ватнике) вводит показатели, нажимает кнопку «расчитать» и получает результат — цифры, картинку-симуляцию и графики, на которых в зелено-красных тонах показывается «степерь п#здеца» на объекте.

Кто учился в 80е-90е на «погромиста» — наверняка сдавали курсовые работы с похожим содержанием.

Тестировать такую софтвину сложно, долго и дорого — из-за сложных расчетных алгоритмов внутри банально некому подтвердить правильность (не дергать же академиков на каждый баг).

Это кстати главная причина по которой до сих пор живут на свете динозавры вроде Fortran.

Сборка же часто происходит в ручном режиме, с чего стабильность выходного бинарника не гарантирована.

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

Вплоть до полной смены окружения — от DOS до Windows 11 или с переходом на Linux, как это часто бывало с подобным софтом.

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

Комбинация

Вот тут на сцену и выходит TCL с его особенностями.

Во-первых это интерпритатор «команд», не компилятор. Тут нет виртуальной машины, нет байткода, но нет и ручного управления памятью, как в Си.

Во-вторых он очень хорошо портируется и встраивается, с минимальными зависимостями от окружения.

В третьих тут есть нормальная обработка ошибок:

if {[catch {open $someFile w} fid]} {
    puts stderr "Could not open $someFile for writing\n$fid"
    exit 1
}

В четвертых — размер.

Оно реально маленькое и компактное: ~4Мб на платформу. Это не Java/.NET где уже по 300Мб только инсталляторы.

Получается идеальная платформа для максимальной долгой поддержки.

Tclkit

Начну с цитаты:

A Tclkit is a single executable file that contains a Tcl interpreter and the startup scripts and support libraries needed to access a starkit bundled together with the Tclkit into a a starpack. A Tclkit can also be also be used as a tclsh workalike.

Вообщем tclkit это такая специальная сборка TCL в единый запускабельный бинарник, с добавлением нескольких ключевых библиотек (вроде MetaKit).

Но это еще не все.

Starkit — это специальная сборка клиентского (т.е вашего) софта, также в единый пакет, подготовленный для запуска через Tclkit.

Starpack — сборка в единый бинарник Tclkit + Starkit, то есть все целиком от среды Tcl с интерпретатором и до вашего приложения упаковывается в один запускаемый файл.

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

Описание:

Displays 3d polyhedra in shaded or wireframe mode, using only the Tk canvas. In the words of one Tcler - "This is without a shadow of doubt, the best piece of software I have ever seen/used ... you've got useful 3D, in a script language, on a Tk canvas, in a few A4 pages of code. Unbelievable!"

На нынешние времена наверное уже врядли впечатлит, особенно если не знать что такое «software rendering», но даст определенное представление.

Вот еще один интересный пример:

Michael McLennan's "Effective Tcl/Tk" demo.

Это набор примеров из книги по Tcl/Tk. Книга кстати интересная, рекомендую.

Вообщем надеюсь какое-то понимание что такое Tclkit сложилось, теперь расскажу как все это собирать в 21м веке.

И начну с самого сложного — со сборки самого Tclkit с нуля.

Делать это необязательно, поскольку готовые сборки под разнообразные платформы доступны и регулярно выкладываются.

Оригинальная система сборки tclkit была выложена на github, но уже какое-то время заброшена и не обновляется.

Поэтому будем использовать более актуальную на 2023й год, под названием KitCreator.

Ради большей хардкорности буду весь процесс производить на FreeBSD, которая официально (как обычно) не поддерживается.

Забираем исходники:

git clone https://github.com/rkeene/KitCreator.git

Актуальная версия находится в «master» ветке.

Ставим пакеты:

pkg install automake tcl86 tk86 bash gmake

bash нужен поскольку система сборки расчитана на запуск из bash:

#! /usr/bin/env bash

На FreeBSD почему-то не создается линк на интерпретатор TCL без номера версии (tclsh), который используется из скриптов сборки.

Поэтому нужно сделать «soft link» вручную:

ln -s /usr/local/bin/tclsh8.6 /usr/local/bin/tclsh

Также специфика FreeBSD в виде своей версии make, «стандартная» линуксовая при этом называется gmake.

Поскольку система сборки в основном написана под Linux и Windows, make также ожидается от GNU, поэтому нужно задать переменную окружения перед запуском:

export MAKE=gmake

После этого запускаем сборку:

./kitcreator 

Если все пройдет успешно, то лог работы будет выглядеть вот так:

Building tcl ... done.
Building tclvfs ... done.
Building zlib ... done.
Building tk ... done.
Building itcl ... done.
Building mk4tcl ... done.
Building kitsh ... done.

После успешной сборки в корне будет готовый бинарник:

Которым уже можно запускать готовые старкиты.

Сам tclkit также является запускаемым и без указания старкита открывает интерактивный шелл Tcl:

Starkit и starpack

То что было выше — про системную часть, теперь расскажу про прикладную.

По хорошему нужно было собрать собственный starkit в качестве примера, но нашел один интересный проект, на примере которого можно показать эту замечательную технологию.

SSG

Есть на свете относительно новая технология для ваяния статичных сайтов — Static Site Generator (SSG).

Смысл ее в том что весь сайт целиком генерируется оффлайн, по набору динамических шаблонов, затем готовые статичные файлы в виде набора html, js и css заливаются на хостинг.

Получается своего рода оффлайн CMS — идеальная штука для всяких технических блогов и сайтов визиток.

Самым известной реализацией является Jekyll.

Tclssg

Была найдена реализация SSG на TCL, использующая технологию Starpack:

https://github.com/tclssg/tclssg

На примере этого проекта я покажу как собирать старкиты.

Результат работы tclssg выглядит вот так:

Итак, сборка.

За сборку старкита для tclssg отвечает отдельный проект на github, поэтому скачиваем именно его а не сам tclssg:

git clone https://github.com/tclssg/tclssg.git

В этом проекте сразу в корне находятся все tclkit, используемые для генерации готовых бинарников starpack:

Нужно скопировать сюда сборку tclkit для FreeBSD из предыдущего шага и добавить в скрипт сборки (build.tcl) строчку:

 freebsd         tclkit-8.6.12

Чтобы получилось вот так:

set tclkits [::packer::sl {
    macosx          tclkit-8.6.3-macosx10.5-ix86+x86_64
    linux-ix86      tclkit-8.6.3-rhel5-ix86
    linux-x86_64    tclkit-8.6.3-rhel5-x86_64
    win32           tclkit-8.6.3-win32.exe
    freebsd         tclkit-8.6.12
}]

Дальше запускаем сборку вызвав make:

Если все сделали правильно, будет отображение генерации starpack для указанного tclkit под FreeBSD — подчеркнутые красным строки выше.

А в каталоге artifacts будут готовые бинарники, в том числе под FreeBSD (самый первый):

Вообщем этот проект можно использовать как шаблон для сборки собственных старкитов и бинарников.

Тестовый шаблон Tclssg

Теперь еще немного расскажу про сам tclssg, коль уж собрали (на свою голову).

Заходим в artifacts и запускаем:

cd ./artifacts
./tclssg-master-c40c2d8ce3-tclkit-8.6.12 init

Эта команда создаст папку website с шаблоном сайта по-умолчанию.

Затем выполняем:

./tclssg-master-c40c2d8ce3-tclkit-8.6.12 build --local

Получим готовые статичные страницы в каталоге website/output.

Для разработки можно запустить:

./tclssg-master-c40c2d8ce3-tclkit-8.6.12 serve --browse

Запустится локальный http-сервер на порту 8080, с динамической генерацией статики при изменении файлов шаблона — т. н. «hot reload».

При наличии параметра --browse откроется браузер по-умолчанию на стартовой странице локального http-сервера.

Выглядит как-то так: