如何将第三方库libxdo集成到Python3 manyLinux构建的C扩展中?
问题描述
我正在为CPython打包一个名为winlin的C扩展,该扩展依赖libxdo库实现Linux窗口操作功能。按流程用python3 -m build生成wheel后,用auditwheel repair处理时遇到兼容性问题:
- 本地构建的wheel受GLIBC版本限制,仅支持
manylinux_2_34_x86_64标签; - 在manylinux2014容器中构建时,auditwheel检测到wheel依赖
libxdo.so.3等多个系统库。
已通过Podman挂载本地libxdo-dev头文件到容器完成编译,但不确定是否需要挂载so文件,还是必须在容器中编译libxdo源码。咨询如何将libxdo的功能与依赖完整集成到该C扩展中,使其符合manyLinux标准。
相关配置
Podman挂载命令
podman run --rm -ti \ -v "$PWD/winlin:/winlin:rw" \ -v "/usr/local/include/xdo:/usr/local/include/xdo:ro" \ -v "/usr/local/lib/xdo:/usr/local/lib/xdo:ro" \ quay.io/pypa/manylinux2014_x86_64
setup.py文件
from setuptools import setup, Extension #from distutils.core import setup, Extension module1 = Extension( 'winlin', define_macros = [('MAJOR_VERSION', '1'),('MINOR_VERSION', '0')], include_dirs = ['/usr/local/include/xdo/'], libraries = ['xdo'], library_dirs = ['/usr/local/lib/xdo/'], sources = ['src/winlin.c'] ) setup( name = 'winlin', version = '1.0', description = 'A tool kit for manipulating windows in linux', author = 'Kurt Godel', author_email = 'corndog@corn.dog', url = 'https://google.com', long_description = '#TODO', ext_modules = [module1] )
winlin.c文件
#include <Python.h> #include <xdo.h> static PyObject* resize(PyObject* self, PyObject *args){ int wid, w, h; if (!PyArg_ParseTuple(args, "iii", &wid, &w, &h)) return NULL; xdo_t *xdo_inst = xdo_new(NULL); xdo_set_window_size(xdo_inst, wid, w, h, 0); xdo_free(xdo_inst); Py_RETURN_NONE; //return Py_BuildValue("s", "it worked, maybe?"); } static char resize_docs[] = "\ change the size of a given window given its id and a new height and width\n\ "; /*----------------------------------------------------------------------------*/ static PyObject* move(PyObject* self, PyObject *args){ int wid, x, y; if (!PyArg_ParseTuple(args, "iii", &wid, &x, &y)) return NULL; xdo_t *xdo_inst = xdo_new(NULL); xdo_move_window(xdo_inst, wid, x, y); xdo_free(xdo_inst); Py_RETURN_NONE; } static char move_docs[] = "\ change the position of a window given its id and a new x and y\n\ "; /*----------------------------------------------------------------------------------*/ static PyMethodDef winlin_funcs[] = { {"resize", (PyCFunction)resize, METH_VARARGS, resize_docs}, {"move", (PyCFunction)move, METH_VARARGS, move_docs}, {NULL} }; static char winlin_module_docs[] = "Module used to manipulate windows in linux"; static struct PyModuleDef winlin_module = { PyModuleDef_HEAD_INIT, "winlin", winlin_module_docs, -1, winlin_funcs }; PyMODINIT_FUNC PyInit_winlin(void){ PyObject* m = PyModule_Create(&winlin_module); return m; }
解决方案
要让winlin符合manyLinux标准,核心是将libxdo静态编译到扩展中,彻底消除系统依赖问题,具体步骤如下:
步骤1:在manylinux2014容器内编译libxdo源码
挂载本地头文件/so的方式不可靠,因为本地库可能依赖更高版本的GLIBC或其他系统库,导致最终wheel仍然不符合manyLinux要求。必须在manylinux2014容器内从头编译libxdo:
- 进入容器后,安装编译依赖:
yum install -y git gcc make libX11-devel libXtst-devel
- 获取xdotool的稳定版源码(libxdo是xdotool的核心库组件),进入源码目录并切换到指定版本(如v3.20211022.1):
git clone <xdotool官方仓库地址> cd xdotool git checkout v3.20211022.1
- 编译并静态安装libxdo:
make libxdo.a # 将头文件和静态库安装到容器内的本地目录,比如/usr/local/xdo-static mkdir -p /usr/local/xdo-static/include/xdo mkdir -p /usr/local/xdo-static/lib cp libxdo.a /usr/local/xdo-static/lib/ cp xdo.h /usr/local/xdo-static/include/xdo/
步骤2:修改setup.py静态链接libxdo
修改Extension配置,使用静态库而非动态库,避免依赖系统的libxdo.so:
from setuptools import setup, Extension module1 = Extension( 'winlin', define_macros = [('MAJOR_VERSION', '1'),('MINOR_VERSION', '0')], include_dirs = ['/usr/local/xdo-static/include/'], # 直接指定静态库文件路径 extra_objects = ['/usr/local/xdo-static/lib/libxdo.a'], # 链接libxdo依赖的系统核心库(manyLinux允许依赖这些基础库) libraries = ['X11', 'Xtst'], sources = ['src/winlin.c'] ) setup( name = 'winlin', version = '1.0', description = 'A tool kit for manipulating windows in linux', author = 'Kurt Godel', author_email = 'corndog@corn.dog', url = 'https://google.com', long_description = '#TODO', ext_modules = [module1] )
步骤3:在容器内构建wheel并处理
- 安装build和auditwheel:
pip install build auditwheel
- 进入项目目录构建wheel:
cd /winlin python -m build --wheel
- 用auditwheel修复wheel:
auditwheel repair dist/*.whl
修复后的wheel会在wheelhouse目录下,此时wheel应该符合manylinux2014_x86_64标准,且不依赖系统的libxdo.so。
关键说明
- 静态编译的优势:将libxdo的代码直接整合到扩展中,不需要额外打包动态库,彻底消除libxdo的依赖问题。
- 系统库依赖:libxdo依赖的libX11、libXtst属于manyLinux允许的系统核心库,无需打包进wheel。
- 容器内编译的必要性:manylinux2014容器基于CentOS7,GLIBC版本为2.17,在容器内编译能保证扩展依赖的GLIBC版本符合低版本要求,生成的wheel兼容更多Linux发行版。
内容的提问来源于stack exchange,提问作者gnarlyninja
相关产品推荐
相关产品推荐

