赞
踩
操作系统环境:Ubuntu 22.04
在安装一个工具应用时,这个应用使用到了chacha20加密算法,所以需要依赖libsodium。按照网上教程下载源码并编译安装:
sudo apt install build-essential
wget https://download.libsodium.org/libsodium/releases/libsodium-1.0.18.tar.gz
tar xf libsodium-1.0.18.tar.gz
cd libsodium-1.0.18
./configure
make
sudo make install
ldconfig
当启动该工具应用时出现报错:
File "/home/ubuntu/.local/lib/python3.7/site-packages/*****/crypto/util.py", line 80, in find_library
path = ctypes.util.find_library(name)
File "/usr/lib/python3.7/ctypes/util.py", line 341, in find_library
_get_soname(_findLib_gcc(name)) or _get_soname(_findLib_ld(name))
File "/usr/lib/python3.7/ctypes/util.py", line 147, in _findLib_gcc
if not _is_elf(file):
File "/usr/lib/python3.7/ctypes/util.py", line 99, in _is_elf
with open(filename, 'br') as thefile:
FileNotFoundError: [Errno 2] No such file or directory: b'liblibsodium.a'
首先确认了libsodium的安装过程,整个安装步骤没有报错,根据安装日志,也在/usr/local/lib/下找到了libsodium.a文件。
网上搜索这个问题,遇到同一问题的人很少,但是却有很多人遇到另一个库"liblibc.a"的报错,他们的解决方案是在libc.a的同一目录下建立软连接liblibc.a,抱着试一试的心态,我在/usr/local/lib下建立了一个软连接
cd /usr/local/lib
sudo ln -s libsodium.a liblibsodium.a
这时候再运行应用,果然运行正常。
根据报错日志
File "/usr/lib/python3.7/ctypes/util.py", line 341, in find_library
_get_soname(_findLib_gcc(name)) or _get_soname(_findLib_ld(name))
File "/usr/lib/python3.7/ctypes/util.py", line 147, in _findLib_gcc
if not _is_elf(file):
File "/usr/lib/python3.7/ctypes/util.py", line 99, in _is_elf
with open(filename, 'br') as thefile:
我们从下往上,定位是在哪一步添加了多出来的lib前缀。
通过分析源码,我们可以发现
elif os.name == "posix": # Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump import re, tempfile ........ def _findLib_gcc(name): # Run GCC's linker with the -t (aka --trace) option and examine the # library name it prints out. The GCC command will fail because we # haven't supplied a proper program with main(), but that does not # matter. expr = os.fsencode(r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)) ........ res = re.findall(expr, trace) if not res: return None for file in res: # Check if the given file is an elf file: gcc can report # some files that are linker scripts and not actual # shared objects. See bpo-41976 for more details if not _is_elf(file): continue return os.fsdecode(file)
在报错日志中调用的_findLib_gcc方法中,是通过正则表达式来查找库文件的,而这里的正则表达式:
expr = os.fsencode(r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name))
已经自动在库名称前添加了lib前缀。同样的根据python官方文档
ctypes.util.find_library(name)
Try to find a library and return a pathname. name is the library name without any prefix like lib, suffix like .so, .dylib or version number (this is the form used for the posix linker option -l). If no library can be found, returns None.
The exact functionality is system dependent.
要求name中是不能含有lib前缀的。所以这时候我们要检查应用在调用find_library(name)时,传入的name是否含有额外的lib前缀了。
查看find_library的调用源码
def find_library(possible_lib_names, search_symbol, library_name, custom_path=None): import ctypes.util ........ lib_names = [] for lib_name in possible_lib_names: lib_names.append(lib_name) lib_names.append('lib' + lib_name) for name in lib_names: if os.name == "nt": paths.extend(find_library_nt(name)) else: path = ctypes.util.find_library(name) if path: paths.append(path)
果然是有一个加lib前缀的操作
lib_names.append('lib' + lib_name)
我们只要注释掉这行代码问题就能解决了。所以这是一个find_library调用不规范引起的报错。
有的电脑上不会发生这个问题,因为还有一个逻辑间接导致的问题的出现,我这台电脑正好是多重因素赶上了。
即使加了多余的前缀lib,在执行re.findall(expr, trace)方法,大部分电脑返回的结果应该是空,但是我这台电脑trace里正巧有个报错信息,含有liblibsodium字段,导致正则表达式匹配出来的结果不为空,才会导致后续的打开文件失败。
b'/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/Scrt1.o\n
/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/crti.o\n
/usr/lib/gcc/x86_64-linux-gnu/11/crtbeginS.o\n
/usr/bin/ld: cannot find -llibsodium: No such file or directory\n
/usr/bin/ld: note to link with /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/libsodium.a use -l:libsodium.a or rename it to liblibsodium.a\n
/usr/lib/gcc/x86_64-linux-gnu/11/libgcc.a\n
/usr/lib/gcc/x86_64-linux-gnu/11/libgcc_s.so\n
/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/libgcc_s.so.1\n
/usr/lib/gcc/x86_64-linux-gnu/11/libgcc.a\n
collect2: error: ld returned 1 exit status\n'
参考:
ctypes.util.find_library(“libc”) fails
re — Regular expression operations
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。