Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions .ci/all_requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,9 @@ ml-dtypes==0.5.1 ; python_version < "3.13" \
--hash=sha256:d13755f8e8445b3870114e5b6240facaa7cb0c3361e54beba3e07fa912a6e12b \
--hash=sha256:fd918d4e6a4e0c110e2e05be7a7814d10dc1b95872accbf6512b80a109b71ae1
# via -r mlir/python/requirements.txt
nanobind==2.7.0 \
--hash=sha256:73b12d0e751d140d6c1bf4b215e18818a8debfdb374f08dc3776ad208d808e74 \
--hash=sha256:f9f1b160580c50dcf37b6495a0fd5ec61dc0d95dae5f8004f87dd9ad7eb46b34
nanobind==2.9.2 \
--hash=sha256:c37957ffd5eac7eda349cff3622ecd32e5ee1244ecc912c99b5bc8188bafd16e \
--hash=sha256:e7608472de99d375759814cab3e2c94aba3f9ec80e62cfef8ced495ca5c27d6e
# via -r mlir/python/requirements.txt
numpy==2.0.2 \
--hash=sha256:0123ffdaa88fa4ab64835dcbde75dcdf89c453c922f18dced6e27c90d1d0ec5a \
Expand Down Expand Up @@ -383,6 +383,10 @@ swig==4.3.1 \
--hash=sha256:efec16327029f682f649a26da726bb0305be8800bd0f1fa3e81bf0769cf5b476 \
--hash=sha256:fc496c0d600cf1bb2d91e28d3d6eae9c4301e5ea7a0dec5a4281b5efed4245a8
# via -r lldb/test/requirements.txt
typing-extensions==4.15.0 \
--hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \
--hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548
# via -r mlir/python/requirements.txt
urllib3==2.5.0 \
--hash=sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760 \
--hash=sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc
Expand Down
121 changes: 103 additions & 18 deletions mlir/cmake/modules/AddMLIRPython.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,89 @@ function(declare_mlir_python_sources name)
endif()
endfunction()

# Function: mlir_generate_type_stubs
# Turns on automatic type stub generation for extension modules.
# Specifically, performs add_custom_command to run nanobind's stubgen on an extension module.
#
# Arguments:
# MODULE_NAME: The fully-qualified name of the extension module (used for importing in python).
# DEPENDS_TARGETS: List of targets these type stubs depend on being built; usually corresponding to the
# specific extension module (e.g., something like StandalonePythonModules.extension._standaloneDialectsNanobind.dso)
# and the core bindings extension module (e.g., something like StandalonePythonModules.extension._mlir.dso).
# OUTPUT_DIR: The root output directory to emit the type stubs into.
# OUTPUTS: List of expected outputs.
# DEPENDS_TARGET_SRC_DEPS: List of cpp sources for extension library (for generating a DEPFILE).
# IMPORT_PATHS: List of paths to add to PYTHONPATH for stubgen.
# PATTERN_FILE: (Optional) Pattern file (see https://nanobind.readthedocs.io/en/latest/typing.html#pattern-files).
# Outputs:
# NB_STUBGEN_CUSTOM_TARGET: The target corresponding to generation which other targets can depend on.
function(mlir_generate_type_stubs)
cmake_parse_arguments(ARG
""
"MODULE_NAME;OUTPUT_DIR;PATTERN_FILE"
"IMPORT_PATHS;DEPENDS_TARGETS;OUTPUTS;DEPENDS_TARGET_SRC_DEPS"
${ARGN})

# for people doing find_package(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
elseif(EXISTS ${nanobind_SOURCE_DIR}/src/stubgen.py)
set(NB_STUBGEN "${nanobind_SOURCE_DIR}/src/stubgen.py")
elseif(EXISTS ${nanobind_SOURCE_DIR}/stubgen.py)
set(NB_STUBGEN "${nanobind_SOURCE_DIR}/stubgen.py")
else()
message(FATAL_ERROR "mlir_generate_type_stubs(): could not locate 'stubgen.py'!")
endif()

file(REAL_PATH "${NB_STUBGEN}" NB_STUBGEN)
set(_import_paths)
foreach(_import_path IN LISTS ARG_IMPORT_PATHS)
file(REAL_PATH "${_import_path}" _import_path)
list(APPEND _import_paths "-i;${_import_path}")
endforeach()
set(_nb_stubgen_cmd
"${Python_EXECUTABLE}"
"${NB_STUBGEN}"
--module
"${ARG_MODULE_NAME}"
"${_import_paths}"
--recursive
--include-private
--output-dir
"${ARG_OUTPUT_DIR}")
if(ARG_PATTERN_FILE)
list(APPEND _nb_stubgen_cmd "-p;${ARG_PATTERN_FILE}")
list(APPEND ARG_DEPENDS_TARGETS "${ARG_PATTERN_FILE}")
endif()

