在非标准位置使用 SSL 支持构建 Python

我需要在一个 RHEL 上安装几个 Python 模块,在这里我没有 root 访问权限。至少其中一个模块还需要访问 Python.h

在这种情况下,我发现最好的办法是在 ~/local中安装 python 及其依赖项。它通常只能工作,但是这次 Python 无法构建 SSL 模块(请参阅下面的详细信息)。这是我正在做的事情的痕迹。

所以我下载了 python 6的源代码,然后我说:

./configure --prefix=/home/fds/rms/local
make >& make.log

对日志的检查显示 ssl 模块尚未编译,但没有提到原因(make 或 configure 中没有出现其他 ssl) :

Failed to find the necessary bits to build these modules:
_bsddb             _curses            _curses_panel
_hashlib           _sqlite3           _ssl   <----------

所以我想,python 根本没有找到任何 ssl 库(这很奇怪,但是嘿... ...)。所以我下载了 openssl-0.9.8 r 和

./config --prefix=/home/fds/rms/local shared
make
make install

现在回到 Python,I./configure 和 make。它失败了,但这次不同:

Failed to build these modules:
_hashlib           _ssl

仔细检查日志文件就会发现:

gcc -pthread -shared build/temp.linux-x86_64-2.6/home/fds/rms/installers/Python-2.6.6/Modules/_ssl.o -L/home/fds/rms/local/lib -L/usr/local/lib -lssl -lcrypto -o build/lib.linux-x86_64-2.6/_ssl.so
*** WARNING: renaming "_ssl" since importing it failed: libssl.so.0.9.8: cannot open shared object file: No such file or directory

所以现在它拾取了库,但是没有完全正确(文件在应该在的地方) :

$ find /home/fds/rms/local -iname libssl.so.0.9.8
/home/fds/rms/local/lib/libssl.so.0.9.8

下一步是跟踪 make,看看它在哪里寻找文件:

