Debian OCaml Packaging Policy

The Debian OCaml Task Force

Revision 0.7.3

This manual is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

A copy of the GNU General Public License is available as /usr/share/common-licenses/GPL on Debian GNU/Linux systems or on the World Wide Web at The GNU Public Licence.


Table of Contents

1. Generalities about OCaml packages in Debian
The Name of the Game
Bytecode and Native Code
Bytecode and Native Code Executables
Bytecode and Native Code Compilers
OCaml in Debian
Packages for OCaml
OCaml Location
Files Used and Produced by the OCaml Compiler
Locally Installing OCaml Programs and Libraries
Registering Documentation with doc-base
Choose the Right Archive Section
2. Packaging OCaml Programs
Creating Packages for OCaml Programs
Bytecode Packages
Bytecode and native versions of programs
3. Packaging OCaml libraries
Creating Packages for OCaml Libraries
Paths for libraries
Handling dependencies on OCaml
Providing META files
Camlp4/Camlp5
Documentation
A. The OCaml CDBS class
B. The Debian OCaml Task Force resources
C. Using the SVN repository
Use SVN and let your users know about it
How to obtain a copy of the SVN repository
Structure of the SVN repository
How to add a new package to the SVN repository
How to set up your package for use with svn-buildpackage
How to build a package with svn-buildpackage
dpatch
D. Using Git for packaging
Using Git for packaging
How to obtain a copy of a package's Git repository
Structure of a Git repository
How to add a new package
How to set up your package for use with git-buildpackage
How to build a package with git-buildpackage
Patches
Quilt-serialized patches

List of Tables

1.1. OCaml Compilers

List of Examples

3.1. Dependency from a -dev package to its companion share library stub package (if any), from the pcre-ocaml package
C.1. Usage example of the Vcs-* fields, from the findlib package
D.1. Usage example of the Vcs-* fields, from the findlib package

Chapter 1. Generalities about OCaml packages in Debian

The Name of the Game

The correct short name of Objective Caml is OCaml. Other spellings/capitalizations like ocaml, OCAML, O'Caml should be avoided when talking about the Objective Caml project, the system, or the programing language.

Bytecode and Native Code

Bytecode and Native Code Executables

The OCaml compiler can produce two kinds of executables: bytecode and native. Native executables (produced by the compiler ocamlopt) are generally faster than bytecode executables since they are compiled specifically for an architecture. Bytecode executables (produced by the compiler ocamlc) have the advantage of being portable, which means that a bytecode executable can be run on any architecture without having to be recompiled. Bytecode executables are smaller than native code executables. If considering only one process the advantage in size is annihilated by the need for the OCaml run time system for executing bytecode, however there is an advantage when running several bytecode processes in parallel since the runtime system can then be shared. It should be noted that OCaml compilers to native code are not provided for every architecture. Only the following ones are supported: amd64, i386, kfreebsd-i386, powerpc, sparc.

Packages providing both native and bytecode versions of a program prog usually name them respectively prog.opt and prog.byte and provide a symbolic link prog to the best available version (generally prog.opt).

Bytecode and Native Code Compilers

The ocaml-native-compilers package contains the OCaml compiler executables built in native mode: ocamlc.opt, which produces bytecode, and ocamlopt.opt, which produces native code. Since the OCaml compilers are themselves written in OCaml this package exists only on architectures where compilation to native code is supported.

The ocaml-nox package contains the OCaml compiler executables built in bytecode mode: ocamlc, which produces bytecode, and on architectures where compilation to native code is supported the compiler ocamlopt, which produces native code. It is important to understand that on architectures where compilation to native code is supported both packages contain compilers from OCaml to both bytecode and native code, the difference lies in the nature (installation size and execution speed) of the compiler executables.

Table 1.1. OCaml Compilers

 Compiles to bytecodeCompiles to native code
Compiler executable in bytecodeocamlcocamlopt
Compiler executable in native codeocamlc.optocamlopt.opt

Compiling with native code versions of the compilers is generally faster than with compilers in bytecode. Unfortunately, the ocaml-native-compilers package is not available on every architecture. Packages should therefore never depend directly on this package. In order to build big programs and benefit from this natively built compiler, packages should depend on ocaml-best-compilers which itself depends on ocaml-native-compilers where available and on ocaml elsewhere. Since it is a virtual package, it cannot (yet) be a versioned dependency. The version dependency should thus be carried by the ocaml dependency. Note that dependency on ocaml-best-compilers is only necessary for real big programs for which compilation takes a lot of resources. For most small programs the compilers from the ocaml-nox package are perfectly sufficient, and faster to install in a build environment than compiler executables in native code.

OCaml in Debian

At the time of this writing, the latest version of OCaml in Debian is 3.10.2.

Packages for OCaml

