Как стать автором
Обновить

Подготовка ваших приложений Inferno к standalone установке

Время на прочтение 4 мин
Количество просмотров 2.5K
Итак, вы написали некое приложение на Limbo, и хотите установить его на другую машину, или распространять через интернет. Скорее всего, там где будет устанавливаться это приложение OS Inferno не установлена. Это горько, но более чем вероятно. :) Что же делать? Обучать пользователей вашего приложения устанавливать и настраивать у себя OS Inferno? Включать полную инсталляцию Inferno (до 250 MB) в архив с каждым вашим приложением? Нет, всё гораздо проще!

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

Загрузка OS Inferno


Бинарник emu уже содержит в себе ядро OS, все драйвера, и виртуальную машину Dis. Когда он запускается, ему необходимо параметром -r передать корневой каталог OS Inferno (сам emu при этом не обязан находится внутри этого каталога, так что можно использовать один emu с несколькими разными инсталляциями OS Inferno — отличающимися установленными приложениями и библиотеками).

Загрузившись, emu просто запускает /dis/emuinit.dis (все пути указаны относительно корневого каталога OS Inferno), который должен проинициализировать систему и запустить либо переданное параметром emu приложение либо шелл. (То же самое делает ядро Linux, когда, загрузившись само, просто передаёт управление на /sbin/init.) Если изучить исходники emuinit выясняется, что «проинициализировать систему» — это очень громко сказано, в Inferno всё делается очень просто, даже по сравнению с максимально упрощённой инициализацией Linux.

Это всё. :) Таким образом, для получения standalone инсталляции OS Inferno с вашим приложением необходимо и достаточно следующих файлов и каталогов:
  • Сам emu, находящийся в любом каталоге.
  • Подкаталог dis/ с файлом emuinit.dis.
  • Необходимые emuinit.dis библиотеки (в подкаталоге dis/lib/).
  • Файл(ы) и каталог(и), необходимые вашему приложению.
  • Библиотеки, необходимые вашему приложению (в том же dis/lib/).

Пример: Hello World


Начнём с простого приложения, без каких либо зависимостей. Вот такого:
implement HelloWorld;
include "sys.m";
include "draw.m";

HelloWorld: module
{
    init: fn(nil: ref Draw->Context, nil: list of string);
};

init(nil: ref Draw->Context, nil: list of string)
{
    sys := load Sys Sys->PATH;
    sys->print("Hello World!\n");
}


Сохраните его в helloworld.b, запустите limbo helloworld.b и вы получите helloworld.dis:
; ls -l
--rw-r--r-- U 0 powerman users     265 Oct 25 02:54 helloworld.b
--rw-r--r-- U 0 powerman users     147 Oct 25 02:54 helloworld.dis

Теперь давайте определим зависимости:
; disdep helloworld.dis
; disdep /dis/emuinit.dis
/dis/lib/arg.dis
/dis/sh.dis
/dis/lib/bufio.dis
/dis/lib/env.dis
/dis/lib/readdir.dis
/dis/lib/filepat.dis
/dis/lib/string.dis

У helloworld.dis зависимостей нет, хотя он и использует модуль Sys. Дело в том, что некоторые основные модули написаны на C и встроены прямо в emu, в том числе Sys. У emuinit.dis зависимостей много, но прямых из них только две — arg и sh. Остальное нужно для sh. А сам sh нужен только в том случае, если мы не указали параметром emu приложение, которое нужно сразу запустить. Поэтому мы можем ограничиться одной библиотекой arg. Поехали:
$ mkdir inferno-standalone
$ mkdir inferno-standalone/dis
$ mkdir inferno-standalone/dis/lib
$ cd inferno-standalone/
$ SRC=/usr/local/inferno/
$ cp $SRC/Linux/386/bin/emu ./
$ cp $SRC/dis/emuinit.dis dis/
$ cp $SRC/dis/lib/arg.dis dis/lib/ 
$ cp $SRC/usr/powerman/helloworld.dis ./
$ ./emu -r. helloworld.dis
Hello World!
$

