Build Boost with multiple Python versions

Caduchon picture Caduchon · Mar 3, 2015 · Viewed 12.9k times · Source

I use several versions of Python on my computer : 2.6.6, 2.7.6 and 2.7.9. When I compile Boost with boost-python, I have to give the Python to use in argument. If I want compatibility, have I to compile Boost for each Python version ? (it's quite huge !) Or is there a way to use only one build of Boost with several python versions ?

Answer

Tanner Sansbury picture Tanner Sansbury · Mar 6, 2015

The official Python development cycle does not describe the stability of the application binary interface (ABI) between releases. For releases before Python 3.2, there is no guarantee for ABI compatibility. For 3.2 and beyond, PEP 384 defines the stable ABI where a subset of the Python/C API is guaranteed to maintain ABI compatibility. To use this subset, Py_LIMITED_API needs to be defined when building Boost.Python and extension modules.

While it primarily depends on the Python/C API types and functionality being used directly in user code or through Boost.Python, in general:

  • for major-level releases, such as Python 2 and Python 3, Boost.Python and user code will need to be recompiled
  • for minor-level releases, such as Python 2.6 and Python 2.7, Boost.Python and user code may need to be recompiled
  • for micro-level releases, Boost.Python and user code rarely needs recompiled

In all cases where Boost.Python needs to be recompiled, no other Boost library should need to be recompiled. When building multiple versions of Boost.Python, verify a clean build occurs. Without a clean build, Boost.Python may build, but fail to properly link. For example, the PyClass_Type symbol should not be referenced in Python 3 Boost.Python builds, but without a clean build, previous build artifacts may populate the library:

$ ./bootstrap.sh --with-python=/usr/bin/python2
...
Detecting Python version... 2.7
$ ./b2 --with-python --buildid=2 # produces libboost_python-2.so
$ ./bootstrap.sh --with-python=/usr/bin/python3 --with-python-root=/usr
...
Detecting Python version... 3.3
$ ./b2 --with-python --buildid=3noclean # produces libboost_python-3noclean.so
$ ./b2 --with-python --clean
$ ./b2 --with-python --buildid=3 # produces libboost_python-3.so

$ nm -D stage/lib/libboost_python-2.so | grep PyClass_Type
                 U PyClass_Type
$ nm -D stage/lib/libboost_python-3noclean.so | grep PyClass_Type
                 U PyClass_Type
$ nm -D stage/lib/libboost_python-3.so | grep PyClass_Type

Note that even though the 3noclean build was built against Python 3, the previous build that was using Python 2 had artifacts that polluted the 3noclean library. Also, be aware that Boost.Python and user code may need recompiled to match the Python's CPU architecture and UCS-2 or UCS-4 unicode configurations.