使用调试 Python 安装在 Windows 上构建 Python-C-Extension
Building a Python-C-Extension on Windows with a debug Python installation
如果我在 Windows 上从源代码构建 CPython,当我想 pip 安装包含 C-Extension 的包时遇到问题。链接库时似乎发生了错误。
例如安装cython时(但在其他C扩展包上也会出现同样的错误):
LINK : fatal error LNK1104: cannot open file 'python38.lib'
error: command 'C:\Program Files (x86)\Microsoft Visual Studio19\Enterprise\VC\Tools\MSVC.23.28105\bin\HostX86\x86\link.exe' failed with exit status 1104
打不开“python38.lib”是因为调试模式下的“.lib”文件调用的是“python38_d.lib”。
一个最小的可重现示例是(在命令行上)基于 Quick Reference of the CPython developer guide:
git clone --branch v3.8.0 https://github.com/python/cpython.git
cd cpython
git checkout v3.8.0
.\PCbuild\build.bat -e -d
.\PCbuild\win32\python_d.exe -m ensurepip
.\PCbuild\win32\python_d.exe -m pip install pip --upgrade -vv
.\PCbuild\win32\python_d.exe -m pip install setuptools --upgrade -vv
.\PCbuild\win32\python_d.exe -m pip install cython -vv
结果distutils.sysconfig.get_config_vars()
是:
{'BINDIR': '...\cpython\PCbuild\win32',
'BINLIBDEST': ...\cpython\Lib',
'EXE': '.exe',
'EXT_SUFFIX': '_d.cp38-win32.pyd',
'INCLUDEPY': '...\cpython\include;...\cpython\PC',
'LIBDEST': '...\cpython\Lib',
'SO': '_d.cp38-win32.pyd',
'VERSION': '38',
'exec_prefix': '...\cpython',
'prefix': '...\cpython',
'srcdir': '...\cpython'}
有什么我想念的吗?是否在 Python 上构建 C-Extensions-debug 构建在 Windows 上根本不受支持?如果支持:我该怎么做?
针对 pythonXY.lib
的链接在 Windows 上有点偷偷摸摸。当您查看 linking 的命令行时,您会看到没有 python-library 传递给 linker,即“link.exe”。注意:这也是 Linux 的情况,但在 Linux 上则不必,因为所需的符号将由 python-可执行文件提供。
然而,很容易to check via dumpbin /dependents resulting.pyd
,有对pythonXY.dll
的依赖,同时将extra_link_args = ["/VERBOSE:LIB"]
添加到扩展定义并触发详细模式linker 会显示 linker 使用 pythonXY.lib
.
偷偷摸摸的部分:Microsoft Compler 有一个 convinience-pragma #pragma comment(lib, ...)
to automatically trigger linking of a library, which is also used in Python-headers:
# if defined(_MSC_VER)
/* So MSVC users need not specify the .lib
file in their Makefile (other compilers are
generally taken care of by distutils.) */
# if defined(_DEBUG)
# pragma comment(lib,"python39_d.lib")
# elif defined(Py_LIMITED_API)
# pragma comment(lib,"python3.lib")
# else
# pragma comment(lib,"python39.lib")
# endif /* _DEBUG */
# endif /* _MSC_VER */
如你所见,要link针对debug版本,需要定义_DEBUG
.
_DEBUG
由 distutils
在 Windows 上自动定义,如果 build_ext
使用选项 --debug
调用,例如
python setup.py build_ext -i --debug
可以 translated to pip
为
pip install --global-option build --global-option --debug XXXXX
可以大致解释为:在安装之前触发 build
命令(其中还包括 build_ext
-命令)和选项 --debug
。
构建调试 C 扩展时的另一个巧妙之处是 more to it on Windows:
#ifdef _DEBUG
# define Py_DEBUG
#endif
定义 Py_DEBUG
宏意味着不兼容的 ABI until Python3.8, because it also assumed Py_TRACE_REFS
这会导致 PyObject
的内存布局不同,并且在发布模式中缺少一些附加功能。
然而,由于 Python3.8,人们可能可以通过提供缺失的 pythonXY_d.lib
/pythonYX.lib
作为 symlink link 到另一个版本。
这段代码有点 hacky,但适用于 MSVC19,允许调试应用程序而无需构建调试 python 库。
#ifdef _DEBUG
#define _DEBUG_WAS_DEFINED
#undef _DEBUG
#endif
#include "Python.h"
#ifdef _DEBUG_WAS_DEFINED
#define _DEBUG
#undef _DEBUG_WAS_DEFINED
#endif
如果我在 Windows 上从源代码构建 CPython,当我想 pip 安装包含 C-Extension 的包时遇到问题。链接库时似乎发生了错误。
例如安装cython时(但在其他C扩展包上也会出现同样的错误):
LINK : fatal error LNK1104: cannot open file 'python38.lib'
error: command 'C:\Program Files (x86)\Microsoft Visual Studio19\Enterprise\VC\Tools\MSVC.23.28105\bin\HostX86\x86\link.exe' failed with exit status 1104
打不开“python38.lib”是因为调试模式下的“.lib”文件调用的是“python38_d.lib”。
一个最小的可重现示例是(在命令行上)基于 Quick Reference of the CPython developer guide:
git clone --branch v3.8.0 https://github.com/python/cpython.git
cd cpython
git checkout v3.8.0
.\PCbuild\build.bat -e -d
.\PCbuild\win32\python_d.exe -m ensurepip
.\PCbuild\win32\python_d.exe -m pip install pip --upgrade -vv
.\PCbuild\win32\python_d.exe -m pip install setuptools --upgrade -vv
.\PCbuild\win32\python_d.exe -m pip install cython -vv
结果distutils.sysconfig.get_config_vars()
是:
{'BINDIR': '...\cpython\PCbuild\win32',
'BINLIBDEST': ...\cpython\Lib',
'EXE': '.exe',
'EXT_SUFFIX': '_d.cp38-win32.pyd',
'INCLUDEPY': '...\cpython\include;...\cpython\PC',
'LIBDEST': '...\cpython\Lib',
'SO': '_d.cp38-win32.pyd',
'VERSION': '38',
'exec_prefix': '...\cpython',
'prefix': '...\cpython',
'srcdir': '...\cpython'}
有什么我想念的吗?是否在 Python 上构建 C-Extensions-debug 构建在 Windows 上根本不受支持?如果支持:我该怎么做?
针对 pythonXY.lib
的链接在 Windows 上有点偷偷摸摸。当您查看 linking 的命令行时,您会看到没有 python-library 传递给 linker,即“link.exe”。注意:这也是 Linux 的情况,但在 Linux 上则不必,因为所需的符号将由 python-可执行文件提供。
然而,很容易to check via dumpbin /dependents resulting.pyd
,有对pythonXY.dll
的依赖,同时将extra_link_args = ["/VERBOSE:LIB"]
添加到扩展定义并触发详细模式linker 会显示 linker 使用 pythonXY.lib
.
偷偷摸摸的部分:Microsoft Compler 有一个 convinience-pragma #pragma comment(lib, ...)
to automatically trigger linking of a library, which is also used in Python-headers:
# if defined(_MSC_VER)
/* So MSVC users need not specify the .lib
file in their Makefile (other compilers are
generally taken care of by distutils.) */
# if defined(_DEBUG)
# pragma comment(lib,"python39_d.lib")
# elif defined(Py_LIMITED_API)
# pragma comment(lib,"python3.lib")
# else
# pragma comment(lib,"python39.lib")
# endif /* _DEBUG */
# endif /* _MSC_VER */
如你所见,要link针对debug版本,需要定义_DEBUG
.
_DEBUG
由 distutils
在 Windows 上自动定义,如果 build_ext
使用选项 --debug
调用,例如
python setup.py build_ext -i --debug
可以 translated to pip
为
pip install --global-option build --global-option --debug XXXXX
可以大致解释为:在安装之前触发 build
命令(其中还包括 build_ext
-命令)和选项 --debug
。
构建调试 C 扩展时的另一个巧妙之处是 more to it on Windows:
#ifdef _DEBUG
# define Py_DEBUG
#endif
定义 Py_DEBUG
宏意味着不兼容的 ABI until Python3.8, because it also assumed Py_TRACE_REFS
这会导致 PyObject
的内存布局不同,并且在发布模式中缺少一些附加功能。
然而,由于 Python3.8,人们可能可以通过提供缺失的 pythonXY_d.lib
/pythonYX.lib
作为 symlink link 到另一个版本。
这段代码有点 hacky,但适用于 MSVC19,允许调试应用程序而无需构建调试 python 库。
#ifdef _DEBUG
#define _DEBUG_WAS_DEFINED
#undef _DEBUG
#endif
#include "Python.h"
#ifdef _DEBUG_WAS_DEFINED
#define _DEBUG
#undef _DEBUG_WAS_DEFINED
#endif