Python distutils не включает сгенерированный модуль SWIG

Я использую distutils для создания rpm из моего проекта. У меня есть это дерево каталогов:

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

мой 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    = '[email protected]',
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']} )

мой MANIFEST.in файл:

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

MANIFEST файл автоматически генерируется python3 setup.py sdist, И когда я бегу python3 setup.py bdist_rpm он компилирует и создает правильные пакеты rpm. Но проблема в том, что когда я запускаю SWIG на источнике C ++, он создает module.py файл, который упаковывает двоичный файл _module.cpython32-mu.so файл, он создается с module_wrap.cpp файл, и он не копируется в my_module каталог.

Что я должен написать setup.py файл для автоматического копирования генерируемых SWIG модулей Python?

А также у меня есть еще один вопрос: когда я устанавливаю пакет rpm, я хочу, чтобы исполняемый файл был создан в /usr/bin или так, чтобы запустить приложение (например, если my_module/my_module1.py это стартовый скрипт приложения, тогда я могу запустить в bash: $ my_module1).

17

Решение

Проблема в том, что build_py (который копирует исходники Python в каталог сборки) build_ext, который работает SWIG.

Вы можете легко создать подкласс команды build и поменять местами порядок, так что build_ext производит module1.py до build_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]
)

Однако есть одна проблема: если вы используете setuptools, а не просто distutils, python setup.py install не будет запускать пользовательскую команду сборки. Это связано с тем, что команда установки setuptools сначала не запускает команду сборки, она запускает egg_info, затем install_lib, которая запускает build_py, а затем build_ext напрямую.

Поэтому, возможно, лучшим решением будет создание подкласса команд build и install и обеспечение запуска 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]
)

Не похоже, что вам нужно беспокоиться о запуске build_ext дважды.

10

Другие решения

Это не полный ответ, потому что у меня нет полного решения.
Причина, по которой модуль не копируется в каталог установки, заключается в том, что его не было, когда процесс установки пытался скопировать его. Последовательность событий:

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

Если вы запускаете второй раз python setup.py install это будет делать то, что вы хотели в первую очередь. Официальная документация SWIG для Python предлагает вам запустить в первую очередь swig создать файл обтекания, а затем запустить setup.py install сделать фактическую установку.

1

Это выглядит как Вы должны добавить py_modules вариант, например:

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

Использование rpm для установки системных скриптов в Linux, вам придется изменить свой файл спецификации. %files раздел рассказывает rpm куда поместить файлы, которые вы можете переместить или на которые ссылаетесь в %post, но такой может быть определяется в setup.py с помощью:

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

Запуск скриптов Python в Bash может быть сделано с обычной первой строкой, как #!/usr/bin/python и исполняемый бит в файле с помощью chmod +x filename,

0
По вопросам рекламы [email protected]