1

I've been having nightmares with this mistery for 3 days. Like I've done many times I downloaded the sources for Python (this time 2.7.13) to compile them in an environtment with no access to the internet (and therefore no other way to get newer versions of software). I'm in Oracle Linux 7.3 (RHEL like environment). By default this one brings python 2.7.5 with it but I need the newer version for some testings and to get pip OOTB.

I did the usual:

# ./configure --enable-shared --with-ensurepip
# make
# make install

Everything ran fine until I tried to install some extra package like requests with pip.

[root@oel7 python_pkgs]# pip install requests-2.11.1/
Traceback (most recent call last):
  File "/usr/local/bin/pip", line 7, in <module>
    from pip import main
ImportError: No module named pip

Huh... Then I tried to check what python was actually installed in /usr/local/

[root@oel7 ~]# /usr/local/bin/python2.7 --version
Python 2.7.5

So I tried to recompile everything BUT without installing the resulting binaries to see what was actually being made inside the sources directory.

[root@oel7 Python-2.7.13]# make distclean
[root@oel7 Python-2.7.13]# ./configure --enable-shared --with-ensurepip
[root@oel7 Python-2.7.13]# ...
[root@oel7 Python-2.7.13]# make
[root@oel7 Python-2.7.13]# ...
[root@oel7 Python-2.7.13]# ./python --version
Python 2.7.5

I don't have a clue of what to do now. Why does the resulting binary says its version is the one that's installed in the system by default? I also tried using another prefix without success.

  • Important note: you appear to be building the sources as root. That's a bad idea. It's also a bad idea to run make install as root. For local sources, both should be done as user. At least for software projects using autotools, this should be installed in /usr/local by default. With regard to your last section, starting with make distclean, I recommend you unpack the sources inside a new directory and check again. – Faheem Mitha Sep 6 '17 at 16:03
  • If you are going to install outside of $HOME, in a directory meant for system-wide installs, running make install as root is not a bad idea, it is a requirement. – njsg Sep 6 '17 at 16:12
2

I...what the...anyways, this also happens on Centos 7 which is more or less RHEL which is more or less Oracle linux. Notably if we run ldd on the resultant binary

-bash-4.2$ ldd ./python
    linux-vdso.so.1 =>  (0x00007ffdb238e000)
    libpython2.7.so.1.0 => /lib64/libpython2.7.so.1.0 (0x00007fc691bfe000)
...

the build of 2.7.13 has for some reason picked up on the system-wide /lib64/libpython2.7* library, version 2.7.5. Without --enabled-shared the version is correctly 2.7.13:

-bash-4.2$ make distclean
...
-bash-4.2$ ./configure --disable-shared --with-ensurepip && make
...
-bash-4.2$ ldd ./python
    linux-vdso.so.1 =>  (0x00007ffffab95000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f59a15a2000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00007f59a139e000)
    libutil.so.1 => /lib64/libutil.so.1 (0x00007f59a119a000)
    libm.so.6 => /lib64/libm.so.6 (0x00007f59a0e98000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f59a0ad7000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f59a17d0000)
-bash-4.2$ ./python --version
Python 2.7.13
-bash-4.2$ 

This is completely undocumented in the python 2.7.13 README file, but one can use LD_* tricks (or ELF-mangling applications, below) to workaround this deficiency of the python build process. Also! If possible avoid building to the default of /usr/local as that will mix whatever version you're building into whatever might be in /usr/local; GNU stow or similar could be used if you do need a /usr/local/bin/python program but want the actual build sequestered off in, say, /usr/local/python-2.7.13:

-bash-4.2$ make distclean
...
-bash-4.2$ ./configure --enable-shared --with-ensurepip --prefix=/usr/local/python-2.7.13
-bash-4.2$ make && sudo make install
...

Ugh, the LD_RUN_PATH method requires two builds, and now the second (the first build installed 2.7.13 libpython2.7 libraries this next build picks up on and uses)...

-bash-4.2$ make distclean
...
-bash-4.2$ ./configure --enable-shared --with-ensurepip --prefix=/usr/local/python-2.7.13
...
-bash-4.2$ LD_RUN_PATH=/usr/local/python-2.7.13/lib make
...
-bash-4.2$ ldd ./python
    linux-vdso.so.1 =>  (0x00007ffca7bcd000)
    libpython2.7.so.1.0 => /usr/local/python-2.7.13/lib/libpython2.7.so.1.0 (0x00007fc6534fb000)
...
-bash-4.2$ sudo make install
...
-bash-4.2$ /usr/local/python-2.7.13/bin/python --version
Python 2.7.13
-bash-4.2$ 

With instead ELF-mangling tools, one of which is https://github.com/NixOS/patchelf which after being installed per the README file in that repository one can do a single python build and install:

-bash-4.2$ sudo rm -rf /usr/local/python-2.7.13
-bash-4.2$  ./configure --enable-shared --with-ensurepip --prefix=/usr/local/python-2.7.13
-bash-4.2$ make
-bash-4.2$ patchelf --set-rpath /usr/local/python-2.7.13/lib python
-bash-4.2$ sudo make install
-bash-4.2$ ldd /usr/local/python-2.7.13/bin/python
    linux-vdso.so.1 =>  (0x00007ffeb57ac000)
    libpython2.7.so.1.0 => /usr/local/python-2.7.13/lib/libpython2.7.so.1.0 (0x00007fcea6b75000)
...
-bash-4.2$ /usr/local/python-2.7.13/bin/python --version
Python 2.7.13
-bash-4.2$ 
  • That's right! I was also googling for this like hell and told some friends until they showed me this and in the comment section of the answer was this other reference so using LD_RUN_PATH=/usr/local/lib make lets you keep the --enable-shared option – Nocturn Sep 6 '17 at 16:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.