使用 Python 安装仅标头库



我有一个在Python扩展中使用的仅标头C++库。我希望能够将它们安装到 Python 的包含路径中,这样我就可以使用 python3 setup.py build 非常轻松地编译扩展。我有部分能力,但有两件事我无法工作(见下文(:

  1. 如何使用python3 setup.py install安装头文件?目前我只得到一些*.egg文件,但没有安装标题。

  2. 如何保留模块的文件结构?当前,文件结构被错误地展平。

什么有效

具有以下setup.py

from setuptools import setup
setup(
   name        = 'so',
   description = 'Example',
   headers     = [
      'so.h',
   ],
)

我可以将模块上传到 PyPi:

python3 setup.py bdist_wheel --universal
twine upload dist/*

然后使用 pip 安装它:

pip3 install so

在我的系统上,然后我在这里找到标题

/usr/local/include/python3.6m/so/so.h

当我使用 Python 编译扩展时,这是可用的。

如何使用"python3 setup.py 安装"?

使用这个策略,我不能简单地运行

python3 setup.py install

在这种情况下,会安装一些so*.egg,但标头不会存储在编译器可用的某个位置。

如何保留文件结构?

当模块有点复杂,并且有一些目录层次结构时,我也会遇到问题。对于以下setup.py

from setuptools import setup
setup(
  name        = 'so',
  description = 'Example',
  headers     = [
    'so.h',
    'so/implementation.h',
  ],
)

问题是标头安装到

/usr/local/include/python3.6m/so/so.h
/usr/local/include/python3.6m/so/implementation.h

从而展平原始文件结构。

如何解决这两个问题?

如何使用

python3 setup.py install安装头文件?

不幸的是,只要您使用setuptools,您就不能。当你打电话给setuptools.setup()时,引擎盖下会发生什么?正在构建(bdist_egg命令(和安装(通过easy_install(的鸡蛋安装程序,bdist_eggeasy_install都不支持包括/安装标头。尽管 distribution 对象带有标头信息,但在 install 命令期间永远不会请求它。这是一个众所周知的古老问题,但从未得到解决,因为显然,头文件的安装不适合鸡蛋构建/安装过程。

因此,您有三个选择(或者我知道的至少三个选项(。其中两个(都会导致切换到distutils(不推荐使用,仅出于完整性考虑而提供:

distutils安装(不推荐(

$ sed 's/from setuptools import setup/from distutils.core import setup/' setup.py

这样,好的老distutils将在执行python setup.py install时负责安装,不会构建鸡蛋安装程序并调用install_headers。但是,这也包括放弃setuptools的所有功能,包括setup()中的其他关键字 args 和所有其他好东西,不用说通过 distutils 安装的软件包不能用 pip 卸载。

old-and-unmanageable安装(不推荐(

运行安装

$ python setup.py install --old-and-unmanageable

这是setuptools明确希望运行distutils安装时提供的开关。不会构建鸡蛋安装程序,而是调用distutils.command.install.install。因此,安装与裸distutils安装相同。

这种方法的缺点:与裸distutils安装相同 plus:setuptools谴责交换机的使用;如果您忘记提供它,则以安装 egg 结束,并且必须重做安装。

python setup.py install替换为pip install(推荐(

pip能够从源目录安装软件包;只需发出

$ pip install dir/

假设dir包含setup.py .这样,从源代码构建了一个wheel文件(与bdist_wheel相同;实际上,此命令首先运行(并安装,管理头文件的安装就可以了。

如何保留模块的文件结构?

您必须稍微调整一下install_headers命令:

import os
from distutils.command.install_headers import install_headers as install_headers_orig
from setuptools import setup
class install_headers(install_headers_orig):
    def run(self):
        headers = self.distribution.headers or []
        for header in headers:
            dst = os.path.join(self.install_dir, os.path.dirname(header))
            self.mkpath(dst)
            (out, _) = self.copy_file(header, dst)
            self.outfiles.append(out)
setup(
    name='so',
    headers=['h1.h', 'subtree/h2.h'],
    cmdclass={'install_headers': install_headers},
    ...
)

这里重要的是线条

dst = os.path.join(self.install_dir, os.path.dirname(header))

原版install_headers将头文件直接复制到install_dir;重载的install_headers命令中的上述行还负责头文件名中的最终子目录。安装软件包时,现在应保留子目录:

$ pip show -f so | grep include
  ../../../include/site/python3.6/so/h1.h
  ../../../include/site/python3.6/so/subtree/h2.h

相关内容

  • 没有找到相关文章

最新更新