I am trying to create a python package (deb & rpm) from cmake
, ideally using cpack
. I did read
- https://cmake.org/cmake/help/latest/cpack_gen/rpm.html and,
- https://cmake.org/cmake/help/latest/cpack_gen/deb.html
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. Using the standard cmake install mechanism, I tried:
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. The only possible solution that I can think of is generating a temporary setup.py
python script (using setuptools
), that will do the install. Typically cmake
would call the following process:
% python setup.py install --root ${ACME_PYTHON_INSTALL_ROOT}
My questions are:
- Did I understand the cmake/cpack documentation correctly for python package ? If so this means I need to generate an intermediate
setup.py
script. - I have been searching through the cmake/cpack codebase (
git grep setuptools
) but did not find helper functions to handle generation ofsetup.py
and passing the result files back tocpack
. Is there an existingcmake
module which I could re-use ?
I did read, some alternative solution, such as:
Which seems overly complex, and geared toward Debian-only based system. I need to handle RPM in my case.
2
Answers
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 abuild
step can be done as follow:And then the ugly part is:
Turns out that the documentation for
install()
is pretty clear about absolute paths:For reference, here is my
setup.py.in
:You can be fancy and remove the
__pycache__
folder using the-B
flag:You can be extra fancy and add debian option such as:
use as:
As mentionned in my other solution, the ugly part is dealing with absolute path in cmake
install()
commands. I was able to refactor the code to avoid usage of absolute path ininstall()
. I simply changed the installation into:And then one simply needs to:
At this point all install path now need to include explicitely
/usr
since we’ve cleared the value forCMAKE_INSTALL_PREFIX
.The above has been tested for deb and rpm packages.
CPACK_BINARY_TGZ
does properly run with the above solution: