CDBS + Autotools + Python

There is a bit of an art to getting CDBS to build packages with Python extensions made with autotools, so hopefully this will help someone. This might be appropriate where you have a library which ships with some Python modules you wish to package.

The basic idea is to re-build separate trees for the various Python versions you wish to support, and then install these separate builds to the same place before creating the final package.

  1. Firstly, add an XS line to the top of your control file with the Python versions to support, such as XS-Python-Version: >=2.3. Then get this into a variable in your rules file with pyversions

    PY_VERSIONS = $(shell pyversions --requested debian/control)

    You'll also want build dependencies on python-all-dev, python-central (>= 0.5).

  2. Your Python package also needs to be setup with the correct variables so it has the right dependencies, etc, something like

    Package: python-package
    Architecture: any
    Section: python
    Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends}
    Provides: ${python:Provides}
    XB-Python-Version: ${python:Versions}
    Description: Python bindings for blah
     Description here
  3. Now the magic is to get multiple builds for each version of Python requested. The first thing to do is add a configure/python-packagename target which will get called early in the package creation phase. In standard make we can make this target depend on "stamp" files for each version of python we need to support. For example

    configure/python-packagename:: $(addprefix configure-stamp-, $(PY_VERSIONS))

    which expands to something like

    configure/python-packagename:: configure-stamp-2.3 configure-stamp-2.4 configure-stamp-2.5
  4. Now we make a implicit rule for anything called configure-stamp-% which will setup separate build directories for the different Python versions.

            mkdir build-$*
            cd build-$* && PYTHON=`which $*` $(DEB_CONFIGURE_SCRIPT_ENV) \
                $(DEB_CONFIGURE_SCRIPT) \
                    $(DEB_CONFIGURE_NORMAL_ARGS) \
                    --disable-maintainer-mode \
                    $(cdbs_configure_flags) \
                    $(DEB_CONFIGURE_EXTRA_FLAGS) \
            touch $@

    You may want to tweak this, and it may be a bit fragile if CDBS decides to change the names of things.

  5. Now we have our extra versions configured, we have to organise actually building them. Do the same thing to create some build stamps, and in the implicit build-stamp rule change to the appropriate build directory.

            make -C build-$*
            touch $@
    build/python-package:: $(addprefix build-stamp-, $(PY_VERSIONS))
  6. Do the same thing for the install step -- hopefully what happens in this stage is that each build will put its shared libraries in /usr/lib/python2.*/site-packages/. Then it is a matter of putting them in python-package.install to be copied.

            make -C build-$* install DESTDIR=$(CURDIR)/debian/tmp
            touch $@
    install/python-package:: $(addprefix install-stamp-, $(PY_VERSIONS))
  7. To setup the right variables, etc, you need to call dh_pycentral for your package on binary-install. See the Python Policy for details on what this will do, especially if you are shipping Python files which need to be pre-compiled.

  8. Finally, clean up by extending the clean rule.

            -rm -rf $(addprefix build-, $(PY_VERSIONS))
            -rm -rf $(addprefix configure-stamp-, $(PY_VERSIONS))
            -rm -rf $(addprefix build-stamp-, $(PY_VERSIONS))
            -rm -rf $(addprefix install-stamp-, $(PY_VERSIONS))

Thanks to Sebastien Bacher, who I think came up with this scheme originally for gnome-menus.