list(TRANSFORM ARG_OUTPUTS PREPEND "${ARG_OUTPUT_DIR}/" OUTPUT_VARIABLE _generated_type_stubs)
set(_depfile "${ARG_OUTPUT_DIR}/${ARG_MODULE_NAME}.d")
if ((NOT EXISTS ${_depfile}) AND ARG_DEPENDS_TARGET_SRC_DEPS)
list(JOIN ARG_DEPENDS_TARGET_SRC_DEPS " " _depfiles)
list(TRANSFORM _generated_type_stubs APPEND ": ${_depfiles}" OUTPUT_VARIABLE _depfiles)
list(JOIN _depfiles "\n" _depfiles)
file(GENERATE OUTPUT "${_depfile}" CONTENT "${_depfiles}")
endif()

message(DEBUG "Generating type-stubs outputs ${_generated_type_stubs}")
add_custom_command(
OUTPUT ${_generated_type_stubs}
COMMAND ${_nb_stubgen_cmd}
WORKING_DIRECTORY "${CMAKE_CURRENT_FUNCTION_LIST_DIR}"
DEPENDS "${ARG_DEPENDS_TARGETS}"
DEPFILE "${_depfile}"
COMMENT "Generating type stubs using: ${_nb_stubgen_cmd}"
)

list(JOIN ARG_DEPENDS_TARGETS "." _name)
set(_name "${_name}.${ARG_MODULE_NAME}.type_stubs")
add_custom_target("${_name}" DEPENDS ${_generated_type_stubs})
set(NB_STUBGEN_CUSTOM_TARGET "${_name}" PARENT_SCOPE)
endfunction()

# Function: declare_mlir_python_extension
# Declares a buildable python extension from C++ source files. The built
# module is considered a python source file and included as everything else.
Expand Down Expand Up @@ -678,26 +761,28 @@ function(add_mlir_python_extension libname extname)
# 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-nested-anon-types
-Wno-unused-parameter
-Wno-zero-length-array
${eh_rtti_enable})
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-nested-anon-types
-Wno-unused-parameter
-Wno-zero-length-array
${eh_rtti_enable})
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)
Expand Down
2 changes: 1 addition & 1 deletion mlir/cmake/modules/MLIRDetectPythonEnv.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ macro(mlir_configure_python_dev_packages)
"extension = '${PYTHON_MODULE_EXTENSION}")

mlir_detect_nanobind_install()
find_package(nanobind 2.4 CONFIG REQUIRED)
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}', "
Expand Down
13 changes: 11 additions & 2 deletions mlir/examples/standalone/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ set(CMAKE_BUILD_WITH_INSTALL_NAME_DIR ON)
set(CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard to conform to")

if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(EXTERNAL_PROJECT_BUILD FALSE)
find_package(MLIR REQUIRED CONFIG)


# Define the default argument to use by `lit` when testing.
set(LLVM_LIT_ARGS "-sv" CACHE STRING "Default options for lit")

Expand All @@ -27,11 +27,19 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
include(AddMLIR)
include(HandleLLVMOptions)
else()
set(EXTERNAL_PROJECT_BUILD TRUE)
# Build via external projects mechanism
set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/bin)
set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/tools/Standalone/lib)

set(MLIR_BINARY_DIR ${CMAKE_BINARY_DIR})
set(MLIR_MAIN_SRC_DIR ${LLVM_MAIN_SRC_DIR}/../mlir)
set(MLIR_INCLUDE_DIR ${MLIR_MAIN_SRC_DIR}/include)
set(MLIR_GENERATED_INCLUDE_DIR ${LLVM_BINARY_DIR}/tools/mlir/include)
set(MLIR_INCLUDE_DIRS "${MLIR_INCLUDE_DIR};${MLIR_GENERATED_INCLUDE_DIR}")

list(APPEND CMAKE_MODULE_PATH "${MLIR_MAIN_SRC_DIR}/cmake/modules")
list(APPEND CMAKE_MODULE_PATH "${LLVM_MAIN_SRC_DIR}/cmake/modules")
endif()

