Итак, вы написали некое приложение на Limbo, и хотите установить его на другую машину, или распространять через интернет. Скорее всего, там где будет устанавливаться это приложение OS Inferno не установлена. Это горько, но более чем вероятно. :) Что же делать? Обучать пользователей вашего приложения устанавливать и настраивать у себя OS Inferno? Включать полную инсталляцию Inferno (до 250 MB) в архив с каждым вашим приложением? Нет, всё гораздо проще!
Давайте посмотрим, как можно урезать Inferno до минимума, необходимого для работы вашего приложения. Для этого надо разобраться, что происходит при запуске
Бинарник
Загрузившись,
Это всё. :) Таким образом, для получения standalone инсталляции OS Inferno с вашим приложением необходимо и достаточно следующих файлов и каталогов:
Начнём с простого приложения, без каких либо зависимостей. Вот такого:
Сохраните его в
Теперь давайте определим зависимости:
У
Итак, у нас есть standalone инсталляция helloworld, готовая к работе на любой системе с Linux (для других OS нужно просто взять emu скомпилированный для этих OS). Давайте посмотрим, сколько она «весит». (Кстати,
Теперь давайте возьмём нормальное приложение. Например, калькулятор, входящий в стандартные утилиты Inferno. Он достаточно навороченный, кстати.
Да, есть такой момент. Чтобы запустить emu на другой машине там должны быть все необходимые emu библиотеки. К счастью, библиотек всего две. К сожалению, обе относятся к X — это libX11 и libXext.
В принципе, эти библиотеки отлично ставятся без необходимости тащить полностью Xorg. Вот что пришлось бы установить на сервере с Gentoo Linux:
Но для работы на сервере сетевого приложения (у которого GUI нет) эти библиотеки абсолютно не нужны. Ведь даже отлаживать это приложение в графическом отладчике я могу на своей рабочей станции, просто подмонтировав каталог
Чтобы собрать
После этого вы сможете запускать
P.S. Каталог inferno-strandalone в .tgz у меня занял 666KB. :-)
Update: добавлена информация об emu-g.
Давайте посмотрим, как можно урезать 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/
с сервера, где запущено приложение. Для решения этой проблемы можно использовать специальную версию emu
— emu-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.