如何使用scikit-build-core构建混合Cython与Python的项目?
如何使用scikit-build-core构建混合Cython与Python的项目?
我完全懂你现在的困扰——之前用setup.py能顺顺利利打包混合Cython和Python的项目,转用scikit-build-core后,不仅嵌套目录里的Cython文件编译不出来,最终wheel里的文件结构也完全不对。别着急,咱们一步步调整配置,把这个问题解决掉。
首先要确认一个前提:你的src/example目录和src/example/c目录下都要有空的__init__.py文件,这样Python才能把它们识别为合法的包,这是打包的基础。
接下来咱们逐个修改配置文件:
1. 调整pyproject.toml,确保Python包被正确识别
在[project]区块里添加包的声明,让构建工具明确要处理哪些Python包:
[project] name = "example" version = "0.1.0" description = "Add your description here" authors = [ { name = "Colinxu2020", email = "colinxu2020@gmail.com" } ] # 新增这一行,指定要打包的包 packages = ["example", "example.c"] [tool.scikit-build] minimum-version = "build-system.requires" build-dir = "build/{wheel_tag}" [build-system] requires = ["scikit-build-core>=0.10", "cython", "cython-cmake"] build-backend = "scikit_build_core.build"
2. 重写CMakeLists.txt,递归处理所有Cython文件并正确安装Python源码
之前的CMake脚本只处理了单个文件,而且模块命名和安装路径都不符合包结构要求,咱们改成递归处理所有pyx文件,同时把Python源码也安装到对应位置:
cmake_minimum_required(VERSION 3.21) project(${SKBUILD_PROJECT_NAME} LANGUAGES CXX) find_package( Python COMPONENTS Interpreter Development.Module REQUIRED) include(UseCython) # 递归查找所有src/example下的pyx文件 file(GLOB_RECURSE pyx_files src/example/**/*.pyx) foreach(pyx_file ${pyx_files}) # 将pyx文件转译为C++文件 cython_transpile(${pyx_file} LANGUAGE CXX OUTPUT_VARIABLE cpp_file) # 生成符合包结构的模块名称:比如src/example/c/e.pyx → example.c.e string(REPLACE "${CMAKE_SOURCE_DIR}/src/example/" "" module_path ${pyx_file}) string(REPLACE ".pyx" "" module_name ${module_path}) string(REPLACE "/" "." module_name ${module_name}) # 创建Python扩展模块 python_add_library(${module_name} MODULE WITH_SOABI "${cpp_file}") # 将编译后的模块安装到对应的包目录下 install(TARGETS ${module_name} DESTINATION example/${module_path}) endforeach() # 安装所有Python源码文件(.py) file(GLOB_RECURSE py_files src/example/**/*.py) foreach(py_file ${py_files}) # 计算文件的安装路径,保持原目录结构 string(REPLACE "${CMAKE_SOURCE_DIR}/src/example/" "" install_path ${py_file}) get_filename_component(install_dir ${install_path} DIRECTORY) install(FILES ${py_file} DESTINATION example/${install_dir}) endforeach()
3. 清理缓存并测试构建
先删除之前的build目录和dist目录,避免旧缓存干扰,然后用uv构建:
uv build --clean
构建完成后,你会在dist目录得到正确的wheel文件,安装测试一下:
uv install dist/example-0.1.0-*.whl
这样生成的wheel文件结构就会和你用setup.py生成的一致了:
- example/a.py
- example/b.pyd
- example/c/d.py
- example/c/e.pyd
备注:内容来源于stack exchange,提问作者colinxu2020
相关产品推荐
相关产品推荐