if(MLIR_ENABLE_BINDINGS_PYTHON)
Expand All @@ -54,8 +62,9 @@ if(MLIR_ENABLE_BINDINGS_PYTHON)
message(STATUS "Enabling Python API")
include(MLIRDetectPythonEnv)
mlir_configure_python_dev_packages()
# Note: for EXTERNAL_PROJECT_BUILD this must be set from the command line.
set(MLIR_PYTHON_PACKAGE_PREFIX "mlir_standalone" CACHE STRING "" FORCE)
set(MLIR_BINDINGS_PYTHON_INSTALL_PREFIX "python_packages/standalone/mlir_standalone" CACHE STRING "" FORCE)
set(MLIR_BINDINGS_PYTHON_INSTALL_PREFIX "python_packages/standalone/${MLIR_PYTHON_PACKAGE_PREFIX}" CACHE STRING "" FORCE)
add_subdirectory(python)
endif()
add_subdirectory(test)
Expand Down
88 changes: 79 additions & 9 deletions mlir/examples/standalone/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ declare_mlir_dialect_python_bindings(
SOURCES
dialects/standalone_pybind11.py
dialects/standalone_nanobind.py
_mlir_libs/_standaloneDialectsNanobind/py.typed
DIALECT_NAME standalone)


Expand Down Expand Up @@ -68,16 +69,85 @@ add_mlir_python_common_capi_library(StandalonePythonCAPI
# Instantiation of all Python modules
################################################################################

set(StandalonePythonModules_ROOT_PREFIX "${MLIR_BINARY_DIR}/${MLIR_BINDINGS_PYTHON_INSTALL_PREFIX}")

# Everything here is very tightly coupled. See the ample descriptions at the bottom of
# mlir/python/CMakeLists.txt.

# For a non-external projects build (e.g., installed distro) the type gen targets for the core _mlir module
# need to be re-declared. On the contrary, for an external projects build, the MLIRPythonExtension.Core.type_stub_gen
# target already exists and can just be added to DECLARED_SOURCES (see below).
if(NOT EXTERNAL_PROJECT_BUILD)
set(_core_type_stub_sources
_mlir/__init__.pyi
_mlir/ir.pyi
_mlir/passmanager.pyi
_mlir/rewrite.pyi
)
get_target_property(_core_extension_srcs MLIRPythonExtension.Core INTERFACE_SOURCES)
mlir_generate_type_stubs(
MODULE_NAME _mlir
DEPENDS_TARGETS StandalonePythonModules.extension._mlir.dso
OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/type_stubs/_mlir_libs"
OUTPUTS "${_core_type_stub_sources}"
DEPENDS_TARGET_SRC_DEPS "${_core_extension_srcs}"
IMPORT_PATHS "${StandalonePythonModules_ROOT_PREFIX}/_mlir_libs"
)
set(_mlir_typestub_gen_target "${NB_STUBGEN_CUSTOM_TARGET}")

list(TRANSFORM _core_type_stub_sources PREPEND "_mlir_libs/")
declare_mlir_python_sources(
StandalonePythonExtension.Core.type_stub_gen
ROOT_DIR "${CMAKE_CURRENT_BINARY_DIR}/type_stubs"
ADD_TO_PARENT StandalonePythonSources
SOURCES "${_core_type_stub_sources}"
)
endif()

get_target_property(_standalone_extension_srcs StandalonePythonSources.NanobindExtension INTERFACE_SOURCES)
mlir_generate_type_stubs(
MODULE_NAME mlir_standalone._mlir_libs._standaloneDialectsNanobind
DEPENDS_TARGETS
StandalonePythonModules.extension._mlir.dso
StandalonePythonModules.extension._standaloneDialectsNanobind.dso
OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/type_stubs/_mlir_libs"
OUTPUTS
_standaloneDialectsNanobind/__init__.pyi
_standaloneDialectsNanobind/standalone.pyi
DEPENDS_TARGET_SRC_DEPS "${_standalone_extension_srcs}"
IMPORT_PATHS "${StandalonePythonModules_ROOT_PREFIX}/.."
)
set(_standaloneDialectsNanobind_typestub_gen_target "${NB_STUBGEN_CUSTOM_TARGET}")

declare_mlir_python_sources(
StandalonePythonSources.type_stub_gen
ROOT_DIR "${CMAKE_CURRENT_BINARY_DIR}/type_stubs"
ADD_TO_PARENT StandalonePythonSources
SOURCES
_mlir_libs/_standaloneDialectsNanobind/__init__.pyi
_mlir_libs/_standaloneDialectsNanobind/standalone.pyi
)
set(_declared_sources
StandalonePythonSources
# TODO: Remove this in favor of showing fine grained registration once
# available.
MLIRPythonExtension.RegisterEverything
MLIRPythonSources.Core
MLIRPythonSources.Dialects.builtin
)
# For an external projects build, the MLIRPythonExtension.Core.type_stub_gen
# target already exists and can just be added to DECLARED_SOURCES.
if(EXTERNAL_PROJECT_BUILD)
list(APPEND _declared_sources MLIRPythonExtension.Core.type_stub_gen)
endif()
add_mlir_python_modules(StandalonePythonModules
ROOT_PREFIX "${MLIR_BINARY_DIR}/${MLIR_BINDINGS_PYTHON_INSTALL_PREFIX}"
ROOT_PREFIX "${StandalonePythonModules_ROOT_PREFIX}"
INSTALL_PREFIX "${MLIR_BINDINGS_PYTHON_INSTALL_PREFIX}"
DECLARED_SOURCES
StandalonePythonSources
# TODO: Remove this in favor of showing fine grained registration once
# available.
MLIRPythonExtension.RegisterEverything
MLIRPythonSources.Core
MLIRPythonSources.Dialects.builtin
DECLARED_SOURCES "${_declared_sources}"
COMMON_CAPI_LINK_LIBS
StandalonePythonCAPI
)
)
if(NOT EXTERNAL_PROJECT_BUILD)
add_dependencies(StandalonePythonModules "${_mlir_typestub_gen_target}")
endif()
add_dependencies(StandalonePythonModules "${_standaloneDialectsNanobind_typestub_gen_target}")
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,9 @@ NB_MODULE(_standaloneDialectsNanobind, m) {
mlirDialectHandleLoadDialect(handle, context);
}
},
nb::arg("context").none() = nb::none(), nb::arg("load") = true);
nb::arg("context").none() = nb::none(), nb::arg("load") = true,
// clang-format off
nb::sig("def register_dialect(context: " MAKE_MLIR_PYTHON_QUALNAME("ir.Context") ", load: bool = True) -> None")
// clang-format on
);
}
28 changes: 20 additions & 8 deletions mlir/include/mlir/Bindings/Python/NanobindAdaptors.h
Original file line number Diff line number Diff line change
Expand Up @@ -512,8 +512,13 @@ class mlir_attribute_subclass : public pure_subclass {
.attr("replace")(superCls.attr("__name__"), captureTypeName);
});
if (getTypeIDFunction) {
def_staticmethod("get_static_typeid",
[getTypeIDFunction]() { return getTypeIDFunction(); });
def_staticmethod(
"get_static_typeid",
[getTypeIDFunction]() { return getTypeIDFunction(); },
// clang-format off
nanobind::sig("def get_static_typeid() -> " MAKE_MLIR_PYTHON_QUALNAME("ir.TypeID"))
// clang-format on
);
nanobind::module_::import_(MAKE_MLIR_PYTHON_QUALNAME("ir"))
.attr(MLIR_PYTHON_CAPI_TYPE_CASTER_REGISTER_ATTR)(
getTypeIDFunction())(nanobind::cpp_function(
Expand Down Expand Up @@ -582,8 +587,9 @@ class mlir_type_subclass : public pure_subclass {

// 'isinstance' method.
static const char kIsinstanceSig[] =
"def isinstance(other_type: " MAKE_MLIR_PYTHON_QUALNAME(
"ir") ".Type) -> bool";
// clang-format off
"def isinstance(other_type: " MAKE_MLIR_PYTHON_QUALNAME("ir.Type") ") -> bool";
// clang-format on
def_staticmethod(
"isinstance",
[isaFunction](MlirType other) { return isaFunction(other); },
Expand All @@ -599,8 +605,13 @@ class mlir_type_subclass : public pure_subclass {
// `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(); });
def_staticmethod(
"get_static_typeid",
[getTypeIDFunction]() { return getTypeIDFunction(); },
// clang-format off
nanobind::sig("def get_static_typeid() -> " MAKE_MLIR_PYTHON_QUALNAME("ir.TypeID"))
// clang-format on
);
nanobind::module_::import_(MAKE_MLIR_PYTHON_QUALNAME("ir"))
.attr(MLIR_PYTHON_CAPI_TYPE_CASTER_REGISTER_ATTR)(
getTypeIDFunction())(nanobind::cpp_function(
Expand Down Expand Up @@ -665,8 +676,9 @@ class mlir_value_subclass : public pure_subclass {

// 'isinstance' method.
static const char kIsinstanceSig[] =
"def isinstance(other_value: " MAKE_MLIR_PYTHON_QUALNAME(
"ir") ".Value) -> bool";
// clang-format off
"def isinstance(other_value: " MAKE_MLIR_PYTHON_QUALNAME("ir.Value") ") -> bool";
// clang-format on
def_staticmethod(
"isinstance",
[isaFunction](MlirValue other) { return isaFunction(other); },
Expand Down
2 changes: 2 additions & 0 deletions mlir/lib/Bindings/Python/DialectPDL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ static void populateDialectPDLSubmodule(const nanobind::module_ &m) {
rangeType.def_property_readonly(
"element_type",
[](MlirType type) { return mlirPDLRangeTypeGetElementType(type); },
nb::sig(
"def element_type(self) -> " MAKE_MLIR_PYTHON_QUALNAME("ir.Type")),
"Get the element type.");

//===-------------------------------------------------------------------===//
Expand Down
Loading