如果你用CPython写了一个扩展,然后要打包到wheel中发布,应该如何操作?你搜索网络,不管英文还是中文,得到的都是一知半解的答案。根据官方的粗浅文档,你可能可以很快完成一个wheel包,但和真正的wheel包差了十万八千里。这里主要考虑两个问题:1.包的结构,2.依赖库如何打包。
学习资源
因为涉及C/C++代码,那么最好的学习资源就是opencv-python的源码。理想情况下,做出来的包应该可以通过pip
命令在任意平台安装。
Scikit-build
那么opencv-python是如何来为不同平台编译wheel的?通过源码可以发现,它用到了scikit-build,通过CMake来编译C/C++代码。我们可以直接运行GitHub上的示例工程来体验下。
这个工程很简单,setup.py
里只写了一个包名:
from skbuild import setup
setup(
name="hello-cpp",
version="1.2.3",
description="a minimal example package (cpp version)",
author='The scikit-build team',
license="MIT",
packages=['hello'],
python_requires=">=3.7",
)
其它的都交给CMakeLists.txt
去完成:
cmake_minimum_required(VERSION 3.4...3.22)
project(hello)
find_package(PythonExtensions REQUIRED)
add_library(_hello MODULE hello/_hello.cxx)
python_extension_module(_hello)
install(TARGETS _hello LIBRARY DESTINATION hello)
pyproject.toml
中配置了编译环境。
[build-system]
requires = [
"setuptools>=42",
"scikit-build>=0.13",
"cmake>=3.18",
"ninja",
]
build-backend = "setuptools.build_meta"
[tool.cibuildwheel]
manylinux-x86_64-image = "manylinux2014"
manylinux-aarch64-image = "manylinux2014"
skip = ["pp*", "*-win32", "*-manylinux_i686", "*-musllinux_*"]
[tool.cibuildwheel.windows]
archs = ["AMD64"]
[tool.cibuildwheel.linux]
repair-wheel-command = "auditwheel repair -w {
dest_dir} {
wheel} --plat manylinux2014_x86_64"
archs = ["x86_64"]
[tool.cibuildwheel.macos]
archs = ["x86_64"]
repair-wheel-command = [
"delocate-listdeps {wheel}",
"delocate-wheel --require-archs {delocate_archs} -w {dest_dir} {wheel}",
]