以非 root 用户身份从源代码构建 Python 时找不到共享库文件

问题描述 投票:0回答:1

我正在尝试以 Linux 上的非 root 用户身份从源代码构建 Python3.12。我知道它需要 openssl (用于 pip)和 libffi 标头,我也尝试从源代码构建它们。这样做我最终在 make 日志中出现以下错误:

[ERROR] _ctypes failed to import: libffi.so.8: cannot open shared object file: No such file or directory
[ERROR] _hashlib failed to import: libcrypto.so.3: cannot open shared object file: No such file or directory
[ERROR] _ssl failed to import: libssl.so.3: cannot open shared object file: No such file or directory
The following modules are *disabled* in configure script:
_sqlite3                                                       

The necessary bits to build these optional modules were not found:
_curses               _curses_panel         _dbm               
_gdbm                 _lzma                 _tkinter           
nis                   readline                                 
To find the necessary bits, look in configure.ac and config.log.

Following modules built successfully but were removed because they could not be imported:
_ctypes               _hashlib              _ssl               

Could not build the ssl module!
Python requires a OpenSSL 1.1.1 or newer

Checked 111 modules (31 built-in, 67 shared, 1 n/a on linux-x86_64, 1 disabled, 8 missing, 3 failed on import)

我希望能够(除其他外)使用 ctype 模块,所以这是次优的。

我采取的步骤

第 1 步:从构建 libffi。在配置 make 文件时,我遵循了 这些 说明并包含了

--prefix=$HOME/.local
(因为这是我想在本地安装所有内容的地方)。 (
./configure --prefix=$HOME/.local
).

第 2 步:从构建 openssl。我(或多或少)遵循了这些指示。我在配置过程中再次包含了

--prefix=$HOME/.local

现在,我的

.local
文件夹看起来像这样:

├── bin
│   ├── c_rehash
│   └── openssl
├── include
│   ├── ffi.h
│   ├── ffitarget.h
│   └── openssl
│       └── <loads of header files>.h
├── lib
│   ├── libcrypto.so
│   ├── libffi.so
│   ├── libssl.so
│   └── pkgconfig
│       └── libffi.pc
├── lib64
│   ├── cmake
│   │   └── OpenSSL
│   │       ├── OpenSSLConfig.cmake
│   │       └── OpenSSLConfigVersion.cmake
│   ├── engines-3
│   │   ├── afalg.so
│   │   ├── capi.so
│   │   ├── loader_attic.so
│   │   └── padlock.so
│   ├── libcrypto.a
│   ├── libcrypto.so
│   ├── libcrypto.so.3
│   ├── libffi.a
│   ├── libffi.la
│   ├── libffi.so
│   ├── libffi.so.8
│   ├── libffi.so.8.1.3
│   ├── libssl.a
│   ├── libssl.so
│   ├── libssl.so.3
│   ├── ossl-modules
│   │   └── legacy.so
│   └── pkgconfig
│       ├── libcrypto.pc
│       ├── libssl.pc
│       └── openssl.pc
├── share
│   ├── ...
...

第3步:从构建Python3.12。在这里,我还包含了this帖子的要点,并尝试包含所有正确的标志等。我怀疑这里出了问题。

配置:

./configure --enable-optimizations --with-lto --with-openssl=$HOME/.local \
--prefix=$HOME/.local/ \
LIBFFI_INCLUDEDIR=$HOME/.local/include \
LDFLAGS="-L$HOME/.local/lib/../lib64 -L$HOME/.local/lib64" \
CFLAGS="-I$HOME/.local/include"

这导致(经过多次尝试)对 libiff 和 openssl 文件的检查产生了一些积极的输出。

构建(由于某种原因重复包含目录,请参阅前面的链接):

make LIBFFI_INCLUDEDIR=$HOME/.local/include

执行

make
会导致帖子开头显示错误。

注: 新功能,不是 Linux 向导)

python linux makefile libffi
1个回答
0
投票

动态库可能很棘手,因为有很多不同的步骤,都需要找到它们。您使用

-L
标志走在正确的轨道上,它告诉编译时链接器在哪里可以找到
libffi.so
,但是当 Python 解释器尝试加载
_ctypes
时,运行时链接器 无法找到它:

[ERROR] _ctypes failed to import: libffi.so.8: cannot open shared object file: No such file or directory

