在非标准位置编译并使用 python-openzwave 和 open-zwave

Compile and use python-openzwave with open-zwave in non-standard location

我手动编译了python-openzwave to work with C++ library.

我想将它用作 Kodi 插件(Pi 3 上的 OpenELEC 运行ning),所以不能使用标准安装。 我编译了所有内容,下载了缺少的 sixlouie 库,现在尝试 运行 hello_world.py

我当前的目录结构如下:

- root
  - bin
      - .lib
      - config
        Alarm.o
        ...
        libopenzwave.a
        libopenzwave.so
        libopenzwave.so.1.4
        ...
  - libopenzwave
      driver.pxd
      group.pxd
      ...
  - louie
      __init__.py
      dispatcher.py
      ...
  - openzwave
      __init__.py
      command.py
      ...
  six.py
  hello_world.py

但是当我 运行 hello_world.py 时,我得到以下错误 -

Traceback (most recent call last):
  File "hello_world.py", line 40, in <module> 
    from openzwave.controller import ZWaveController 
  File "/storage/.kodi/addons/service.multimedia.open-zwave/openzwave/controller.py", line 34, in <module> 
    from libopenzwave import PyStatDriver, PyControllerState 
ImportError: No module named libopenzwave

如果我将 libopenzwave.alibopenzwave.so 移动到根文件夹,则会出现以下错误:

Traceback (most recent call last):
  File "hello_world.py", line 40, in <module> 
    from openzwave.controller import ZWaveController 
  File "/storage/.kodi/addons/service.multimedia.open-zwave/openzwave/controller.py", line 34, in <module> 
    from libopenzwave import PyStatDriver, PyControllerState 
ImportError: dynamic module does not define init function (initlibopenzwave)

我的设置有什么问题?

一般来说,所需的步骤包括调用 make build,它负责为 openzwave 构建 .cpp 文件并下载所有依赖项(包括 Cython);和 make install 其中 运行 是 setup-apisetup-lib.py(此设置脚本还为 openzwave 创建了 C++ Python 扩展),setup-web.pysetup-manager.py

因为你不能像你指定的那样 运行 make install 而是使用他们提供的存档,所以在构建 openzwave 库之后,创建 python 扩展的唯一其他选项make build,正在为其生成 .so 文件,但没有安装到标准位置。

在与 Cython 脚本相同的文件夹中为 cython 扩展构建 .so 由 运行ning 完成:

python setup.py build_ext --inplace

这应该在 src-lib 中创建一个名为 libopenzwave.so 的共享库(它不同于 bin/ 目录中包含的 libopenzwave.so),它包含指定的所有功能在扩展模块中。您可以尝试将其添加到 libopenzwave 文件夹。

如果在 make build 期间传递特殊的编译器标志以构建 openzwave 库,则在执行 setup-lib.py 脚本时应指定相同的编译器标志。这可以通过在执行之前指定 CFLAGS 来完成(如指定的 here),否则您可能会遇到 error adding symbols: File in wrong format.

之类的问题

这是从问题的角度对 python-openzwave 构建的描述。几乎所有步骤都对应于根 Makefile 的目标。

  • 先决条件。 有几个独立的目标,几乎没有组织。大多数使用特定于 Debian 的命令。
    • 如果从存档构建,则不需要 Cython (详情如下)
  • openzwave C++ 库openzwave openzwave/.lib/ 目标)。
    • 构建逻辑:openzwave/Makefile,不带参数调用(但具有继承的环境)。
    • 输入:openzwave/ 子树(包括 libhidapilibtinyxml,静态链接)。
    • 输出:openzwave/.lib/libopenzwave.{a,so}
    • 接受 PREFIX 作为环境变量(默认为 /usr/local
      • 唯一影响我们的效果是:$(PREFIX)/etc/openzwave/ 被分配给一个宏,该宏添加了配置文件的搜索位置 (Options.cpp):config/ -> /etc/openzwave/ -> <custom location>.
  • libopenzwave Python C 扩展模块install-lib 目标 - 是的,库存 Makefile 不能只构建它;目标不会'甚至没有对图书馆的依赖)。
    • 构建逻辑:setup-lib.py
    • 输入:src-lib/openzwave/.lib/libopenzwave.a
    • 输出:build/<...>/libopenzwave.so - 是的,与 openzwave 的输出同名,因此请避免混淆它们
      • 默认情况下,openzwave 与模块 静态链接,因此您无需将前者包含到部署中
      • 但是,该模块确实需要库中的 config 文件夹。打包时包含在构建脚本中。
    • 相反,不需要从存档构建 Cython, 存档已经包含生成的 .cpp
    • 现在,问题是:模块本身使用 pkg_resources 来定位其数据。因此,您不能只将 .soconfig 放入当前目录,然后就此结束。你需要让 pkg_resources.get_distribution('libopenzwave') 成功。
      • pkg_resources claims to support "normal filesystem packages, .egg files, and unpacked .egg files."
      • 特别是,我能够做到这一点:制作一个 .egg (setup-lib.py bdist_egg),将其解压到当前目录并将 EGG-INFO 重命名为 libopenzwave.egg-info (就像在 site-packages 中一样)。如果我在导入模块之前没有特别将 .so 的位置添加到 PYTHON_PATH/sys.path 中,则会发出 UserWarning
  • openzwavepyozwmanpyozwweb Python 包 (install)
    • 这些是纯粹的 Python 包。第一个使用C扩展模块,其他使用第一个。
    • 构建逻辑:setup-api.pysetup-manager.pysetup-web.py
    • 输入:src-*/
    • 输出:(纯Python)
    • 他们只使用 pkg_resources.declare_namespace(),所以在 sys.path 上使用适当的 files/dirs 就可以了,没有任何 .egg-info