]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
cmake/modules: add PythonPackage.cmake
authorJohn Mulligan <jmulligan@redhat.com>
Mon, 13 Apr 2026 21:24:24 +0000 (17:24 -0400)
committerJohn Mulligan <jmulligan@redhat.com>
Wed, 6 May 2026 13:32:25 +0000 (09:32 -0400)
Time is marching on and the state of the art with python packaging has
not stood still. In Python 3.12, distutils has been removed after being
deprecated for a couple of versions. According to the Python Packaging
User Guide [1]: "However, `python setup.py` and the use of `setup.py` as a
command line tool are deprecated."

Currently, ceph provides a decent sized and growing library of python
code in `src/python-common/ceph`. It currently relies on `setup.py` and
the deprecated `python setup.py install` command. This change aims to be
the first step in moving toward a more contemporary approach so that we
don't get caught late when the older approaches really stop working.

Because ceph's primary diver of "build stuff" is CMake, there was an
existing `cmake/modules/Distutils.cmake` that invokes a `python setup.py
install` command. Rather than risk breaking older distros we add a new
`cmake/modules/PythonPackage.cmake` file that uses the PEP 517/518
[2][3] style

of packaging. I could not find some existing CMake support for this
so unfortunately I had to write this.

The approach taken is loosely based on what the rpm build process does.
It invokes pip's wheel subcommand to build a wheel (during the build
phase) and then uses pip to install the wheel to install the content
to the system.

A future commit will add conditional support for using this approach
in src/python-common.

[1] https://packaging.python.org/en/latest/discussions/setup-py-deprecated/
[2] https://peps.python.org/pep-0517/
[3] https://peps.python.org/pep-0518/

Signed-off-by: John Mulligan <jmulligan@redhat.com>
cmake/modules/PythonPackage.cmake [new file with mode: 0644]

diff --git a/cmake/modules/PythonPackage.cmake b/cmake/modules/PythonPackage.cmake
new file mode 100644 (file)
index 0000000..7453edf
--- /dev/null
@@ -0,0 +1,84 @@
+find_package(Python3 ${WITH_PYTHON3} EXACT
+  QUIET
+  REQUIRED
+  COMPONENTS Interpreter)
+
+function(create_python_package pkgname)
+  set(options BUILD_ISOLATION)
+  set(oneValueArgs WHEELDIR)
+  cmake_parse_arguments(PARSE_ARGV 0 pypkg
+    "${options}" "${oneValueArgs}" "")
+  if(NOT "${pypkg_WHEELDIR}")
+    set(pypkg_WHEELDIR "${CMAKE_CURRENT_BINARY_DIR}/wheels/${pkgname}")
+  endif()
+
+  python_package_build_pip_wheel(
+    "${pkgname}" "${pypkg_WHEELDIR}" "${pypkg_BUILD_ISOLATION}"
+  )
+  python_package_install_pip_wheel("${pkgname}" "${pypkg_WHEELDIR}")
+endfunction(create_python_package)
+
+
+function(
+  python_package_build_pip_wheel
+  pkgname
+  wheeldir
+  build_isolation
+)
+  list(APPEND build_args
+    --wheel-dir "${wheeldir}"
+    --no-deps
+    --use-pep517
+    --disable-pip-version-check
+    --no-clean
+    --progress-bar=off
+    --verbose
+  )
+  if(NOT "${build_isolation}")
+    list(APPEND build_args --no-build-isolation)
+  endif()
+  list(APPEND build_args "${CMAKE_CURRENT_SOURCE_DIR}")
+
+  add_custom_command(
+    OUTPUT ${wheeldir}
+    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/pyproject.toml
+    COMMAND ${Python3_EXECUTABLE} -m pip wheel ${build_args}
+  )
+  if(NOT TARGET build-wheel-${pkgname})
+    add_custom_target(build-wheel-${pkgname} ALL
+      DEPENDS ${wheeldir})
+  endif()
+endfunction(python_package_build_pip_wheel)
+
+function(
+  python_package_install_pip_wheel
+  pkgname
+  wheeldir
+)
+  list(APPEND install_args
+    "--prefix=${CMAKE_INSTALL_PREFIX}"
+    --no-deps
+    --disable-pip-version-check
+    --progress-bar=off
+    --root-user-action=ignore
+    --verbose
+    --ignore-installed
+    --no-warn-script-location
+    --no-index
+    --no-cache-dir
+    --find-links "${wheeldir}"
+    "${pkgname}"
+  )
+
+  install(CODE "
+    set(args \"${install_args}\")
+    if(DEFINED ENV{DESTDIR})
+      list(INSERT args 1 --root=\$ENV{DESTDIR})
+    endif()
+    message(DEBUG PythonPackage.install_cmd=
+      \"${Python3_EXECUTABLE} -m pip install\" \"\${args}\")
+    execute_process(
+      COMMAND ${Python3_EXECUTABLE} -m pip install \${args}
+      WORKING_DIRECTORY \"${CMAKE_CURRENT_BINARY_DIR}\"
+      COMMAND_ERROR_IS_FATAL ANY)")
+endfunction(python_package_install_pip_wheel)