首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在setup.py中添加特定于平台的包数据?

问如何在setup.py中添加特定于平台的包数据?
EN

Stack Overflow用户
提问于 2021-10-20 14:32:29
回答 2查看 222关注 0票数 1

我需要在用setup.py构建的车轮中部署特定于平台的包数据。

作为背景,我试图使用预构建的二进制文件和ctypesgen为某个库创建Python绑定。我有一个具有特定于平台的子目录的数据树,其中包含一个绑定文件和一个二进制文件,每个子目录都是:

代码语言:javascript
复制
data/
    macos-arm64/
        _bindings.py
        binary.dylib
    linux-x64/
        _bindings.py
        binary.so
    windows-x64/
        _bindings.py
        binary.dll
    ...

我有一个源树:

代码语言:javascript
复制
src/
    package_name/
        __init__.py
        __main__.py
        ...

问题:如何构建只包含相应二进制和绑定的特定于平台的包?

部署到最终用户的最终目录树在结构上应该如下所示:

代码语言:javascript
复制
package_name/
    __init__.py
    __main__.py
    _bindings.py
    binary.xyz
    ...
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-07-26 19:33:20

这是我目前用于pypdfium2的解决方案

  • 创建一类受支持的平台,其值与数据目录名称相对应:
代码语言:javascript
复制
class PlatformNames:
    darwin_x64  = "darwin_x64"
    linux_x64   = "linux_x64"
    windows_x64 = "windows_x64"
    # ...
    sourcebuild = "sourcebuild"
  • 使用一个函数包装setuptools.setup(),该函数以平台名称为参数,并根据需要将平台相关文件复制到源树中:
代码语言:javascript
复制
# A list of non-python file names to consider for inclusion in the installation, e. g.
Libnames = (
    "somelib.so",
    "somelib.dll",
    "somelib.dylib",
)

# _clean() removes possible old binaries/bindings
# _copy_bindings() copies the new stuff into the source tree
# _get_bdist() returns a custom `wheel.bdist_wheel` subclass with the `get_tag()` and `finalize_options()` functions overridden so as to tag the wheels according to their target platform.

def mkwheel(pl_name):
    _clean()
    _copy_bindings(pl_name)
    setuptools.setup(
        package_data = {"": Libnames},
        cmdclass = {"bdist_wheel": _get_bdist(pl_name)},
        # ...
    )
    # not cleaning up afterwards so that editable installs work (`pip3 install -e .`)
  • 在setup.py中,查询定义目标平台的自定义环境变量(例如,$PYP_TARGET_PLATFORM)。
    • 如果设置为指示需要源分发(例如sdist)的值,则运行原始setuptools.setup()函数,而不复制任何构建工件。
    • 如果设置为平台名称,则为请求的平台构建。这使得包装平台无关,避免了本地主机制造车轮的需要。
    • 如果未设置,则使用sysconfig.get_platform()检测主机平台,并使用相应的PlatformNames成员调用mkwheel()。
      • 如果检测到的平台不受支持,则触发执行源构建、将创建的文件移动到data/sourcebuild/并运行mkwheel(PlatformNames.sourcebuild)的代码。

  • 编写一个脚本,迭代平台名称,设置环境变量,并为每个环境变量运行python3 -m build --no-isolation --skip-dependency-check --wheel。还使用--sdist调用--sdist一次,而不是使用--wheel和环境变量设置为源分发的值。

如果一切顺利,特定于平台的车轮和源发行版将被写入dist/中。

也许仅仅通过查看pypdfium2 2的代码(特别是setup.py、setup_base.py和craft_packages.py),就可以更容易地理解这一点。

免责声明:我对的设置基础设施没有经验,只是出于个人的需要编写了这段代码。我承认,这种做法有点“无趣”。如果有可能在使用setuptools时以一种更正式的方式实现同样的目标,我很想听听它。

更新1:这个概念的一个负面含义是,内容被错误地放在purelib文件夹中,尽管按照PEP 427应该是platlib。我不知道如何用不同的方法指导轮子/安装工具。幸运的是,这只是一个化妆品问题。

更新2:找到了解决purelib问题的方法:

代码语言:javascript
复制
class BinaryDistribution (setuptools.Distribution):
    def has_ext_modules(self):
        return True

setuptools.setup(
    # ...
    distclass = BinaryDistribution,
)
票数 2
EN

Stack Overflow用户

发布于 2022-06-16 01:22:14

不完全像您所描述的那样,但为了简单起见,我会提供一个为所有支持的平台构建的轮子。

setup.py

代码语言:javascript
复制
import setuptools

setuptools.setup(
    name='package_name',
    packages=[
        'macos-arm64',
        'linux-x64',
        ...
    ],
    include_package_data=True
)

MANIFEST.in

代码语言:javascript
复制
include macos-arm64/binary.dylib
include linux-x64/binary.so
...

您需要调整导入代码,以便根据平台导入正确的绑定。

setuptools文档更详细地描述了如何做到这一点。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69647983

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档