使用调试Python安装在Windows上构建Python-C-Extension

发布于 2021-01-29 15:00:39

如果我从Windows上的源代码构建CPython,则在要点安装包含C-Extension的软件包时会遇到问题。似乎在链接库时发生错误。

例如,在安装cython时(但在其他C扩展软件包上,它也因相同的错误而崩溃):

链接:致命错误LNK1104:无法打开文件’python38.lib’

错误:命令’C:\ Program Files(x86)\ Microsoft Visual Studio \ 2019 \ Enterprise \
VC \ Tools \ MSVC \ 14.23.28105 \ bin \ HostX86 \ x86 \
link.exe’失败,退出状态为1104

它无法打开“ python38.lib”的原因是因为在调试模式下的“ .lib”文件称为“ python38_d.lib”。

一个最小的可复制示例是(在命令行上)基于CPython开发人员指南快速参考

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'}

有什么我想念的吗?是否完全不支持在Windows上的Python调试版本上构建C-Extensions?如果支持:我该怎么办?

关注者
0
被浏览
122
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    pythonXY.lib在Windows上,针对的链接有点偷偷摸摸。当您查看用于链接的命令行时,您会看到没有python库传递给链接器,即’link.exe’。注意:对于Linux也是如此,但是在Linux上则不必这样做,因为所需的符号将由python-
    executable提供。

    但是,很容易通过来检查是否 dumpbin /dependents resulting.pyd存在依赖关系pythonXY.dll,并且还extra_link_args = ["/VERBOSE:LIB"]对扩展定义进行了添加,并且触发链接器的详细模式将显示该链接器使用pythonXY.lib

    偷偷摸摸的部分:Microsoft Compler具有便利的编译指示,#pragma comment(lib, ...)可以自动触发库的链接,该链接也用在Python标头中

    #               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 */
    

    如您所见,要链接到调试版本,需要定义_DEBUG

    _DEBUGdistutilsWindows自动定义,如果build_ext通过options调用--debug,例如

    python setup.py build_ext -i --debug
    

    可以翻译pip

    pip install --global-option build --global-option --debug XXXXX
    

    它可以大致解释为:触发build命令(还包括build_ext-command),--debug在安装前带有选项。


    构建调试C扩展时的另一种功能,在Windows上还有更多功能

    #ifdef _DEBUG
    #       define Py_DEBUG
    #endif
    

    Python3.8之前定义 Py_DEBUG宏意味着无与伦比的ABI
    ,因为它还假设这会导致发布模式的不同内存布局以及某些其他功能缺失。Py_TRACE_REFSPyObject

    但是,从Python3.8开始,通过提供缺少的pythonXY_d.lib/pythonYX.lib作为链接到另一个版本的符号链接,可能可以摆脱它。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看