如何在包安装中包含 (script-built) 个库?
How to include (script-built) libraries with package installation?
我正在制作一个 Python 包,它有一个 C++ 扩展模块和它需要的其他人的共享库。我希望一切都可以通过 pip
安装。我当前的 setup.py
文件在我使用 pip install -e .
时有效,但当我不使用开发模式时(e.i。省略 -e
)我得到 "cannot open shared object file" 在Python 中导入模块时。我相信原因是 setuptools 不认为共享库是我的包的一部分,所以当文件被复制到安装目录时,库的相对 link 在安装过程中被破坏。
这是我的 setup.py
文件的样子:
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)
我将一些 setuptools 命令子类化,以便在编译扩展之前构建 shared-library。 clib_install.sh
是一个 bash 脚本,它在本地下载并构建 /clib
中的共享库,创建 headers(在 /clib/include
中)和 .so 文件(在 /clib/lib
).为了解决 linking 到 shared-library 依赖项的问题,我使用 $ORIGIN/../clib/lib
作为 link 参数,这样就不需要 clib
的绝对路径了。
不幸的是,/clib
目录没有被复制到安装位置。我尝试修改 package_data
但它没有复制我的目录。事实上,我什至不知道 pip/setuptools 在调用脚本后对 /clib
做了什么,我猜它是在某个临时构建目录中创建的,然后被删除了。我不确定如何在制作完成后将 /clib
带到它需要的位置。
package_data={
'mypack': [
'clib/include/*.h',
'clib/lib/*.so',
'docs/*md',
]
},
我正在制作一个 Python 包,它有一个 C++ 扩展模块和它需要的其他人的共享库。我希望一切都可以通过 pip
安装。我当前的 setup.py
文件在我使用 pip install -e .
时有效,但当我不使用开发模式时(e.i。省略 -e
)我得到 "cannot open shared object file" 在Python 中导入模块时。我相信原因是 setuptools 不认为共享库是我的包的一部分,所以当文件被复制到安装目录时,库的相对 link 在安装过程中被破坏。
这是我的 setup.py
文件的样子:
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)
我将一些 setuptools 命令子类化,以便在编译扩展之前构建 shared-library。 clib_install.sh
是一个 bash 脚本,它在本地下载并构建 /clib
中的共享库,创建 headers(在 /clib/include
中)和 .so 文件(在 /clib/lib
).为了解决 linking 到 shared-library 依赖项的问题,我使用 $ORIGIN/../clib/lib
作为 link 参数,这样就不需要 clib
的绝对路径了。
不幸的是,/clib
目录没有被复制到安装位置。我尝试修改 package_data
但它没有复制我的目录。事实上,我什至不知道 pip/setuptools 在调用脚本后对 /clib
做了什么,我猜它是在某个临时构建目录中创建的,然后被删除了。我不确定如何在制作完成后将 /clib
带到它需要的位置。
package_data={
'mypack': [
'clib/include/*.h',
'clib/lib/*.so',
'docs/*md',
]
},