Я использую несколько версий Python на своем компьютере: 2.6.6
, 2.7.6
и 2.7.9
. Когда я компилирую Boost с boost-python, я должен дать Python использовать аргумент. Если мне нужна совместимость, мне нужно скомпилировать Boost для каждой версии Python? (это довольно просто!) Или есть способ использовать только одну сборку Boost с несколькими версиями python?
Build Boost с несколькими версиями Python
Ответ 1
Официальный цикл Python не описывает стабильность бинарного интерфейса приложения (ABI) между выпусками. Для релизов перед Python 3.2 нет гарантии совместимости с ABI. Для 3.2 и выше PEP 384 определяет стабильную ABI, где гарантируется подмножество API Python/C для обеспечения совместимости с ABI. Чтобы использовать это подмножество, Py_LIMITED_API
необходимо определить при создании Boost.Python и модулей расширения.
В то время как это зависит в первую очередь от типов API Python/C API, которые используются непосредственно в коде пользователя или через Boost.Python, в общем случае:
- для выпусков основного уровня, таких как Python 2 и Python 3, Boost.Python и код пользователя необходимо будет перекомпилировать.
- для выпусков второстепенных уровней, таких как Python 2.6 и Python 2.7, Boost.Python и код пользователя, возможно, необходимо перекомпилировать.
- для выпусков на микроуровне, Boost.Python и код пользователя редко нуждаются в перекомпилированной работе.
Во всех случаях, когда Boost.Python необходимо перекомпилировать, никакая другая библиотека Boost не нуждается в повторной компиляции. При создании нескольких версий Boost.Python проверяется сборка clean. Без чистой сборки Boost.Python может создавать, но не правильно связывать. Например, символ PyClass_Type
не должен упоминаться в строках Python 3 Boost.Python, но без чистой сборки предыдущие артефакты сборки могут заполнять библиотеку:
$ ./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
Обратите внимание, что даже если сборка 3noclean
была построена против Python 3, в предыдущей сборке, использующей Python 2, были артефакты, которые загрязнили библиотеку 3noclean
. Кроме того, имейте в виду, что Boost.Python и код пользователя могут потребоваться перекомпилировать в соответствии с архитектурой процессора Python и конфигурациями Unicode UCS-2 или UCS-4.
Ответ 2
Начиная с Boost 1.67, вы можете создать boost, чтобы он генерировал отдельную версию libboost_python для каждой указанной вами версии Python без необходимости очищать или перестраивать как часть процесса.
Например, я редактирую tools/build/src/user-config.jam
чтобы он содержал версии Python в системе:
using python : 2.7 : /opt/python/cp27-cp27mu/bin/python : /opt/python/cp27-cp27mu/include/python2.7 : /opt/python/cp27-cp27mu/lib ;
using python : 3.5 : /opt/python/cp35-cp35m/bin/python : /opt/python/cp35-cp35m/include/python3.5m : /opt/python/cp35-cp35m/lib ;
using python : 3.6 : /opt/python/cp36-cp36m/bin/python : /opt/python/cp36-cp36m/include/python3.6m : /opt/python/cp36-cp36m/lib ;
using python : 3.7 : /opt/python/cp37-cp37m/bin/python : /opt/python/cp37-cp37m/include/python3.7m : /opt/python/cp37-cp37m/lib ;
Затем я запускаю ./b2 python=2.7,3.5,3.6,3.7
для этапа сборки.
Некоторые последующие пакеты ожидают, что библиотеки Python для повышения будут называться libboost_python.so
для Python 2.x и libboost_python3.so
для Python 3.x, и вам может потребоваться явно указать -lboost_python27
, -lboost_python35
и т.д., Чтобы получить эти программы. правильно связать.