From 6a5c4cc171bb644b7cb835d6a47bedd0fd6705ca Mon Sep 17 00:00:00 2001 From: jase231 Date: Tue, 23 Jun 2026 17:21:57 +0200 Subject: [PATCH] [cmake] Produce python .dist-info metadata --- CMakeLists.txt | 3 +++ bindings/pyroot/pythonizations/test/CMakeLists.txt | 2 ++ .../pyroot/pythonizations/test/package_metadata.py | 10 ++++++++++ cmake/modules/InstallPythonMetadata.cmake | 12 ++++++++++++ cmake/modules/RootBuildOptions.cmake | 1 + config/METADATA.in | 3 +++ pyproject.toml | 3 +++ test/PostInstall/CMakeLists.txt | 6 ++++++ 8 files changed, 40 insertions(+) create mode 100644 bindings/pyroot/pythonizations/test/package_metadata.py create mode 100644 cmake/modules/InstallPythonMetadata.cmake create mode 100644 config/METADATA.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d2314110fd2d..7945ee63a3078 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -691,6 +691,9 @@ if(pyroot) set(PYTESTS_WILLFAIL WILLFAIL) endif() +#---Insert Python metadata for ROOT import package---------------------------------------------- +include(InstallPythonMetadata) + #---Configure Testing using CTest---------------------------------------------------------------- configure_file(${CMAKE_SOURCE_DIR}/cmake/modules/CTestCustom.cmake ${CMAKE_BINARY_DIR} COPYONLY) if(testing) diff --git a/bindings/pyroot/pythonizations/test/CMakeLists.txt b/bindings/pyroot/pythonizations/test/CMakeLists.txt index 33bb48b3339f3..57736f4723c74 100644 --- a/bindings/pyroot/pythonizations/test/CMakeLists.txt +++ b/bindings/pyroot/pythonizations/test/CMakeLists.txt @@ -184,6 +184,8 @@ endif() ROOT_ADD_PYUNITTEST(regression_18441 regression_18441.py) +ROOT_ADD_PYUNITTEST(package_metadata package_metadata.py PYTHON_DEPS importlib) + if(NOT MSVC OR CMAKE_SIZEOF_VOID_P EQUAL 8 OR win_broken_tests) # Test the conversion and low level views of interpreter-defined C++ arrays to NumPy # We do not run this test on Windows x86 due to an interpreter issue with arrays: diff --git a/bindings/pyroot/pythonizations/test/package_metadata.py b/bindings/pyroot/pythonizations/test/package_metadata.py new file mode 100644 index 0000000000000..637397347d567 --- /dev/null +++ b/bindings/pyroot/pythonizations/test/package_metadata.py @@ -0,0 +1,10 @@ +import importlib.metadata as meta +import unittest + + +class PackageMetadata(unittest.TestCase): + def test_query_metadata(self): + try: + meta.version("ROOT") + except Exception: + raise AssertionError("importlib failed to access .dist-info metadata for ROOT package") diff --git a/cmake/modules/InstallPythonMetadata.cmake b/cmake/modules/InstallPythonMetadata.cmake new file mode 100644 index 0000000000000..25eb0612a78f9 --- /dev/null +++ b/cmake/modules/InstallPythonMetadata.cmake @@ -0,0 +1,12 @@ +# Installs Python METADATA and INSTALLER files for compatibility with importlib.metadata +# The presence of INSTALLER (along with intentionally neglecting RECORD) prevents +# package managers from uninstalling or otherwise touching the ROOT import package if +# it wasn't installed via a wheel. +# See: https://packaging.python.org/en/latest/specifications/recording-installed-packages/ + +# scikit-build-core handles metadata so only do this for non-wheel builds to avoid conflict +if(NOT _wheel_build) + configure_file("${CMAKE_SOURCE_DIR}/config/METADATA.in" "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/root-${ROOT_VERSION}.dist-info/METADATA" @ONLY NEWLINE_STYLE UNIX) + file(WRITE "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/root-${ROOT_VERSION}.dist-info/INSTALLER" "CMake") + install(DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/root-${ROOT_VERSION}.dist-info" DESTINATION "${CMAKE_INSTALL_PYTHONDIR}") +endif() diff --git a/cmake/modules/RootBuildOptions.cmake b/cmake/modules/RootBuildOptions.cmake index 776626e82abce..d42523e7260c0 100644 --- a/cmake/modules/RootBuildOptions.cmake +++ b/cmake/modules/RootBuildOptions.cmake @@ -192,6 +192,7 @@ option(roottest "Build roottest (implies testing=ON)" OFF) option(test_roofit_hs3testsuite "Setup and use the HS3 conformance test suite (requires network)" OFF) option(testing "Enable testing with CTest" OFF) option(asan "Build ROOT with address sanitizer instrumentation (only GCC is currently supported)" OFF) +option(_wheel_build "ROOT is being packaged as a wheel, do not install .dist-info metadata" OFF) set(gcctoolchain "" CACHE PATH "Set path to GCC toolchain used to build llvm/clang") diff --git a/config/METADATA.in b/config/METADATA.in new file mode 100644 index 0000000000000..d43d95b6da150 --- /dev/null +++ b/config/METADATA.in @@ -0,0 +1,3 @@ +Metadata-Version: 2.2 +Name: root +Version: @ROOT_VERSION@ \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 5f4f50d05bfe5..096eba25b8703 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,6 +47,9 @@ opengl="OFF" runtime_cxxmodules="ON" fail-on-missing="ON" +# Prevent CMake from producing its own .dist-info metadata +_wheel_build="ON" + # Explicitly list components that gminimal implicitly turns off as documentation # tmva-pymva and tpython are disabled for manylinux compatibility # see https://peps.python.org/pep-0513/#libpythonx-y-so-1 diff --git a/test/PostInstall/CMakeLists.txt b/test/PostInstall/CMakeLists.txt index 4a73e4300a290..d25749949ca22 100644 --- a/test/PostInstall/CMakeLists.txt +++ b/test/PostInstall/CMakeLists.txt @@ -36,5 +36,11 @@ if(BUILD_TESTING) PROPERTIES ENVIRONMENT PYTHONPATH=${ROOT_LIBRARY_DIR} PASS_REGULAR_EXPRESSION "myHistoName" ) + add_test(NAME python-package-metadata + COMMAND ${Python3_EXECUTABLE} -c "import importlib.metadata as meta, ROOT; meta.version(\"ROOT\")" + ) + set_tests_properties(python-package-metadata + PROPERTIES ENVIRONMENT PYTHONPATH=${ROOT_LIBRARY_DIR} + ) endif() endif()