Python 使用setuptools和swig构建模块
我有很多SWIG接口(foo.I、bar.I等)。我想使用setuptools将它们构建到我的平台(MS Windows)的Python(3.6.4)模块中。该模块应包括SWIG生成的Python文件(*.py)、二进制扩展(*.pyd)和编译的缓存(*.pyc)。My setup.py本质上是这样的:Python 使用setuptools和swig构建模块,python,python-3.x,swig,setuptools,Python,Python 3.x,Swig,Setuptools,我有很多SWIG接口(foo.I、bar.I等)。我想使用setuptools将它们构建到我的平台(MS Windows)的Python(3.6.4)模块中。该模块应包括SWIG生成的Python文件(*.py)、二进制扩展(*.pyd)和编译的缓存(*.pyc)。My setup.py本质上是这样的: from setuptools import setup, Extension from pathlib import Path paths=list(Path('.').glob('*.i')
from setuptools import setup, Extension
from pathlib import Path
paths=list(Path('.').glob('*.i'))
py=[path.stem for path in paths]
ext=[Extension('_' + path.stem, [str(path)]) for path in paths]
setup(py_modules=py, ext_modules=ext)
ext=[Extension(name='_' + path.stem,
sources=[str(path)],
swig_opts=['-I../include', '-c++'],
include_dirs=['../include'])
for path in paths]
现在,我通过以下步骤构建它:
python setup.py build_ext -I..\include --swig-opts="-I..\include -c++" -b pkg
python setup.py build_py -c -d pkg
echo. > pkg\__init__.py
通过这些步骤,我在pkg
目录下得到了我想要的东西
我的问题是:使用一次调用setup.py
,例如setup.py build
,是否无法获得这种效果?我认为构建应该调用build_ext,但是我看不到如何传递,例如swig opts选项
更新
通过SWIG选项已解决(h/t@hoefling)。解决方案如下所示:
from setuptools import setup, Extension
from pathlib import Path
paths=list(Path('.').glob('*.i'))
py=[path.stem for path in paths]
ext=[Extension('_' + path.stem, [str(path)]) for path in paths]
setup(py_modules=py, ext_modules=ext)
ext=[Extension(name='_' + path.stem,
sources=[str(path)],
swig_opts=['-I../include', '-c++'],
include_dirs=['../include'])
for path in paths]
然而,随着洋葱层的剥落,我现在可以看到下面的一层,即:setup.py build
作为一个调用,希望首先运行build\u py
,然后运行build\u ext
。你能理解为什么这个失败吗?我没有Python源代码。我的模块中的Python脚本将由SWIG生成,但SWIG只有在build\u ext
步骤中才能运行。因此,我以同样的问题结束,那就是如何在一次调用中构建模块
C:\some\path> python setup.py build
running build
running build_py
file foo.py (for module foo) not found
file foo.py (for module foo) not found
running build_ext
building '_foo' extension
swigging foo.i to foo_wrap.cpp
swig.exe -python -I../include -c++ -o foo_wrap.cpp foo.i
creating build
creating build\temp.win-amd64-3.6
creating build\temp.win-amd64-3.6\Release
cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -I../include /EHsc /Tpfoo_wrap.cpp /Fobuild\temp.win-amd64-3.6\Release\foo_wrap.obj foo_wrap.cpp
Creating build\wib.win-amd64-3.6
link.exe /nologo /INCREMENTAL:NO /LTCG /DLL /MANIFEST:EMBED,ID=2 /MANIFESTUAC:NO /EXPORT:PyInit__foo build\temp.win-amd64-3.6\Release\foo_wrap.obj /IMPLIB:build\temp.win-amd64-3.6\Release\_foo.cp36-win_amd64.lib
Creating library build\temp.win-amd64-3.6\Release\_foo.cp36-win_amd64.lib and object build\temp.win-amd64-3.6\Release\_foo.cp36-win_amd64.exp
Generating code
Finished generating code
完成后,foo.py存在于foo.i旁边的当前工作目录中,而_foo.cp36-win_amd64.pyd存在于build\lib.win-amd64-3.6下。(仅供参考,为了保护专有信息,我对该成绩单进行了轻微编辑,例如,我没有显示所有命令回音的完整路径。我也没有在源代码中包含bar.I。)
澄清:
找不到文件foo.py(用于模块foo)
问题是,一旦您声明
py_模块
,distutils
在build
中包含build_py
子命令,并且由于build
类中的sub_命令
列表的顺序,它总是首先执行。它根本不知道SWIG稍后将在build\u ext
中生成python模块包装器。我想你可以把这看作是一个bug,因为人们期望distutils
能够处理生成的模块,但是meh
由于您只有SWIG接口,并且所有python模块都是生成的包装器(因此在您的情况下,build\u ext
不依赖于build\u py
),因此您可以更改build
中子命令的顺序,以便首先执行build\u ext
,然后执行其余命令。这将确保在执行build\u py
之前生成python模块
基本上,您需要重写build
命令类,并更改sub_命令
列表中元素的顺序。在python中有很多方法可以对列表重新排序;下面是我的建议。为了对列表进行重新排序,我使用了列表条件分区配方:
由于基本思想(参见@hoefling的答案)是对build命令进行子类化,以设置其sub_commands属性,因此这是有效的:
from setuptools import setup, Extension
from distutils.command.build import build
class build_alt_order(build):
def __init__(self, *args):
super().__init__(*args)
self.sub_commands = [('build_ext', build.has_ext_modules),
('build_py', build.has_pure_modules)]
setup(py_modules=['foo.py', ...],
ext_modules=[Extension('_foo', swig_opts=...), ...],
cmdclass={'build':build_alt_order})
在setup.py
中集成了一个带有SWIG的演示项目。
它有两个扩展。
其中一个(C。)是C,另一个是C++,带有STL(STLLIGH.SPEP,CPP)。
生成的py文件丢失的问题也可以通过类BuildPy(build\u py)
解决
build\u ext
支持开箱即用的SWIG,因此扩展名(名称、文件、SWIG\u opts=['-I../include','-c++'])
应该可以正常生成。@hoefling这对于传递SWIG选项是正确的,谢谢。至于其他错误-您能发布完整的错误消息吗?只需将文本从终端复制并粘贴到您的问题中。啊,我现在知道问题是什么了。执行此操作,并解释如何执行此操作。或者,这里有一个稍微简单的版本,我发现它也更通用,因为它也适用于安装
: