setup.py: 运行 build_ext 先于其他

setup.py: run build_ext before anything else

我正在使用 setup.py 在 build_ext 步骤中创建一大堆 SWIG 接口文件。这需要先 运行,因为后续构建步骤需要 python 文件的完整列表才能正常工作(比如将 python 文件复制到包目录,创建 egg,创建源列表等)。

这就是当您执行 setup.py install:

时当前发生的情况
running install
running bdist_egg
running egg_info
running install_lib
running build_py
running build_ext

build_py 步骤尝试将它找到的所有 python 文件复制到构建目录。这些文件直到 build_ext 运行s 才存在(swig 创建了一堆 .py 文件)。

This answer 建议更改 sub_commands 但这似乎没有任何作用。

我试过将 install 命令 class 像这样子 class 到 运行 build_ext 之前:

class Build_ext_first(setuptools.command.install.install):
    def run(self):
        self.run_command("build_ext")
        super(Build_ext_first, self).run()

..然后使用 cmdclass:

进行设置
setup(
    ...
    cmdclass = {'install' : Build_ext_first}
)

但这没有用,因为 super 不适用于旧式 classes 并且 install 显然不继承自 object

我如何先build_ext

看来旧的 super() 方法是向前兼容的,所以我就这样做了:

class Build_ext_first(setuptools.command.install.install):
    def run(self):
        self.run_command("build_ext")
        return setuptools.command.install.install.run(self)


setup(
    ...,
    cmdclass = {'install' : Build_ext_first}
)

因为害怕 post 对 2 岁的孩子 post。我认为解决这个问题的正确方法是在 "build" 阶段修复它:

from setuptools import setup, find_packages, Extension
from setuptools.command.build_py import build_py as _build_py    

class build_py(_build_py):
    def run(self):
        self.run_command("build_ext")
        return super().run()

setup(...,
    cmdclass = {'build_py' : build_py},
)

这种方式适用于 bdist_wheel 以及安装(尚未测试其他内容)。

请注意 super 语法在 Python 2 中略有不同:

class build_py(_build_py):
    def run(self):
        self.run_command("build_ext")
        return _build_py.run(self)