The ocaml package depends on all the basic packages needed to develop programs with OCaml. More specifically, the packaging of OCaml is split into smaller packages. The packages with suffix -nox contain libraries that don't need X (i.e., for programs that don't use the Graphics or LablTk modules) in order to avoid dependencies on big packages for users who do not need to run graphical applications. Here is the list of binary packages into which OCaml is split:

  1. The ocaml and ocaml-nox packages contain the compiler and its libraries.

  2. The ocaml-native-compilers package contains the OCaml compilers built in native mode (ocamlc.opt and ocamlopt.opt).

    Note

    The compilers themselves are built in native mode, nonetheless, both compilers for compiling toward bytecode and native code are contained in this package.

  3. The ocaml-base and ocaml-base-nox packages contain the interpreter and runtime libraries needed by bytecode programs compiled with OCaml (in particular, the package ocaml-base-nox contains the ocamlrun program).

  4. The ocaml-interp package contains the toplevel system for OCaml (ocaml) which provides for an interactive interpreter of the language.

  5. The ocaml-mode package contains the OCaml Emacs mode (the one provided with OCaml, not the tuareg mode which is in the package tuareg-mode).

  6. The ocaml-source package contains the sources of the OCaml compiler.

  7. The ocaml-compiler-libs package contains some internal libraries of the OCaml compiler (needed only in very rare cases, e.g. for developing languages which reuse OCaml internals).

Since libraries produced by OCaml are binary incompatible when compiled with different releases of OCaml, versioned virtual packages are also provided by packages at items (1) and (2): ocaml-3.10.2, ocaml-nox-3.10.2, ocaml-base-3.10.2, ocaml-base-nox-3.10.2.

OCaml Location

The root of all installed OCaml libraries is the OCaml standard library directory, which is /usr/lib/ocaml/VERSION/, at the time of writing /usr/lib/ocaml/3.10.2. This location can be obtained from the OCaml compiler by invoking it as ocamlc -where.

Files Used and Produced by the OCaml Compiler

