[英]Creating a python package (deb/rpm) from cmake
I am trying to create a python package (deb & rpm) from cmake
, ideally using cpack
.我正在尝试从cmake
创建一个 python package (deb & rpm),最好使用cpack
。 I did read我确实读过
The installation works just fine (using component install) for my shared library.对于我的共享库,安装工作正常(使用组件安装)。 However I cannot make sense of the documentation to install the python binding (glue) code.但是,我无法理解安装 python 绑定(胶水)代码的文档。 Using the standard cmake install mechanism, I tried:使用标准的 cmake 安装机制,我试过:
install(
FILES __init__.py library.py
DESTINATION ${ACME_PYTHON_PACKAGE_DIR}/project_name
COMPONENT python)
And then using brute-force approach ended-up with:然后使用蛮力方法最终得到:
# debian based package (relative path)
set(ACME_PYTHON_PACKAGE_DIR lib/python3/dist-packages)
and和
# rpm based package (full path required)
set(ACME_PYTHON_PACKAGE_DIR /var/lang/lib/python3.8/site-packages)
The above is derived from:以上来源于:
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']
while:尽管:
rpm % python -c 'import site; print(site.getsitepackages())'
['/var/lang/lib/python3.8/site-packages']
It is pretty clear that the brute-force approach will not be portable, and is doomed to fail on the next release of python.很明显,蛮力方法将无法移植,并且在 python 的下一个版本中注定会失败。 The only possible solution that I can think of is generating a temporary setup.py
python script (using setuptools
), that will do the install.我能想到的唯一可能的解决方案是生成一个临时setup.py
python 脚本(使用setuptools
),它将进行安装。 Typically cmake
would call the following process :通常cmake
会调用以下过程:
% python setup.py install --root ${ACME_PYTHON_INSTALL_ROOT}
My questions are:我的问题是:
setup.py
script.如果是这样,这意味着我需要生成一个中间setup.py
脚本。git grep setuptools
) but did not find helper functions to handle generation of setup.py
and passing the result files back to cpack
.我一直在搜索 cmake/cpack 代码库( git grep setuptools
)但没有找到帮助函数来处理setup.py
的生成并将结果文件传回cpack
。 Is there an existing cmake
module which I could re-use?是否有可以重复使用的现有cmake
模块?I did read, some alternative solution, such as:我确实阅读了一些替代解决方案,例如:
Which seems overly complex, and geared toward Debian-only based system.这似乎过于复杂,并且面向仅基于 Debian 的系统。 I need to handle RPM in my case.在我的情况下,我需要处理 RPM。
I am going to post the temporary solution I am using at the moment, until someone provide something more robust.我将发布我目前正在使用的临时解决方案,直到有人提供更强大的东西。
So I eventually manage to stumble upon:所以我最终设法偶然发现:
Re-using the above to do an install
step instead of a build
step can be done as follow:重新使用上述内容来执行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)
And then the ugly part is:然后丑陋的部分是:
install(
# trailing slash is important:
DIRECTORY ${SETUP_OUTPUT}/
DESTINATION "/" # FIXME may cause issues with other cpack generators
COMPONENT python)
Turns out that the documentation for install()
is pretty clear about absolute paths :事实证明install()
的文档对绝对路径非常清楚:
DESTINATION [...] As absolute paths are not supported by cpack installer generators, it is preferable to use relative paths throughout.
For reference, here is my setup.py.in
:作为参考,这是我的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'])
As mentionned in my other solution , the ugly part is dealing with absolute path in cmake install()
commands.正如我在其他解决方案中提到的,丑陋的部分是在 cmake install()
命令中处理绝对路径。 I was able to refactor the code to avoid usage of absolute path in install()
.我能够重构代码以避免在install()
中使用绝对路径。 I simply changed the installation into:我只是将安装更改为:
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)
And then one simply needs to:然后只需要:
set(CMAKE_INSTALL_PREFIX "/")
set(CPACK_PACKAGING_INSTALL_PREFIX "/")
include(CPack)
At this point all install path now need to include explicitely /usr
since we've cleared the value for CMAKE_INSTALL_PREFIX
.此时,所有安装路径现在都需要明确包含/usr
,因为我们已经清除了CMAKE_INSTALL_PREFIX
的值。
The above has been tested for deb and rpm packages.以上已针对 deb 和 rpm 包进行了测试。 CPACK_BINARY_TGZ
does properly run with the above solution: CPACK_BINARY_TGZ
确实可以使用上述解决方案正常运行:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.