LDP/LDP/retired/PLD-Guide/ocaml.xml

318 lines
12 KiB
XML

<section id='ocaml'>
<title>OCaml Packages</title>
<abstract>
<para>
This section describes how to prepare packages which contain
applications written in OCaml, OCaml modules and OCaml language
itself.
</para>
</abstract>
<section id='ocaml.name'>
<title>Naming conventions</title>
<para>
OCaml libraries should have names prefixed with
<literal>ocaml-</literal> (examples: <literal>ocaml-camlp4</literal>,
<literal>ocaml-odbc</literal>). Similarly tools that are only usable
during OCaml development (like <literal>ocaml-otags</literal> or
<literal>ocaml-mlglade</literal>) also should be prefixed with
<literal>ocaml-</literal>.
</para>
<para>
However programs, that have same general use outside OCaml
development shouldn't. For example there is <literal>hevea</literal>
package, not <literal>ocaml-hevea</literal>.
</para>
<para>
Rationale: it should be easy to identify tools usable during
ocaml development just by looking at their name. Also we don't want
to clutter global package namespace (think about
<literal>postgres</literal> package). However information
that hevea is written in ocaml is of little importance to the
end user.
</para>
<para>
Package name should be all in lowercase. There is no
<literal>HeVeA</literal> or any other <literal>WEirD-StUFF</literal>.
Same goes for directory it is installed in. For example for
<literal>ocaml-lablgl</literal> it is
<literal>%{_libdir}/lablgl</literal>, not
<literal>%{_libdir}/lablGL</literal>. Also findlib package names
should be all in lowercase.
</para>
<para>
Rationale: it is hard to remember capitalization of name, when it
needs to be used in compiler flags.
</para>
</section>
<section id='ocaml.dist'>
<title>What is distributed?</title>
<para>
When you create package with OCaml module, following files should
be included in package:
<itemizedlist>
<listitem>
<para>
All <filename>*.cmi</filename> files.
</para>
</listitem>
<listitem>
<para>
All <filename>*.cmx</filename> files. They contain small
inline functions and therefore are needed during compilation.
</para>
</listitem>
<listitem>
<para>
<filename>*.cma</filename> and <filename>*.cmxa</filename>
archives. They are often called <filename>foo.cma</filename>
and <filename>foo.cmxa</filename>
</para>
</listitem>
<listitem>
<para>
<filename>*.a</filename> archives for corresponding
<filename>*.cmxa</filename> (<filename>foo.a</filename> for
<filename>foo.cmxa</filename>).
</para>
</listitem>
<listitem>
<para>
<filename>*.a</filename> archives with compiled C parts
of library (this is often <filename>libfoo.a</filename>).
</para>
</listitem>
<listitem>
<para>
<filename>dll*.so</filename> dynamic link library for
runtime system (<filename>dllfoo.so</filename>). If package
contains parts written in C and doesn't produce
<filename>dll*.so</filename>, you should fix it. See
<filename>ocaml-odbc.spec</filename> for an example.
</para>
</listitem>
<listitem>
<para>
Any examples. They are often very helpful. If there is just one,
or two files, you can gzip them and put as
<literal>%doc</literal>. Otherwise copy them to
<literal>%{_examplesdir}</literal>.
</para>
</listitem>
</itemizedlist>
</para>
<para>
Following files should NOT be distributed:
<itemizedlist>
<listitem>
<para>
<filename>*.cmo</filename> object files. There is however
one exception -- if file is needed for link (like
<filename>gtkInit.cmo</filename> in lablgtk or
<filename>std_exit.cmo</filename> in OCaml itself),
then it should be of course included.
</para>
</listitem>
<listitem>
<para>
<filename>*.o</filename> for corresponding
<filename>*.cmx</filename>. They are included in
<filename>*.a</filename> anyway. Exception -- as above.
</para>
</listitem>
<listitem>
<para>
<filename>*.ml</filename> sources.
</para>
</listitem>
<listitem>
<para>
<filename>*.mli</filename> interface sources. However, if
package lacks any documentation (which is unfortunately often
the case), you can include <filename>*.mli</filename>, but
it should be gziped and placed in package as
<literal>%doc</literal>.
</para>
</listitem>
</itemizedlist>
</para>
</section>
<section id='ocaml.lang'>
<title>OCaml Language</title>
<para>
Package with OCaml itself is split into several subpackages:
<variablelist>
<varlistentry>
<term>ocaml-runtime</term>
<listitem>
<para>
<filename>ocamlrun</filename> and base
<filename>dll*.so</filename>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>ocaml</term>
<listitem>
<para>
Bytecode and native compilers, standard library,
debugger and other tools.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>ocaml-camlp4</term>
<listitem>
<para>
Pre Processor Pretty Printer. Provides:
<literal>camlp4</literal>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>ocaml-x11graphics</term>
<listitem>
<para>
Just <filename>dllgraphics.so</filename>. Not in
<literal>ocaml-runtime</literal> since it requires
<literal>XFree86-libs</literal> to run.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>ocaml-x11graphics-devel</term>
<listitem>
<para>
Development parts of <literal>Graphics</literal>
module. Similar split holds for
<literal>ocaml-labltk</literal> and
<literal>ocaml-labltk-devel</literal> subpackages.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>ocaml-devel</term>
<listitem>
<para>
<filename>*.cm[iox]</filename> files resulting
from compilation of OCaml compiler itself. It is needed
by some programs.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
Standard OCaml library path is <filename>%{_libdir}/ocaml</filename>.
<filename>%{_libdir}/ocaml/ld.conf</filename> contains just this
directory (see below for details).
</para>
<para>
OCaml C includes are placed in <filename>%{_includedir}/caml</filename>,
but compatibility symlink <filename>%{_libdir}/ocaml/caml</filename>
is provided.
</para>
<para>
<command>ocamlc</command> and <command>ocamlcopt</command> are symlinked
to <command>ocamlc.opt</command> and <command>ocamlcopt.opt</command>
respectively. However <command>ocamlc.byte</command> and
<command>ocamlcopt.byte</command> are also provided in case there
are some problems with .opt compilers.
</para>
</section>
<section id='ocaml.modules'>
<title>OCaml Modules</title>
<para>
If package has <filename>dll*.so</filename> stuff, it should be split
into two parts -- base package with just <filename>dll*.so</filename>
and <literal>-devel</literal> subpackage with rest. If there is
no <filename>dll*.so</filename> we produce just
<literal>-devel</literal> subpackage. For example is library
<literal>foo</literal> is written all in OCaml, so there is no
<filename>dll*.so</filename>, you should make
<filename>ocaml-foo.spec</filename> with no <literal>%files</literal>
section for main package, just for <literal>ocaml-foo-devel</literal>.
</para>
<para>
While having just <literal>-devel</literal> might seem odd, but:
<itemizedlist>
<listitem>
<para>
It is consistent.
</para>
</listitem>
<listitem>
<para>
If OCaml will ever support dynamic loading (of either bytecode
libraries or native code libraries (this can be done even
now, but needs to be further investigated)), we won't have to
change package names.
</para>
</listitem>
</itemizedlist>
</para>
<para>
Package named <literal>foo</literal> should be installed in
<filename>%{_libdir}/ocaml/foo</filename>. Also
<filename>dll*.so</filename> should go there, but there should be
symlinks to them in <filename>%{_libdir}/ocaml</filename>.
Therefore there is no need to modify
<filename>%{_libdir}/ocaml/ld.conf</filename>.
</para>
<para>
<filename>%{_libdir}/ocaml/foo</filename> should be owned by
<literal>ocaml-foo</literal>, not by <literal>ocaml-foo-devel</literal>.
</para>
<para>
Base package should use rpm macro
<literal>%require_eq ocaml-runtime</literal>, while -devel package
<literal>%require_eq ocaml</literal>, so they won't be installed with
possibly incompatible OCaml version.
</para>
</section>
<section id='ocaml.findlib'>
<title>findlib</title>
<para>
findlib is package management tool for OCaml libraries. Information
about packages is stored in <filename>META</filename> files.
<!-- need more... -->
</para>
<para>
Even if package use findlib to install itself, it should be placed
in <filename>%{_libdir}/ocaml/foo</filename>, not in
<filename>%{_libdir}/ocaml/site-lib/foo</filename> (this is to be
consistent with packages not using findlib). However
<filename>META</filename> file should be installed in
<filename>%{_libdir}/ocaml/site-lib/foo/META</filename>.
</para>
<para>
If there is no <filename>META</filename> file for package, you
should consider creating one.
</para>
</section>
<section id='ocaml.flags'>
<title>Flags for compilation</title>
<para>
<filename>.c</filename> files should be compiled with
<filename>%{__cc}</filename> (not <command>gcc</command>,
<command>cc</command> nor <command>ocamlc</command>).
During compilation standard <literal>%{rpmcflags}</literal>
should be used (this is the same as with other packages in PLD).
</para>
<para>
<filename>.ml</filename> should not be compiled with
<option>-g</option> <command>ocamlc</command> option. If bundled
<filename>Makefile</filename> does so, you should fix it.
</para>
</section>
<section id='ocaml.toplevel'>
<title>Toplevel systems</title>
<para>
As OCaml can now handle dynamic loading interactive systems are
not of much use (one can always do <literal>#load
"foobar.cma"</literal>). However if you feel interactive system
linked with some library might be needed, separate it into
<literal>-toplevel</literal> subpackage.
</para>
</section>
</section>