[devel] OCaml packaging

Grigory Batalov =?iso-8859-1?q?bga_=CE=C1_altlinux=2Eorg?=
Сб Дек 23 12:11:04 MSK 2006


Здравствуйте!

Складывается ощущение, что после Виталия Луговского у нас не было серьёзных
знатоков OCaml =). Давайте соберём хотя бы отрывочные знания и, возможно,
сформируем некое policy.

1. Ликбез.
----------

Objective Caml (http://caml.inria.fr/ocaml/index.en.html) - функциональный
язык с элементами императивного стиля. Компиляторы OCaml могут создавать
байт-код и нативный код, и сами, в свою очередь, имеются в вариантах байт-
кода и нативные. Например:

ocamlc       - байт-кодный компилятор в байт-код
ocamlc.opt   - нативный компилятор в байт-код
ocamlopt     - байт-кодный компилятор в нативный код
ocamlopt.opt - нативный компилятор в нативный код

(Примечание: в наших пакетах ocamlc и ocamlopt обычно являются
 символическими ссылками на ocamlc.opt и ocamlopt.opt соответственно.)

Байт-код существует для большей переносимости, т.е. предполагается,
что байт-код одинаково выполняется на любой архитектуре, где существует
интерпретатор байт-кода - ocamlrun (он бывает только нативный).

С другой стороны, от нативного кода ожидается бОльшая производительность.

Байт-код можно отличить по заголовку "#!/usr/bin/ocamlrun" в первой
строке, за которой следуют двоичные данные. Существует вариант линковки,
когда интерпретатор байт-кода (ocamlrun) внедряется в конечную программу
и его самостоятельная копия для запуска уже не требуется. Такая программа
выглядит как обычный исполняемый файл, но командой strip можно отсечь
от него байт-код, после чего останется уже знакомый нам ocamlrun =).

Во втором случае кросс-платформенность программы неочевидна:
с одной стороны, она не выполнится на посторонней архитектуре,
с другой - можно выполнить содержащийся в ней байт-код с помощью
нативной версии ocamlrun: "ocamlrun ./progname --args".

Существуют следующие типы (расширения) файлов:
.ml   - исходные тексты
.mli  - описания интерфейсов
.cmi  - скомпилированные описания интерфейсов
.cmo  - скомпилированные в байт-код исходные тексты
.cma  - собранный в библиотеку байт-код
.cmx  - скомпилированные нативно исходные тексты
.cmxa - собранный в библиотеку нативный код
.o    - скомпилированный нативный код (ELF)
.a    - статическая библиотека из этих ELF-ов

Исполняемый байт-код получается сборкой всех .cma и .cmo, нативный -
сборкой всех .cmxa и .cmx. При этом для каждого .cmxa должен иметься
одноимённый .a, а для .cmx - .o (они так и генерируются компилятором
попарно.)

Проблема 1.
-----------
Раз существует архитектуро-независимый байт-код, неплохо бы его помещать
в noarch-пакеты. Однако, из одного spec-файла rpm собирает пакеты только
какой-нибудь одной архитектуры, так что, выделив байт-код в отдельный
пакет, мы всё равно назовём его i586 или x86_64. Раз так, стоит ли вообще
его выделять? Не лучше ли собирать всё нативно?

Сейчас в наших пакетах одни только нативные версии ocamlc и ocamlopt, но
есть и байт-кодные, и нативные ocamldoc, camlp4r и т.д. Непоследовательно.

2. Бинарная несовместимость.
----------------------------
После выпуска 3.08.3 в рассылке Debian возникли вопросы, а существует ли
бинарная совместимость между разными версиями OCaml?
http://lists.debian.org/debian-ocaml-maint/2005/01/msg00042.html

Оказалось, что даже между 3.08.2 и 3.08.3 её может не быть. Причины
тому (по мнению Jacques Garrigue) изложены в этой ветке:
http://lists.debian.org/debian-ocaml-maint/2005/01/msg00050.html

А вот здесь признание Xavier Leroy (одного из разработчиков OCaml) в том,
что бинарная совместимость никогда не входила в их планы =) :
http://lists.debian.org/debian-ocaml-maint/2005/01/msg00056.html

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

