繁体   English   中英

从 cmake 创建 python package (deb/rpm)

[英]Creating a python package (deb/rpm) from cmake

我正在尝试从cmake创建一个 python package (deb & rpm),最好使用cpack 我确实读过

对于我的共享库,安装工作正常(使用组件安装)。 但是,我无法理解安装 python 绑定(胶水)代码的文档。 使用标准的 cmake 安装机制,我试过:

install(
  FILES __init__.py library.py
  DESTINATION ${ACME_PYTHON_PACKAGE_DIR}/project_name
  COMPONENT python)

然后使用蛮力方法最终得到:

# debian based package (relative path)
set(ACME_PYTHON_PACKAGE_DIR lib/python3/dist-packages)

# rpm based package (full path required)
set(ACME_PYTHON_PACKAGE_DIR /var/lang/lib/python3.8/site-packages)

以上来源于:

debian % python -c 'import site; print(site.getsitepackages())'
['/usr/local/lib/python3.9/dist-packages', '/usr/lib/python3/dist-packages', '/usr/lib/python3.9/dist-packages']

尽管:

rpm % python -c 'import site; print(site.getsitepackages())'
['/var/lang/lib/python3.8/site-packages']

很明显,蛮力方法将无法移植,并且在 python 的下一个版本中注定会失败。 我能想到的唯一可能的解决方案是生成一个临时setup.py python 脚本(使用setuptools ),它将进行安装。 通常cmake会调用以下过程

% python setup.py install --root ${ACME_PYTHON_INSTALL_ROOT}

我的问题是:

  • 我是否正确理解了 python package 的 cmake/cpack 文档? 如果是这样,这意味着我需要生成一个中间setup.py脚本。
  • 我一直在搜索 cmake/cpack 代码库( git grep setuptools )但没有找到帮助函数来处理setup.py的生成并将结果文件传回cpack 是否有可以重复使用的现有cmake模块?

我确实阅读了一些替代解决方案,例如:

这似乎过于复杂,并且面向仅基于 Debian 的系统。 在我的情况下,我需要处理 RPM。

我将发布我目前正在使用的临时解决方案,直到有人提供更强大的东西。

所以我最终设法偶然发现:

重新使用上述内容来执行install步骤而不是build步骤可以如下完成:

find_package(PythonInterp REQUIRED)

set(SETUP_PY_IN "${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in")
set(SETUP_PY "${CMAKE_CURRENT_BINARY_DIR}/setup.py")
set(SETUP_DEPS "${CMAKE_CURRENT_SOURCE_DIR}/project_name/__init__.py")
set(SETUP_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/build-python")

configure_file(${SETUP_PY_IN} ${SETUP_PY})

add_custom_command(
  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/setup_timestamp
  COMMAND ${PYTHON_EXECUTABLE} ARGS ${SETUP_PY} install --root ${SETUP_OUTPUT}
  COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/setup_timestamp
  DEPENDS ${SETUP_DEPS})

add_custom_target(target ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/setup_timestamp)

然后丑陋的部分是:

install(
  # trailing slash is important:
  DIRECTORY ${SETUP_OUTPUT}/
  DESTINATION "/" # FIXME may cause issues with other cpack generators
  COMPONENT python)

事实证明install()的文档对绝对路径非常清楚:

 DESTINATION [...] As absolute paths are not supported by cpack installer generators, it is preferable to use relative paths throughout.

作为参考,这是我的setup.py.in

from setuptools import setup

if __name__ == '__main__':
    setup(name='project_name_python',
          version='${PROJECT_VERSION}',
          package_dir={'': '${CMAKE_CURRENT_SOURCE_DIR}'},
          packages=['project_name'])

正如我在其他解决方案中提到的,丑陋的部分是在 cmake install()命令中处理绝对路径。 我能够重构代码以避免在install()中使用绝对路径。 我只是将安装更改为:

install(
  # trailing slash is important:
  DIRECTORY ${SETUP_OUTPUT}/
  # "." syntax is a reliable mechanism, see:
  # https://gitlab.kitware.com/cmake/cmake/-/issues/22616
  DESTINATION "."
  COMPONENT python)

然后只需要:

set(CMAKE_INSTALL_PREFIX "/")
set(CPACK_PACKAGING_INSTALL_PREFIX "/")
include(CPack)

此时,所有安装路径现在都需要明确包含/usr ,因为我们已经清除了CMAKE_INSTALL_PREFIX的值。

以上已针对 deb 和 rpm 包进行了测试。 CPACK_BINARY_TGZ确实可以使用上述解决方案正常运行:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM