我有一个 Python/Rust 项目,它使用 PyO3 构建一个用 Rust 编写的 Python 扩展。
我用
maturin
设置了它,并且它在本地运行良好 - 它将构建一个轮子 (.whl) 并在其中构建是我的 Python 代码和 Rust 扩展共享对象,正如我所期望的那样。
我需要与 Yocto 交叉编译它(不幸的是,我被 Langdale 困住了),以将其放入我的嵌入式根文件系统中,我很快意识到我需要放弃
maturin
for
setuptools-rust
,因为 Yocto Langdale 根本没有
maturin
支持。
所以现在我的 Rust/Python/PyO3 项目是设置与
setuptools-rust
示例非常相似,我可以在本地构建它,生成的轮子包含我期望的内容。
目录布局:
.
├── Cargo.lock
├── Cargo.toml
├── pyproject.toml
├── python
│ └── my_project
│ └── my_module.py
└── src
└── lib.rs
project.toml
(部分):
[build-system]
requires = ["setuptools>=61.0.0", "setuptools_scm>=8", "setuptools-rust"]
build-backend = "setuptools.build_meta"
[tool.setuptools.packages]
find = { where = ["python"] }
[[tool.setuptools-rust.ext-modules]]
target = "my_project._lib"
path = "Cargo.toml"
binding = "PyO3"
Cargo.toml
(部分):|| |但它不会在 Yocto 中构建,其配方类似于:
[lib]
name = "_lib"
crate-type = ["cdylib"]
path = "src/lib.rs"
[dependencies]
pyo3 = "0.22.0"
错误是:
inherit externalsrc
EXTERNALSRC = "${TOPDIR}/../../my_project"
inherit python_setuptools_build_meta
不知道该怎么做。看起来有时会出现 Python <3.11 和 Python 3.11 之间的 tomli drop-in 问题。
| File "build/tmp/work/cortexa72-cortexa53-xilinx-linux/my_package/1.0-r0/recipe-sysroot-native/usr/lib/python3.10/site-packages/picobuild/__init__.py", line 93, in __init__
| pyproject = tomllib.load(f)
| AttributeError: module 'tomli' has no attribute 'load'
在弄清楚我需要继承
而不是
python_setuptools3_rust
之后,我的 bitbake 配方现在看起来像这样:
python_setuptools_build_meta
这似乎成功构建并打包了我项目的
inherit externalsrc
EXTERNALSRC = "${TOPDIR}/../../my_project"
inherit python_setuptools3_rust
Python
部分,但 Rust 扩展(我期望看到
或
.so
文件)完全不存在。| ||我已经浏览了 Yocto 日志,我可以看到对
.pyd
的引用(我猜是旧的构建方式),但没有任何特定于 Rust 的内容。我开始认为
太旧了,无法处理
python setup.py bdist_wheel
,但bbclass
python_setuptools3_rust
似乎也无法构建它(由于tomli错误)。
pyproject.toml
此时我已经没有文档或示例来指导我了。 我对如何继续感到有点茫然。
python_setuptools_build_meta
我被 Yocto Langdale 困住了,这真是太遗憾了,因为最新的 LTS,Scarthgap,似乎确实有
支持。
It's a real shame I'm stuck with Yocto Langdale because the latest LTS, Scarthgap, does seem to have
maturin
support.
很遗憾你被困在 Yocto Langdale 上,因为它缺乏对
maturin
和更新的构建工具的支持确实让使用 PyO3 变得很棘手。不过,根据你提供的信息,让我们尝试解决这个问题。
看起来你已经能够解决
tomli
问题,并且你的 Yocto 配方现在正在使用
python_setuptools3_rust
类。然而,问题在于 Rust 扩展没有被构建。
以下是可能出错的地方以及我们如何调试的方法:
-
setuptools-rust
配置: -
缺少依赖项: 确保你的 Yocto 配方在构建时将
setuptools-rust
包含为依赖项。这通常是通过在你的配方的DEPENDS
或RDEPENDS
中添加python3-setuptools-rust
来完成的。 -
Python 版本:
setuptools-rust
1.2.0 以上版本支持使用pyproject.toml
。确保你的 Yocto 构建环境中安装了正确版本的setuptools-rust
。 -
Cargo: 验证
cargo
是否在你的 Yocto 构建环境中可用,并且setuptools-rust
能够找到它。你可能需要添加cargo
包(例如,cargo-native
)。 -
Yocto 构建过程:
-
日志记录: 仔细检查 Yocto 构建日志以获取更多信息。寻找与
setuptools-rust
、cargo
或 Rust 构建相关的任何错误或警告。这可以提供有关扩展未构建原因的线索。 -
构建目录:
检查 Yocto 构建目录(通常是
build/tmp/work/…/your-package/
)。查找 Rust 扩展源(src/lib.rs
)和Cargo.toml
文件,以查看它们是否被正确复制到构建环境中。 -
手动构建: 作为最后的手段,尝试在 Yocto 构建环境中手动运行
python3 setup.py bdist_wheel
。这可以揭示任何特定的构建问题或配置错误。 -
解决方法(如果以上方法都不起作用):
-
python_src_module
: 虽然这并不理想,但在 Yocto Langdale 中构建 PyO3 扩展的另一种方法是使用python_src_module
类。这个类不太复杂,并且可能与旧版本的工具配合得更好。但是,你需要修改你的项目结构并手动处理一些构建步骤。
以下是使用
python_src_module
方法的简要示例:
-
将你的 Rust 代码移动到一个名为
src
的子目录中。 -
创建一个名为
setup.py
的文件,其中包含用于构建 Rust 扩展的基本指令。 -
在你的 Yocto 配方中,继承
python_src_module
并设置S = "${WORKDIR}/src"
。
以下是修改后的
setup.py
的示例:
from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext
import subprocess
class BuildExt(build_ext):
def run(self):
subprocess.check_call(['cargo', 'build', '--release'], cwd='src')
super().run()
setup(
name='my_project',
version='1.0',
ext_modules=[
Extension('my_project._lib', ['src/lib.rs']),
],
cmdclass={'build_ext': BuildExt},
)
请记住,这只是一个基本的示例,你可能需要根据你的项目结构和依赖项进行调整。
调试 Yocto 构建问题可能很棘手且耗时。希望这些建议可以帮助你找到问题的原因并解决它,或者至少让你走上正确的轨道。
标签:python,rust,yocto,openembedded,pyo3 From: 78805524