README.rst 7.33 KB
Newer Older
André Anjos's avatar
André Anjos committed
1 2 3 4
.. vim: set fileencoding=utf-8 :
.. Andre Anjos <andre.anjos@idiap.ch>
.. Thu 30 Jan 08:46:53 2014 CET

André Anjos's avatar
André Anjos committed
5
.. image:: https://travis-ci.org/bioidiap/bob.extension.svg?branch=master
André Anjos's avatar
André Anjos committed
6
   :target: https://travis-ci.org/bioidiap/bob.extension
7 8
.. image:: http://img.shields.io/badge/docs-latest-orange.png
   :target: https://www.idiap.ch/software/bob/docs/latest/bioidiap/bob.extension/master/index.html
André Anjos's avatar
André Anjos committed
9 10
.. image:: https://coveralls.io/repos/bioidiap/bob.extension/badge.png
   :target: https://coveralls.io/r/bioidiap/bob.extension
André Anjos's avatar
André Anjos committed
11 12 13 14 15 16
.. image:: http://img.shields.io/github/tag/bioidiap/bob.extension.png
   :target: https://github.com/bioidiap/bob.extension
.. image:: http://img.shields.io/pypi/v/bob.extension.png
   :target: https://pypi.python.org/pypi/bob.extension
.. image:: http://img.shields.io/pypi/dm/bob.extension.png
   :target: https://pypi.python.org/pypi/bob.extension
André Anjos's avatar
André Anjos committed
17

18 19 20 21
===========================================
 Python/C++ Bob Extension Building Support
===========================================

22 23 24
This package provides a simple mechanims for building Python/C++ extensions for
`Bob <http://www.idiap.ch/software/bob/>`_. You use this package by including
it in your ``setup.py`` file.
25 26

Building with ``zc.buildout`` is possible using the ``develop`` recipe in
André Anjos's avatar
André Anjos committed
27
`bob.buildout <http://pypi.python.org/pypi/bob.buildout>`_. Follow the
28
instructions described on that package for this recipe.
29

30 31
Further documentation on this package can be found `here <https://www.idiap.ch/software/bob/docs/latest/bioidiap/bob.extension/master/index.html>`_.

32 33 34 35 36 37
Preparing for C++ Compilation
-----------------------------

Creating C++/Python bindings should be trivial. Firstly, edit your ``setup.py``
so that you include the following::

38
  from setuptools import dist
André Anjos's avatar
André Anjos committed
39
  dist.Distribution(dict(setup_requires=['bob.extension']))
40
  from bob.extension import Extension, Library, build_ext
41

42 43 44
  ...

  setup(
André Anjos's avatar
André Anjos committed
45

André Anjos's avatar
André Anjos committed
46
    name="bob.myext",
47 48 49 50
    version="1.0.0",
    ...

    setup_requires=[
André Anjos's avatar
André Anjos committed
51
        'bob.extension',
52 53 54 55
        ],

    ...
    ext_modules=[
André Anjos's avatar
André Anjos committed
56
      Extension("bob.myext._myext",
57
        [
André Anjos's avatar
André Anjos committed
58 59 60
          "bob/myext/ext/file1.cpp",
          "bob/myext/ext/file2.cpp",
          "bob/myext/ext/main.cpp",
61
        ],
62 63
        packages = [ #pkg-config modules to append
          'blitz>=0.10',
64 65 66 67
        ],
        bob_packages = [ #optionally, bob C++ modules to import
          "bob.core"
        ],
68
        include_dirs = [ #optionally, include directories
André Anjos's avatar
André Anjos committed
69
          "bob/myext/ext/headers/",
70 71
        ],
      ),
72 73 74
      ... #add more extensions if you wish
    ],

75 76 77 78
    cmdclass = {
      'build_ext': build_ext
    },

79
    ...
80
  )
81 82

These modifications will allow you to compile extensions that are linked
83 84
against the named ``pkg-config`` modules. Other modules and options can be set
manually using `the standard options for python extensions
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
<http://docs.python.org/2/extending/building.html>`_.

Adding pure C++ libraries
-------------------------