Итак, у нас есть standalone инсталляция helloworld, готовая к работе на любой системе с Linux (для других OS нужно просто взять emu скомпилированный для этих OS). Давайте посмотрим, сколько она «весит». (Кстати, emu под Linux по умолчанию не strip-нут, так что его можно заметно уменьшить.)
$ strip emu
$ find -type f -printf "%8s %p\n"
 1562504 ./emu
     147 ./helloworld.dis
     652 ./dis/lib/arg.dis
    1518 ./dis/emuinit.dis

Пример: калькулятор


Теперь давайте возьмём нормальное приложение. Например, калькулятор, входящий в стандартные утилиты Inferno. Он достаточно навороченный, кстати.
; disdep /dis/calc.dis
/dis/lib/arg.dis
/dis/lib/bufio.dis
/dis/lib/daytime.dis
/dis/lib/string.dis
/dis/lib/rand.dis
$ cp $SRC/dis/calc.dis ./
$ cp $SRC/dis/lib/{bufio,daytime,string,rand}.dis dis/lib/
$ find -type f -printf "%8s %p\n"
   32567 ./calc.dis
 1562504 ./emu
     147 ./helloworld.dis
    4630 ./dis/lib/bufio.dis
     652 ./dis/lib/arg.dis
     209 ./dis/lib/rand.dis
    4051 ./dis/lib/string.dis
    4701 ./dis/lib/daytime.dis
    1518 ./dis/emuinit.dis
$ ./emu -r. calc.dis
1+2
3
exit
$ ./emu -r. calc.dis 1+2
3
$

Погодите, а как же зависимости самого emu?


Да, есть такой момент. Чтобы запустить emu на другой машине там должны быть все необходимые emu библиотеки. К счастью, библиотек всего две. К сожалению, обе относятся к X — это libX11 и libXext.

В принципе, эти библиотеки отлично ставятся без необходимости тащить полностью Xorg. Вот что пришлось бы установить на сервере с Gentoo Linux:
# emerge -pv x11-libs/libX11 x11-libs/libXext

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild  N    ] x11-misc/util-macros-1.1.5  47 kB
[ebuild  N    ] x11-proto/xproto-7.0.10  140 kB
[ebuild  N    ] x11-proto/inputproto-1.4.2.1  47 kB
[ebuild  N    ] x11-proto/kbproto-1.0.3  57 kB
[ebuild  N    ] x11-proto/xf86bigfontproto-1.1.2  37 kB
[ebuild  N    ] x11-libs/xtrans-1.0.3  USE="-debug" 101 kB
[ebuild  N    ] x11-proto/bigreqsproto-1.0.2  36 kB
[ebuild  N    ] x11-proto/xcmiscproto-1.1.2  36 kB
[ebuild  N    ] x11-proto/xextproto-7.0.2  67 kB
[ebuild  N    ] x11-libs/libXau-1.0.3  USE="-debug" 225 kB
[ebuild  N    ] x11-libs/libXdmcp-1.0.2  USE="-debug" 216 kB
[ebuild  N    ] x11-libs/libX11-1.1.4  USE="-debug -ipv6 -xcb" 1,540 kB
[ebuild  N    ] x11-libs/libXext-1.0.3  USE="-debug" 256 kB

Total: 13 packages (13 new), Size of downloads: 2,799 kB

Но для работы на сервере сетевого приложения (у которого GUI нет) эти библиотеки абсолютно не нужны. Ведь даже отлаживать это приложение в графическом отладчике я могу на своей рабочей станции, просто подмонтировав каталог /prog/ с сервера, где запущено приложение. Для решения этой проблемы можно использовать специальную версию emuemu-g, которая собирается и работает без libX11 и libXext.

emu-g

Чтобы собрать emu-g нужно запустить
mk CONF=emu-g install

После этого вы сможете запускать emu-g вместо emu (кстати, emu-g весит после strip-ания всего 700KB):
$ emu-g
; pwd
/usr/powerman
; wm/wm
wm: cannot load $Draw: module not built-in
;


P.S. Каталог inferno-strandalone в .tgz у меня занял 666KB. :-)

Update: добавлена информация об emu-g.
Теги:
Хабы:
+20
Комментарии 35
Комментарии Комментарии 35

Публикации

Истории

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн