2015-10-16 37 views
8

Mam moduł Pythona, który wywołuje zewnętrzny plik binarny, zbudowany ze źródła C.Kompilowanie i instalowanie pliku wykonywalnego C przy użyciu setuptools/setup.py python?

Źródło tego zewnętrznego pliku wykonywalnego jest częścią mojego modułu python, rozprowadzanego jako plik .tar.gz.

Czy istnieje sposób rozpakowania, a następnie skompilowanie tego zewnętrznego pliku wykonywalnego i zainstalowanie go za pomocą setuptools/setup.py?

Co chciałbym osiągnąć to:

  • zainstalowaniu tego pliku binarnego w środowiskach wirtualnych
  • zarządzać kompilację/instalację binarny używając setup.py install, setup.py build itp
  • dokonywania binarny częścią mojego moduł python, który może być dystrybuowany jako koło bez zewnętrznych zależności.
+0

Czy rozwiązałeś ten problem? Jeśli tak, czy możesz udostępnić swoje rozwiązanie? Dzięki –

+0

Zrobiłem w końcu, wkrótce dodam odpowiedź. –

Odpowiedz

3

Rozwiązany w końcu przez modyfikację setup.py, aby dodać dodatkowe procedury obsługi dla poleceń, które wykonały instalację.

Przykładem setup.py który robi to może być:

import os 
from setuptools import setup 
from setuptools.command.install import install 
import subprocess 

def get_virtualenv_path(): 
    """Used to work out path to install compiled binaries to.""" 
    if hasattr(sys, 'real_prefix'): 
     return sys.prefix 

    if hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix: 
     return sys.prefix 

    if 'conda' in sys.prefix: 
     return sys.prefix 

    return None 


def compile_and_install_software(): 
    """Used the subprocess module to compile/install the C software.""" 
    src_path = './some_c_package/' 

    # compile the software 
    cmd = "./configure CFLAGS='-03 -w -fPIC'" 
    venv = get_virtualenv_path() 
    if venv: 
     cmd += ' --prefix=' + os.path.abspath(venv) 
    subprocess.check_call(cmd, cwd=src_path, shell=True) 

    # install the software (into the virtualenv bin dir if present) 
    subprocess.check_call('make install', cwd=src_path, shell=True) 


class CustomInstall(install): 
    """Custom handler for the 'install' command.""" 
    def run(self): 
     compile_and_install_software() 
     super().run() 


setup(name='foo', 
     # ...other settings skipped... 
     cmdclass={'install': CustomInstall}) 

Teraz kiedy python setup.py install nazywa zwyczaj CustomInstall klasa jest używana, to następnie kompiluje i instaluje oprogramowanie przed zwykłej instalacji kroki są prowadzone.

Możesz także zrobić podobne działanie w przypadku innych kroków, które Cię interesują (np. Build/develop/bdist_egg itd.).

Alternatywą jest uczynienie funkcji compile_and_install_software() podklasą setuptools.Command i utworzenie dla niej pełnoprawnej komendy setuptools.

Jest to bardziej skomplikowane, ale pozwala na takie czynności, jak określanie go jako podkomend innego polecenia (np. Unikanie dwukrotnego uruchamiania) i przekazywanie do niego opcji niestandardowych w wierszu poleceń.