我可以在 distutils 命令中添加包含路径吗?
Can I add an include path in a distutils command?
我正在努力将 Python 接口打包到 C 库。 C 库以带有 headers 和编译库的二进制分发 tarball 的形式出现。我想用它制作一个 bdist_wheel
,连同我构建的 Python 扩展,以及 headers.
我写了几个 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)
问题是,我不确定如何获取 headers 库的路径来构建我的扩展,因为它们安装到 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 脚本。
在进一步考虑这个问题之后,我决定使用 Cython 接口提交库的 headers,因为它们是接口的一部分,并且是构建所必需的。这样,代码记录并使用特定的固定版本,并且可以与兼容的二进制文件一起分发。
您可以在库可用后修改 InstallLibraryCommand
中的扩展。我可能还会将 extraction/installation 代码移动到 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)
我正在努力将 Python 接口打包到 C 库。 C 库以带有 headers 和编译库的二进制分发 tarball 的形式出现。我想用它制作一个 bdist_wheel
,连同我构建的 Python 扩展,以及 headers.
我写了几个 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)
问题是,我不确定如何获取 headers 库的路径来构建我的扩展,因为它们安装到 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 脚本。
在进一步考虑这个问题之后,我决定使用 Cython 接口提交库的 headers,因为它们是接口的一部分,并且是构建所必需的。这样,代码记录并使用特定的固定版本,并且可以与兼容的二进制文件一起分发。
您可以在库可用后修改 InstallLibraryCommand
中的扩展。我可能还会将 extraction/installation 代码移动到 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)