_ctypes
模块实际上是作为
.so
库本身实现的,它是一个ELF(Executable和LinkableFormat)文件。 ELF 文件中有一个部分存储动态链接信息。我能够重现您的
_ctypes
问题,并且我使用
readelf -d
显示此文件的内容;我怀疑你的看起来很相似:

$ readelf -d ./Modules/_ctypes_failed.cpython-312-x86_64-linux-gnu.so

Dynamic section at offset 0x3aca0 contains 28 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libpthread.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [ld-linux-x86-64.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libffi.so.8]
 0x0000000000000001 (NEEDED)             Shared library: [libdl.so.2]
 0x000000000000000c (INIT)               0xe000
 0x000000000000000d (FINI)               0x32b4c
 0x0000000000000019 (INIT_ARRAY)         0x3bc80
 0x000000000000001b (INIT_ARRAYSZ)       16 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x3bc90
 0x000000000000001c (FINI_ARRAYSZ)       16 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x328
 0x0000000000000005 (STRTAB)             0x1948
 0x0000000000000006 (SYMTAB)             0x370
 0x000000000000000a (STRSZ)              3975 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000003 (PLTGOT)             0x3c000
 0x0000000000000002 (PLTRELSZ)           4488 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0xc1d0
 0x0000000000000007 (RELA)               0x2b88
 0x0000000000000008 (RELASZ)             38472 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffffe (VERNEED)            0x2aa8
 0x000000006fffffff (VERNEEDNUM)         5
 0x000000006ffffff0 (VERSYM)             0x28d0
 0x000000006ffffff9 (RELACOUNT)          1558
 0x0000000000000000 (NULL)               0x0

您可以从

NEEDED
条目中看到该库依赖于其他几个库,包括
libffi.so.8
。但是,由于该文件不在标准位置,因此运行时链接器找不到它。解决此问题的一种方法是使用
LD_LIBRARY_PATH
环境变量(正如 Ulrich Eckhardt 在评论中建议的那样)。不过,我更喜欢另一种方法,它不需要您重新配置环境。

ELF 文件的动态部分支持

RUNPATH
条目类型,它允许您为
NEEDED
库硬编码附加搜索路径。您可以添加带有
RUNPATH
链接器标志的
-rpath
条目(包装在
-Wl
标志中,告诉
gcc
将参数传递给真正的链接器)。将其添加到配置命令的
LDFLAGS
中,如下所示:

LDFLAGS="-L$HOME/.local/lib/../lib64 -L$HOME/.local/lib64 -Wl,-rpath,$HOME/.local/lib64"

我自己尝试过(在我的机器上是

/lib
而不是
/lib64
),它修复了
_ctypes
错误。在这里您可以看到原因:

$ readelf -d ./Modules/_ctypes.cpython-312-x86_64-linux-gnu.so

Dynamic section at offset 0x21cd8 contains 28 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libffi.so.8]
 0x0000000000000001 (NEEDED)             Shared library: [libdl.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libpthread.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000001d (RUNPATH)            Library runpath: [/home/chuck/.local/lib]
 0x000000000000000c (INIT)               0x6000
 0x000000000000000d (FINI)               0x1b508
 0x0000000000000019 (INIT_ARRAY)         0x22cc8
 0x000000000000001b (INIT_ARRAYSZ)       8 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x22cd0
 0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x2f0
 0x0000000000000005 (STRTAB)             0x15f0
 0x0000000000000006 (SYMTAB)             0x318
 0x000000000000000a (STRSZ)              3663 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000003 (PLTGOT)             0x23000
 0x0000000000000002 (PLTRELSZ)           3864 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0x4ea0
 0x0000000000000007 (RELA)               0x2698
 0x0000000000000008 (RELASZ)             10248 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffffe (VERNEED)            0x25d8
 0x000000006fffffff (VERNEEDNUM)         4
 0x000000006ffffff0 (VERSYM)             0x2440
 0x000000006ffffff9 (RELACOUNT)          389
 0x0000000000000000 (NULL)               0x0

顺便说一句,当我按照您的步骤操作时,我还看到 OpenSSL 3 的错误,因此我安装了 OpenSSL 1.1.1w,这修复了

_hashlib
_ssl
故障。

© www.soinside.com 2019 - 2024. All rights reserved.