libsodium引用报错FileNotFoundError: [Errno 2] No such file or directory: b‘liblibsodium.a‘

Posted feiniao8651

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了libsodium引用报错FileNotFoundError: [Errno 2] No such file or directory: b‘liblibsodium.a‘相关的知识,希望对你有一定的参考价值。

问题

操作系统环境: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调用不规范引起的报错。

参考:
ctypes.util.find_library(“libc”) fails

以上是关于libsodium引用报错FileNotFoundError: [Errno 2] No such file or directory: b‘liblibsodium.a‘的主要内容,如果未能解决你的问题,请参考以下文章

CentOS 7.3 安装 libsodium 1.0.18

libsodium PHP将私钥存储在文件中

使用 libsodium 构建一个简单的项目 [重复]

在 PHP 7.1 中安装 libsodium 时出错

Tomcat启动报FileNotFound异常解决方案

项目中使用libsodium扩展