I need to install several Python modules on a RHEL where I don't have root access. At least one of the modules also needs access to Python.h
.
In this case I find that the best thing is to install python and it dependencies in ~/local
. It usually just works, but this time Python fails to build the SSL module (see details below). Here's the trace of what I'm doing.
So I downloaded python 6 source and off I went:
./configure --prefix=/home/fds/rms/local
make >& make.log
An inspection to log reveals that ssl module has not been compiled, but there is no mention of the cause (no other occurence of ssl in make or configure):
Failed to find the necessary bits to build these modules:
_bsddb _curses _curses_panel
_hashlib _sqlite3 _ssl <----------
So I figure, python is not finding any ssl library at all (which is strange, but hey...). So I download openssl-0.9.8r and
./config --prefix=/home/fds/rms/local shared
make
make install
Now back to Python, I ./configure and make again. It fails, but this time it's different:
Failed to build these modules:
_hashlib _ssl
A closer inspection to the log file reveals this:
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
So now it's picking up the library but not quite getting it right (the file is there where is should be):
$ find /home/fds/rms/local -iname libssl.so.0.9.8
/home/fds/rms/local/lib/libssl.so.0.9.8
Next thing is tracing make and see where is it looking for the file:
$ 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
Mhhh, it's looking in all the wrong places. I try to give a hint:
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
But nothing changes, and make
does not seem to try /home/fds/rms/local/lib
at all.
I haven't done this in years, so maybe I'm overlooking something. Can anyone help with the problem?
Thanks in advance.
You need to edit Modules/Setup.dist
to specify the location of OpenSSL if it is not in the standard location. From Getting SSL Support in Python 2.5.1:
If you find yourself on a linux box needing ssl support in python (to use a client in things like httplib.HTTPSConnection or imaplib.IMAP4_SSL), then let me save you a couple of hours of hunting around the web (of course if you have found this then that means you've done some level hunting already!).
You'll know if you need ssl support compiled into your python installation if you get the following exception message: AttributeError: 'module' object has no attribute 'ssl'
In order to make that go away so you can continue happily slinging python code, you'll need to first make sure you have OpenSSL installed. By default it is installed from source at: /usr/local/ssl
If that directory doesn't exist, then grab the source package.
Do the standard:
tar zxf openssl-0.9.8g.tar.gz cd openssl-0.9.8g ./config make make install
Then grab the python sources for 2.5.1 and: tar zxf Python-2.5.1.tgz && cd Python-2.5.1
Then you need to edit the Modules/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 uncomment lines 206-209, then:
./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.
On Linux Red Hat 7.7 x86_64, the following worked to install openssl-1.1.1d and Python-3.8.1 in my home directory (/home/unix/vangalen):
Install OpenSSL source1 source2
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
Install Python source2 source3 source4
cd ~
wget https://www.python.org/ftp/python/3.8.1/Python-3.8.1.tgz
tar xf Python-3.8.1.tgz
Modify Python-3.8.1/Modules/Setup in a text editor. If this file doesn't exist you may need to go through a failed run first. Uncomment lines and adjust the alias for SSL in lines 206 to 213::
_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 has a good method, and is relevant as of 2021, but I disagree with some details.
His method of modifying the Modules/Setup
file results in the libssl.so and libcrypto.so libraries becoming dynamic dependencies of the python
binary itself. This is not as intended -- those are supposed to be dependencies of python importable .so
's, like _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.
This is my modification of @PeterValGalen's approach:
# 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.
When done this way, the openssl libs are not dependencies of the python binary, but are dependencies of the _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)
And it works:
$ ./python -c "import ssl; print('yay')"
yay
$ ./python Lib/test/test_ssl.py
# ... lots of good stuff...
OK (skipped=10)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With