[Mlir-commits] [mlir] [MLIR][Python] use FetchContent_Declare for nanobind and remove pybind (PR #161230)
Maksim Levental
llvmlistbot at llvm.org
Mon Sep 29 11:11:34 PDT 2025
https://github.com/makslevental updated https://github.com/llvm/llvm-project/pull/161230
>From 9f734413041f2aec016b90412b116126174dbefc Mon Sep 17 00:00:00 2001
From: makslevental <maksim.levental at gmail.com>
Date: Mon, 29 Sep 2025 09:45:40 -0700
Subject: [PATCH] [MLIR][Python] use FetchContent_Declare for nanobind and
remove pybind
---
mlir/cmake/modules/AddMLIRPython.cmake | 127 ++--
mlir/cmake/modules/MLIRDetectPythonEnv.cmake | 123 ++--
.../examples/standalone/python/CMakeLists.txt | 18 -
.../python/StandaloneExtensionPybind11.cpp | 38 --
.../dialects/standalone_pybind11.py | 6 -
.../standalone/test/python/smoketest.py | 11 +-
.../mlir/Bindings/Python/PybindAdaptors.h | 616 ------------------
mlir/python/CMakeLists.txt | 61 +-
mlir/python/mlir/dialects/python_test.py | 11 +-
mlir/python/requirements.txt | 2 -
mlir/test/python/dialects/python_test.py | 31 +-
mlir/test/python/lib/CMakeLists.txt | 1 -
.../python/lib/PythonTestModulePybind11.cpp | 118 ----
13 files changed, 130 insertions(+), 1033 deletions(-)
delete mode 100644 mlir/examples/standalone/python/StandaloneExtensionPybind11.cpp
delete mode 100644 mlir/examples/standalone/python/mlir_standalone/dialects/standalone_pybind11.py
delete mode 100644 mlir/include/mlir/Bindings/Python/PybindAdaptors.h
delete mode 100644 mlir/test/python/lib/PythonTestModulePybind11.cpp
diff --git a/mlir/cmake/modules/AddMLIRPython.cmake b/mlir/cmake/modules/AddMLIRPython.cmake
index 208cbdd1dd535..2f2f65320e970 100644
--- a/mlir/cmake/modules/AddMLIRPython.cmake
+++ b/mlir/cmake/modules/AddMLIRPython.cmake
@@ -123,12 +123,12 @@ function(mlir_generate_type_stubs)
"IMPORT_PATHS;DEPENDS_TARGETS;OUTPUTS;DEPENDS_TARGET_SRC_DEPS"
${ARGN})
- # for people doing find_package(nanobind)
+ # for people installing a distro (e.g., pip install) of nanobind
if(EXISTS ${nanobind_DIR}/../src/stubgen.py)
set(NB_STUBGEN "${nanobind_DIR}/../src/stubgen.py")
elseif(EXISTS ${nanobind_DIR}/../stubgen.py)
set(NB_STUBGEN "${nanobind_DIR}/../stubgen.py")
- # for people using FetchContent_Declare and FetchContent_MakeAvailable
+ # for people using nanobind git source tree (e.g., FetchContent_Declare and FetchContent_MakeAvailable)
elseif(EXISTS ${nanobind_SOURCE_DIR}/src/stubgen.py)
set(NB_STUBGEN "${nanobind_SOURCE_DIR}/src/stubgen.py")
elseif(EXISTS ${nanobind_SOURCE_DIR}/stubgen.py)
@@ -203,11 +203,10 @@ endfunction()
# EMBED_CAPI_LINK_LIBS: Dependent CAPI libraries that this extension depends
# on. These will be collected for all extensions and put into an
# aggregate dylib that is linked against.
-# PYTHON_BINDINGS_LIBRARY: Either pybind11 or nanobind.
function(declare_mlir_python_extension name)
cmake_parse_arguments(ARG
""
- "ROOT_DIR;MODULE_NAME;ADD_TO_PARENT;PYTHON_BINDINGS_LIBRARY"
+ "ROOT_DIR;MODULE_NAME;ADD_TO_PARENT"
"SOURCES;PRIVATE_LINK_LIBS;EMBED_CAPI_LINK_LIBS"
${ARGN})
@@ -216,20 +215,15 @@ function(declare_mlir_python_extension name)
endif()
set(_install_destination "src/python/${name}")
- if(NOT ARG_PYTHON_BINDINGS_LIBRARY)
- set(ARG_PYTHON_BINDINGS_LIBRARY "pybind11")
- endif()
-
add_library(${name} INTERFACE)
set_target_properties(${name} PROPERTIES
# Yes: Leading-lowercase property names are load bearing and the recommended
# way to do this: https://gitlab.kitware.com/cmake/cmake/-/issues/19261
- EXPORT_PROPERTIES "mlir_python_SOURCES_TYPE;mlir_python_EXTENSION_MODULE_NAME;mlir_python_EMBED_CAPI_LINK_LIBS;mlir_python_DEPENDS;mlir_python_BINDINGS_LIBRARY"
+ EXPORT_PROPERTIES "mlir_python_SOURCES_TYPE;mlir_python_EXTENSION_MODULE_NAME;mlir_python_EMBED_CAPI_LINK_LIBS;mlir_python_DEPENDS"
mlir_python_SOURCES_TYPE extension
mlir_python_EXTENSION_MODULE_NAME "${ARG_MODULE_NAME}"
mlir_python_EMBED_CAPI_LINK_LIBS "${ARG_EMBED_CAPI_LINK_LIBS}"
mlir_python_DEPENDS ""
- mlir_python_BINDINGS_LIBRARY "${ARG_PYTHON_BINDINGS_LIBRARY}"
)
# Set the interface source and link_libs properties of the target
@@ -318,14 +312,12 @@ function(add_mlir_python_modules name)
elseif(_source_type STREQUAL "extension")
# Native CPP extension.
get_target_property(_module_name ${sources_target} mlir_python_EXTENSION_MODULE_NAME)
- get_target_property(_bindings_library ${sources_target} mlir_python_BINDINGS_LIBRARY)
# Transform relative source to based on root dir.
set(_extension_target "${modules_target}.extension.${_module_name}.dso")
add_mlir_python_extension(${_extension_target} "${_module_name}"
INSTALL_COMPONENT ${modules_target}
INSTALL_DIR "${ARG_INSTALL_PREFIX}/_mlir_libs"
OUTPUT_DIRECTORY "${ARG_ROOT_PREFIX}/_mlir_libs"
- PYTHON_BINDINGS_LIBRARY ${_bindings_library}
LINK_LIBS PRIVATE
${sources_target}
${ARG_COMMON_CAPI_LINK_LIBS}
@@ -730,7 +722,7 @@ endfunction()
function(add_mlir_python_extension libname extname)
cmake_parse_arguments(ARG
""
- "INSTALL_COMPONENT;INSTALL_DIR;OUTPUT_DIRECTORY;PYTHON_BINDINGS_LIBRARY"
+ "INSTALL_COMPONENT;INSTALL_DIR;OUTPUT_DIRECTORY"
"SOURCES;LINK_LIBS"
${ARGN})
if(ARG_UNPARSED_ARGUMENTS)
@@ -738,7 +730,7 @@ function(add_mlir_python_extension libname extname)
endif()
# The extension itself must be compiled with RTTI and exceptions enabled.
- # Also, some warning classes triggered by pybind11 are disabled.
+ # Also, some warning classes triggered by nanobind are disabled.
set(eh_rtti_enable)
if (MSVC)
set(eh_rtti_enable /EHsc /GR)
@@ -746,62 +738,53 @@ function(add_mlir_python_extension libname extname)
set(eh_rtti_enable -frtti -fexceptions)
endif ()
- # The actual extension library produces a shared-object or DLL and has
- # sources that must be compiled in accordance with pybind11 needs (RTTI and
- # exceptions).
- if(NOT DEFINED ARG_PYTHON_BINDINGS_LIBRARY OR ARG_PYTHON_BINDINGS_LIBRARY STREQUAL "pybind11")
- pybind11_add_module(${libname}
- ${ARG_SOURCES}
- )
- elseif(ARG_PYTHON_BINDINGS_LIBRARY STREQUAL "nanobind")
- nanobind_add_module(${libname}
- NB_DOMAIN ${MLIR_BINDINGS_PYTHON_NB_DOMAIN}
- FREE_THREADED
- ${ARG_SOURCES}
- )
+ nanobind_add_module(${libname}
+ NB_DOMAIN ${MLIR_BINDINGS_PYTHON_NB_DOMAIN}
+ FREE_THREADED
+ ${ARG_SOURCES}
+ )
- if (NOT MLIR_DISABLE_CONFIGURE_PYTHON_DEV_PACKAGES
- AND (LLVM_COMPILER_IS_GCC_COMPATIBLE OR CLANG_CL))
- # Avoid some warnings from upstream nanobind.
- # If a superproject set MLIR_DISABLE_CONFIGURE_PYTHON_DEV_PACKAGES, let
- # the super project handle compile options as it wishes.
- get_property(NB_LIBRARY_TARGET_NAME TARGET ${libname} PROPERTY LINK_LIBRARIES)
- target_compile_options(${NB_LIBRARY_TARGET_NAME}
- PRIVATE
- -Wall -Wextra -Wpedantic
- -Wno-c++98-compat-extra-semi
- -Wno-cast-qual
- -Wno-covered-switch-default
- -Wno-deprecated-literal-operator
- -Wno-nested-anon-types
- -Wno-unused-parameter
- -Wno-zero-length-array
- ${eh_rtti_enable})
-
- target_compile_options(${libname}
- PRIVATE
- -Wall -Wextra -Wpedantic
- -Wno-c++98-compat-extra-semi
- -Wno-cast-qual
- -Wno-covered-switch-default
- -Wno-deprecated-literal-operator
- -Wno-nested-anon-types
- -Wno-unused-parameter
- -Wno-zero-length-array
- ${eh_rtti_enable})
- endif()
+ if (NOT MLIR_DISABLE_CONFIGURE_PYTHON_DEV_PACKAGES
+ AND (LLVM_COMPILER_IS_GCC_COMPATIBLE OR CLANG_CL))
+ # Avoid some warnings from upstream nanobind.
+ # If a superproject set MLIR_DISABLE_CONFIGURE_PYTHON_DEV_PACKAGES, let
+ # the super project handle compile options as it wishes.
+ get_property(NB_LIBRARY_TARGET_NAME TARGET ${libname} PROPERTY LINK_LIBRARIES)
+ target_compile_options(${NB_LIBRARY_TARGET_NAME}
+ PRIVATE
+ -Wall -Wextra -Wpedantic
+ -Wno-c++98-compat-extra-semi
+ -Wno-cast-qual
+ -Wno-covered-switch-default
+ -Wno-deprecated-literal-operator
+ -Wno-nested-anon-types
+ -Wno-unused-parameter
+ -Wno-zero-length-array
+ ${eh_rtti_enable})
+
+ target_compile_options(${libname}
+ PRIVATE
+ -Wall -Wextra -Wpedantic
+ -Wno-c++98-compat-extra-semi
+ -Wno-cast-qual
+ -Wno-covered-switch-default
+ -Wno-deprecated-literal-operator
+ -Wno-nested-anon-types
+ -Wno-unused-parameter
+ -Wno-zero-length-array
+ ${eh_rtti_enable})
+ endif()
- if(APPLE)
- # NanobindAdaptors.h uses PyClassMethod_New to build `pure_subclass`es but nanobind
- # doesn't declare this API as undefined in its linker flags. So we need to declare it as such
- # for downstream users that do not do something like `-undefined dynamic_lookup`.
- # Same for the rest.
- target_link_options(${libname} PUBLIC
- "LINKER:-U,_PyClassMethod_New"
- "LINKER:-U,_PyCode_Addr2Location"
- "LINKER:-U,_PyFrame_GetLasti"
- )
- endif()
+ if(APPLE)
+ # NanobindAdaptors.h uses PyClassMethod_New to build `pure_subclass`es but nanobind
+ # doesn't declare this API as undefined in its linker flags. So we need to declare it as such
+ # for downstream users that do not do something like `-undefined dynamic_lookup`.
+ # Same for the rest.
+ target_link_options(${libname} PUBLIC
+ "LINKER:-U,_PyClassMethod_New"
+ "LINKER:-U,_PyCode_Addr2Location"
+ "LINKER:-U,_PyFrame_GetLasti"
+ )
endif()
target_compile_options(${libname} PRIVATE ${eh_rtti_enable})
@@ -839,11 +822,11 @@ function(add_mlir_python_extension libname extname)
if(WIN32)
# On Windows, pyconfig.h (and by extension python.h) hardcode the version of the
# python library which will be used for linkage depending on the flavor of the build.
- # pybind11 has a workaround which depends on the definition of Py_DEBUG (if Py_DEBUG
- # is not passed in as a compile definition, pybind11 undefs _DEBUG when including
+ # nanobind has a workaround which depends on the definition of Py_DEBUG (if Py_DEBUG
+ # is not passed in as a compile definition, nanobind undefs _DEBUG when including
# python.h, so that the release python library would be used).
- # Since mlir uses pybind11, we can leverage their workaround by never directly
- # pyconfig.h or python.h and instead relying on the pybind11 headers to include the
+ # Since mlir uses nanobind, we can leverage their workaround by never directly
+ # pyconfig.h or python.h and instead relying on the nanobind headers to include the
# necessary python headers. This results in mlir always linking against the
# release python library via the (undocumented) cmake property Python3_LIBRARY_RELEASE.
target_link_libraries(${libname} PRIVATE ${Python3_LIBRARY_RELEASE})
diff --git a/mlir/cmake/modules/MLIRDetectPythonEnv.cmake b/mlir/cmake/modules/MLIRDetectPythonEnv.cmake
index d18f8c06158b2..396f669a6f6d2 100644
--- a/mlir/cmake/modules/MLIRDetectPythonEnv.cmake
+++ b/mlir/cmake/modules/MLIRDetectPythonEnv.cmake
@@ -46,81 +46,52 @@ macro(mlir_configure_python_dev_packages)
message(STATUS "Found python include dirs: ${Python3_INCLUDE_DIRS}")
message(STATUS "Found python libraries: ${Python3_LIBRARIES}")
message(STATUS "Found numpy v${Python3_NumPy_VERSION}: ${Python3_NumPy_INCLUDE_DIRS}")
- mlir_detect_pybind11_install()
- find_package(pybind11 2.10 CONFIG REQUIRED)
- message(STATUS "Found pybind11 v${pybind11_VERSION}: ${pybind11_INCLUDE_DIR}")
- message(STATUS "Python prefix = '${PYTHON_MODULE_PREFIX}', "
- "suffix = '${PYTHON_MODULE_SUFFIX}', "
- "extension = '${PYTHON_MODULE_EXTENSION}")
-
- mlir_detect_nanobind_install()
- find_package(nanobind 2.9 CONFIG REQUIRED)
- message(STATUS "Found nanobind v${nanobind_VERSION}: ${nanobind_INCLUDE_DIR}")
- message(STATUS "Python prefix = '${PYTHON_MODULE_PREFIX}', "
- "suffix = '${PYTHON_MODULE_SUFFIX}', "
- "extension = '${PYTHON_MODULE_EXTENSION}")
- endif()
-endmacro()
-
-# Detects a pybind11 package installed in the current python environment
-# and sets variables to allow it to be found. This allows pybind11 to be
-# installed via pip, which typically yields a much more recent version than
-# the OS install, which will be available otherwise.
-function(mlir_detect_pybind11_install)
- if(pybind11_DIR)
- message(STATUS "Using explicit pybind11 cmake directory: ${pybind11_DIR} (-Dpybind11_DIR to change)")
- else()
- message(STATUS "Checking for pybind11 in python path...")
- execute_process(
- COMMAND "${Python3_EXECUTABLE}"
- -c "import pybind11;print(pybind11.get_cmake_dir(), end='')"
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
- RESULT_VARIABLE STATUS
- OUTPUT_VARIABLE PACKAGE_DIR
- ERROR_QUIET)
- if(NOT STATUS EQUAL "0")
- message(STATUS "not found (install via 'pip install pybind11' or set pybind11_DIR)")
- return()
- endif()
- message(STATUS "found (${PACKAGE_DIR})")
- set(pybind11_DIR "${PACKAGE_DIR}" PARENT_SCOPE)
- endif()
-endfunction()
-
-
-# Detects a nanobind package installed in the current python environment
-# and sets variables to allow it to be found. This allows nanobind to be
-# installed via pip, which typically yields a much more recent version than
-# the OS install, which will be available otherwise.
-function(mlir_detect_nanobind_install)
- if(nanobind_DIR)
- message(STATUS "Using explicit nanobind cmake directory: ${nanobind_DIR} (-Dnanobind_DIR to change)")
- else()
- message(STATUS "Checking for nanobind in python path...")
- execute_process(
- COMMAND "${Python3_EXECUTABLE}"
- -c "import nanobind;print(nanobind.cmake_dir(), end='')"
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
- RESULT_VARIABLE STATUS
- OUTPUT_VARIABLE PACKAGE_DIR
- ERROR_QUIET)
- if(NOT STATUS EQUAL "0")
- message(STATUS "not found (install via 'pip install nanobind' or set nanobind_DIR)")
- return()
+ message(STATUS "Python extension suffix for modules: '${Python3_SOABI}'")
+ if(nanobind_DIR)
+ message(STATUS "Using explicit nanobind cmake directory: ${nanobind_DIR} (-Dnanobind_DIR to change)")
+ find_package(nanobind 2.9 CONFIG REQUIRED)
+ else()
+ include(FetchContent)
+# # nanobind uses tsl-robin-map and since we're not using GIT for nanobind we need to
+# # get tsl-robin-map manually too.
+# FetchContent_Declare(
+# tsl-robin-map
+# OVERRIDE_FIND_PACKAGE
+# # timestamp the files with the extraction time instead of archive time
+# DOWNLOAD_EXTRACT_TIMESTAMP FALSE
+# URL https://github.com/Tessil/robin-map/archive/refs/tags/v1.4.0.tar.gz
+# # put this last otherwise windows parses everything after the hash as part of the hash???
+# URL_HASH MD5=d56a879c94e021c55d8956e37deb3e4f
+# )
+# FetchContent_MakeAvailable(tsl-robin-map)
+# # Tell nanobind to use find_project(tsl-robin-map) instead of searching its
+# # submodule folder.
+# set(NB_USE_SUBMODULE_DEPS OFF CACHE INTERNAL "Switch off Nanobind submodule deps")
+# FetchContent_Declare(
+# nanobind
+# OVERRIDE_FIND_PACKAGE
+# # timestamp the files with the extraction time instead of archive time
+# DOWNLOAD_EXTRACT_TIMESTAMP FALSE
+# URL https://github.com/wjakob/nanobind/archive/refs/tags/v2.9.0.tar.gz
+# # put this last otherwise windows parses everything after the hash as part of the hash???
+# URL_HASH MD5=df0e9de9d5fd817df264584be4917fd0
+# )
+# FetchContent_MakeAvailable(nanobind)
+ FetchContent_Declare(
+ nanobind
+ GIT_REPOSITORY https://github.com/wjakob/nanobind.git
+ GIT_TAG v2.9.0
+ GIT_SHALLOW TRUE
+ OVERRIDE_FIND_PACKAGE
+ )
+ FetchContent_MakeAvailable(nanobind)
+ if(CMAKE_VERSION VERSION_LESS "3.24.0")
+ # OVERRIDE_FIND_PACKAGE not implemented so have to set the dirs manually.
+ set(nanobind_DIR "${nanobind_SOURCE_DIR}/cmake" CACHE INTERNAL "")
+ endif()
+ # no PACKAGE_VERSION in this path but we know it's 2.9 of course.
+ find_package(nanobind CONFIG REQUIRED)
endif()
- message(STATUS "found (${PACKAGE_DIR})")
- set(nanobind_DIR "${PACKAGE_DIR}" PARENT_SCOPE)
- execute_process(
- COMMAND "${Python3_EXECUTABLE}"
- -c "import nanobind;print(nanobind.include_dir(), end='')"
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
- RESULT_VARIABLE STATUS
- OUTPUT_VARIABLE PACKAGE_DIR
- ERROR_QUIET)
- if(NOT STATUS EQUAL "0")
- message(STATUS "not found (install via 'pip install nanobind' or set nanobind_DIR)")
- return()
- endif()
- set(nanobind_INCLUDE_DIR "${PACKAGE_DIR}" PARENT_SCOPE)
+ message(STATUS "Found nanobind: ${NB_DIR}")
endif()
-endfunction()
+endmacro()
diff --git a/mlir/examples/standalone/python/CMakeLists.txt b/mlir/examples/standalone/python/CMakeLists.txt
index 905c944939756..108c343714421 100644
--- a/mlir/examples/standalone/python/CMakeLists.txt
+++ b/mlir/examples/standalone/python/CMakeLists.txt
@@ -16,27 +16,10 @@ declare_mlir_dialect_python_bindings(
ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/mlir_standalone"
TD_FILE dialects/StandaloneOps.td
SOURCES
- dialects/standalone_pybind11.py
dialects/standalone_nanobind.py
_mlir_libs/_standaloneDialectsNanobind/py.typed
DIALECT_NAME standalone)
-
-declare_mlir_python_extension(StandalonePythonSources.Pybind11Extension
- MODULE_NAME _standaloneDialectsPybind11
- ADD_TO_PARENT StandalonePythonSources
- SOURCES
- StandaloneExtensionPybind11.cpp
- PRIVATE_LINK_LIBS
- LLVMSupport
- EMBED_CAPI_LINK_LIBS
- MLIRCAPIIR
- MLIRCAPIArith
- MLIRCAPITransforms
- StandaloneCAPI
- PYTHON_BINDINGS_LIBRARY pybind11
-)
-
declare_mlir_python_extension(StandalonePythonSources.NanobindExtension
MODULE_NAME _standaloneDialectsNanobind
ADD_TO_PARENT StandalonePythonSources
@@ -49,7 +32,6 @@ declare_mlir_python_extension(StandalonePythonSources.NanobindExtension
MLIRCAPIArith
MLIRCAPITransforms
StandaloneCAPI
- PYTHON_BINDINGS_LIBRARY nanobind
)
diff --git a/mlir/examples/standalone/python/StandaloneExtensionPybind11.cpp b/mlir/examples/standalone/python/StandaloneExtensionPybind11.cpp
deleted file mode 100644
index da8c2167dc36b..0000000000000
--- a/mlir/examples/standalone/python/StandaloneExtensionPybind11.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-//===- StandaloneExtensionPybind11.cpp - Extension module -----------------===//
-//
-// This is the pybind11 version of the example module. There is also a nanobind
-// example in StandaloneExtensionNanobind.cpp.
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "Standalone-c/Dialects.h"
-#include "mlir-c/Dialect/Arith.h"
-#include "mlir/Bindings/Python/PybindAdaptors.h"
-
-using namespace mlir::python::adaptors;
-
-PYBIND11_MODULE(_standaloneDialectsPybind11, m) {
- //===--------------------------------------------------------------------===//
- // standalone dialect
- //===--------------------------------------------------------------------===//
- auto standaloneM = m.def_submodule("standalone");
-
- standaloneM.def(
- "register_dialects",
- [](MlirContext context, bool load) {
- MlirDialectHandle arithHandle = mlirGetDialectHandle__arith__();
- MlirDialectHandle standaloneHandle =
- mlirGetDialectHandle__standalone__();
- mlirDialectHandleRegisterDialect(arithHandle, context);
- mlirDialectHandleRegisterDialect(standaloneHandle, context);
- if (load) {
- mlirDialectHandleLoadDialect(arithHandle, context);
- mlirDialectHandleRegisterDialect(standaloneHandle, context);
- }
- },
- py::arg("context") = py::none(), py::arg("load") = true);
-}
diff --git a/mlir/examples/standalone/python/mlir_standalone/dialects/standalone_pybind11.py b/mlir/examples/standalone/python/mlir_standalone/dialects/standalone_pybind11.py
deleted file mode 100644
index bfb98e404e13f..0000000000000
--- a/mlir/examples/standalone/python/mlir_standalone/dialects/standalone_pybind11.py
+++ /dev/null
@@ -1,6 +0,0 @@
-# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-# See https://llvm.org/LICENSE.txt for license information.
-# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-from ._standalone_ops_gen import *
-from .._mlir_libs._standaloneDialectsPybind11.standalone import *
diff --git a/mlir/examples/standalone/test/python/smoketest.py b/mlir/examples/standalone/test/python/smoketest.py
index 26d84fd63e947..f8819841fac45 100644
--- a/mlir/examples/standalone/test/python/smoketest.py
+++ b/mlir/examples/standalone/test/python/smoketest.py
@@ -1,16 +1,7 @@
-# RUN: %python %s pybind11 | FileCheck %s
# RUN: %python %s nanobind | FileCheck %s
-import sys
from mlir_standalone.ir import *
-
-if sys.argv[1] == "pybind11":
- from mlir_standalone.dialects import standalone_pybind11 as standalone_d
-elif sys.argv[1] == "nanobind":
- from mlir_standalone.dialects import standalone_nanobind as standalone_d
-else:
- raise ValueError("Expected either pybind11 or nanobind as arguments")
-
+from mlir_standalone.dialects import standalone_nanobind as standalone_d
with Context():
standalone_d.register_dialects()
diff --git a/mlir/include/mlir/Bindings/Python/PybindAdaptors.h b/mlir/include/mlir/Bindings/Python/PybindAdaptors.h
deleted file mode 100644
index edc69774be922..0000000000000
--- a/mlir/include/mlir/Bindings/Python/PybindAdaptors.h
+++ /dev/null
@@ -1,616 +0,0 @@
-//===- PybindAdaptors.h - Interop with MLIR APIs via pybind11 -------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-// This file contains adaptors for clients of the core MLIR Python APIs to
-// interop via MLIR CAPI types, using pybind11. The facilities here do not
-// depend on implementation details of the MLIR Python API and do not introduce
-// C++-level dependencies with it (requiring only Python and CAPI-level
-// dependencies).
-//
-// It is encouraged to be used both in-tree and out-of-tree. For in-tree use
-// cases, it should be used for dialect implementations (versus relying on
-// Pybind-based internals of the core libraries).
-//===----------------------------------------------------------------------===//
-
-#ifndef MLIR_BINDINGS_PYTHON_PYBINDADAPTORS_H
-#define MLIR_BINDINGS_PYTHON_PYBINDADAPTORS_H
-
-#include <pybind11/functional.h>
-#include <pybind11/pybind11.h>
-#include <pybind11/pytypes.h>
-#include <pybind11/stl.h>
-
-#include "mlir-c/Bindings/Python/Interop.h"
-#include "mlir-c/Diagnostics.h"
-#include "mlir-c/IR.h"
-
-#include "llvm/ADT/Twine.h"
-
-namespace py = pybind11;
-using namespace py::literals;
-
-// Raw CAPI type casters need to be declared before use, so always include them
-// first.
-namespace pybind11 {
-namespace detail {
-
-/// Helper to convert a presumed MLIR API object to a capsule, accepting either
-/// an explicit Capsule (which can happen when two C APIs are communicating
-/// directly via Python) or indirectly by querying the MLIR_PYTHON_CAPI_PTR_ATTR
-/// attribute (through which supported MLIR Python API objects export their
-/// contained API pointer as a capsule). Throws a type error if the object is
-/// neither. This is intended to be used from type casters, which are invoked
-/// with a raw handle (unowned). The returned object's lifetime may not extend
-/// beyond the apiObject handle without explicitly having its refcount increased
-/// (i.e. on return).
-static py::object mlirApiObjectToCapsule(py::handle apiObject) {
- if (PyCapsule_CheckExact(apiObject.ptr()))
- return py::reinterpret_borrow<py::object>(apiObject);
- if (!py::hasattr(apiObject, MLIR_PYTHON_CAPI_PTR_ATTR)) {
- auto repr = py::repr(apiObject).cast<std::string>();
- throw py::type_error(
- (llvm::Twine("Expected an MLIR object (got ") + repr + ").").str());
- }
- return apiObject.attr(MLIR_PYTHON_CAPI_PTR_ATTR);
-}
-
-// Note: Currently all of the following support cast from py::object to the
-// Mlir* C-API type, but only a few light-weight, context-bound ones
-// implicitly cast the other way because the use case has not yet emerged and
-// ownership is unclear.
-
-/// Casts object <-> MlirAffineMap.
-template <>
-struct type_caster<MlirAffineMap> {
- PYBIND11_TYPE_CASTER(MlirAffineMap, _("MlirAffineMap"));
- bool load(handle src, bool) {
- py::object capsule = mlirApiObjectToCapsule(src);
- value = mlirPythonCapsuleToAffineMap(capsule.ptr());
- if (mlirAffineMapIsNull(value)) {
- return false;
- }
- return !mlirAffineMapIsNull(value);
- }
- static handle cast(MlirAffineMap v, return_value_policy, handle) {
- py::object capsule =
- py::reinterpret_steal<py::object>(mlirPythonAffineMapToCapsule(v));
- return py::module::import(MAKE_MLIR_PYTHON_QUALNAME("ir"))
- .attr("AffineMap")
- .attr(MLIR_PYTHON_CAPI_FACTORY_ATTR)(capsule)
- .release();
- }
-};
-
-/// Casts object <-> MlirAttribute.
-template <>
-struct type_caster<MlirAttribute> {
- PYBIND11_TYPE_CASTER(MlirAttribute, _("MlirAttribute"));
- bool load(handle src, bool) {
- py::object capsule = mlirApiObjectToCapsule(src);
- value = mlirPythonCapsuleToAttribute(capsule.ptr());
- return !mlirAttributeIsNull(value);
- }
- static handle cast(MlirAttribute v, return_value_policy, handle) {
- py::object capsule =
- py::reinterpret_steal<py::object>(mlirPythonAttributeToCapsule(v));
- return py::module::import(MAKE_MLIR_PYTHON_QUALNAME("ir"))
- .attr("Attribute")
- .attr(MLIR_PYTHON_CAPI_FACTORY_ATTR)(capsule)
- .attr(MLIR_PYTHON_MAYBE_DOWNCAST_ATTR)()
- .release();
- }
-};
-
-/// Casts object -> MlirBlock.
-template <>
-struct type_caster<MlirBlock> {
- PYBIND11_TYPE_CASTER(MlirBlock, _("MlirBlock"));
- bool load(handle src, bool) {
- py::object capsule = mlirApiObjectToCapsule(src);
- value = mlirPythonCapsuleToBlock(capsule.ptr());
- return !mlirBlockIsNull(value);
- }
-};
-
-/// Casts object -> MlirContext.
-template <>
-struct type_caster<MlirContext> {
- PYBIND11_TYPE_CASTER(MlirContext, _("MlirContext"));
- bool load(handle src, bool) {
- if (src.is_none()) {
- // Gets the current thread-bound context.
- // TODO: This raises an error of "No current context" currently.
- // Update the implementation to pretty-print the helpful error that the
- // core implementations print in this case.
- src = py::module::import(MAKE_MLIR_PYTHON_QUALNAME("ir"))
- .attr("Context")
- .attr("current");
- }
- py::object capsule = mlirApiObjectToCapsule(src);
- value = mlirPythonCapsuleToContext(capsule.ptr());
- return !mlirContextIsNull(value);
- }
-};
-
-/// Casts object <-> MlirDialectRegistry.
-template <>
-struct type_caster<MlirDialectRegistry> {
- PYBIND11_TYPE_CASTER(MlirDialectRegistry, _("MlirDialectRegistry"));
- bool load(handle src, bool) {
- py::object capsule = mlirApiObjectToCapsule(src);
- value = mlirPythonCapsuleToDialectRegistry(capsule.ptr());
- return !mlirDialectRegistryIsNull(value);
- }
- static handle cast(MlirDialectRegistry v, return_value_policy, handle) {
- py::object capsule = py::reinterpret_steal<py::object>(
- mlirPythonDialectRegistryToCapsule(v));
- return py::module::import(MAKE_MLIR_PYTHON_QUALNAME("ir"))
- .attr("DialectRegistry")
- .attr(MLIR_PYTHON_CAPI_FACTORY_ATTR)(capsule)
- .release();
- }
-};
-
-/// Casts object <-> MlirLocation.
-template <>
-struct type_caster<MlirLocation> {
- PYBIND11_TYPE_CASTER(MlirLocation, _("MlirLocation"));
- bool load(handle src, bool) {
- if (src.is_none()) {
- // Gets the current thread-bound context.
- src = py::module::import(MAKE_MLIR_PYTHON_QUALNAME("ir"))
- .attr("Location")
- .attr("current");
- }
- py::object capsule = mlirApiObjectToCapsule(src);
- value = mlirPythonCapsuleToLocation(capsule.ptr());
- return !mlirLocationIsNull(value);
- }
- static handle cast(MlirLocation v, return_value_policy, handle) {
- py::object capsule =
- py::reinterpret_steal<py::object>(mlirPythonLocationToCapsule(v));
- return py::module::import(MAKE_MLIR_PYTHON_QUALNAME("ir"))
- .attr("Location")
- .attr(MLIR_PYTHON_CAPI_FACTORY_ATTR)(capsule)
- .release();
- }
-};
-
-/// Casts object <-> MlirModule.
-template <>
-struct type_caster<MlirModule> {
- PYBIND11_TYPE_CASTER(MlirModule, _("MlirModule"));
- bool load(handle src, bool) {
- py::object capsule = mlirApiObjectToCapsule(src);
- value = mlirPythonCapsuleToModule(capsule.ptr());
- return !mlirModuleIsNull(value);
- }
- static handle cast(MlirModule v, return_value_policy, handle) {
- py::object capsule =
- py::reinterpret_steal<py::object>(mlirPythonModuleToCapsule(v));
- return py::module::import(MAKE_MLIR_PYTHON_QUALNAME("ir"))
- .attr("Module")
- .attr(MLIR_PYTHON_CAPI_FACTORY_ATTR)(capsule)
- .release();
- };
-};
-
-/// Casts object <-> MlirFrozenRewritePatternSet.
-template <>
-struct type_caster<MlirFrozenRewritePatternSet> {
- PYBIND11_TYPE_CASTER(MlirFrozenRewritePatternSet,
- _("MlirFrozenRewritePatternSet"));
- bool load(handle src, bool) {
- py::object capsule = mlirApiObjectToCapsule(src);
- value = mlirPythonCapsuleToFrozenRewritePatternSet(capsule.ptr());
- return value.ptr != nullptr;
- }
- static handle cast(MlirFrozenRewritePatternSet v, return_value_policy,
- handle) {
- py::object capsule = py::reinterpret_steal<py::object>(
- mlirPythonFrozenRewritePatternSetToCapsule(v));
- return py::module::import(MAKE_MLIR_PYTHON_QUALNAME("rewrite"))
- .attr("FrozenRewritePatternSet")
- .attr(MLIR_PYTHON_CAPI_FACTORY_ATTR)(capsule)
- .release();
- };
-};
-
-/// Casts object <-> MlirOperation.
-template <>
-struct type_caster<MlirOperation> {
- PYBIND11_TYPE_CASTER(MlirOperation, _("MlirOperation"));
- bool load(handle src, bool) {
- py::object capsule = mlirApiObjectToCapsule(src);
- value = mlirPythonCapsuleToOperation(capsule.ptr());
- return !mlirOperationIsNull(value);
- }
- static handle cast(MlirOperation v, return_value_policy, handle) {
- if (v.ptr == nullptr)
- return py::none();
- py::object capsule =
- py::reinterpret_steal<py::object>(mlirPythonOperationToCapsule(v));
- return py::module::import(MAKE_MLIR_PYTHON_QUALNAME("ir"))
- .attr("Operation")
- .attr(MLIR_PYTHON_CAPI_FACTORY_ATTR)(capsule)
- .release();
- };
-};
-
-/// Casts object <-> MlirValue.
-template <>
-struct type_caster<MlirValue> {
- PYBIND11_TYPE_CASTER(MlirValue, _("MlirValue"));
- bool load(handle src, bool) {
- py::object capsule = mlirApiObjectToCapsule(src);
- value = mlirPythonCapsuleToValue(capsule.ptr());
- return !mlirValueIsNull(value);
- }
- static handle cast(MlirValue v, return_value_policy, handle) {
- if (v.ptr == nullptr)
- return py::none();
- py::object capsule =
- py::reinterpret_steal<py::object>(mlirPythonValueToCapsule(v));
- return py::module::import(MAKE_MLIR_PYTHON_QUALNAME("ir"))
- .attr("Value")
- .attr(MLIR_PYTHON_CAPI_FACTORY_ATTR)(capsule)
- .attr(MLIR_PYTHON_MAYBE_DOWNCAST_ATTR)()
- .release();
- };
-};
-
-/// Casts object -> MlirPassManager.
-template <>
-struct type_caster<MlirPassManager> {
- PYBIND11_TYPE_CASTER(MlirPassManager, _("MlirPassManager"));
- bool load(handle src, bool) {
- py::object capsule = mlirApiObjectToCapsule(src);
- value = mlirPythonCapsuleToPassManager(capsule.ptr());
- return !mlirPassManagerIsNull(value);
- }
-};
-
-/// Casts object <-> MlirTypeID.
-template <>
-struct type_caster<MlirTypeID> {
- PYBIND11_TYPE_CASTER(MlirTypeID, _("MlirTypeID"));
- bool load(handle src, bool) {
- py::object capsule = mlirApiObjectToCapsule(src);
- value = mlirPythonCapsuleToTypeID(capsule.ptr());
- return !mlirTypeIDIsNull(value);
- }
- static handle cast(MlirTypeID v, return_value_policy, handle) {
- if (v.ptr == nullptr)
- return py::none();
- py::object capsule =
- py::reinterpret_steal<py::object>(mlirPythonTypeIDToCapsule(v));
- return py::module::import(MAKE_MLIR_PYTHON_QUALNAME("ir"))
- .attr("TypeID")
- .attr(MLIR_PYTHON_CAPI_FACTORY_ATTR)(capsule)
- .release();
- };
-};
-
-/// Casts object <-> MlirType.
-template <>
-struct type_caster<MlirType> {
- PYBIND11_TYPE_CASTER(MlirType, _("MlirType"));
- bool load(handle src, bool) {
- py::object capsule = mlirApiObjectToCapsule(src);
- value = mlirPythonCapsuleToType(capsule.ptr());
- return !mlirTypeIsNull(value);
- }
- static handle cast(MlirType t, return_value_policy, handle) {
- py::object capsule =
- py::reinterpret_steal<py::object>(mlirPythonTypeToCapsule(t));
- return py::module::import(MAKE_MLIR_PYTHON_QUALNAME("ir"))
- .attr("Type")
- .attr(MLIR_PYTHON_CAPI_FACTORY_ATTR)(capsule)
- .attr(MLIR_PYTHON_MAYBE_DOWNCAST_ATTR)()
- .release();
- }
-};
-
-} // namespace detail
-} // namespace pybind11
-
-namespace mlir {
-namespace python {
-namespace adaptors {
-
-/// Provides a facility like py::class_ for defining a new class in a scope,
-/// but this allows extension of an arbitrary Python class, defining methods
-/// on it is a similar way. Classes defined in this way are very similar to
-/// if defined in Python in the usual way but use Pybind11 machinery to do
-/// it. These are not "real" Pybind11 classes but pure Python classes with no
-/// relation to a concrete C++ class.
-///
-/// Derived from a discussion upstream:
-/// https://github.com/pybind/pybind11/issues/1193
-/// (plus a fair amount of extra curricular poking)
-/// TODO: If this proves useful, see about including it in pybind11.
-class pure_subclass {
-public:
- pure_subclass(py::handle scope, const char *derivedClassName,
- const py::object &superClass) {
- py::object pyType =
- py::reinterpret_borrow<py::object>((PyObject *)&PyType_Type);
- py::object metaclass = pyType(superClass);
- py::dict attributes;
-
- thisClass =
- metaclass(derivedClassName, py::make_tuple(superClass), attributes);
- scope.attr(derivedClassName) = thisClass;
- }
-
- template <typename Func, typename... Extra>
- pure_subclass &def(const char *name, Func &&f, const Extra &...extra) {
- py::cpp_function cf(
- std::forward<Func>(f), py::name(name), py::is_method(thisClass),
- py::sibling(py::getattr(thisClass, name, py::none())), extra...);
- thisClass.attr(cf.name()) = cf;
- return *this;
- }
-
- template <typename Func, typename... Extra>
- pure_subclass &def_property_readonly(const char *name, Func &&f,
- const Extra &...extra) {
- py::cpp_function cf(
- std::forward<Func>(f), py::name(name), py::is_method(thisClass),
- py::sibling(py::getattr(thisClass, name, py::none())), extra...);
- auto builtinProperty =
- py::reinterpret_borrow<py::object>((PyObject *)&PyProperty_Type);
- thisClass.attr(name) = builtinProperty(cf);
- return *this;
- }
-
- template <typename Func, typename... Extra>
- pure_subclass &def_staticmethod(const char *name, Func &&f,
- const Extra &...extra) {
- static_assert(!std::is_member_function_pointer<Func>::value,
- "def_staticmethod(...) called with a non-static member "
- "function pointer");
- py::cpp_function cf(std::forward<Func>(f), py::name(name),
- py::scope(thisClass), extra...);
- thisClass.attr(cf.name()) = py::staticmethod(cf);
- return *this;
- }
-
- template <typename Func, typename... Extra>
- pure_subclass &def_classmethod(const char *name, Func &&f,
- const Extra &...extra) {
- static_assert(!std::is_member_function_pointer<Func>::value,
- "def_classmethod(...) called with a non-static member "
- "function pointer");
- py::cpp_function cf(std::forward<Func>(f), py::name(name),
- py::scope(thisClass), extra...);
- thisClass.attr(cf.name()) =
- py::reinterpret_borrow<py::object>(PyClassMethod_New(cf.ptr()));
- return *this;
- }
-
- py::object get_class() const { return thisClass; }
-
-protected:
- py::object superClass;
- py::object thisClass;
-};
-
-/// Creates a custom subclass of mlir.ir.Attribute, implementing a casting
-/// constructor and type checking methods.
-class mlir_attribute_subclass : public pure_subclass {
-public:
- using IsAFunctionTy = bool (*)(MlirAttribute);
- using GetTypeIDFunctionTy = MlirTypeID (*)();
-
- /// Subclasses by looking up the super-class dynamically.
- mlir_attribute_subclass(py::handle scope, const char *attrClassName,
- IsAFunctionTy isaFunction,
- GetTypeIDFunctionTy getTypeIDFunction = nullptr)
- : mlir_attribute_subclass(
- scope, attrClassName, isaFunction,
- py::module::import(MAKE_MLIR_PYTHON_QUALNAME("ir"))
- .attr("Attribute"),
- getTypeIDFunction) {}
-
- /// Subclasses with a provided mlir.ir.Attribute super-class. This must
- /// be used if the subclass is being defined in the same extension module
- /// as the mlir.ir class (otherwise, it will trigger a recursive
- /// initialization).
- mlir_attribute_subclass(py::handle scope, const char *typeClassName,
- IsAFunctionTy isaFunction, const py::object &superCls,
- GetTypeIDFunctionTy getTypeIDFunction = nullptr)
- : pure_subclass(scope, typeClassName, superCls) {
- // Casting constructor. Note that it hard, if not impossible, to properly
- // call chain to parent `__init__` in pybind11 due to its special handling
- // for init functions that don't have a fully constructed self-reference,
- // which makes it impossible to forward it to `__init__` of a superclass.
- // Instead, provide a custom `__new__` and call that of a superclass, which
- // eventually calls `__init__` of the superclass. Since attribute subclasses
- // have no additional members, we can just return the instance thus created
- // without amending it.
- std::string captureTypeName(
- typeClassName); // As string in case if typeClassName is not static.
- py::cpp_function newCf(
- [superCls, isaFunction, captureTypeName](py::object cls,
- py::object otherAttribute) {
- MlirAttribute rawAttribute = py::cast<MlirAttribute>(otherAttribute);
- if (!isaFunction(rawAttribute)) {
- auto origRepr = py::repr(otherAttribute).cast<std::string>();
- throw std::invalid_argument(
- (llvm::Twine("Cannot cast attribute to ") + captureTypeName +
- " (from " + origRepr + ")")
- .str());
- }
- py::object self = superCls.attr("__new__")(cls, otherAttribute);
- return self;
- },
- py::name("__new__"), py::arg("cls"), py::arg("cast_from_attr"));
- thisClass.attr("__new__") = newCf;
-
- // 'isinstance' method.
- def_staticmethod(
- "isinstance",
- [isaFunction](MlirAttribute other) { return isaFunction(other); },
- py::arg("other_attribute"));
- def("__repr__", [superCls, captureTypeName](py::object self) {
- return py::repr(superCls(self))
- .attr("replace")(superCls.attr("__name__"), captureTypeName);
- });
- if (getTypeIDFunction) {
- def_staticmethod("get_static_typeid",
- [getTypeIDFunction]() { return getTypeIDFunction(); });
- py::module::import(MAKE_MLIR_PYTHON_QUALNAME("ir"))
- .attr(MLIR_PYTHON_CAPI_TYPE_CASTER_REGISTER_ATTR)(
- getTypeIDFunction())(pybind11::cpp_function(
- [thisClass = thisClass](const py::object &mlirAttribute) {
- return thisClass(mlirAttribute);
- }));
- }
- }
-};
-
-/// Creates a custom subclass of mlir.ir.Type, implementing a casting
-/// constructor and type checking methods.
-class mlir_type_subclass : public pure_subclass {
-public:
- using IsAFunctionTy = bool (*)(MlirType);
- using GetTypeIDFunctionTy = MlirTypeID (*)();
-
- /// Subclasses by looking up the super-class dynamically.
- mlir_type_subclass(py::handle scope, const char *typeClassName,
- IsAFunctionTy isaFunction,
- GetTypeIDFunctionTy getTypeIDFunction = nullptr)
- : mlir_type_subclass(
- scope, typeClassName, isaFunction,
- py::module::import(MAKE_MLIR_PYTHON_QUALNAME("ir")).attr("Type"),
- getTypeIDFunction) {}
-
- /// Subclasses with a provided mlir.ir.Type super-class. This must
- /// be used if the subclass is being defined in the same extension module
- /// as the mlir.ir class (otherwise, it will trigger a recursive
- /// initialization).
- mlir_type_subclass(py::handle scope, const char *typeClassName,
- IsAFunctionTy isaFunction, const py::object &superCls,
- GetTypeIDFunctionTy getTypeIDFunction = nullptr)
- : pure_subclass(scope, typeClassName, superCls) {
- // Casting constructor. Note that it hard, if not impossible, to properly
- // call chain to parent `__init__` in pybind11 due to its special handling
- // for init functions that don't have a fully constructed self-reference,
- // which makes it impossible to forward it to `__init__` of a superclass.
- // Instead, provide a custom `__new__` and call that of a superclass, which
- // eventually calls `__init__` of the superclass. Since attribute subclasses
- // have no additional members, we can just return the instance thus created
- // without amending it.
- std::string captureTypeName(
- typeClassName); // As string in case if typeClassName is not static.
- py::cpp_function newCf(
- [superCls, isaFunction, captureTypeName](py::object cls,
- py::object otherType) {
- MlirType rawType = py::cast<MlirType>(otherType);
- if (!isaFunction(rawType)) {
- auto origRepr = py::repr(otherType).cast<std::string>();
- throw std::invalid_argument((llvm::Twine("Cannot cast type to ") +
- captureTypeName + " (from " +
- origRepr + ")")
- .str());
- }
- py::object self = superCls.attr("__new__")(cls, otherType);
- return self;
- },
- py::name("__new__"), py::arg("cls"), py::arg("cast_from_type"));
- thisClass.attr("__new__") = newCf;
-
- // 'isinstance' method.
- def_staticmethod(
- "isinstance",
- [isaFunction](MlirType other) { return isaFunction(other); },
- py::arg("other_type"));
- def("__repr__", [superCls, captureTypeName](py::object self) {
- return py::repr(superCls(self))
- .attr("replace")(superCls.attr("__name__"), captureTypeName);
- });
- if (getTypeIDFunction) {
- // 'get_static_typeid' method.
- // This is modeled as a static method instead of a static property because
- // `def_property_readonly_static` is not available in `pure_subclass` and
- // we do not want to introduce the complexity that pybind uses to
- // implement it.
- def_staticmethod("get_static_typeid",
- [getTypeIDFunction]() { return getTypeIDFunction(); });
- py::module::import(MAKE_MLIR_PYTHON_QUALNAME("ir"))
- .attr(MLIR_PYTHON_CAPI_TYPE_CASTER_REGISTER_ATTR)(
- getTypeIDFunction())(pybind11::cpp_function(
- [thisClass = thisClass](const py::object &mlirType) {
- return thisClass(mlirType);
- }));
- }
- }
-};
-
-/// Creates a custom subclass of mlir.ir.Value, implementing a casting
-/// constructor and type checking methods.
-class mlir_value_subclass : public pure_subclass {
-public:
- using IsAFunctionTy = bool (*)(MlirValue);
-
- /// Subclasses by looking up the super-class dynamically.
- mlir_value_subclass(py::handle scope, const char *valueClassName,
- IsAFunctionTy isaFunction)
- : mlir_value_subclass(
- scope, valueClassName, isaFunction,
- py::module::import(MAKE_MLIR_PYTHON_QUALNAME("ir")).attr("Value")) {
- }
-
- /// Subclasses with a provided mlir.ir.Value super-class. This must
- /// be used if the subclass is being defined in the same extension module
- /// as the mlir.ir class (otherwise, it will trigger a recursive
- /// initialization).
- mlir_value_subclass(py::handle scope, const char *valueClassName,
- IsAFunctionTy isaFunction, const py::object &superCls)
- : pure_subclass(scope, valueClassName, superCls) {
- // Casting constructor. Note that it hard, if not impossible, to properly
- // call chain to parent `__init__` in pybind11 due to its special handling
- // for init functions that don't have a fully constructed self-reference,
- // which makes it impossible to forward it to `__init__` of a superclass.
- // Instead, provide a custom `__new__` and call that of a superclass, which
- // eventually calls `__init__` of the superclass. Since attribute subclasses
- // have no additional members, we can just return the instance thus created
- // without amending it.
- std::string captureValueName(
- valueClassName); // As string in case if valueClassName is not static.
- py::cpp_function newCf(
- [superCls, isaFunction, captureValueName](py::object cls,
- py::object otherValue) {
- MlirValue rawValue = py::cast<MlirValue>(otherValue);
- if (!isaFunction(rawValue)) {
- auto origRepr = py::repr(otherValue).cast<std::string>();
- throw std::invalid_argument((llvm::Twine("Cannot cast value to ") +
- captureValueName + " (from " +
- origRepr + ")")
- .str());
- }
- py::object self = superCls.attr("__new__")(cls, otherValue);
- return self;
- },
- py::name("__new__"), py::arg("cls"), py::arg("cast_from_value"));
- thisClass.attr("__new__") = newCf;
-
- // 'isinstance' method.
- def_staticmethod(
- "isinstance",
- [isaFunction](MlirValue other) { return isaFunction(other); },
- py::arg("other_value"));
- }
-};
-
-} // namespace adaptors
-
-} // namespace python
-} // namespace mlir
-
-#endif // MLIR_BINDINGS_PYTHON_PYBINDADAPTORS_H
diff --git a/mlir/python/CMakeLists.txt b/mlir/python/CMakeLists.txt
index 9f5246de6bda0..cea5b252e0faf 100644
--- a/mlir/python/CMakeLists.txt
+++ b/mlir/python/CMakeLists.txt
@@ -440,11 +440,11 @@ declare_mlir_dialect_python_bindings(
DIALECT_NAME smt)
declare_mlir_dialect_python_bindings(
- ADD_TO_PARENT MLIRPythonSources.Dialects
- ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/mlir"
- TD_FILE dialects/SPIRVOps.td
- SOURCES dialects/spirv.py
- DIALECT_NAME spirv)
+ ADD_TO_PARENT MLIRPythonSources.Dialects
+ ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/mlir"
+ TD_FILE dialects/SPIRVOps.td
+ SOURCES dialects/spirv.py
+ DIALECT_NAME spirv)
declare_mlir_dialect_python_bindings(
ADD_TO_PARENT MLIRPythonSources.Dialects
@@ -501,7 +501,6 @@ declare_mlir_python_extension(MLIRPythonExtension.Core
MODULE_NAME _mlir
ADD_TO_PARENT MLIRPythonSources.Core
ROOT_DIR "${PYTHON_SOURCE_DIR}"
- PYTHON_BINDINGS_LIBRARY nanobind
SOURCES
MainModule.cpp
IRAffine.cpp
@@ -540,7 +539,6 @@ declare_mlir_python_extension(MLIRPythonExtension.Core
declare_mlir_python_extension(MLIRPythonExtension.RegisterEverything
MODULE_NAME _mlirRegisterEverything
ROOT_DIR "${PYTHON_SOURCE_DIR}"
- PYTHON_BINDINGS_LIBRARY nanobind
SOURCES
RegisterEverything.cpp
PRIVATE_LINK_LIBS
@@ -551,11 +549,10 @@ declare_mlir_python_extension(MLIRPythonExtension.RegisterEverything
MLIRCAPIRegisterEverything
)
-declare_mlir_python_extension(MLIRPythonExtension.Dialects.Linalg.Pybind
+declare_mlir_python_extension(MLIRPythonExtension.Dialects.Linalg.Nanobind
MODULE_NAME _mlirDialectsLinalg
ADD_TO_PARENT MLIRPythonSources.Dialects.linalg
ROOT_DIR "${PYTHON_SOURCE_DIR}"
- PYTHON_BINDINGS_LIBRARY nanobind
SOURCES
DialectLinalg.cpp
PRIVATE_LINK_LIBS
@@ -565,11 +562,10 @@ declare_mlir_python_extension(MLIRPythonExtension.Dialects.Linalg.Pybind
MLIRCAPILinalg
)
-declare_mlir_python_extension(MLIRPythonExtension.Dialects.GPU.Pybind
+declare_mlir_python_extension(MLIRPythonExtension.Dialects.GPU.Nanobind
MODULE_NAME _mlirDialectsGPU
ADD_TO_PARENT MLIRPythonSources.Dialects.gpu
ROOT_DIR "${PYTHON_SOURCE_DIR}"
- PYTHON_BINDINGS_LIBRARY nanobind
SOURCES
DialectGPU.cpp
PRIVATE_LINK_LIBS
@@ -579,11 +575,10 @@ declare_mlir_python_extension(MLIRPythonExtension.Dialects.GPU.Pybind
MLIRCAPIGPU
)
-declare_mlir_python_extension(MLIRPythonExtension.Dialects.LLVM.Pybind
+declare_mlir_python_extension(MLIRPythonExtension.Dialects.LLVM.Nanobind
MODULE_NAME _mlirDialectsLLVM
ADD_TO_PARENT MLIRPythonSources.Dialects.llvm
ROOT_DIR "${PYTHON_SOURCE_DIR}"
- PYTHON_BINDINGS_LIBRARY nanobind
SOURCES
DialectLLVM.cpp
PRIVATE_LINK_LIBS
@@ -593,11 +588,10 @@ declare_mlir_python_extension(MLIRPythonExtension.Dialects.LLVM.Pybind
MLIRCAPILLVM
)
-declare_mlir_python_extension(MLIRPythonExtension.Dialects.Quant.Pybind
+declare_mlir_python_extension(MLIRPythonExtension.Dialects.Quant.Nanobind
MODULE_NAME _mlirDialectsQuant
ADD_TO_PARENT MLIRPythonSources.Dialects.quant
ROOT_DIR "${PYTHON_SOURCE_DIR}"
- PYTHON_BINDINGS_LIBRARY nanobind
SOURCES
DialectQuant.cpp
PRIVATE_LINK_LIBS
@@ -607,11 +601,10 @@ declare_mlir_python_extension(MLIRPythonExtension.Dialects.Quant.Pybind
MLIRCAPIQuant
)
-declare_mlir_python_extension(MLIRPythonExtension.Dialects.NVGPU.Pybind
+declare_mlir_python_extension(MLIRPythonExtension.Dialects.NVGPU.Nanobind
MODULE_NAME _mlirDialectsNVGPU
ADD_TO_PARENT MLIRPythonSources.Dialects.nvgpu
ROOT_DIR "${PYTHON_SOURCE_DIR}"
- PYTHON_BINDINGS_LIBRARY nanobind
SOURCES
DialectNVGPU.cpp
PRIVATE_LINK_LIBS
@@ -621,11 +614,10 @@ declare_mlir_python_extension(MLIRPythonExtension.Dialects.NVGPU.Pybind
MLIRCAPINVGPU
)
-declare_mlir_python_extension(MLIRPythonExtension.Dialects.PDL.Pybind
+declare_mlir_python_extension(MLIRPythonExtension.Dialects.PDL.Nanobind
MODULE_NAME _mlirDialectsPDL
ADD_TO_PARENT MLIRPythonSources.Dialects.pdl
ROOT_DIR "${PYTHON_SOURCE_DIR}"
- PYTHON_BINDINGS_LIBRARY nanobind
SOURCES
DialectPDL.cpp
PRIVATE_LINK_LIBS
@@ -635,11 +627,10 @@ declare_mlir_python_extension(MLIRPythonExtension.Dialects.PDL.Pybind
MLIRCAPIPDL
)
-declare_mlir_python_extension(MLIRPythonExtension.Dialects.SparseTensor.Pybind
+declare_mlir_python_extension(MLIRPythonExtension.Dialects.SparseTensor.Nanobind
MODULE_NAME _mlirDialectsSparseTensor
ADD_TO_PARENT MLIRPythonSources.Dialects.sparse_tensor
ROOT_DIR "${PYTHON_SOURCE_DIR}"
- PYTHON_BINDINGS_LIBRARY nanobind
SOURCES
DialectSparseTensor.cpp
PRIVATE_LINK_LIBS
@@ -649,11 +640,10 @@ declare_mlir_python_extension(MLIRPythonExtension.Dialects.SparseTensor.Pybind
MLIRCAPISparseTensor
)
-declare_mlir_python_extension(MLIRPythonExtension.Dialects.Transform.Pybind
+declare_mlir_python_extension(MLIRPythonExtension.Dialects.Transform.Nanobind
MODULE_NAME _mlirDialectsTransform
ADD_TO_PARENT MLIRPythonSources.Dialects.transform
ROOT_DIR "${PYTHON_SOURCE_DIR}"
- PYTHON_BINDINGS_LIBRARY nanobind
SOURCES
DialectTransform.cpp
PRIVATE_LINK_LIBS
@@ -663,11 +653,10 @@ declare_mlir_python_extension(MLIRPythonExtension.Dialects.Transform.Pybind
MLIRCAPITransformDialect
)
-declare_mlir_python_extension(MLIRPythonExtension.Dialects.IRDL.Pybind
+declare_mlir_python_extension(MLIRPythonExtension.Dialects.IRDL.Nanobind
MODULE_NAME _mlirDialectsIRDL
ADD_TO_PARENT MLIRPythonSources.Dialects.irdl
ROOT_DIR "${PYTHON_SOURCE_DIR}"
- PYTHON_BINDINGS_LIBRARY nanobind
SOURCES
DialectIRDL.cpp
PRIVATE_LINK_LIBS
@@ -681,7 +670,6 @@ declare_mlir_python_extension(MLIRPythonExtension.AsyncDialectPasses
MODULE_NAME _mlirAsyncPasses
ADD_TO_PARENT MLIRPythonSources.Dialects.async
ROOT_DIR "${PYTHON_SOURCE_DIR}"
- PYTHON_BINDINGS_LIBRARY nanobind
SOURCES
AsyncPasses.cpp
PRIVATE_LINK_LIBS
@@ -695,7 +683,6 @@ if(MLIR_ENABLE_EXECUTION_ENGINE)
MODULE_NAME _mlirExecutionEngine
ADD_TO_PARENT MLIRPythonSources.ExecutionEngine
ROOT_DIR "${PYTHON_SOURCE_DIR}"
- PYTHON_BINDINGS_LIBRARY nanobind
SOURCES
ExecutionEngineModule.cpp
PRIVATE_LINK_LIBS
@@ -709,7 +696,6 @@ declare_mlir_python_extension(MLIRPythonExtension.GPUDialectPasses
MODULE_NAME _mlirGPUPasses
ADD_TO_PARENT MLIRPythonSources.Dialects.gpu
ROOT_DIR "${PYTHON_SOURCE_DIR}"
- PYTHON_BINDINGS_LIBRARY nanobind
SOURCES
GPUPasses.cpp
PRIVATE_LINK_LIBS
@@ -722,7 +708,6 @@ declare_mlir_python_extension(MLIRPythonExtension.LinalgPasses
MODULE_NAME _mlirLinalgPasses
ADD_TO_PARENT MLIRPythonSources.Dialects.linalg
ROOT_DIR "${PYTHON_SOURCE_DIR}"
- PYTHON_BINDINGS_LIBRARY nanobind
SOURCES
LinalgPasses.cpp
PRIVATE_LINK_LIBS
@@ -731,11 +716,10 @@ declare_mlir_python_extension(MLIRPythonExtension.LinalgPasses
MLIRCAPILinalg
)
-declare_mlir_python_extension(MLIRPythonExtension.Dialects.SMT.Pybind
+declare_mlir_python_extension(MLIRPythonExtension.Dialects.SMT.Nanobind
MODULE_NAME _mlirDialectsSMT
ADD_TO_PARENT MLIRPythonSources.Dialects.smt
ROOT_DIR "${PYTHON_SOURCE_DIR}"
- PYTHON_BINDINGS_LIBRARY nanobind
SOURCES
DialectSMT.cpp
# Headers must be included explicitly so they are installed.
@@ -752,7 +736,6 @@ declare_mlir_python_extension(MLIRPythonExtension.SparseTensorDialectPasses
MODULE_NAME _mlirSparseTensorPasses
ADD_TO_PARENT MLIRPythonSources.Dialects.sparse_tensor
ROOT_DIR "${PYTHON_SOURCE_DIR}"
- PYTHON_BINDINGS_LIBRARY nanobind
SOURCES
SparseTensorPasses.cpp
PRIVATE_LINK_LIBS
@@ -765,7 +748,6 @@ declare_mlir_python_extension(MLIRPythonExtension.TransformInterpreter
MODULE_NAME _mlirTransformInterpreter
ADD_TO_PARENT MLIRPythonSources.Dialects.transform
ROOT_DIR "${PYTHON_SOURCE_DIR}"
- PYTHON_BINDINGS_LIBRARY nanobind
SOURCES
TransformInterpreter.cpp
PRIVATE_LINK_LIBS
@@ -807,23 +789,10 @@ if(MLIR_INCLUDE_TESTS)
ADD_TO_PARENT MLIRPythonTestSources.Dialects.PythonTest
SOURCES "dialects/_python_test_ops_gen.py")
- declare_mlir_python_extension(MLIRPythonTestSources.PythonTestExtensionPybind11
- MODULE_NAME _mlirPythonTestPybind11
- ADD_TO_PARENT MLIRPythonTestSources.Dialects
- ROOT_DIR "${MLIR_SOURCE_DIR}/test/python/lib"
- PYTHON_BINDINGS_LIBRARY pybind11
- SOURCES
- PythonTestModulePybind11.cpp
- PRIVATE_LINK_LIBS
- LLVMSupport
- EMBED_CAPI_LINK_LIBS
- MLIRCAPIPythonTestDialect
- )
declare_mlir_python_extension(MLIRPythonTestSources.PythonTestExtensionNanobind
MODULE_NAME _mlirPythonTestNanobind
ADD_TO_PARENT MLIRPythonTestSources.Dialects
ROOT_DIR "${MLIR_SOURCE_DIR}/test/python/lib"
- PYTHON_BINDINGS_LIBRARY nanobind
SOURCES
PythonTestModuleNanobind.cpp
PRIVATE_LINK_LIBS
diff --git a/mlir/python/mlir/dialects/python_test.py b/mlir/python/mlir/dialects/python_test.py
index 9380896c8c06e..56d3c0f7a5465 100644
--- a/mlir/python/mlir/dialects/python_test.py
+++ b/mlir/python/mlir/dialects/python_test.py
@@ -5,12 +5,7 @@
from ._python_test_ops_gen import *
-def register_python_test_dialect(registry, use_nanobind):
- if use_nanobind:
- from .._mlir_libs import _mlirPythonTestNanobind
+def register_python_test_dialect(registry):
+ from .._mlir_libs import _mlirPythonTestNanobind
- _mlirPythonTestNanobind.register_dialect(registry)
- else:
- from .._mlir_libs import _mlirPythonTestPybind11
-
- _mlirPythonTestPybind11.register_dialect(registry)
+ _mlirPythonTestNanobind.register_dialect(registry)
diff --git a/mlir/python/requirements.txt b/mlir/python/requirements.txt
index abe09259bb1e8..5ff9500e50127 100644
--- a/mlir/python/requirements.txt
+++ b/mlir/python/requirements.txt
@@ -1,6 +1,4 @@
-nanobind>=2.9, <3.0
numpy>=1.19.5, <=2.1.2
-pybind11>=2.10.0, <=2.13.6
PyYAML>=5.4.0, <=6.0.1
ml_dtypes>=0.1.0, <=0.6.0; python_version<"3.13" # provides several NumPy dtype extensions, including the bf16
ml_dtypes>=0.5.0, <=0.6.0; python_version>="3.13"
diff --git a/mlir/test/python/dialects/python_test.py b/mlir/test/python/dialects/python_test.py
index 1194e32c960c8..5a9acc7dcf6bb 100644
--- a/mlir/test/python/dialects/python_test.py
+++ b/mlir/test/python/dialects/python_test.py
@@ -1,5 +1,4 @@
-# RUN: %PYTHON %s pybind11 | FileCheck %s
-# RUN: %PYTHON %s nanobind | FileCheck %s
+# RUN: %PYTHON %s | FileCheck %s
import sys
import typing
from typing import Union, Optional
@@ -10,26 +9,14 @@
import mlir.dialects.tensor as tensor
import mlir.dialects.arith as arith
-if sys.argv[1] == "pybind11":
- from mlir._mlir_libs._mlirPythonTestPybind11 import (
- TestAttr,
- TestType,
- TestTensorValue,
- TestIntegerRankedTensorType,
- )
-
- test.register_python_test_dialect(get_dialect_registry(), use_nanobind=False)
-elif sys.argv[1] == "nanobind":
- from mlir._mlir_libs._mlirPythonTestNanobind import (
- TestAttr,
- TestType,
- TestTensorValue,
- TestIntegerRankedTensorType,
- )
-
- test.register_python_test_dialect(get_dialect_registry(), use_nanobind=True)
-else:
- raise ValueError("Expected pybind11 or nanobind as argument")
+from mlir._mlir_libs._mlirPythonTestNanobind import (
+ TestAttr,
+ TestType,
+ TestTensorValue,
+ TestIntegerRankedTensorType,
+)
+
+test.register_python_test_dialect(get_dialect_registry())
def run(f):
diff --git a/mlir/test/python/lib/CMakeLists.txt b/mlir/test/python/lib/CMakeLists.txt
index 9a813dace2f54..f51a7b44e64dd 100644
--- a/mlir/test/python/lib/CMakeLists.txt
+++ b/mlir/test/python/lib/CMakeLists.txt
@@ -1,7 +1,6 @@
set(LLVM_OPTIONAL_SOURCES
PythonTestCAPI.cpp
PythonTestDialect.cpp
- PythonTestModulePybind11.cpp
PythonTestModuleNanobind.cpp
)
diff --git a/mlir/test/python/lib/PythonTestModulePybind11.cpp b/mlir/test/python/lib/PythonTestModulePybind11.cpp
deleted file mode 100644
index 94a5f5178d16e..0000000000000
--- a/mlir/test/python/lib/PythonTestModulePybind11.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-//===- PythonTestModule.cpp - Python extension for the PythonTest dialect -===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-// This is the pybind11 edition of the PythonTest dialect module.
-//===----------------------------------------------------------------------===//
-
-#include "PythonTestCAPI.h"
-#include "mlir-c/BuiltinAttributes.h"
-#include "mlir-c/BuiltinTypes.h"
-#include "mlir-c/IR.h"
-#include "mlir/Bindings/Python/PybindAdaptors.h"
-
-namespace py = pybind11;
-using namespace mlir::python::adaptors;
-using namespace pybind11::literals;
-
-static bool mlirTypeIsARankedIntegerTensor(MlirType t) {
- return mlirTypeIsARankedTensor(t) &&
- mlirTypeIsAInteger(mlirShapedTypeGetElementType(t));
-}
-
-PYBIND11_MODULE(_mlirPythonTestPybind11, m) {
- m.def(
- "register_python_test_dialect",
- [](MlirContext context, bool load) {
- MlirDialectHandle pythonTestDialect =
- mlirGetDialectHandle__python_test__();
- mlirDialectHandleRegisterDialect(pythonTestDialect, context);
- if (load) {
- mlirDialectHandleLoadDialect(pythonTestDialect, context);
- }
- },
- py::arg("context"), py::arg("load") = true);
-
- m.def(
- "register_dialect",
- [](MlirDialectRegistry registry) {
- MlirDialectHandle pythonTestDialect =
- mlirGetDialectHandle__python_test__();
- mlirDialectHandleInsertDialect(pythonTestDialect, registry);
- },
- py::arg("registry"));
-
- mlir_attribute_subclass(m, "TestAttr",
- mlirAttributeIsAPythonTestTestAttribute,
- mlirPythonTestTestAttributeGetTypeID)
- .def_classmethod(
- "get",
- [](const py::object &cls, MlirContext ctx) {
- return cls(mlirPythonTestTestAttributeGet(ctx));
- },
- py::arg("cls"), py::arg("context") = py::none());
-
- mlir_type_subclass(m, "TestType", mlirTypeIsAPythonTestTestType,
- mlirPythonTestTestTypeGetTypeID)
- .def_classmethod(
- "get",
- [](const py::object &cls, MlirContext ctx) {
- return cls(mlirPythonTestTestTypeGet(ctx));
- },
- py::arg("cls"), py::arg("context") = py::none());
-
- auto typeCls =
- mlir_type_subclass(m, "TestIntegerRankedTensorType",
- mlirTypeIsARankedIntegerTensor,
- py::module::import(MAKE_MLIR_PYTHON_QUALNAME("ir"))
- .attr("RankedTensorType"))
- .def_classmethod(
- "get",
- [](const py::object &cls, std::vector<int64_t> shape,
- unsigned width, MlirContext ctx) {
- MlirAttribute encoding = mlirAttributeGetNull();
- return cls(mlirRankedTensorTypeGet(
- shape.size(), shape.data(), mlirIntegerTypeGet(ctx, width),
- encoding));
- },
- "cls"_a, "shape"_a, "width"_a, "context"_a = py::none());
-
- assert(py::hasattr(typeCls.get_class(), "static_typeid") &&
- "TestIntegerRankedTensorType has no static_typeid");
-
- MlirTypeID mlirRankedTensorTypeID = mlirRankedTensorTypeGetTypeID();
-
- py::module::import(MAKE_MLIR_PYTHON_QUALNAME("ir"))
- .attr(MLIR_PYTHON_CAPI_TYPE_CASTER_REGISTER_ATTR)(mlirRankedTensorTypeID,
- "replace"_a = true)(
- pybind11::cpp_function([typeCls](const py::object &mlirType) {
- return typeCls.get_class()(mlirType);
- }));
-
- auto valueCls = mlir_value_subclass(m, "TestTensorValue",
- mlirTypeIsAPythonTestTestTensorValue)
- .def("is_null", [](MlirValue &self) {
- return mlirValueIsNull(self);
- });
-
- py::module::import(MAKE_MLIR_PYTHON_QUALNAME("ir"))
- .attr(MLIR_PYTHON_CAPI_VALUE_CASTER_REGISTER_ATTR)(
- mlirRankedTensorTypeID)(
- pybind11::cpp_function([valueCls](const py::object &valueObj) {
- py::object capsule = mlirApiObjectToCapsule(valueObj);
- MlirValue v = mlirPythonCapsuleToValue(capsule.ptr());
- MlirType t = mlirValueGetType(v);
- // This is hyper-specific in order to exercise/test registering a
- // value caster from cpp (but only for a single test case; see
- // testTensorValue python_test.py).
- if (mlirShapedTypeHasStaticShape(t) &&
- mlirShapedTypeGetDimSize(t, 0) == 1 &&
- mlirShapedTypeGetDimSize(t, 1) == 2 &&
- mlirShapedTypeGetDimSize(t, 2) == 3)
- return valueCls.get_class()(valueObj);
- return valueObj;
- }));
-}
More information about the Mlir-commits
mailing list