OCaml Policy: различия между версиями

Материал из ALT Linux Wiki
(Import from freesource.info)
 
(+DraftPolicy)
Строка 1: Строка 1:
[[Category:Policy]]
{{MovedFromFreesourceInfo|AltLinux/Policy/OCaml}}
{{MovedFromFreesourceInfo|AltLinux/Policy/OCaml}}
{{DraftPolicy
|responsible=...
}}


(По мотивам [http://lists.altlinux.org/pipermail/devel/2006-December/052422.html письма] bga@ в devel@)
(По мотивам [http://lists.altlinux.org/pipermail/devel/2006-December/052422.html письма] bga@ в devel@)
Строка 16: Строка 18:
кода и нативные. Например:
кода и нативные. Например:


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


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


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


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


Байт-код можно отличить по заголовку "#!/usr/bin/ocamlrun" в первой
Байт-код можно отличить по заголовку «#!/usr/bin/ocamlrun» в первой
строке, за которой следуют двоичные данные. Существует вариант линковки,
строке, за которой следуют двоичные данные. Существует вариант линковки,
когда интерпретатор байт-кода (ocamlrun) внедряется в конечную программу
когда интерпретатор байт-кода (ocamlrun) внедряется в конечную программу
Строка 39: Строка 41:
Во втором случае кросс-платформенность программы неочевидна:
Во втором случае кросс-платформенность программы неочевидна:
с одной стороны, она не выполнится на посторонней архитектуре,
с одной стороны, она не выполнится на посторонней архитектуре,
с другой - можно выполнить содержащийся в ней байт-код с помощью
с другой — можно выполнить содержащийся в ней байт-код с помощью
нативной версии ocamlrun: "ocamlrun ./progname --args".
нативной версии ocamlrun: «ocamlrun ./progname --args».


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


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


Строка 67: Строка 69:


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


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


Строка 103: Строка 105:
Requires: %{get_dep ocaml}
Requires: %{get_dep ocaml}


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


Строка 115: Строка 117:
влияет версия. Например, упомянутый мной camlp4 3.09.3 не стал работать
влияет версия. Например, упомянутый мной camlp4 3.09.3 не стал работать
с синтаксическими расширениями pa_*.cmo от 3.08.0 по причине
с синтаксическими расширениями pa_*.cmo от 3.08.0 по причине
"interface mismatch on Grammar".
«interface mismatch on Grammar».


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


Строка 128: Строка 130:
а нативные ни от чего не зависят =).
а нативные ни от чего не зависят =).


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


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

Версия от 18:27, 19 сентября 2008

Freesource-logo.png Blue Glass Arrow.svg MediaWiki logo.png
Эта страница была перемещена с freesource.info.
Эта страница наверняка требует чистки и улучшения — смело правьте разметку и ссылки.
Просьба по окончанию убрать этот шаблон со страницы.
Stub.png
Черновик политики Sisyphus
Автор(ы) — ...


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

TODO: дополнить использованием макросов из rpm-build-ocaml

Ликбез

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 и т. д. Непоследовательно.

Бинарная несовместимость

После выпуска 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.