One of the software packages (xraylib) I am working on, consists of a C-library with bindings to a number of other languages such as Python, Fortran 2003, IDL, Java, Ruby, Lua and Perl. Apart from IDL and Fortran 2003, the source code for these bindings is generated automatically using swig, although with considerable language-specific modifications to the swig interface file.
The bindings source code afterwards needs to be compiled into a dynamically loadable library, which will then be loaded at runtime by the program whenever the user needs to use a function or variable from the bindings (actually from the underlying C-library, but exposed through the swig generated bindings). As a rule, each programming language that supports such dynamically loadable libraries comes with specific instructions on how to generate the libraries from the bindings source code, often using platform independent tools.
However, these tools never seem to integrate well with autoconf and automake and lead to quite complicated Makefile.am files. A considerable more easy approach would consist of relying on libtool’s functionality of generating these dynamically loadable libraries (called modules in the libtool documentation). In this series of posts I will share my experiences on generating bindings to the aforementioned languages using libtool in a relatively clear and easy way. All the code has been tested on Linux and Mac OS X. It may also work on Windows though, provided you install a bash shell with the required tools.
In this first post I will discuss Python extension modules.
Checking for python development tools
If you want to create an autotools based project consisting of a C-library and python bindings, then one of the first things that configure will need to check for is the presence of the python interpreter and the development kit consisting of the python headers and some essential tools. I accomplished this by adding the following lines into configure.ac
As can be seen from this snippet, I depend on two m4 macros to obtain the required information: AM_PATH_PYTHON, which searches for Python interpreter and subsequently sets a number of variables that will be used at installation time, and AX_PYTHON_DEVEL (I am using a heavily modified version of the code found at autoconf archives), which will check for the required headers and perform a test compilation to make sure everything works.
Writing the Makefile.am
The Python way of building and installing extensions relies on the Distutils package, and is guaranteed to work on all platforms but integrates with difficulty into autotools based installation scripts.
However, recent versions of automake come with built-in support for installing python source files (and even byte-compile them), and comes with some recommendations on how to build your Python extensions module (possibly linked to a C-library as in our case) using libtool. The following example code is based upon these recommendations but also contains additional Makefile targets that deal with generating the Python extension module source through swig. Let’s assume our original C-library is called
mytest, and is located in the
src subfolder of the source tree. The Python bindings will be built in the
In this example, I followed the Python recommendations with regard to naming the extension module:
In this case, the accompanying Python module will be automatically generated by swig, and will be called
mytest.py, while the extension module will receive the libtool name
_mytest.la. The actual library extension will be platform dependent (.so on Linux/Mac OS X, .dll on Windows).
When writing an autotools based project using these guidelines, you should have no problem compiling and installing your python bindings and the C-library it depends on, with the familiar commands:
The full code follows: as usual it’s a github gist so feel free to clone it and hack away at it.