简体   繁体   English

python distutils不包括SWIG生成的模块

[英]python distutils not include the SWIG generated module

I am using distutils to create an rpm from my project. 我正在使用distutils从我的项目中创建一个rpm。 I have this directory tree: 我有这个目录树:

project/
        my_module/
                 data/file.dat
                 my_module1.py
                 my_module2.py
        src/
            header1.h
            header2.h
            ext_module1.cpp
            ext_module2.cpp
            swig_module.i
        setup.py
        MANIFEST.in
        MANIFEST

my setup.py : 我的setup.py

from distutils.core import setup, Extension

module1 = Extension('my_module._module',
                sources=['src/ext_module1.cpp',
                         'src/ext_module2.cpp',
                         'src/swig_module.i'],
                swig_opts=['-c++', '-py3'],
                include_dirs=[...],
                runtime_library_dirs=[...],
                libraries=[...],
                extra_compile_args=['-Wno-write-strings'])

setup(  name            = 'my_module',
        version         = '0.6',
        author          = 'microo8',
        author_email    = 'magyarvladimir@gmail.com',
        description     = '',
        license         = 'GPLv3',
        url             = '',
        platforms       = ['x86_64'],
        ext_modules     = [module1],
        packages        = ['my_module'],
        package_dir     = {'my_module': 'my_module'},
        package_data    = {'my_module': ['data/*.dat']} )

my MANIFEST.in file: 我的MANIFEST.in文件:

include src/header1.h
include src/header2.h

the MANIFEST file is automatically generated by python3 setup.py sdist . MANIFEST文件由python3 setup.py sdist自动生成。 And when i run python3 setup.py bdist_rpm it compiles and creates correct rpm packages. 当我运行python3 setup.py bdist_rpm它会编译并创建正确的rpm包。 But the problem is that when im running SWIG on a C++ source, it creates a module.py file that wraps the binary _module.cpython32-mu.so file, it is created with the module_wrap.cpp file, and it isnt copied to the my_module directory. 但问题是,当我在C ++源代码上运行SWIG时,它会创建一个包装二进制_module.cpython32-mu.so文件的module.py文件,它是用module_wrap.cpp文件创建的,并且它不会被复制到my_module目录。

What I must write to the setup.py file to automatically copy the SWIG generated python modules? 我必须写什么来setup.py文件自动复制SWIG生成的python模块?

And also I have another question: When I install the rpm package, I want that an executable will be created, in /usr/bin or so, to run the application (for example if the my_module/my_module1.py is the start script of the application then I can run in bash: $ my_module1 ). 我还有另一个问题:当我安装rpm包时,我希望在/usr/bin创建一个可执行文件来运行应用程序(例如,如果my_module/my_module1.py是启动脚本然后我可以在bash中运行应用程序: $ my_module1 )。

The problem is that build_py (which copies python sources to the build directory) comes before build_ext , which runs SWIG. 问题是build_py (将python源复制到构建目录)出现在运行SWIG的build_ext之前。

You can easily subclass the build command and swap around the order, so build_ext produces module1.py before build_py tries to copy it. 您可以轻松地对构建命令进行子类化并按顺序进行交换,因此build_ext会在build_py尝试复制之前生成module1.py

from distutils.command.build import build

class CustomBuild(build):
    sub_commands = [
        ('build_ext', build.has_ext_modules), 
        ('build_py', build.has_pure_modules),
        ('build_clib', build.has_c_libraries), 
        ('build_scripts', build.has_scripts),
    ]

module1 = Extension('_module1', etc...)

setup(
    cmdclass={'build': CustomBuild},
    py_modules=['module1'],
    ext_modules=[module1]
)

However, there is one problem with this: If you are using setuptools, rather than just plain distutils, running python setup.py install won't run the custom build command. 但是,这有一个问题:如果您使用的是setuptools,而不仅仅是普通的distutils,那么运行python setup.py install将不会运行自定义构建命令。 This is because the setuptools install command doesn't actually run the build command first, it runs egg_info, then install_lib, which runs build_py then build_ext directly. 这是因为setuptools install命令实际上并不首先运行build命令,它运行egg_info,然后运行install_lib,它直接运行build_py和build_ext。

So possibly a better solution is to subclass both the build and install command, and ensure build_ext gets run at the start of both. 所以可能更好的解决方案是继承构建和安装命令,并确保build_ext在两者的开头运行。

from distutils.command.build import build
from setuptools.command.install import install

class CustomBuild(build):
    def run(self):
        self.run_command('build_ext')
        build.run(self)


class CustomInstall(install):
    def run(self):
        self.run_command('build_ext')
        self.do_egg_install()

setup(
    cmdclass={'build': CustomBuild, 'install': CustomInstall},
    py_modules=['module1'],
    ext_modules=[module1]
)

It doesn't look like you need to worry about build_ext getting run twice. 看起来你不必担心build_ext会运行两次。

It's not a complete answer, because I don't have the complete solution. 这不是一个完整的答案,因为我没有完整的解决方案。 The reason why the module is not copied to the install directory is because it wasn't present when the setup process tried to copy it. 模块未复制到安装目录的原因是因为在安装过程尝试复制模块时它不存在。 The sequence of events is: 事件的顺序是:

running install
running build
running build_py
file my_module.py (for module my_module) not found
file vcanmapper.py (for module vcanmapper) not found
running build_ext

If you run a second time python setup.py install it will do what you wanted in the first place. 如果你第二次运行python setup.py install ,它将首先完成你想要的。 The official SWIG documentation for Python proposes you run first swig to generate the wrap file, and then run setup.py install to do the actual installation. Python的官方SWIG文档建议您运行第一个swig来生成包装文件,然后运行setup.py install来进行实际安装。

It looks like you have to add a py_modules option, eg: 看起来你必须添加一个py_modules选项,例如:

setup(...,
  ext_modules=[Extension('_foo', ['foo.i'],
                         swig_opts=['-modern', '-I../include'])],
  py_modules=['foo'],
)

Using rpm to Install System Scripts in Linux , you'll have to modify your spec file. 使用rpm在Linux中安装系统脚本 ,您必须修改您的spec文件。 The %files section tells rpm where to put the files, which you can move or link to in %post , but such can be defined in setup.py using: %files部分告诉rpm将文件放在哪里,你可以在%post移动或链接到这些文件,但是可以setup.py使用以下命令定义:

options = {'bdist_rpm':{'post_install':'post_install', 'post_uninstall':'post_uninstall'}},

Running Python scripts in Bash can be done with the usual first line as #!/usr/bin/python and executable bit on the file using chmod +x filename . 在Bash中运行Python脚本可以使用通常的第一行#!/usr/bin/python和使用chmod +x filename的文件上的可执行位来完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM