解决auditwheel repair过程rpath被修改的问题
问题背景
AuditWheel是一个用于修复Python的whl包的工具,例如在这个CyFES开源库中,因为使用到了Cython和CUDA编译动态链接库的技术,方便Python调用。但是在编译CUDA算子时如果使用到了运行时库,那么在第一步构建whl包的时候不会自动包含运行时库,而第二步使用auditwheel进行whl包修复的时候,会自动把运行时库相关的动态链接库拷贝到whl包中。首先看一下修复前的whl包的目录树:
$ unzip -l dist/CyFES-2.7-cp37-cp37m-linux_x86_64.whl
Archive: dist/CyFES-2.7-cp37-cp37m-linux_x86_64.whl
Length Date Time Name
--------- ---------- ----- ----
2071 2024-09-02 07:54 CyFES-2.7.data/data/cyfes/FES.cuh
1731 2024-08-27 02:47 CyFES-2.7.data/data/cyfes/FES_f32.cuh
692112 2024-09-02 09:38 CyFES-2.7.data/data/cyfes/libcufes.1.so
55472 2024-09-02 09:38 CyFES-2.7.data/data/cyfes/libcufes.so
1628 2024-09-02 07:54 cyfes/__init__.py
6117 2024-09-02 07:54 cyfes/__main__.py
3632 2024-08-16 06:52 cyfes/utils.py
1457723 2024-09-02 09:38 cyfes/wrapper.c
1545248 2024-09-02 09:38 cyfes/wrapper.cpython-37m-x86_64-linux-gnu.so
1245635 2024-09-02 09:38 cyfes/wrapper_f32.c
1213984 2024-09-02 09:38 cyfes/wrapper_f32.cpython-37m-x86_64-linux-gnu.so
2071 2024-09-02 07:54 cyfes/kernels/FES.cuh
1731 2024-08-27 02:47 cyfes/kernels/FES_f32.cuh
0 2024-08-29 07:45 cyfes/kernels/__init__.py
1063 2024-09-02 09:38 CyFES-2.7.dist-info/LICENSE
5588 2024-09-02 09:38 CyFES-2.7.dist-info/METADATA
104 2024-09-02 09:38 CyFES-2.7.dist-info/WHEEL
6 2024-09-02 09:38 CyFES-2.7.dist-info/top_level.txt
1569 2024-09-02 09:38 CyFES-2.7.dist-info/RECORD
--------- -------
6237485 19 files
这里只有动态编译构建过程中生成的libcufes.so和wrapper动态链接库文件。再看看使用auditwheel repair修复之后的whl包目录树结构:
$ unzip -l fix-dist/CyFES-2.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Archive: fix-dist/CyFES-2.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Length Date Time Name
--------- ---------- ----- ----
0 2024-09-02 09:39 cyfes/
0 2024-09-02 09:39 CyFES-2.7.data/
0 2024-09-02 09:39 CyFES-2.7.dist-info/
0 2024-09-02 09:39 CyFES.libs/
0 2024-09-02 09:39 cyfes/kernels/
1457723 2024-09-02 09:39 cyfes/wrapper.c
1213984 2024-09-02 09:39 cyfes/wrapper_f32.cpython-37m-x86_64-linux-gnu.so
6117 2024-09-02 09:39 cyfes/__main__.py
1564760 2024-09-02 09:39 cyfes/wrapper.cpython-37m-x86_64-linux-gnu.so
1628 2024-09-02 09:39 cyfes/__init__.py
3632 2024-09-02 09:39 cyfes/utils.py
1245635 2024-09-02 09:39 cyfes/wrapper_f32.c
0 2024-09-02 09:39 cyfes/kernels/__init__.py
2071 2024-09-02 09:39 cyfes/kernels/FES.cuh
1731 2024-09-02 09:39 cyfes/kernels/FES_f32.cuh
0 2024-09-02 09:39 CyFES-2.7.data/data/
0 2024-09-02 09:39 CyFES-2.7.data/data/cyfes/
63696 2024-09-02 09:39 CyFES-2.7.data/data/cyfes/libcufes.so
692112 2024-09-02 09:39 CyFES-2.7.data/data/cyfes/libcufes.1.so
2071 2024-09-02 09:39 CyFES-2.7.data/data/cyfes/FES.cuh
1731 2024-09-02 09:39 CyFES-2.7.data/data/cyfes/FES_f32.cuh
150 2024-09-02 09:39 CyFES-2.7.dist-info/WHEEL
1063 2024-09-02 09:39 CyFES-2.7.dist-info/LICENSE
1784 2024-09-02 09:39 CyFES-2.7.dist-info/RECORD
6 2024-09-02 09:39 CyFES-2.7.dist-info/top_level.txt
5588 2024-09-02 09:39 CyFES-2.7.dist-info/METADATA
523312 2024-09-02 09:39 CyFES.libs/libcudart-80664282.so.10.2.89
168192 2024-09-02 09:39 CyFES.libs/libgomp-a34b3233.so.1.0.0
--------- -------
6956986 28 files
在这个新的结构中,auditwheel自动把依赖的cudart运行时库和omp分布式库拷贝到了whl包中。这样在本地安装之后,会在site-packages路径下找到一个CyFES.libs的目录,其中就存储了相关的两个动态链接库。那么接下来问题就出现了,在使用$ python3 setup.py sdist bdist_wheel --universal构建的时候,动态链接库libcufes.so是有rpath的,但是使用auditwheel修复之后,rpath消失了:
$ python3 -m auditwheel lddtree build/cyfes/libcufes.so
INFO:auditwheel.main_lddtree:{
"interp": null,
"path": "build/cyfes/libcufes.so",
"realpath": "build/cyfes/libcufes.so",
"needed": [
"libcudart.so.10.2",
"librt.so.1",
"libpthread.so.0",
"libdl.so.2",
"libstdc++.so.6",
"libm.so.6",
"libgcc_s.so.1",
"libc.so.6"
],
"rpath": [],
"runpath": [],
或者也可以使用$ patchelf --print-rpath xxx.so来查看动态链接库的rpath路径。
解决方案
首先我们梳理一下思路。如果这个问题不修复,那么导致的直接结果是,使用$ python3 -m pip install xxx.whl之后,安装过程不报错,但是调用相关函数时会出现段错误的报错。出现这个错误的根本原因是找不到相应的cudart和omp动态链接库。如果不使用auditwheel修复的话,这个包是不完整的,应用在不同版本的cuda上有可能报错。那么解决问题的方向应该是,让libcufes.so能够准确的找到auditwheel拷贝cudart和omp动态链接库文件的位置,也就是site-packages/CyFES.libs/。有了思路再看怎么实现的问题,首先是可以通过Makefile配置相关的运行时路径。换句话说,就是运行或者调用libcufes.so文件时会索引到的路径,只要把这个路径配置到cudart和omp所在路径,就可以索引到相关的库,也就不会报错。还有一种解决方案是,在编译构建完成后,通过patchelf工具直接修改libcufes.so动态链接库的rpath。
因为CyFES毕竟是一个Python库,综合考虑下来,在setup.py文件中配置patchelf命令是一个不错的选项。还有三个需要注意的点:
- 不同的Python版本,site-packages路径是不一样的;
- 不能使用绝对路径配置rpath;
- auditwheel修复whl包时会同时修改目标文件的rpath列表中的第一个路径。
针对于第一个问题,我们只要把支持的几个Python路径都配置上就可以了,例如把rpath配置为/lib/python3.7/site-packages/CyFES.libs:/lib/python3.8/site-packages/CyFES.libs,这样就支持了两个版本的Python路径。对于第二个问题,我们可以在rpath中使用$ORIGIN相对路径,也就是文件所在的当前位置。在安装cyfes时,会产生三个路径下的文件,分别存放data、lib和核心文件。其中lib与核心文件目录都在site-packages/路径下。因而彼此之间的相对路径索引形式是固定的,也就可以固定写在setup.py中进行配置。第三个问题,也很容易解决,只要在rpath的第一个位置放一个无用路径,随便它怎么改。最终形成的指令是这样的:
$ patchelf --set-rpath $ORIGIN:$ORIGIN/../lib/python3.7/site-packages/CyFES.libs:$ORIGIN/../lib/python3.8/site-packages/CyFES.libs:$ORIGIN/../lib/python3.9/site-packages/CyFES.libs:$ORIGIN/../lib/python3.10/site-packages/CyFES.libs libcufes.so
这样就可以解决libcufes.so动态链接库的rpath被auditwheel修改的问题,经过测试可以正常索引到相关的CUDA运行时和omp的动态链接库。
总结概要
在开源Python项目中,如果使用到了Cython或者CUDA C++等需要编译的后端技术,那么要传到pypi上就需要经过一个PEP标准的审查。要通过审查,就要经过多个版本的Python的构建,以及auditwheel修复的过程。本文解决了一个auditwheel修复过程中有可能出现的rpath路径索引问题。
版权声明
本文首发链接为:https://www.cnblogs.com/dechinphy/p/auditwheel.html
作者ID:DechinPhy
更多原著文章:https://www.cnblogs.com/dechinphy/
请博主喝咖啡:https://www.cnblogs.com/dechinphy/gallery/image/379634.html
解决auditwheel repair过程rpath被修改的问题的更多相关文章
- 解决SQL订阅过程中找不到已经创建的订阅
原文:解决SQL订阅过程中找不到已经创建的订阅 之前有写过一篇博客,主要是图解SQL复制技术:图解SQL 2008数据库复制,当时的测试环境是在我本地同一个服务器上面,所以测试的时候可谓是一帆风顺,最 ...
- vue组件中的样式属性:scoped,解决在父组件中无法修改子组件样式问题
Scoped CSS规范是Web组件产生不污染其他组件,也不被其他组件污染的CSS规范. vue组件中的style标签标有scoped属性时表明style里的css样式只适用于当前组件元素,它是通过使 ...
- 关于解决配置Tomact过程中出现的相关问题
最近在学习JavaWeb, 但是在第一步的时候就出现问题了, 什么问题呢, 就是关于Tomact的配置. 下面我就详细说明一下我配置过程中出现的问题以及怎么解决的, 希望对大家能有所帮助. 首先,我 ...
- Aandroid 解决apk打包过程中出现的“Certificate for <jcenter.bintray.com> doesn't match any of the subject alternative names: [*.aktana.com, aktana.com]”的问题
有时候,apk打包过程中会出现“Certificate for <jcenter.bintray.com> doesn't match any of the subject alterna ...
- log4j 日志信息的引入(通用版)——解决项目运行过程中的日志信息
定义 log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.GUI组件,甚至是套接口服务器.NT的事件记录器.UNIX Syslog守护进程 ...
- 解决docker容器中文乱码,修改docker容器编码格式
前台上传文件到服务器后,服务器返回给前台的文件列表中出现中文乱码,所有的中文文件名全部变成?,英文文件名则正常显示. 问题经过定位,发现后台代码的multipartfile类在执行transterto ...
- 高可用的Spring FTP上传下载工具类(已解决上传过程常见问题)
前言 最近在项目中需要和ftp服务器进行交互,在网上找了一下关于ftp上传下载的工具类,大致有两种. 第一种是单例模式的类. 第二种是另外定义一个Service,直接通过Service来实现ftp的上 ...
- 解决Windows2003的IE安全级别不能修改的问题
默认装完win2k3IE安全级别是不能修改的,不管怎么样修改,系统总提示说 “此域的推荐安全级别是“安全级-高”.您选择的级别较低.还是返回最高级别的.刚才弄voip,在win2k3虚拟机测试,差点气 ...
- 解决SharePoint下载文件时自动修改扩展名的问题
今天,有人告诉了我一个有趣的问题.当用户将一个扩展名为.ai的文件(Adobe illustrator格式的文件)上载到SharePoint 2013文档库中之后,点击它下载时,下载提示栏所显示的文件 ...
- 解决url传递过程中加号变空格的问题
url传递过程中加号变空格 在接收url参数的过程中,会发现如果参数中存在‘+’号,接收后会变成空格. 如11+22接收后变成11 22. 要解决这个问题,需要将加号替换为%2B进行传递. 如11%2 ...
随机推荐
- SpringBoot 整合EasyExcel 获取动态Excel列名
导读 最近负责消息网关,里面有个短信模板导入功能,因为不同模板编号对应不同参数,导入后的数据定时发送,涉及到Excel中列名不固定问题,于是想根据列名+值,组合成一个大JSON,具体代码如下. 引入依 ...
- Spring常见面试题总结
Spring是什么? Spring是一个轻量级的IoC和AOP容器框架.是为Java应用程序提供基础性服务的一套框架,目的是用于简化企业应用程序的开发,它使得开发者只需要关心业务需求.常见的配置方式有 ...
- 解锁网络无限可能:揭秘微软工程师力作——付费代理IP池深度改造与实战部署指南
基于付费代理的代理IP池 项目来源 此项目为微软某个工程师构建的代理IP池,我对此进行了改造.可以用于生产环境中的爬虫项目 阅读前建议 阅读我之前发布的爬虫基础的文章,了解代理如何获取.使用等. 分为 ...
- iOS开发基础100 - MDM证书申请流程
申请成为MDM Vendor 首先需要拥有一个 iOS Developer Enterprise Program 帐号; 申请成为MDM Vendor,iOS企业开发帐号默认不支持MDM功能,需要向苹 ...
- iOS开发基础102-后台保活方案
iOS系统在后台执行程序时,有严格的限制,为了更好地管理资源和电池寿命,iOS会限制应用程序在后台的运行时间.然而,iOS提供了一些特定的策略和技术,使得应用程序可以在特定场景下保持后台运行(即&qu ...
- oeasy教您玩转python - 007 - # 字符本质
字符本质 回忆上次内容 hello world 不是从来就有的 来自于unix和c 虽然我们今天有各种先进的学习手段 最早的高级语言学习是从最早的那张打字机用纸的手写代码起源的 所以输出用的是 p ...
- 免费的壁纸API
最近在给EasyDesktop增加背景的功能, 考虑自己在服务器上部署壁纸, 维护成本比较高, 就找了几个免费的壁纸接口, 体验还不错, 这里简单记录一下. 1.Bing壁纸API 地址是: http ...
- SMU Summer 2024 Contest Round 2 (7.9)zhaosang
A-A http://162.14.124.219/contest/1006/problem/A 考查用vector画图 我枚举到n==5才开始用,浪费40分钟,还是找规律太慢,得多学 做题代码如下: ...
- Vue cil路由如何回到初始状态
前景:我们在网页里进入路由的地址后,会发现地址栏中会加上我们的路由地址,这样我就知道当前在哪个位置.但是这样子我们如何手动刷新浏览器,想要浏览器回到根路径的话,是无法直接回去的,因为地址没有更改.再怎 ...
- docker 容器挂载技术
创建和使用桥接网络 docker network create --driver bridge --subnet 192.168.13.0/24 --gateway 192.168.13.1 mqyn ...