Примечание: Казалось бы, эта несовместимость противоречит кросс-
платформенности байт-кода, да и вообще его сути. Но можно предположить,
что в рамках одной версии компилятора и интерпретатора байт-код кросс-
платформен, а в разных - нет. Впрочем, camlp4, собранный как байт-код
на x86_64 компилятором 3.09.3 отлично запустился на i586 c интерпретатором
3.08.0 =). Вопрос в том, будем ли мы надеяться на удачу и ждать, не наступит
ли кто на грабли? Мне кажется, пока нет чёткого заключения "наш байт-код
не зависит от версии интерпретатора", лучше жёстко закрепить версию. Если
такое заключение всё же было, а я пропустил, пожалуйста, укажите.

Проблема 2.
-----------
В свежих spec-файлах стала появляться зависимость
Requires: %{get_dep ocaml}

что, вообще говоря, неверно, т.к. порождает
Requires: ocaml >= 3.09.1

или вроде того. См. выше про несовместимость. Лучше было указывать
Requires: ocaml = %{get_SVR ocaml}

что порождает
Requires: ocaml = 3.09.1-alt1

Кроме того, нужно разобраться, для чего нужны зависимости, и на что
влияет версия. Например, упомянутый мной camlp4 3.09.3 не стал работать
с синтаксическими расширениями pa_*.cmo от 3.08.0 по причине
"interface mismatch on Grammar".

Все .cmi, .cmo, .cma, .cmxa должны линковаться тем же компилятором, что
и сами были порождены. Таким образом, на бинарные библиотеки накладывается
зависимость Requires: ocaml = <версия>, где <версия> определяется в момент
сборки. Третий, зависимый по "BuildRequires: libname" пакет при сборке
вытянет именно эту <версию>.

Байт-кодные программы должны зависеть по
Requires: ocaml-runtime = <версия>

а нативные ни от чего не зависят =).

При сборке ранее указывалось "BuildRequires: ocaml = <версия>". Я считаю,
что достаточно "BuildRequires: ocaml", а <версия> определится с помощью
%{get_SVR ocaml}. Это позволит при выходе нового OCaml пересобирать
зависимые пакеты роботу.

Итого, от мэйнтейнера требуется собрать по spec-файлу бинарные пакеты
и внимательно их рассмотреть: есть исполняемый байткод внутри - проставить
зависимость на ocaml-runtime = <версия>, есть .cmo/.cmi/.cmx/.cma/.cmxa -
проставить зависимость на ocaml = <версия>. В пакеты libname-runtime стоит
класть только библиотеки, необходимые для запуска использующего их байт-
кода. Обычно это %_libdir/ocaml/stublibs/dll*.so. Все прочие, "не необ-
ходимые" файлы пусть остаются в libname.

К счастью, у нас немного программ на OCaml, так что проверить и пере-
собрать их возможно одному человеку:

bibtex2html-1.54-alt1.src.rpm
camltemplate-0.9.1-alt1.src.rpm
coq-8.0pl3-alt1.src.rpm
ecasound-2.4.4-alt1.src.rpm
fftw3-3.0.1-alt0.7.src.rpm
findlib-1.1.2pl1-alt2.src.rpm
hevea-1.07-alt2.src.rpm
lablGL-1.01-alt3.src.rpm
lablgtk2-2.6.0-alt2.src.rpm
libcamlimages-2.2.0-alt4.src.rpm
libocamlsdl-0.7.2-alt3.src.rpm
mldonkey-2.8.0-alt1.src.rpm
ocamldsort-0.12-alt3.1.src.rpm
ocaml-ulex-0.9-alt1.src.rpm
pcre-ocaml-5.09.0-alt3.src.rpm
SpamOracle-1.2-alt2.src.rpm
swig-1.3.29-alt1.src.rpm
wyrd-1.1.1-alt1.src.rpm

(и ещё несколько в orphaned). Я этим занимаюсь.

Остаётся вопрос из "Проблемы 1": как паковать и паковать ли исполняемый
байт-код? Ну и вообще, что думает сообщество о предложенном материале?

Доплнительная информация: как пакуют OCaml в Debian
http://pkg-ocaml-maint.alioth.debian.org/ocaml_packaging_policy.html/index.html

-- 
 Grigory Batalov,
 ALT Linux Team
----------- следующая часть -----------
Было удалено вложение не в текстовом формате...
Имя     : =?iso-8859-1?q?=CF=D4=D3=D5=D4=D3=D4=D7=D5=C5=D4?=
Тип     : application/pgp-signature
Размер  : 189 байтов
Описание: =?iso-8859-1?q?=CF=D4=D3=D5=D4=D3=D4=D7=D5=C5=D4?=
Url     : <http://lists.altlinux.org/pipermail/devel/attachments/20061223/8f8d9e83/attachment-0001.bin>


Подробная информация о списке рассылки Devel