OCaml Policy: различия между версиями
(Import from freesource.info) |
(+DraftPolicy) |
||
Строка 1: | Строка 1: | ||
{{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 — нативный компилятор в байт-код | ||
ocamlopt — байт-кодный компилятор в нативный код | |||
ocamlopt. | ocamlopt.opt — нативный компилятор в нативный код | ||
(Примечание: в наших пакетах ocamlc и ocamlopt обычно являются | (Примечание: в наших пакетах ocamlc и ocamlopt обычно являются | ||
символическими ссылками на ocamlc.opt и ocamlopt.opt соответственно.) | символическими ссылками на ocamlc.opt и ocamlopt.opt соответственно.) | ||
Байт-код существует для большей переносимости, | Байт-код существует для большей переносимости, то есть предполагается, | ||
что байт-код одинаково выполняется на любой архитектуре, где существует | что байт-код одинаково выполняется на любой архитектуре, где существует | ||
интерпретатор байт- | интерпретатор байт-кода — ocamlrun (он бывает только нативный). | ||
С другой стороны, от нативного кода ожидается бОльшая производительность. | С другой стороны, от нативного кода ожидается бОльшая производительность. | ||
Байт-код можно отличить по заголовку | Байт-код можно отличить по заголовку «#!/usr/bin/ocamlrun» в первой | ||
строке, за которой следуют двоичные данные. Существует вариант линковки, | строке, за которой следуют двоичные данные. Существует вариант линковки, | ||
когда интерпретатор байт-кода (ocamlrun) внедряется в конечную программу | когда интерпретатор байт-кода (ocamlrun) внедряется в конечную программу | ||
Строка 39: | Строка 41: | ||
Во втором случае кросс-платформенность программы неочевидна: | Во втором случае кросс-платформенность программы неочевидна: | ||
с одной стороны, она не выполнится на посторонней архитектуре, | с одной стороны, она не выполнится на посторонней архитектуре, | ||
с | с другой — можно выполнить содержащийся в ней байт-код с помощью | ||
нативной версии ocamlrun: | нативной версии ocamlrun: «ocamlrun ./progname --args». | ||
Существуют следующие типы (расширения) файлов: | Существуют следующие типы (расширения) файлов: | ||
. | .ml — исходные тексты | ||
. | .mli — описания интерфейсов | ||
. | .cmi — скомпилированные описания интерфейсов | ||
. | .cmo — скомпилированные в байт-код исходные тексты | ||
. | .cma — собранный в библиотеку байт-код | ||
. | .cmx — скомпилированные нативно исходные тексты | ||
. | .cmxa — собранный в библиотеку нативный код | ||
. | .o — скомпилированный нативный код (ELF) | ||
. | .a — статическая библиотека из этих ELF-ов | ||
Исполняемый байт-код получается сборкой всех .cma и .cmo, нативный - | Исполняемый байт-код получается сборкой всех .cma и .cmo, нативный - | ||
сборкой всех .cmxa и .cmx. При этом для каждого .cmxa должен иметься | сборкой всех .cmxa и .cmx. При этом для каждого .cmxa должен иметься | ||
одноимённый .a, а для . | одноимённый .a, а для .cmx — .o (они так и генерируются компилятором | ||
попарно.) | попарно.) | ||
Строка 67: | Строка 69: | ||
Сейчас в наших пакетах одни только нативные версии ocamlc и ocamlopt, но | Сейчас в наших пакетах одни только нативные версии ocamlc и ocamlopt, но | ||
есть и байт-кодные, и нативные ocamldoc, camlp4r | есть и байт-кодные, и нативные ocamldoc, camlp4r и т. д. Непоследовательно. | ||
== Бинарная несовместимость == | == Бинарная несовместимость == | ||
Строка 91: | Строка 93: | ||
платформенности байт-кода, да и вообще его сути. Но можно предположить, | платформенности байт-кода, да и вообще его сути. Но можно предположить, | ||
что в рамках одной версии компилятора и интерпретатора байт-код кросс- | что в рамках одной версии компилятора и интерпретатора байт-код кросс- | ||
платформен, а в | платформен, а в разных — нет. Впрочем, 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». | |||
Все .cmi, .cmo, .cma, .cmxa должны линковаться тем же компилятором, что | Все .cmi, .cmo, .cma, .cmxa должны линковаться тем же компилятором, что | ||
и сами были порождены. Таким образом, на бинарные библиотеки накладывается | и сами были порождены. Таким образом, на бинарные библиотеки накладывается | ||
зависимость Requires: ocaml = <версия>, где <версия> определяется в момент | зависимость Requires: ocaml = <версия>, где <версия> определяется в момент | ||
сборки. Третий, зависимый по | сборки. Третий, зависимый по «[[BuildRequires|BuildRequires]]: libname» пакет при сборке | ||
вытянет именно эту <версию>. | вытянет именно эту <версию>. | ||
Строка 128: | Строка 130: | ||
а нативные ни от чего не зависят =). | а нативные ни от чего не зависят =). | ||
При сборке ранее указывалось | При сборке ранее указывалось «[[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. |
Версия от 21:27, 19 сентября 2008
(По мотивам письма bga@ в devel@) Складывается ощущение, что после Виталия Луговского у нас не было серьёзных знатоков OCaml =). Давайте соберём хотя бы отрывочные знания и, возможно, сформируем некое policy.
Ликбез
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.