2017-11-09 12 views
1

현재 Fortran 모듈을 가져 오는 Python 프로젝트에서 작업 중입니다. setup.py 잘 작동 pip install -e .와 나는 현재를 설치하고있어 그pip 설치에 명령 줄 인수 전달

from numpy.distutils.core import Extension 
from numpy.distutils.core import setup 

ext = Extension(
    name = "fortran_module", 
    sources = ["fortran_module.f90"], 
    extra_f90_compile_args = ["-some -compile -arguments"] 
) 

setup(
    ..., 
    ..., 
    ..., 
    ext_modules = [ext], 
    ..., 
    ..., 
    ... 
) 

, 비슷합니다. 하지만 때로는 extra_f90_compile_args을 변경해야하며 설치 중에 pip을 사용하여 setup.py 파일을 변경하는 대신 명령 줄 인수로 제공하고 싶습니다. 예를 들어 이런 식으로 뭔가 :

pip install -e --compile_args="-O3 -fbacktrace -fbounds-check -fopenmp" . 

IT는 setup.py 파일에 pip를 통해 명령 줄 인수를 전달 할 수 있습니까?

관련하여 setup.py에 다른 설정 옵션을 전달하고 싶습니다. 예를 들어

pip install -e --setup=setup1 . 

또는

pip install -e --setup=setup2 . 

그리고 그들 중 setup1 또는 setup2 또는 아무것도 전달되지 여부에 따라, 나는 다른 포트란 소스 파일을 포함하고 다른 extra_f90_compile_args로 컴파일하고 싶습니다.

이것이 가능합니까?


편집 :의 다음 예를 살펴 보자 : 포트란 모듈의 OpenMP와 병렬된다. 이제는 병렬로 컴파일할지 여부를 사용자가 결정하도록합니다. OpenMP 라이브러리를 사용할 수없고 사용자가 직렬 버전을 컴파일해야 할 수도 있습니다. 나는 그것이 if - 블록의 코드를 실행

pip install . --install-option="--build=parallel" 

에 이것을 설치하면

from numpy.distutils.core import Extension 
from numpy.distutils.core import setup 
import os 
from setuptools.command.install import install as _install 

extra_f90_compile_args = "" 
extra_link_args = "" 

class install(_install): 
    user_options = _install.user_options + [('build=', None, None)] 

    def initialize_options(self): 
     _install.initialize_options(self) 
     self.build = None 

    def finalize_options(self): 
     _install.finalize_options(self) 

    def run(self): 
     global extra_f90_compile_args 
     global extra_link_args 
     if(self.build == "parallel"): 
      extra_f90_compile_args += "-fopenmp" 
      extra_link_args += "-lgomp" 
      os.makedirs("~/test/") 
     _install.run(self) 

ext = Extension(
    name="test_module.fortran_module", 
    sources=["test_module/fortran_module.f90"], 
    extra_f90_compile_args=[extra_f90_compile_args], 
    extra_link_args=[extra_link_args] 
) 

setup(
    name="test_module", 
    packages=["test_module"], 
    ext_modules=[ext], 
    cmdclass={'install': install} 
) 

을 다음과 같이

setup.py 지금 보인다. 이를 확인하기 위해 test/ 디렉토리를 만들었습니다. build이 제공되지 않았거나 parallel과 다른 경우 test/ 디렉토리가 생성되지 않습니다.

그러나 코드는 OpenMP로 컴파일되지 않습니다. 나는 객체가 호출되기 전에 setup()의 호출이 만들어지기 때문에 인수가 평가되는 곳이라고 생각한다. 인수를 먼저 평가 한 다음 인수에 따라 Extension 개체를 만든 다음 setup()으로 호출하십시오.

어떻게하면됩니까?

+0

https://stackoverflow.com/a/33200591/7976758 – phd

+0

본인 및 다른 여러 질문에 대해 알고 있습니다. 그러나, 나는 그것이 내 사건에서 작동하도록 할 수 없습니다. 편집을 참조하십시오. – Sebastian

+0

추가 된 코드에는 들여 쓰기 문제가 있습니다 - 메서드가 제대로 들여 쓰기되지 않습니다. 고쳐주세요. – phd

답변

1

소스 코드를 파헤 치면 지금 대답 할 수 있습니다.

setup.py 파일이 설치

from numpy.distutils.command.install import install as _install 
from numpy.distutils.core import Extension 
from numpy.distutils.core import setup 

extF = Extension(name="test_module.fortran_module", 
       sources=["test_module/fortran_module.f90"]) 
compile_args_parallel = "-fopenmp" 
link_args_parallel = "-lgomp" 

class install(_install): 
    user_options = _install.user_options + [('build=', None, None)] 

    def initialize_options(self): 
     _install.initialize_options(self) 
     self.build = None 

    def finalize_options(self): 
     _install.finalize_options(self) 
     if(self.build == "parallel"): 
      for ext in self.distribution.ext_modules: 
       if(ext.name == "test_module.fortran_module"): 
        ext.extra_f90_compile_args = compile_args_parallel 
        ext.extra_link_args = link_args_parallel 

    def run(self): 
     _install.run(self) 

setup(
    name="test_module", 
    packages=["test_module"], 
    ext_modules=[extF], 
    cmdclass={"install": install} 
) 

pip install . 

와 직렬 버전

pip install . --install-option="--build=parallel" 

는 포트란 모듈의 병렬 버전을 설치를 설치한다.