fontes Python compilar uma versão diferente

1

Eu tenho tido pesadelos com esse mistério por 3 dias. Como eu fiz muitas vezes eu baixei as fontes do Python (desta vez 2.7.13) para compilá-las em um ambiente sem acesso à internet (e, portanto, nenhuma outra maneira de obter versões mais novas de Programas). Eu estou no Oracle Linux 7.3 (ambiente semelhante ao RHEL). Por padrão, este traz o python 2.7.5, mas eu preciso da versão mais recente para alguns testes e para obter pip OOTB.

Eu fiz o usual:

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

Tudo correu bem até que tentei instalar algum pacote extra, como pedidos com 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 ... Então tentei verificar o que o python foi realmente instalado em /usr/local/

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

Então eu tentei recompilar tudo MAS sem instalar os binários resultantes para ver o que realmente estava sendo feito dentro do diretório de fontes.

[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

Eu não tenho ideia do que fazer agora. Por que o binário resultante diz que sua versão é a que está instalada no sistema por padrão? Eu também tentei usar outro prefixo sem sucesso.

    
por Nocturn 06.09.2017 / 16:49

1 resposta

2

Eu ... o que o ... de qualquer forma, isso também acontece no Centos 7, que é mais ou menos RHEL, que é mais ou menos Oracle linux. Notavelmente, se executarmos ldd no binário resultante

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

a compilação do 2.7.13 foi por algum motivo recuperada na biblioteca /lib64/libpython2.7* do sistema, versão 2.7.5. Sem --enabled-shared a versão está correta 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$ 

Isso é completamente não documentado no arquivo python de 2.7.13 README , mas é possível usar LD_* tricks (ou aplicativos ELF-mangling, abaixo) para solucionar essa deficiência do processo de compilação do python. Além disso! Se possível, evite construir o padrão /usr/local , pois isso irá misturar qualquer versão que você esteja construindo em qualquer coisa que esteja em /usr/local ; O GNU stow ou semelhante pode ser usado se você precisar de um programa /usr/local/bin/python , mas quiser que a construção real seja sequestrada, digamos, em /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, o método LD_RUN_PATH requer duas compilações, e agora a segunda (a primeira compilação instalada em 2.7.13% das bibliotecaslibpython2.7 que esta próxima compilação pega e usa) ...

-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$ 

Com ferramentas ELF-mangling, uma das quais é link que, depois de ser instalada pelo arquivo README nesse repositório é possível fazer uma única compilação e instalação em python:

-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$ 
    
por 06.09.2017 / 18:15