不依赖distutils/setuptools制作可pip安装的Python模块
替代方案:无需distutils/setuptools制作可pip安装的SWIG C模块
好问题!既然没法依赖distutils或setuptools,咱们可以借助PEP 517/518定义的现代Python包构建规范,搭配第三方构建工具来实现pip可安装的包——完全绕开那俩老工具,还能完美适配你的SWIG封装C模块场景。下面是几个靠谱的方案:
方案1:Meson构建系统 + meson-python后端
Meson是轻量高效的构建工具,配合meson-python后端可以无缝对接pip的安装流程,专门适合处理C/C+++Python混合项目。
步骤:
- 编写
meson.build配置文件,处理SWIG编译逻辑:
project('my_swig_module', 'c', 'python', version: '0.1.0') # 找到Python环境 py = import('python') python = py.find_installation() # 声明SWIG模块 swig_mod = python.swig_module( name: 'my_module', interface_files: 'my_module.i', sources: 'my_c_code.c', # 如果你的C代码依赖其他库,这里可以加link_with参数 ) # 安装模块到Python的site-packages目录 install_subdir( swig_mod, install_dir: python.get_install_dir() / 'my_module' )
- 编写
pyproject.toml,告诉pip用meson-python作为构建后端:
[build-system] requires = ["meson-python>=0.13.0"] build-backend = "mesonpy" [project] name = "my_swig_module" version = "0.1.0"
- 直接用pip安装:
pip install .
pip会自动下载meson-python,调用Meson完成SWIG编译、模块安装的全流程。
方案2:CMake + scikit-build-core后端
如果你更熟悉CMake,scikit-build-core是专门为Python项目设计的CMake集成后端,同样支持PEP 517规范,处理SWIG模块也很顺手。
步骤:
- 编写
CMakeLists.txt配置SWIG编译:
cmake_minimum_required(VERSION 3.18) project(my_swig_module) # 找到Python和SWIG find_package(Python REQUIRED COMPONENTS Interpreter Development) find_package(SWIG REQUIRED) include(${SWIG_USE_FILE}) # 设置SWIG生成Python代码的参数 set(CMAKE_SWIG_FLAGS "-python") # 声明SWIG模块 swig_add_library(my_module TYPE MODULE LANGUAGE python SOURCES my_module.i my_c_code.c ) # 链接Python库 swig_link_libraries(my_module Python::Python) # 安装模块到正确位置 install(TARGETS my_module DESTINATION ${Python_SITEARCH} )
- 编写
pyproject.toml指定scikit-build-core后端:
[build-system] requires = ["scikit-build-core>=0.7.0"] build-backend = "scikit_build_core.build" [project] name = "my_swig_module" version = "0.1.0"
- 执行pip安装:
pip install .
方案3:自定义PEP 517构建后端(高度定制化)
如果上面的工具都不符合你的需求,还可以自己写一个极简的PEP 517构建后端,完全手动控制SWIG编译和文件复制流程。
示例(简化版):
- 编写
build.py实现构建逻辑:
import os import subprocess import shutil from setuptools import distutils # 仅用其工具函数,不依赖核心构建流程 def build_wheel(wheel_directory, config_settings=None, metadata_directory=None): # 1. 运行SWIG生成Python绑定和C包装代码 subprocess.run([ "swig", "-python", "-o", "my_module_wrap.c", "my_module.i" ], check=True) # 2. 编译C代码(这里假设用gcc,可根据系统调整) python_include = distutils.sysconfig.get_python_inc() subprocess.run([ "gcc", "-shared", "-fPIC", "-I" + python_include, "my_c_code.c", "my_module_wrap.c", "-o", "_my_module.so" ], check=True) # 3. 准备wheel内容 wheel_name = "my_swig_module-0.1.0-cp310-cp310-linux_x86_64.whl" # 根据实际环境调整 wheel_path = os.path.join(wheel_directory, wheel_name) module_dir = os.path.join(wheel_directory, "my_swig_module") os.makedirs(module_dir, exist_ok=True) shutil.copy("_my_module.so", module_dir) shutil.copy("my_module.py", module_dir) # 4. 生成wheel(实际可借助wheel库简化打包逻辑) return wheel_name
- 编写
pyproject.toml指定自定义后端:
[build-system] requires = ["wheel"] build-backend = "build" [project] name = "my_swig_module" version = "0.1.0"
这个方案自由度最高,但需要你自己处理各种系统兼容性(比如不同编译器、Python版本的路径差异),适合对构建流程有特殊要求的场景。
注意事项
- 确保系统中已经安装了SWIG和对应的C编译器(比如Linux下的gcc、macOS下的clang、Windows下的MSVC),pip在构建时会自动调用这些工具。
- 测试安装时可以加
--no-cache-dir参数,避免缓存干扰:pip install --no-cache-dir . - 如果你的模块有系统级依赖(比如某个C库),可以在
pyproject.toml的[project.optional-dependencies]里添加提示,或者在构建脚本里做依赖检查。
内容的提问来源于stack exchange,提问作者user5669394
相关产品推荐
相关产品推荐

