我们获得了一个库的完整C ++源代码,称为MyAwesomeLib
。目标是将其部分功能暴露给python,因此我们使用swig创建一个包装器并生成一个名为PyMyAwesomeLib
的python包。
目录结构现在看起来像
root_dir
|-src/
|-lib/
| |- libMyAwesomeLib.so
| |- _PyMyAwesomeLib.so
|-swig/
| |- PyMyAwesomeLib.py
|-python/
|- Script_using_myawesomelib.py
到目前为止一切顺利。理想情况下,我们接下来要做的就是将lib/*.so
swig/*.py
和python/*.py
以 pythonic 方式复制到site-packages
中的相应目录中,即使用
python setup.py install
然而,当我尝试使用setuptools
和distutils
来实现这个简单的目标时,我感到非常困惑。这两个工具都通过内部系统处理python扩展的编译,其中使用setup(ext_module=[Extension(...)])
传递源文件,编译器标志等。但这很荒谬,因为MyAsesomeLib
有一个基于makefile的功能完备的构建系统。移植makefile中嵌入的逻辑将是多余的,并且是完全不必要的工作。
经过一些研究,似乎还有两个选项,我可以覆盖setuptools.command.build
和setuptools.command.install
来使用现有的makefile并直接复制结果,或者我可以以某种方式让{{1}了解这些文件并要求它在安装过程中复制它们。第二种方式更具吸引力,但它让我头疼。我没有成功地尝试了以下选项
setuptools
,package_data
不起作用,因为* .so文件不受版本控制,并且它们不在任何包中。include_package_data
似乎无效,因为文件仅在运行data_files
时被包含,但在python setup.py sdist
时被忽略。这与我想要的相反。 python setup.py install
文件不应包含在源代码发行版中,而是在安装步骤中复制。.so
失败的原因与MANIFEST.in
相同。data_files
也不起作用,但说实话,我不知道eager_resources
和eager_resources
或data_files
之间的区别。我认为这实际上是一种常见情况,我希望有一个简单的解决方案。任何帮助将不胜感激。
答案 0 :(得分:1)
移植makefile中嵌入的逻辑将是多余的 完全不必要的工作。
不幸的是,这正是我必须要做的。我现在一直在努力解决同样的问题。
移植它实际上并不是太糟糕。 distutils does understand SWIG extensions,但这是他们相当随意地实施的。运行SWIG创建Python文件,当前构建顺序假定在运行build_ext
之前已考虑所有Python文件。那个fix并不难,但令人讨厌的是他们声称支持SWIG而不提这个。 Distutils在编译时会尝试跨平台,因此使用它仍然是一个优势。
如果您不想将整个构建系统移植过来,请使用系统的软件包管理器。许多复杂的库都这样做(但他们也尝试使用setup.py)。例如,要在Ubuntu上获取numpy和lxml,您只需执行以下操作:
sudo apt-get install python-numpy python-lxml
。没有点子。
我意识到你宁愿写一个设置文件而不是处理每个包管理器,所以这可能不是很有帮助。
如果你试图去setuptools路线,我遇到了一个致命的缺陷:依赖。
例如,如果您要分发基于SWIG的项目,那么它将需要libpython。如果他们没有,会发生这样的错误:
#include <Python.h>
error: File not found
这对普通用户来说非常无益。
更糟糕的是,如果您需要共享库但用户的库已过期,则用户可能会遇到一些疯狂的错误。您可以使用他们的C ++编译器来输出Google友好的错误消息,以便他们能够解决这个问题。
长期解决方案是让setuptools / distutils更好地检测非python库,希望与Ruby的gem一样好。我几乎不得不自己动手。例如,在这个setup.py我工作中你可以看到顶层的一些函数我一起入侵以进行依赖性检测(仍然不能在所有系统上工作......绝对不是Windows) 。