$ strace -f make 2>&1 | grep libssl.so.0.9.8
[pid  5584] open("/lib/libssl.so.0.9.8", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  5584] open("/usr/lib/libssl.so.0.9.8", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  5584] open("/lib64/tls/x86_64/libssl.so.0.9.8", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  5584] open("/lib64/tls/libssl.so.0.9.8", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  5584] open("/lib64/x86_64/libssl.so.0.9.8", O_RDONLY) = -1 ENOENT (No such file or   directory)
[pid  5584] open("/lib64/libssl.so.0.9.8", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  5584] open("/usr/lib64/tls/x86_64/libssl.so.0.9.8", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  5584] open("/usr/lib64/tls/libssl.so.0.9.8", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  5584] open("/usr/lib64/x86_64/libssl.so.0.9.8", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  5584] open("/usr/lib64/libssl.so.0.9.8", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  5584] write(1, "*** WARNING: renaming \"_ssl\" sin"..., 131*** WARNING: renaming "_ssl" since importing it failed: libssl.so.0.9.8: cannot open shared object file: No such file or directory
[pid  5584] open("/lib/libssl.so.0.9.8", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  5584] open("/usr/lib/libssl.so.0.9.8", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  5584] open("/lib64/libssl.so.0.9.8", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  5584] open("/usr/lib64/tls/libssl.so.0.9.8", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  5584] open("/usr/lib64/libssl.so.0.9.8", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid  5584] write(1, "*** WARNING: renaming \"_hashlib\""..., 135*** WARNING: renaming "_hashlib" since importing it failed: libssl.so.0.9.8: cannot open shared object file: No such file or directory

嗯,它找错地方了。我试着给点提示:

CPPFLAGS="-I/home/fds/rms/local/include -I/home/fds/rms/local/include/openssl" LDFLAGS="-L/home/fds/rms/local/lib" ./configure --prefix=/home/fds/rms/local

但是什么都没有改变,而且 make似乎根本没有尝试 /home/fds/rms/local/lib

我很多年没做这个了,所以可能我忽略了什么。有人能帮我解决这个问题吗?

Thanks in advance.

124309 次浏览

尝试将 -Wl,-rpath,/home/fds/rms/local/lib添加到 LDPATH

如果 OpenSSL 不在标准位置,则需要编辑 Modules/Setup.dist来指定它的位置。来自 在 Python 2.5.1中获得 SSL 支持:

如果您发现自己在 Linux 机器上需要 python 中的 ssl 支持(到 在 httplib.HTTPSConnection 或 imaplib.IMAP4_SSL), then let me save you a couple of hours of hunting (当然,如果你已经找到了这个,那么这意味着 你已经做了一些水平狩猎了!)。

You'll know if you need ssl support compiled into your python 如果您收到以下异常消息: AttributeError: ‘ module’对象没有属性‘ ssl’

这样你就可以继续愉快地卖毒品了 在使用 python 代码时,首先需要确保您拥有 OpenSSL 默认情况下,它是从源代码安装的:/usr/local/ssl

如果该目录不存在,那么获取源代码包。

执行标准:

tar zxf openssl-0.9.8g.tar.gz
cd openssl-0.9.8g
./config
make
make install

然后获取2.5.1和: tar zxf Python-2.5.1. tgz 的 Python 源代码 & & cd Python-2.5.1

然后您需要编辑 Module/Setup.dist:

204:# Socket module helper for SSL support; you must comment out the other
205:# socket line above, and possibly edit the SSL variable:
206:SSL=/usr/local/ssl
207:_ssl _ssl.c \
208:    -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
209:    -L$(SSL)/lib -lssl -lcrypto

If you installed OpenSSL in the default locations you can just 取消评论行206-209,然后:

./configure
make
make install

Then verify your installation with:

python /usr/local/lib/python2.5/test/test_socket_ssl.py
test_rude_shutdown ...
test_basic ...
test_timeout ...

Make sure the changes to Modules/Setup.dist get picked up by cleaning the source root (e.g. make distclean) and run configure and make again.

在 Bourne shell (/bin/sh 或/bin/bash)中:

$ LD_LIBRARY_PATH=/usr/local/lib
$ export LD_LIBRARY_PATH
$ make

in the C-shell (/bin/csh or /bin/tcsh):

% setenv LD_LIBRARY_PATH /usr/local/lib
% make

对我来说,编辑 Modules/Setup是不够的,因为 _hashlib模块最终仍然使用了错误的 OpenSSL 版本; 在我的 SLES 系统上,在运行时没有考虑到 LD_LIBRARY_PATH

工作原理是通过按照 GitHub 补丁: eddy-geek/python _ customsl. diff编辑 setup.py,然后编辑 make clean && make,静态地将本地 OpenSSL 链接到 _ssl_hashlib

关于我为什么在 使用自定义 openssl 版本编译 python 时的 Coredump的 Stack Overflow 上使用静态链接的更多细节。

我得到了同样的结果,直到我回到 openssl 的日志。 在那里我看到你需要使用-fPIC 时,建设 openssl: Building’_ ssl’扩展名:

gcc -pthread -fPIC -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/usr/local/ssl/include -I. -IInclude -I./Include -I/usr/local/include -I/home/feramos/Python-2.7.3/Include -I/home/feramos/Python-2.7.3 -c /home/feramos/Python-2.7.3/Modules/_ssl.c -o build/temp.linux-x86_64-2.7/home/feramos/Python-2.7.3/Modules/_ssl.o
gcc -pthread -shared build/temp.linux-x86_64-2.7/home/feramos/Python-2.7.3/Modules/_ssl.o -L/usr/local/ssl/lib -L/usr/local/lib -lssl -lcrypto -o build/lib.linux-x86_64-2.7/_ssl.so
/usr/bin/ld: /usr/local/ssl/lib/libcrypto.a(x86_64cpuid.o): relocation R_X86_64_PC32 against `OPENSSL_cpuid_setup' can not be used when making a shared object; recompile with -fPIC


openssl-0.9.8g]# .config -fPIC

然后,make,make install for openssl,然后再次构建 Python。

下面是我在 Python 2.7.11中使用的完整过程。


In top level Python2.7.11 source dir:

  1. 更改 Modules/Setup.distModules/Setup: 取消注释 _ssl部分,取消注释 _socket(如果已经注释了,则禁止操作) ,取消注释并适当设置 SSL (到达新的 SSL lib/includes的路径等)

    注意: 模块/安装文件最初并不存在,但是在第一次运行之后,我相信它会从模块/Setup.dist 获得内容。确保在每次运行之前都在这里反映更改。

  2. 应用补丁: http://gist.github.com/eddy-geek/9604982 (如果以前运行过 make,则 make distclean)

    ./configure --prefix=/root/.local/aks/py-ssl/python2.7 --enable-shared
    
    
    # modify: Makefile -> set svnversion to ""
    
    
    make
    
    
    make altinstall
    

I'm building Python2.7.13 and I see this same issue. For 2.7.13 you have to use "openssl1.0.0e" or above to make it work. I tried openssl-0.9.8g and it doesn't work. 而且不知怎么的,我不能仅仅修改 Module/Setup.dist 就让它工作,所以我必须手动编译那个 _ ssl.o。 我猜这是因为我提供的 openssl-0.9.8 g 无法工作,它搜索系统默认的 libssl.so.10也无法工作。

我有一组用于静态 openssl 和静态 libintl 的补丁,分别用于下面的2和3。

对于 OPENSSL (第一个补丁) ,必须设置 env var OPENSSL _ ROOT。

This is based on the patch from http://gist.github.com/eddy-geek/9604982 .

对于 Python 2.7.14:

Https://gist.github.com/rkitover/2d9e5baff1f1cc4f2618dee53083bd35

Https://gist.github.com/rkitover/afab7ed3ac7ce1860c43a258571c8ae1

对于 Python 3.6.3:

Https://gist.github.com/rkitover/93d89a679705875c59275fb0a8f22b45

Https://gist.github.com/rkitover/b18f19eafda3775a9652cc9cdf3ec914

对于 MAC OS HIGH Sierra, 和 Python-3.5.6 在上面的答案中,openssl 的安装是使用 source 完成的,但是如果您使用 brew 安装,它会告诉您安装的包在哪里,所以如果您使用 brew 安装 openssl

brew install openssl

这将在 /usr/local/Cellar/openssl/1.0.2o _ 2/上安装 openssl,这个路径需要在 Module/Setup.dist 中更新,地址是

按照上面提到的答案,在没有提到 openssl 安装位置的地方更新 Module/Setup.dist

在以上行中,将 SSL 值更新为

SSL=/usr/local/Cellar/openssl/1.0.2o_2/

取消注释, 做一个 CMM,您的 python 将用 openssl 编译。

在 Linux Red Hat 7.7 x86 _ 64上,下面的代码可以在我的 home 目录(/home/unix/vangalen)中安装 Openssl-1.1.1 dPython-3.8.1:

Install OpenSSL 来源1 < a href = “ https://tech拾遗. com/install-python-openssl-support-lessons/”rel = “ noReferrer”> source 2

cd ~
wget https://www.openssl.org/source/openssl-1.1.1d.tar.gz
tar -xzf openssl-1.1.1d.tar.gz
cd /home/unix/vangalen/openssl-1.1.1d
./config --prefix=/home/unix/vangalen/openssl --openssldir=/home/unix/vangalen/openssl
make
make test
make install

安装 Python Source 2 来源3 < a href = “ https://stackoverflow.com/questions/50246699/python-error-while-load-share-library-libssl-so-1-1-cannot-open-share”> source 4

cd ~
wget https://www.python.org/ftp/python/3.8.1/Python-3.8.1.tgz
tar xf Python-3.8.1.tgz

在文本编辑器中修改 Python-3.8.1/Module/Setup。如果该文件不存在,您可能需要首先执行失败的运行。取消注释行并在第206至213行中调整 SSL 的别名:

_socket socketmodule.c


# Socket module helper for SSL support; you must comment out the other
# socket line above, and possibly edit the SSL variable:
SSL=/home/unix/vangalen/openssl
_ssl _ssl.c \
-DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
-L$(SSL)/lib -lssl -lcrypto
cd ~/Python-3.8.1
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/home/unix/vangalen/openssl/lib
./configure --prefix=/home/unix/vangalen/py-381 --with-openssl=/home/unix/vangalen/openssl
make
make test
make install

@ PeterVanGalen 有一个很好的方法从2021年开始是相关的,但我不同意一些细节。

他修改 Modules/Setup文件的方法导致 libssl.so 和 libcryp.so 库成为 python二进制文件本身的动态依赖项。这不是预期的——这些应该是 Python 可导入的 .so的依赖项,如 _ssl.cpython-39-x86_64-linux-gnu.so

His method also doesn't include a solution for how libssl.so and libcrypto.so will be found at runtime, rather than build time. This matters if they are in some unusual, custom path, or else python will either not run at all or be unable to import ssl. You could solve it in lots of ways (LD_LIBRARY_PATH and ld.so.conf come to mind) but I opted to use rpath, so that the .so files can always be found in their custom location when I use this python, but will otherwise stay out of the way.

这是我对@PeterValGalen 方法的修改:

# First we need openssl installed in a custom location...
tar zxf openssl-1.1.1j.tar.gz
cd openssl-1.1.1j
./config --prefix=/my/weird/path --openssldir=/my/weird/path/ssl
make
make install  # Add `sudo` if needed for permission to /my/weird/path.
cd ..


# Now the python part...
wget https://www.python.org/ftp/python/3.9.2/Python-3.9.2.tgz
tar xf Python-3.9.2.tgz
cd Python-3.9.2
LDFLAGS="${LDFLAGS} -Wl,-rpath=/my/weird/path/lib" ./configure --with-openssl=/my/weird/path
make
make install  # Add `sudo` if needed for permissions.

这样做时,openssl 库不是 python 二进制文件的依赖项,而是 _ssl*.so的依赖项

$ ldd ./python | grep weird
# [Nothing]


$ ldd build/lib.linux-x86_64-3.9/_ssl.cpython-39-x86_64-linux-gnu.so  | grep weird
libssl.so.1.1 => /my/weird/path/lib/libssl.so.1.1 (0x00007f733ee73000)
libcrypto.so.1.1 => /my/weird/path/lib/libcrypto.so.1.1 (0x00007f733e9ab000)

而且很有效:

$ ./python -c "import ssl; print('yay')"
yay


$ ./python Lib/test/test_ssl.py
# ... lots of good stuff...
OK (skipped=10)

OpenSSL

cd /opt
sudo wget https://www.openssl.org/source/openssl-1.1.1q.tar.gz --no-check-certificate
sudo mkdir /opt/openssl
sudo tar xfvz openssl-1.1.1q.tar.gz --directory /opt/openssl
export LD_LIBRARY_PATH=/opt/openssl/lib
cd /opt/openssl/openssl-1.1.1q/
sudo ./config --prefix=/opt/openssl --openssldir=/opt/openssl/ssl
sudo make
sudo make test
sudo make install
sudo ln -s /usr/local/bin/openssl /usr/bin/openssl

Python 3.9.13

cd /usr/src
sudo wget https://www.python.org/ftp/python/3.9.13/Python-3.9.13.tgz
sudo tar xzf Python-3.9.13.tgz
cd /usr/src/Python-3.9.13
sudo CFLAGS="-I/opt/openssl/include/" LDFLAGS="${LDFLAGS} -Wl,-rpath=$LD_LIBRARY_PATH" ./configure --enable-optimizations --with-openssl=/opt/openssl
sudo make altinstall -j6
sudo ln -s /usr/local/bin/python3.9 /usr/bin/python3

Pip3

sudo ln -s /usr/local/bin/pip3.9 /usr/bin/pip3
pip3 install --upgrade pip

在 Ubuntu 14.04.06上测试