2017-09-20 13 views
0

나는 C++ 확장 모듈과 그것이 필요로하는 다른 누군가의 공유 라이브러리를 가진 Python 패키지를 만들고있다. pip을 통해 모든 것을 설치하고 싶습니다. 내 현재 setup.py 파일은 pip install -e .을 사용할 때 작동하지만 개발 모드 (e.i. -e 생략)를 사용하지 않을 경우 "공유 객체 파일을 열 수 없음" 파이썬 모듈을 가져올 때. 그 이유는 setuptools가 공유 라이브러리를 내 패키지의 일부로 간주하지 않기 때문에 파일이 설치 디렉토리에 복사 될 때 라이브러리에 대한 상대 링크가 설치 중에 손상된다는 것입니다. 나는 그것이 확장을 컴파일하기 전에 공유 라이브러리를 구축하기 위해 setuptools에 명령의 일부를 서브 클래스패키지 설치시 (스크립트 작성) 라이브러리를 포함시키는 방법은 무엇입니까?

from setuptools import setup, Extension, Command 
import setuptools.command.develop 
import setuptools.command.build_ext 
import setuptools.command.install 
import distutils.command.build 
import subprocess 
import sys 
import os 

# This function downloads and builds the shared-library 
def run_clib_install_script(): 
    build_clib_cmd = ['bash', 'clib_install.sh'] 
    if subprocess.call(build_clib_cmd) != 0: 
     sys.exit("Failed to build C++ dependencies") 

# I make a new command that will build the shared-library 
class build_clib(Command): 
    user_options = [] 
    def initialize_options(self): 
     pass 
    def finalize_options(self): 
     pass 
    def run(self): 
     run_clib_install_script() 

# I subclass install so that it will call my new command 
class install(setuptools.command.install.install): 
    def run(self): 
     self.run_command('build_clib') 
     setuptools.command.install.install.run(self) 

# I do the same for build... 
class build(distutils.command.build.build): 
    sub_commands = [ 
     ('build_clib', lambda self: True), 
     ] + distutils.command.build.build.sub_commands 

# ...and the same for develop 
class develop(setuptools.command.develop.develop): 
    def run(self): 
     self.run_command('build_clib') 
     setuptools.command.develop.develop.run(self) 

# These are my includes... 
# note that /clib/include only exists after calling clib_install.sh 
cwd = os.path.dirname(os.path.abspath(__file__)) 
include_dirs = [ 
    cwd, 
    cwd + '/clib/include', 
    cwd + '/common', 
] 

# These are my arguments for the compiler to my shared-library 
lib_path = os.path.join(cwd, "clib", "lib") 
library_dirs = [lib_path] 
link_args = [os.path.join(lib_path, "libclib.so")] 

# My extension module gets these arguments so it can link to clib 
mygen_module = Extension('mygen', 
        language="c++14", 
        sources=["common/mygen.cpp"], 
        libraries=['clib'], 
        extra_compile_args=['-std=c++14'], 
        include_dirs=include_dirs, 
        library_dirs=library_dirs, 
        extra_link_args=link_args 
         + ['-Wl,-rpath,$ORIGIN/../clib/lib']) 

# I use cmdclass to override the default setuptool commands 
setup(name='mypack', 
     cmdclass = {'install': install, 
        'build_clib': build_clib, 'build': build, 
        'develop': develop}, 
     packages=['mypack'], 
     ext_package='mypack', 
     ext_modules=[mygen_module], 
     # package_dir={'mypack': '.'}, 
     # package_data={'mypack': ['docs/*md']}, 
     include_package_data=True) 

: 여기

처럼 내 setup.py 파일이 모습입니다. clib_install.sh은 로컬로 /clib에 공유 라이브러리를 다운로드하고 빌드하며 헤더 (/clib/include) 및 .so 파일 (/clib/lib)을 작성하는 bash 스크립트입니다. 공유 라이브러리 종속성에 연결하는 문제를 해결하기 위해 $ORIGIN/../clib/lib을 링크 인수로 사용하여 clib의 절대 경로가 필요하지 않습니다.

불행히도 /clib 디렉토리가 설치 위치에 복사되지 않습니다. 내가 package_data로 땜질려고했지만 내 디렉토리를 복사하지 않았다. 사실 나는 심지어 스크립트가 호출 된 후 /clib으로 pip/setuptools가 어떤 역할을하는지 알지 못한다. 나는 그것이 임시 빌드 디렉토리에서 만들어졌고 이후에 삭제된다고 생각한다. 나는 그것이 만들어지는 후에있을 필요가있는 곳까지 /clib를 얻는 방법을 모르고있다.

답변

0
package_data={ 
    'mypack': [ 
     'clib/include/*.h', 
     'clib/lib/*.so', 
     'docs/*md', 
    ] 
},