Most of the bob packages will include pure C++ code that can be used in other packages.
When your package should export a library with pure C++ code as well, you can build it with the ``Library`` extension.
You can simply add this ``Library`` to the list of ``ext_modules`` as follows::

  setup(
    ...
    ext_modules=[
      Library("bob_myext",
        [
          "bob/myext/ext/cpp/cppfile1.cpp",
          "bob/myext/ext/cpp/cppfile2.cpp",
        ],
        package_directory = os.path.dirname(os.path.realpath(__file__)),
        target_directory = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'bob', 'myext'),
        version = "1.0.0",
        bob_packages = [...],
        packages = [...],
        ...
      ),
      Extension("bob.my_ext._myext",
        ...
        libraries = ["bob_myext",...]
      )
    ],

    cmdclass = {
      'build_ext': build_ext
    },

    ...
  )

This will compile the given source files of the library using `CMake <http://www.cmake.org>`_.
Please assure that the name of the library ``bob_myext`` is compatible with your package name so that the library can be imported in other packages using the ``bob_packages`` list.

Also, it is assumed that **all** header files that are exported by the C++ library are listed in the *bob/myext/include* directory.
This directory is automatically added to the list of include directories -- in your own package and in all other packages that use the ``bob_packages`` list.

Compiling the module
--------------------

To hook-in the building on the package through ``zc.buildout``, add the following section to your ``buildout.cfg``::
132

André Anjos's avatar
André Anjos committed
133 134
  [bob.myext]
  recipe = bob.buildout:develop
135 136
  verbose = true ;enables command-line verbosity
  debug = true ;compiles the module in debug mode
137 138 139 140 141 142

If you need to build multiple eggs, you will need **one entry per project** on
your ``buildout.cfg``. This includes, possibly, dependent projects. Currently,
``zc.buildout`` ignores the ``setup_requires`` entry on your ``setup.py`` file.
The recipe above creates a new interpreter that hooks that package in and
builds the project considering variables like ``prefixes`` into consideration.
André Anjos's avatar
André Anjos committed
143

144 145 146 147 148 149 150 151 152 153
By default, the extension code is compiled into a local directory called ``build``.
This directory, after compilation, can be removed without issues, the resulting libraries will be copied into the package directories.
To change the build directory of your package, and all other bob packages, you can define the ``BOB_BUILD_DIRECTORY`` environment variable, e.g.,::

  $ python bootstrap.py
  $ BOB_BUILD_DIRECTORY=/tmp/bob_build_dir ./bin/buildout

Again, after successful compilation, this directory can be removed safely.


154 155
Python API to pkg-config and Boost
----------------------------------
André Anjos's avatar
André Anjos committed
156 157 158 159 160 161

This package alson contains a set of Pythonic bindings to the popular
pkg-config configuration utility. It allows distutils-based setup files to
query for libraries installed on the current system through that command line
utility.  library.

162 163
Using the ``pkgconfig`` class
=============================
André Anjos's avatar
André Anjos committed
164 165 166 167 168 169

To use this package at your ``setup.py`` file, you will need to let distutils
know it needs it before importing it. You can achieve this with the following
trick::

  from setuptools import dist
André Anjos's avatar
André Anjos committed
170 171
  dist.Distribution(dict(setup_requires='bob.extension'))
  from bob.extension.pkgconfig import pkgconfig
André Anjos's avatar
André Anjos committed
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191

.. note::

   In this case, distutils should automatically download and install this
   package on the environment it is required to setup other package.

After inclusion, you can just instantiate an object of type ``pkgconfig``::

  >>> zlib = pkgconfig('zlib')
  >>> zlib.version # doctest: SKIP
  1.2.8
  >>> zlib.include_directories() # doctest: SKIP
  ['/usr/include']
  >>> zlib.library_dirs # doctest: SKIP
  ['/usr/lib']
  >>> zlib > '1.2.6'
  True
  >>> zlib > '1.2.10'
  False

192 193 194 195 196 197 198 199

Using the ``boost`` class
=========================

To use this package at your ``setup.py`` file, you will also need the same
trick as with ``pkgconfig``::

  from setuptools import dist
André Anjos's avatar
André Anjos committed
200 201
  dist.Distribution(dict(setup_requires='bob.extension'))
  from bob.extension.boost import boost
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216

After inclusion, you can just instantiate an object of type ``boost``::

  >>> boost_pkg = boost('>= 1.47')
  >>> boost.version # doctest: SKIP
  1.50.0
  >>> boost.include_directory # doctest: SKIP
  '/usr/include'
  >>> libpaths, libnames = boost.libconfig(['system', 'python'])
  >>> print(libpaths) # doctest: SKIP
  ['/usr/lib']
  >>> print(libnames) # doctest: SKIP
  ['boost_system-mt', 'boost_python-mt-py27']