The OCaml compiler can produce or use the following kind of files:

  • bytecode executables (they can be recognized since they start with the shebang line #!/usr/bin/ocamlrun)

  • bytecode executables linked in custom mode. They are generated by ocamlc (or ocamlc.opt), when the -custom flag is given at link time. Those executables are in ELF format and include both the final bytecode and the bytecode interpreter. strip should never be invoked on them, since it will remove the bytecode part.

  • native executables (in ELF format)

  • bytecode libraries (*.cma)

  • native libraries (*.cmxa)

  • shared libraries (for C bindings) (dll*.so, lib*.so)

  • static libraries (for C bindings) (lib*.a)

  • bytecode object files (*.cmo)

  • native object files (*.cmx)

  • configuration files for handling libraries with ocamlfind (META)

Locally Installing OCaml Programs and Libraries

Locally installed files are files that are installed directly by the system administrator, in contrast to files installed through Debian packages. Installation and use of locally installed OCaml related programs is out of the scope of this document. However, in order to have it work with a standard Debian installation, a local system administrator should follow these guidelines:

  • Executable files should be installed in /usr/local/bin.

  • Shared libraries (for C bindings) should be installed in /usr/local/lib/ocaml/3.10.2/stublibs/

  • Basically, every other file should be installed in /usr/local/lib/ocaml/3.10.2/. This includes in particular bytecode libraries (*.cma), native libraries (*.cmxa), bytecode object files (*.cmo), native object files (*.cmx), static libraries (*.a) and META files.

The default configuration of ocamlfind (the OCaml library manager recommended in Debian) first looks for a local installation of libraries and then for libraries installed by Debian packages. The next section describes the standard paths for files contained in Debian packages.

Warning

The + preceding any library in the -I of ocamlc or ocamlopt won't be expanded to the local standard library path. You need to specify the path entirely.

Registering Documentation with doc-base

Documentation relevant to programming in OCaml (language, tools, libraries, ...) should be registered with doc-base in Section Programming/OCaml.

Choose the Right Archive Section

Packages that are intended for OCaml development, as opposed to more general tools that just happen to be implemented in OCaml, should have their Section set to ocaml.

Chapter 2. Packaging OCaml Programs

Creating Packages for OCaml Programs

Any package providing executables built from OCaml source should conform to the following guidelines.

The source package should, if possible, use the name of the upstream package without modifications.

Programs which are not particularly CPU hungry should be compiled into bytecode form, and the corresponding binary packages should be Architecture: all in order to minimize archive usage and avoid the need of rebuilding them on all architectures. See the section called “Bytecode Packages” for details on this kind of packages.

Other programs should be compiled into native form on architectures where the native compiler is available, and into bytecode on other architectures. See the section called “Bytecode and native versions of programs” for details on how to achieve this. The corresponding binary packages should be Architecture: any and will need to be built on any architecture.

All bytecode executables should be linked dynamically against the shared libraries for C bindings, so as to not bloat the archive. That said, often the upstream authors will favor statically linked bytecode executables, because so they don't need to worry about the presence of the dll stub libraries and such. This is not a valid reason to use statically linked bytecode in a Debian package.

Bytecode Packages

A bytecode package has all its binaries compiled into bytecode. It depends on a package containing the OCaml runtime system. By consequence, such a package has its architecture field set to all.

A bytecode package must depend on ocaml-base-nox-3.10.2 (or ocaml-base-3.10.2 if the program either uses the Graphics or the LablTk module). In order for the package to be able to be rebuilt or even binNMUed without a change in the packaging, this version should not be hardcoded in the debian/control file. Instead, the package should depend on ocaml-base-nox-${F:OCamlABI} and use OCAMLABI := $(shell ocamlc -version) and dh_gencontrol -- -VF:OCamlABI="$(OCAMLABI)" in the debian/rules file.

A bytecode package must build-depend-indep on ocaml-nox-3.10.2 (or ocaml-3.10.2 if the program either uses the Graphics or the LablTk module). The current version number of OCaml should not be hardcoded into the build-dependency (this is a deviation from a practice which used be recommended but is depreciated now). Of course, if it is necessary to ensure that the version of OCaml has a certain value then version constraints can be used. However, this should be justified by the requirements of the compilation of the program.

Bytecode programs which are compiled by ocamlc -custom must not be stripped. In particular, their package should be excluded from the dh_strip script. When compiled this way, an elf executable is generated containing the ocaml interpreter, and the bytecode of the program in a section which is removed when the program is stripped. For more information, see the bug 256900. An override for the lintian warning is considered as acceptable in this situation.

Bytecode programs should not be compiled for debugging, i.e. they should not be compiled passing the -g option to ocamlc (or ocamlc.opt).

Bytecode and native versions of programs

As explained in #bytecode-native, native OCaml compilers are not available everywhere. For architectures missing native compiler, a bytecode version of the program should be provided.

The package's debian/rules should build the native code executable if supported on the architecture it is built on, and fall back to building the bytecode version if no working native code compiler is available. Exceptions to this are the executables who are small or not time critical, which may be built only as bytecode. It is the decision of the individual maintainers to choose this, maybe guided by the practice of the upstream author.

The availability of the native compiler can be tested in the debian/rules file by testing the possibility of executing /usr/bin/ocamlopt, and build the bytecode version or the native version of the program according to the result of the test. This is a sample snippet of debian/rules doing so:

          build-stamp:
                  dh_testdir

                  if [ -x /usr/bin/ocamlopt ]; then \
                          $(MAKE) opt; \
                  else \
                          $(MAKE) all; \
                  fi
        

The bytecode versions are portable. In order to spare the buildds and the Debian archive, bytecode versions should be compiled once for all for big packages (which either take a lot of place on disks or take a lot of time to build). For example, the spamoracle package provides the spamoracle-byte package which is Architecture: all and contains the bytecode version of spamoracle, and the spamoracle package which contains the native version of spamoracle and is available only where a native OCaml compiler is available (Architecture: amd64 i386 kfreebsd-i386 powerpc sparc).

Bytecode versions of the programs should depend on ocaml-base-nox-3.10.2 (or ocaml-base-3.10.2 the program either uses the Graphics or the LablTk module). In order for the package to be able to be rebuilt or even binNMUed without a change in the packaging, this version should not be hardcoded in the debian/control file. Instead, the package should depend on ocaml-base-nox-${F:OCamlABI} and use OCAMLABI := $(shell ocamlc -version) and dh_gencontrol -- -VF:OCamlABI="$(OCAMLABI)" in the debian/rules file.

The following is a snippet of a sample debian/control:

          Package: spamoracle-byte
          Architecture: all
          Depends: ocaml-base-nox-${F:OCamlABI}
          Provides: spamoracle
          Conflicts: spamoracle
          Replaces: spamoracle
        

The following its pairing debian/rules snippet:

          OCAMLABI := $(shell ocamlc -version)
          ...
          binary-indep: build install
          dh_gencontrol -i -- -VF:OCamlABI="$(OCAMLABI)"
        

In the case where there is only one package, which provides either a native version where available or a bytecode version otherwise, the dependency on ocaml-base-nox-3.10.2 should be added only when the package is built in native mode. For example, the debian/control of approx contains:

          Package: approx
          Architecture: any
          Depends: ${shlibs:Depends}, ${F:OCamlRun}, adduser, bzip2, curl
        

and the corresponding debian/rules contains:

          OCAMLABI = $(shell ocamlc -version)
          BYTECODE = $(shell [ -x /usr/bin/ocamlopt ] || echo yes)
          OCAMLRUN = $(if $(BYTECODE),ocaml-base-nox-$(OCAMLABI))
          ...
          binary-arch:
                  ...
                  dh_gencontrol -- -VF:OCamlRun="$(OCAMLRUN)"
        

Chapter 3. Packaging OCaml libraries

Creating Packages for OCaml Libraries

A package which provides an OCaml library called xxx should be split as follows:

  • For libraries which are not purely programmed in OCaml (e.g. C bindings), libxxx-ocaml should provide the shared library stubs (dll*.so), and all other stuff needed to run a bytecode executable that links into this library. It should depend on ocaml-base-3.10.2 (or ocaml-base-nox-3.10.2) as well as any other library needed. The versioned dependency on ocaml-base is important since libraries are binary incompatible between releases of OCaml.

    libxxx-ocaml packages should be in Section: libs

  • libxxx-ocaml-dev should provide the rest of the library package, in fact anything needed to develop programs using the library. If the library uses other libraries or C libraries, this package should depend on them.

    libxxx-ocaml-dev should depend on its companion libxxx-ocaml package (if any). The reason is that at compile time the OCaml compiler will try to load the shared library stubs, aborting the compilation in case of failure. Hence the development package is useless if the corresponding stub package is missing. To ensure compatibility the dependency among the two packages should be strictly versioned. In order for the resulting packages to be binNMU safe this requirement states that the dependency should make use of a ${binary:Version} substitution variable.

    Example 3.1. Dependency from a -dev package to its companion share library stub package (if any), from the pcre-ocaml package

        Package: libpcre-ocaml
        Architecture: any
        Section: libs
        Depends: ocaml-base-nox-${F:OCamlABI}, ${shlibs:Depends}, ${misc:Depends}
        ...
    
        Package: libpcre-ocaml-dev
        Architecture: any
        Section: libdevel
        Depends: ocaml-nox-${F:OCamlABI}, libpcre3-dev (>= 4.5), libpcre-ocaml (= ${binary:Version}), ocaml-findlib (>= 1.1), ${misc:Depends}
        ...
                          


    libxxx-ocaml-dev packages should be in Section: libdevel

    All OCaml bytecode libraries (*.cma) and bytecode object files (*.cmo) should be compiled for debugging, i.e. they should be compiled passing the -g option to ocamlc (or ocamlc.opt).

Optionally, two other packages may be created:

  • libxxx-ocaml-bin may include binaries provided by the library source package if they are numerous. This package should conform with the same regulations as other packages providing ocaml programs. It is only needed to split off this package if there is a significant number of programs included in the library, if not, the programs should go into libxxx-ocaml-dev.

  • libxxx-ocaml-doc may include any kind of documentation provided by the library source package or as separate documentation. Again, if there is only little documentation, they should go with the -dev package.

It is recommended that libraries use the -pack option to pack all the modules provided by the library into one module. We don't think upstream libraries will be moving to this scheme anytime soon (unless we actively lobby for it) so this is just a recommendation for now.

It is recommended that each library package ships a META file in order to make the library usable via ocamlfind (see the Debian package ocaml-findlib). See the section called “Providing META files” for more information on this.

Paths for libraries

Libraries should be installed in /usr/lib/ocaml/3.10.2/ or in a subdirectory of this directory. This includes in particular bytecode libraries (*.cma), native libraries (*.cmxa), bytecode object files (*.cmo), native object files (*.cmx), static libraries (*.a) and META files. The only exception to this rule is for shared libraries (dll*.so) which should be installed in /usr/lib/ocaml/3.10.2/stublibs, as can it be seen in the /usr/lib/ocaml/3.10.2/ld.conf file.

If upstream developers already use a subdirectory of the OCaml standard library path, this path should be preserved in the Debian package but made relative to the standard library path of OCaml. Before using the provided subdirectory, packagers should obviously check if there is no subdirectory name clash with another OCaml library.

If upstream developers don't use this scheme, packagers are encouraged not to install this library in the standard library directory. They should create at least a subdirectory per source package (in order to avoid name clashes). Packagers should also consider to do a larger separation by creating a subdirectory per binary package (in order to avoid META name clash). A suggested rule to choose name for this subdirectory is to use either the package name provided by the META of the upstream, or the name of the library itself.

Handling dependencies on OCaml

Some parts of the package need to know the current version of OCaml. For example, libraries should be installed /usr/lib/ocaml/3.10.2/. However, the current version of OCaml should never be hardcoded in the package (3.10.2 here). This would make a binNMU impossible when the version of OCaml changes. Instead .in files should be used where @OCamlABI@ is replaced at build-time by the current OCaml version.

For example, the package ocaml-mad would normally contain a file libmad-ocaml-dev.install for installing files with dh_install, containing:

          usr/lib/ocaml/3.10.2/mad/META
          usr/lib/ocaml/3.10.2/mad/*.a
          usr/lib/ocaml/3.10.2/mad/*.cm*
          usr/lib/ocaml/3.10.2/mad/*.ml*
          

In order to avoid the explicit mention of the version of OCaml (3.10.2), the package actually contains instead a file libmad-ocaml-dev.install.in which contains:

          usr/lib/ocaml/@OCamlABI@/mad/META
          usr/lib/ocaml/@OCamlABI@/mad/*.a
          usr/lib/ocaml/@OCamlABI@/mad/*.cm*
          usr/lib/ocaml/@OCamlABI@/mad/*.ml*
          

The string @OCamlABI@ is substituted at build-time by the version of OCaml. Here are the relevant parts of the debian/rules file:

          OCAMLABI := $(shell ocamlc -version)
          OFILES := $(filter-out debian/control,$(patsubst %.in,%,$(wildcard debian/*.in)))

          ocamlinit:
                  for f in $(OFILES); do sed -e 's/@OCamlABI@/$(OCAMLABI)/g' $$f.in > $$f; done

          config.status: ocamlinit configure
                  [...]

          .PHONY: build clean binary-indep binary-arch binary install ocamlinit
          

The only exception to this rule (properly handled by the example above) is the debian/control file, which should never be generated at build-time. As explained in #bytecode-native-prog, the dependency should nevertheless not hardcode the version of OCaml: the debian/control file should have a Depends: ocaml-base-nox-${F:OCamlABI} which is filled by a dh_gencontrol -s -- -VF:OCamlABI="$(OCAMLABI)" in the debian/rules file.

Providing META files

The ocaml-findlib provides a tool (named ocamlfind) to handle OCaml libraries and store information about libraries dependencies, compiler flags, linking options, etc. Meta informations regarding a library are contained in files (usually one for each library), named META files, contained in the library directory. The distribution of META files is the best way to make more easy to use the Debian-specific oragnization of libraries. Packages distributing META files should suggest the use of ocamlfind, that is have a Suggest: ocaml-findlib.

By default, ocamlfind will look for META in this order:

  • /usr/lib/ocaml/3.10.2/METAS/

  • /usr/lib/ocaml/3.10.2/package/

The naming scheme of META is pretty simple.

  • If the META file is placed in the subdirectory of the package, it should be called META.

  • If the META file is placed in /usr/lib/ocaml/3.10.2/METAS/, it should be called META.packagename, where packagename is the name of the subdirectory where the library is stored.

For example, the META file for the lablgtk library is named META and has path /usr/lib/ocaml/3.10.2/lablgtk/META, where /usr/lib/ocaml/3.10.2 is the main OCaml installation directory and lablgtk is the lablgtk library directory.

If upstream doesn't provide a META, packagers are encouraged to create one. In this case, the META should be sent to upstream authors, in order to have it included in the next version of the upstream source. For more information about META files, have a look at the Findlib manual, at the several META files provided by other packages (e.g. lablgtk, pxp, pcre, netstring, lablgl, ...) or ask on the debian-ocaml-maint mailing list for help.

Camlp4/Camlp5

Actually, Camlp4 extensions should be processed just as standard OCaml library. The META file distributed with this syntax extension should follow the OSR: META files for packages containing syntax extensions. In particular, the syntax extension should be contained in a syntax sub packages.

The naming convention of the package is to use the same naming as with standard package, replacing -ocaml- by the syntax extension name, -camlp4-.

If a package contains at the same time syntax extension and library, it is up to the maintainer to choose the most relevant name for the package. Whatever the name chosen for the package, the other name should be a Provide of the package.

For example, consider the package sexplib310. It provides a syntax extension and a library, which is the runtime support of the additional function generated by the syntax extension. Since the most common use of sexplib310 is through its syntax extension, the package is name libsexplib-camlp4-dev and it also provide libsexplib-ocaml-dev.

Camlp5 is an alternate pretty-printer and preprocessor for OCaml (which is compatible with pre-3.10.0 version). Syntax extension are handled through exactly the same scheme as for Camlp4 except that package name use -camlp5- rather than -camlp4-.

Documentation

The documentation is a joint effort of The Debian OCaml Task Force and usptream. There are many ways to have documentation:

  • header files (*.mli),

  • source files (*.ml),

  • specific documentation provided by the upstream,

  • OCamldoc generated documentation.

This documentation should be browsable by different mean, from the most simple to the most complex. At least, they should all be readable with simple text editor. Specific and ocamldoc generated documentations should be provided in HTML format. There are also at least two specific OCaml browser : docbrowse shipped with cameleon and ocamlbrowser shipped with OCaml itself. The first one, needs specific ocamldoc generated documentation. The second one enables the user to browse directly the prototype of each function shipped in the cmi gives to the application.

You can generate ocamldoc-specific documentation by using the -dump of this application. By using this, you dump the intermediary representation of the document that will be generated by ocamldoc. This can be used to generate HTML documentation and manpages, by reloading this file (using -load).

As of today, there is no way to post-process ocamldoc specific documentation. A Debian package is under construction to do this task. It will be referred as ocamldoc-base.

Appendix A. The OCaml CDBS class

To help maintainers of OCaml-related packages in adhering to this policy, a class for the CDBS build system has been made available and is shipped as part of the ocaml-nox package. Please consider using it in your packages at it will both ease your work and permit to perform changes to a wide range of packages acting on a single piece of software (the CDBS class itself).

To use the class in your package it is enough to include the file /usr/share/cdbs/1/rules/ocaml.mk from your debian/rules. If you use debhelper (please do) you should include the OCaml class after the debhelper on. A typical debian/rules heading for a package using plain Makefile (i.e. no autotools) and dpatch is as follows:

  #!/usr/bin/make -f
  include /usr/share/cdbs/1/rules/dpatch.mk
  include /usr/share/cdbs/1/rules/debhelper.mk
  include /usr/share/cdbs/1/class/makefile.mk
  include /usr/share/cdbs/1/rules/ocaml.mk
    

For an example of such a package see the pcre-ocaml Debian source package.

A detailed description of how to use the OCaml CDBS class should be provided in this section, but at the time of writing is a future work :-). In the meantime if you know CDBS, the .mk files which compose the OCaml class are well commented and they should give you enough information to customize the build process of your package. The latest version of them is available in the repository of the The Debian OCaml Task Force and can be browsed on the web:

ocaml-vars.mk

contains (Makefile) convenience variables which can be used in debian/rules

ocaml.mk

implements the class logic

Appendix B. The Debian OCaml Task Force resources

Appendix C. Using the SVN repository

Use SVN and let your users know about it

(Hopefully) All OCaml-related Debian packages are maintained using a centralized Subversion (SVN for short) repository. This practice reduce the efforts needed to contribute work inside The Debian OCaml Task Force and, in case of need, provides a place where to massively perform changes to all OCaml-related Debian packages.

Nonetheless, Debian users can benefit knowing we are using a SVN repository (they can for instance subscribe to the RSS feed for changes or have a place where to look for finding patches corresponding to bugs tagged "pending" in the BTS).

For this reason it is recommended to add the Vcs-Svn and Vcs-Browser fields to the debian/control of packages maintained in The Debian OCaml Task Force SVN repository. Its name specifies that we are using Subversion as our Version Control System (VCS); their values are the URLs pointing to the package's trunk directory and to a browsable view of the same directory. See Bug #391023 (which contains the forthcoming text for the Debian Developer's Reference) for more information about these fields.

The general scheme for using the fields are thus:

    Vcs-Svn: svn://svn.debian.org/svn/pkg-ocaml-maint/trunk/packages/PACKAGE_NAME
    Vcs-Browser: http://svn.debian.org/wsvn/pkg-ocaml-maint/trunk/packages/PACKAGE_NAME/trunk/
      

Example C.1. Usage example of the Vcs-* fields, from the findlib package

    Source: findlib
    Section: devel
    Priority: optional
    Maintainer: Stefano Zacchiroli <zack@debian.org>
    Build-Depends: debhelper (>> 4.0.0), ocaml (>= 3.09.2), m4, gawk | awk, dpatch, cdbs
    Standards-Version: 3.7.2
    Vcs-Svn: svn://svn.debian.org/svn/pkg-ocaml-maint/trunk/packages/findlib
    Vcs-Browser: http://svn.debian.org/wsvn/pkg-ocaml-maint/trunk/packages/findlib/trunk/

    Package: ocaml-findlib
    Section: devel
    Architecture: any
    Depends: ocaml-nox-${F:OCamlABI}, ${shlibs:Depends}, ${misc:Depends}
    Description: Management tool for OCaml programming language libraries
    ...
        


How to obtain a copy of the SVN repository

You can obtain a copy of debian-ocaml-maint SVN repository by

    svn co svn+ssh://svn.debian.org/svn/pkg-ocaml-maint
        

You must be member of the Debian OCaml Task Force in order to have write access to the repository.

Structure of the SVN repository

We keep all files of the debian subdirectory under SVN control, and upstream only as a compressed tarball. The rationale behind this is that changes to upstream files should be managed by the dpatch patch manager. Hence, all the diffs to upstream files are kept in a subdirectory of debian/, and it is not necessary to manage upstream on file-by-file basis.

The structure of the pkg-ocaml-maint SVN repository is as follows, where generic names are indicated in square brackets [ .. ], and where the contents of subdirectories not directly relevant for package management are not detailed:

   tags
     packages
       [package1]
         [version1]
         [version2]
         ...
       [package2]
         [version1]
         ...
       ...
     projects
   test
   trunk
     packages
       [package1]
         trunk
           debian
         tarballs
           [upstream-tarball-version1]
           [upstream-tarball-version2]
           ...
       [package2]
       ...
     policy
     projects
     tools
          

How to add a new package to the SVN repository

Place yourself in the directory trunk/packages of your working copy of the SVN repository. Create a directory with the same name as your source package (let's say, my-package), and subdirectories tarballs and trunk. Put the current upstream tarball in tarballs, and the current debian directory with all its relevant files in trunk. This should now look like this:

   trunk/packages/my_package
     tarballs
       my_package_1.2.3.orig.tar.gz
     trunk
       debian
         changelog
         control
         copyright
         patches
           00_list
           01_patch1.dpatch
           ...
         ...
         

If everything is in order you can do a svn add my_package from the trunk/packages directory, and eventually svn commit.

How to set up your package for use with svn-buildpackage

Please see the svn-buildpackage documentation for complete information. The important issues here are:

  • Since we keep upstream as a tarball we have to use svn-buildpackage in so-called merge mode. This means that, before compiling the package, the debianized source tree is constructed by untarring the orig tarball, and then merging the contents of the trunk subdirectory in it.

  • The structure of our SVN repository is not among the default structures of svn-buildpackage. Hence, we have to override the default location of some directories.

Place yourself in trunk/packages/my_packages/trunk, and do the following: svn propset mergeWithUpstream 1 debian. This registers the property "mergeWithUpstream" with the current directory, such that svn-buildpackage knows that it has to use merge mode as explained above.

Create a file debian/svn-deblayout with the following contents:

  tagsUrl=svn+ssh://svn.debian.org/svn/pkg-ocaml-maint/tags/packages/my_package
          

Remember that "my_package" has to be replaced by the name of your actual package. svn-buildpackage will not include this file in the source package when actually building the package.

If you tried svn-buildpackage before writing your debian/svn-deblayout remember to delete .svn/deb-layout, since svn-buildpackages caches here the content of svn-deblayout (that would be empty in this case) and will ignore your debian/svn-deblayout.

How to build a package with svn-buildpackage

Please refer to the svn-builpackage documentation for more complete information. Here is just a quick guide.

All options, except those starting on --svn, are passed to dpkg-buildpackage. Hence, basic usage should be something like this (from the trunk/packages/my_package/trunk directory): svn-buildpackage -rfakeroot -uc -us.

svn-buildpackage will complain when your copy of the debian directory is not in sync with the repository. You may use the option --svn-ignore-new to override this behaviour. The package will be build in the directory ../build-area.

If your package is ready for upload you may use the --svn-tag option for the final build. This will put a tag in the svn-repository on the current version, and add a new entry in the changlog to start working on the upcomming next version: svn-buildpackage --svn-tag. Provided you have commited all your changes to the svn repository, this will after a successful build of the package create a tag for the current version in tags/packages/my_package. The tagging is done directly in the SVN repository.

Tip

Some useful aliases taken from the svn-buildpackage HOWTO:

  alias svn-b='svn-buildpackage -rfakeroot --svn-dont-clean -us -uc --svn-ignore'
  alias svn-bt='svn-buildpackage -rfakeroot --svn-lintian --svn-dont-clean --svn-tag'
              

The former (svn-b) is to be used for test builds, while you are working on your package; while the latter (svn-bt) is to be used at the end, after you commit your changes and just before uploading a new version of the package to the debian archive.

Adding -k<your gpg id> to the svn-bt alias may also be useful when working on collaboratively maintained packages:

  alias svn-bt='svn-buildpackage -rfakeroot -k<gpgid> --svn-lintian --svn-dont-clean --svn-tag'
              

dpatch

dpatch will work properly at package build time with the SVN structure described above since all of the build process will be carried out in a fresh directory. However, invoking debian/rules with the "clean" target in the trunk/ directory will fail since dpatch is unable to de-apply patches. Passing --svn-dont-clean to svn-buildpackage fixes this misbehaviour (aliases suggested above already include this flag).

If you want to use dpatch-edit-patch to handle patches, you will need to invoke it in "debian only mode" (-b flag, see man dpatch-edit-patch) and to tell him where to find the upstream tarball. Adding the following line to your ~/.dpatch.conf will be enough:

  conf_origtargzpath=../tarballs
          

Appendix D. Using Git for packaging

Using Git for packaging

This appendix is still under construction!

(Hopefully) All OCaml-related Debian packages are maintained using centralized Git repositories. This practice reduce the efforts needed to contribute work inside The Debian OCaml Task Force and, in case of need, provides a place where to massively perform changes to all OCaml-related Debian packages.

In the past, we were using Subversion, but we are progressively migrating our packages to Git.

Debian users can benefit knowing we are using a Git repository (they can for instance subscribe to the RSS feed for changes or have a place where to look for finding patches corresponding to bugs tagged "pending" in the BTS).

For this reason it is recommended to add the Vcs-Git and Vcs-Browser fields to the debian/control of packages maintained in The Debian OCaml Task Force Git repository. Its name specifies that we are using Git as our Version Control System (VCS); their values are the URLs pointing to the package's repository and to a browsable view of the same directory. See the Debian Developer's Reference for more information about these fields.

The general scheme for using the fields are thus:

  Vcs-Git: git://git.debian.org/git/pkg-ocaml-maint/packages/PACKAGE_NAME.git
    Vcs-Browser: http://git.debian.org/?p=pkg-ocaml-maint/packages/PACKAGE_NAME.git
  

Example D.1. Usage example of the Vcs-* fields, from the findlib package

  Source: findlib
    Section: devel
    Priority: optional
    Maintainer: Debian OCaml Maintainers <debian-ocaml-maint@lists.debian.org>
    Uploaders: Stefano Zacchiroli <zack@debian.org>
    Build-Depends: debhelper (>> 5.0.0), ocaml (>= 3.11.0), camlp4 (>= 3.11.0), m4, gawk | awk, dpatch, cdbs, dh-ocaml
    Standards-Version: 3.8.0
    Vcs-Git: git://git.debian.org/git/pkg-ocaml-maint/packages/findlib.git
    Vcs-Browser: http://git.debian.org/?p=pkg-ocaml-maint/packages/findlib.git
    Homepage: http://projects.camlcity.org/projects/findlib.html

    Package: ocaml-findlib
    Section: devel
    Architecture: any
    Depends: ocaml-nox-${F:OCamlABI}, ${shlibs:Depends}, ${misc:Depends}
    Description: Management tool for OCaml programming language libraries
    ...
  


This document assumes that you have the following packages installed: git-buildpackage and pristine-tar.

How to obtain a copy of a package's Git repository

There is one Git repository per package. To get the list of packages managed with git, you can use the following command (your ssh must be configured properly):

  ssh git.debian.org ls /git/pkg-ocaml-maint/packages
  

You can obtain a copy of the repository for a package with:

  checkout-d-o-m-git-repo package
  

The checkout-d-o-m-git-repos script is available in the Subversion repository. You can get a copy with:

  svn co svn://svn.debian.org/svn/pkg-ocaml-maint/trunk/projects/git-guide
  

You must be member of the Debian OCaml Task Force in order to have the right to push to the central repository.

Structure of a Git repository

We keep all upstream sources under Git control, in a branch called upstream. This branch usually consists of successive unpacked upstream tarballs. When importing a new upstream tarball, the following command should be used:

  git-import-orig --pristine-tar [--no-dch] <name_version.orig.tar.gz>
  

The --pristine-tar is mandatory to store information for reconstructing the upstream tarball from the repository. That information is not suited for human use and is stored in the pristine-tar branch. Optionally, --no-dch can be given to automatically update the Debian changelog (without committing it).

The master branch contains upstream sources along with the debian/ directory. git-import-orig automatically creates a (local) tag in the upstream branch, and merges upstream into master when importing a new tarball. Changes related to Debian should be done in this branch.

How to add a new package

Let's take dose2 as an example. The following command (the new-d-o-m-git-repo is available at the same location of checkout-d-o-m-git-repo):

  new-d-o-m-git-repo dose2 /some/where/dose2-1.2.tar.gz
  

will create the remote repository on Alioth, set up notifications, and inject the given tarball in the repository in the upstream branch (using pristine-tar). More details there. You can then check it out and start using it.

If the tarball name is missing, new-d-o-m-git-repo will check that the current directory is a git repository, and then push it to Alioth. This allows you to create the repository locally, work on it, and only push it when it is in good shape. It is recommended to check it out after, and use the checked out version, to make sure everything went well, and to have local branches tracking remote ones.

How to set up your package for use with git-buildpackage

Put the following in debian/gbp.conf:

  # Configuration file for git-buildpackage and friends

    [DEFAULT]
    # the default branch for upstream sources:
    upstream-branch = upstream
    # the default branch for the debian patch:
    debian-branch = master
    # use pristine-tar:
    pristine-tar = True
  

The first two settings are not really useful since they are the defaults, but it might be handy to have them around when working with several branches. The pristine-tar is necessary if tarballs are imported. Please see the git-buildpackage documentation for complete information.

If you tried git-buildpackage before writing your debian/gbp.conf, remember to delete the .orig tarball, and rebuild after writing debian/gbp.conf. Alternatively, you can invoke git-buildpackage with the --git-pristine-tar option.

How to build a package with git-buildpackage

Please refer to the git-builpackage documentation for more complete information. Here is just a quick guide.

All options, except those starting on --git, are passed to dpkg-buildpackage. Hence, basic usage should be something like this (from the root of the repository): git-buildpackage -rfakeroot -uc -us. The package will be built in place, and the result will be put in the parent directory.

git-buildpackage will complain when your repository is not clean. You may use the option --git-ignore-new to override this behaviour.

If your package is ready for upload you may use the --git-tag option for the final build. This will create a tag in your local repository. Provided you have commited all your changes to the Git repository, this will after a successful build of the package create a tag for the current version.

Tip

Tags created by git-import-orig and git-buildpackage are not automatically pushed, you have to push them explicitly with the following command: git push --tags. Be careful if you use local tags!

You can add the --dry-run option to git push to see what will be done.

To build with pbuilder (or cowbuilder), use the following:

  git-buildpackage \
      --git-builder="pdebuild --debbuildopts '-I.git -i\.git -uc -us'" \
      --git-cleaner="fakeroot debian/rules clean"
  

Patches

We have not yet decided on how to deal with patches in upstream (this topic is under discussion). Possibilities include direct commits in the master branch, use of TopGit and quilt-serialized patches, and raw quilt or dpatch.

Quilt-serialized patches

Patches can be serialized using Git. Two tools are used to apply and save the patches in debian/patches/series.

  • dom-apply-patches: Creates the branch patch-queue and checkout it. Then, it applies all patches listed in debian/patches/series.

  • dom-save-patches:

    • Move back to branch master

    • Save all patches present in branch patch-queue (where each commit represents a patch to upstream) in debian/patches/

    • Update debian/patches/series

    • Remove branch patch-queue

The branch patch-queue is used only locally and should never be pushed.