Итак, вы написали некое приложение на 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.