使用多个 Python 版本构建 Boost
Build Boost with multiple Python versions
我在我的计算机上使用了几个版本的 Python:2.6.6
、2.7.6
和 2.7.9
。当我使用 boost-python 编译 Boost 时,我必须提供 Python 以在参数中使用。如果我想要兼容性,我必须为每个 Python 版本编译 Boost 吗?(它非常庞大!)或者有没有办法只使用一个构建的 Boost 和多个 python 版本 ?
官方 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 其中 Python/C API 的子集保证保持 ABI 兼容性。要使用此子集,需要在构建 Boost.Python 和扩展模块时定义 Py_LIMITED_API
。
虽然它主要取决于直接在用户代码中或通过 Boost.Python 使用的 Python/C API 类型和功能,但一般来说:
- 对于主要级别的版本,例如Python 2 和Python 3,Boost.Python 和用户代码将需要重新编译
- 对于次要版本,例如 Python 2.6 和 Python 2.7,Boost.Python 和用户代码可能需要重新编译
- 对于微级别发布,Boost.Python 用户代码很少需要重新编译
在所有 Boost.Python 需要重新编译的情况下,不需要重新编译其他 Boost 库。在构建 Boost.Python 的多个版本时,验证 clean 构建是否发生。如果没有干净的构建,Boost.Python 可能会构建,但无法正确构建 link。例如,不应在 Python 3 Boost.Python 构建中引用 PyClass_Type
符号,但如果没有干净的构建,以前的构建工件可能会填充库:
$ ./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 的 CPU 体系结构和 UCS-2 或 UCS-4 unicode 配置。
从 Boost 1.67 开始,您可以构建 boost,以便它为您指定的每个版本的 Python 生成一个单独的 libboost_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
进行构建步骤。
一些下游包期望 boost python 库被调用 libboost_python.so
for Python 2.x 和 libboost_python3.so
for Python 3.x,并且您可能需要明确指定 -lboost_python27
、-lboost_python35
等才能使这些程序正确地 link。
我在我的计算机上使用了几个版本的 Python:2.6.6
、2.7.6
和 2.7.9
。当我使用 boost-python 编译 Boost 时,我必须提供 Python 以在参数中使用。如果我想要兼容性,我必须为每个 Python 版本编译 Boost 吗?(它非常庞大!)或者有没有办法只使用一个构建的 Boost 和多个 python 版本 ?
官方 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 其中 Python/C API 的子集保证保持 ABI 兼容性。要使用此子集,需要在构建 Boost.Python 和扩展模块时定义 Py_LIMITED_API
。
虽然它主要取决于直接在用户代码中或通过 Boost.Python 使用的 Python/C API 类型和功能,但一般来说:
- 对于主要级别的版本,例如Python 2 和Python 3,Boost.Python 和用户代码将需要重新编译
- 对于次要版本,例如 Python 2.6 和 Python 2.7,Boost.Python 和用户代码可能需要重新编译
- 对于微级别发布,Boost.Python 用户代码很少需要重新编译
在所有 Boost.Python 需要重新编译的情况下,不需要重新编译其他 Boost 库。在构建 Boost.Python 的多个版本时,验证 clean 构建是否发生。如果没有干净的构建,Boost.Python 可能会构建,但无法正确构建 link。例如,不应在 Python 3 Boost.Python 构建中引用 PyClass_Type
符号,但如果没有干净的构建,以前的构建工件可能会填充库:
$ ./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 的 CPU 体系结构和 UCS-2 或 UCS-4 unicode 配置。
从 Boost 1.67 开始,您可以构建 boost,以便它为您指定的每个版本的 Python 生成一个单独的 libboost_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
进行构建步骤。
一些下游包期望 boost python 库被调用 libboost_python.so
for Python 2.x 和 libboost_python3.so
for Python 3.x,并且您可能需要明确指定 -lboost_python27
、-lboost_python35
等才能使这些程序正确地 link。