правильный setup.py для смешивания Python и C ++

1

Я пытаюсь смешивать оба языка, и я следую за хорошим примером, представленным pybind здесь. Я действительно проверил это сообщение, чтобы улучшить его, чтобы я мог вернуться к функциям Python всякий раз, когда компилируемая функция не существует. Проблема, которую я сейчас имею в том, что мой configure.py не создает правильный пакет. Позвольте мне развиться: структура моего кода выглядит примерно так:

$ tree .
.
├── AUTHORS.md
├── CMakeLists.txt
├── LICENSE
├── MANIFEST.in
├── Makefile
├── README.md
├── conda.recipe
│   ├── bld.bat
│   └── ...
├── docs
│   ├── Makefile
│   └── ...
├── cmake_example
│   ├── __init__.py
│   ├── __main__.py
│   ├── geometry
│   │   ├── __init__.py
│   │   ├── triangle.py
│   │   └── ...
│   ├── quadrature
│   │   ├── __init__.py
│   │   ├── legendre
│   │   └── ...
│   └── utils
│       ├── __init__.py
│       ├── classes.py
│       └── ...
├── pybind11
│   ├── CMakeLists.txt
│   └── ...
├── setup.py
├── src
│   └── main.cpp
└── tests
    └── test.py

Где я добавляю многоточие для упрощения структуры каталогов, но вы можете видеть, что есть несколько модулей. Теперь мой файл setup.py выглядит так

import os
import re
import sys
import platform
import subprocess
import glob

from setuptools import setup, Extension, find_packages
from setuptools.command.build_ext import build_ext
from distutils.version import LooseVersion

class CMakeExtension(Extension):
    def __init__(self, name, sourcedir=''):
        Extension.__init__(self, name, sources=[])
        self.sourcedir = os.path.abspath(sourcedir)    

class CMakeBuild(build_ext):
    def run(self):
        try:
            out = subprocess.check_output(['cmake', '--version'])
        except OSError:
            raise RuntimeError("CMake must be installed to build the following extensions: " +
                               ", ".join(e.name for e in self.extensions))

        if platform.system() == "Windows":
            cmake_version = LooseVersion(re.search(r'version\s*([\d.]+)', out.decode()).group(1))
            if cmake_version < '3.1.0':
                raise RuntimeError("CMake >= 3.1.0 is required on Windows")

        for ext in self.extensions:
            self.build_extension(ext)

    def build_extension(self, ext):
        extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name)))
        cmake_args = ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + extdir,
                      '-DPYTHON_EXECUTABLE=' + sys.executable]

        cfg = 'Debug' if self.debug else 'Release'
        build_args = ['--config', cfg]

        if platform.system() == "Windows":
            cmake_args += ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), extdir)]
            if sys.maxsize > 2**32:
                cmake_args += ['-A', 'x64']
            build_args += ['--', '/m']
        else:
            cmake_args += ['-DCMAKE_BUILD_TYPE=' + cfg]
            build_args += ['--', '-j2']

        env = os.environ.copy()
        env['CXXFLAGS'] = '{} -DVERSION_INFO=\\"{}\\"'.format(env.get('CXXFLAGS', ''),
                                                              self.distribution.get_version())
        if not os.path.exists(self.build_temp):
            os.makedirs(self.build_temp)
        subprocess.check_call(['cmake', ext.sourcedir] + cmake_args, cwd=self.build_temp, env=env)
        subprocess.check_call(['cmake', '--build', '.'] + build_args, cwd=self.build_temp)


kwargs = dict(
    name="cmake_example",
    ext_modules=[CMakeExtension('cmake_example._mymath')],
    cmdclass=dict(build_ext=CMakeBuild),
    zip_safe=False,
    packages='cmake_example',
)

# likely there are more exceptions
try:
    setup(**kwargs)
except subprocess.CalledProcessError:
    print("ERROR: Cannot compile C accelerator module, use pure python version")
    del kwargs['ext_modules']
    setup(**kwargs)

который я взял с этой должности. Когда я пытаюсь построить колесо, используя python setup.py bdist_wheel, а затем я устанавливаю с помощью pip install. , Я не могу использовать свой код, потому что он жалуется, что пакеты не найдены:

>>> import cmake_example
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/aaragon/Local/cmake_example/cmake_example/__init__.py", line 11, in <module>
    from .geometry import Triangle
ModuleNotFoundError: No module named 'cmake_example.geometry'

Если я вручную добавлю setup.py список с packages=['cmake_example', cmake_example.geometry] то он работает, но я не думаю, что это правильный способ сделать это, потому что было бы очень сложно идти в ногу с добавление новых модулей. Я видел, что где-то я мог заменить эту строку и использовать findpackages setuptools, но эта функция не cmake_example к модулю, поэтому она все еще ломается. Какой правильный способ сделать то, что я пытаюсь сделать?

Теги:
setup.py
pybind11

1 ответ

1
Лучший ответ

Если я вручную добавлю setup.py список с пакетами = ['cmake_example', cmake_example.geometry], то он работает, но я не думаю, что это правильный способ сделать это, потому что было бы очень сложно идти в ногу с добавление новых модулей.

Либо вы делаете это вручную, либо когда ему сложно идти в ногу с добавлением новых модулей там setuptools.find_packages. Используйте как:

from setuptools import setup, find_packages
setup(
    name="HelloWorld",
    version="0.1",
    packages=find_packages(),
)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню