Могу ли я добавить путь для включения в команду distutils? - PullRequest
2 голосов
/ 11 марта 2020

Я работаю над упаковкой интерфейса Python в библиотеку C. Библиотека C поставляется в виде бинарного дистрибутива с заголовками и скомпилированной библиотекой. Я хочу сделать из него bdist_wheel вместе с моими встроенными расширениями Python и заголовками.

Я написал пару команд distutils для извлечения и установки библиотеки следующим образом:

from distutils.core import Command
from distutils.command.build import build

import os
import tarfile

class ExtractLibraryCommand(Command):
    description = 'extract library from binary distribution'

    def initialize_options(self):
        self.build_lib = None
        self.build_temp = None
        self.library_dist = os.environ.get('LIBRARY_DIST')

    def finalize_options(self):
        self.set_undefined_options('build',
                                   ('build_lib', 'build_lib'),
                                   ('build_temp', 'build_temp'))

        assert os.path.exists(self.library_dist), 'Library dist {} does not exist'.format(self.library_dist)

    def run(self):
        with tarfile.open(self.library_dist, 'r') as tf: 
            tf.extractall(path=self.build_temp)

class InstallLibraryCommand(Command):
    description = 'install library from extracted distribution'

    def initialize_options(self):
        self.build_lib = None
        self.build_temp = None

    def finalize_options(self):
        self.set_undefined_options('build',
                                   ('build_lib', 'build_lib'),
                                   ('build_temp', 'build_temp'))

    def run(self):
            self.copy_tree(
                os.path.join(os.path.join(build_temp, 'my_library')),
                os.path.join(self.build_lib, os.path.join('my_package', 'my_library'))
            )

Затем я перезаписываю шаг build, чтобы включить мои новые команды.

class BuildCommand(build):
    def run(self):
        self.run_command('extract_library')
        self.run_command('install_library')
        build.run(self)

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

from setuptools import setup, find_packages
from setuptools.extension import Extension
from Cython.Build import cythonize

extensions = [
    Extension(
        'package.library.*',
        ['package/library/*.pyx'],
        include_dirs=???,
    ),
]

setup(
    packages=find_packages(),
    ...
    ext_modules=cythonize(extensions),
)

РЕДАКТИРОВАТЬ: Для пояснения, это один сценарий setup.py.

Ответы [ 2 ]

2 голосов
/ 12 марта 2020

Вы можете изменить расширения в InstallLibraryCommand после того, как библиотека станет доступной. Возможно, я бы также переместил код извлечения / установки в finalize_options вместо run, так как, на мой взгляд, установка библиотеки на этапе сборки несколько запоздала (делает библиотеку недоступной на этапе настройки). Пример:

class InstallLibraryCommand(Command):
    def finalize_options(self):
        ...
        with tarfile.open(self.library_dist, 'r') as tf: 
            tf.extractall(path=self.build_temp)
        include_path = os.path.join(self.build_lib, os.path.join('my_package', 'my_library'))
        self.copy_tree(
                os.path.join(os.path.join(build_temp, 'my_library')),
                include_path
        )
        for ext in self.distribution.ext_modules:
            ext.include_dirs.append(include_path)
0 голосов
/ 11 марта 2020

Поразмыслив над этой проблемой, я решил зафиксировать заголовки библиотеки с помощью интерфейса Cython, поскольку они являются частью интерфейса и необходимы для сборки. Таким образом, код документирует и использует конкретную фиксированную версию и может распространяться с совместимыми двоичными файлами.

...