Skip to content

Commit 1fe31d0

Browse files
maksleventaljpienaar
authored andcommitted
Automerge: [MLIR][Python] use FetchContent_Declare for nanobind and remove pybind (#161230)
Inspired by this comment llvm/llvm-project#157930 (comment) (and long-standing issues related to finding nanobind/pybind in the right place), this PR moves to using `FetchContent_Declare` to get the nanobind dependency. This is pretty standard (see e.g., [IREE](https://github.com/iree-org/iree/blob/cf60359b7443b0e92e15fb6ffc011525dc40e772/CMakeLists.txt#L842-L848)). This PR also removes pybind which has been deprecated for almost a year (llvm/llvm-project#117922) and which isn't compatible (for whatever reason) with `FetchContent_Declare`. --------- Co-authored-by: Jacques Pienaar <[email protected]>
2 parents b01dea7 + 84a2148 commit 1fe31d0

File tree

18 files changed

+121
-1082
lines changed

18 files changed

+121
-1082
lines changed

.ci/all_requirements.txt

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -194,10 +194,6 @@ ml-dtypes==0.5.1 ; python_version < "3.13" \
194194
--hash=sha256:d13755f8e8445b3870114e5b6240facaa7cb0c3361e54beba3e07fa912a6e12b \
195195
--hash=sha256:fd918d4e6a4e0c110e2e05be7a7814d10dc1b95872accbf6512b80a109b71ae1
196196
# via -r mlir/python/requirements.txt
197-
nanobind==2.9.2 \
198-
--hash=sha256:c37957ffd5eac7eda349cff3622ecd32e5ee1244ecc912c99b5bc8188bafd16e \
199-
--hash=sha256:e7608472de99d375759814cab3e2c94aba3f9ec80e62cfef8ced495ca5c27d6e
200-
# via -r mlir/python/requirements.txt
201197
numpy==2.0.2 \
202198
--hash=sha256:0123ffdaa88fa4ab64835dcbde75dcdf89c453c922f18dced6e27c90d1d0ec5a \
203199
--hash=sha256:11a76c372d1d37437857280aa142086476136a8c0f373b2e648ab2c8f18fb195 \
@@ -299,10 +295,6 @@ pyasn1-modules==0.4.2 \
299295
--hash=sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a \
300296
--hash=sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6
301297
# via google-auth
302-
pybind11==2.13.6 \
303-
--hash=sha256:237c41e29157b962835d356b370ededd57594a26d5894a795960f0047cb5caf5 \
304-
--hash=sha256:ba6af10348c12b24e92fa086b39cfba0eff619b61ac77c406167d813b096d39a
305-
# via -r mlir/python/requirements.txt
306298
pyyaml==6.0.1 \
307299
--hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \
308300
--hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \

mlir/cmake/modules/AddMLIRPython.cmake

Lines changed: 55 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,12 @@ function(mlir_generate_type_stubs)
123123
"IMPORT_PATHS;DEPENDS_TARGETS;OUTPUTS;DEPENDS_TARGET_SRC_DEPS"
124124
${ARGN})
125125

126-
# for people doing find_package(nanobind)
126+
# for people installing a distro (e.g., pip install) of nanobind
127127
if(EXISTS ${nanobind_DIR}/../src/stubgen.py)
128128
set(NB_STUBGEN "${nanobind_DIR}/../src/stubgen.py")
129129
elseif(EXISTS ${nanobind_DIR}/../stubgen.py)
130130
set(NB_STUBGEN "${nanobind_DIR}/../stubgen.py")
131-
# for people using FetchContent_Declare and FetchContent_MakeAvailable
131+
# for people using nanobind git source tree (e.g., FetchContent_Declare and FetchContent_MakeAvailable)
132132
elseif(EXISTS ${nanobind_SOURCE_DIR}/src/stubgen.py)
133133
set(NB_STUBGEN "${nanobind_SOURCE_DIR}/src/stubgen.py")
134134
elseif(EXISTS ${nanobind_SOURCE_DIR}/stubgen.py)
@@ -226,11 +226,10 @@ endfunction()
226226
# EMBED_CAPI_LINK_LIBS: Dependent CAPI libraries that this extension depends
227227
# on. These will be collected for all extensions and put into an
228228
# aggregate dylib that is linked against.
229-
# PYTHON_BINDINGS_LIBRARY: Either pybind11 or nanobind.
230229
function(declare_mlir_python_extension name)
231230
cmake_parse_arguments(ARG
232231
""
233-
"ROOT_DIR;MODULE_NAME;ADD_TO_PARENT;PYTHON_BINDINGS_LIBRARY"
232+
"ROOT_DIR;MODULE_NAME;ADD_TO_PARENT"
234233
"SOURCES;PRIVATE_LINK_LIBS;EMBED_CAPI_LINK_LIBS"
235234
${ARGN})
236235

@@ -239,20 +238,15 @@ function(declare_mlir_python_extension name)
239238
endif()
240239
set(_install_destination "src/python/${name}")
241240

242-
if(NOT ARG_PYTHON_BINDINGS_LIBRARY)
243-
set(ARG_PYTHON_BINDINGS_LIBRARY "pybind11")
244-
endif()
245-
246241
add_library(${name} INTERFACE)
247242
set_target_properties(${name} PROPERTIES
248243
# Yes: Leading-lowercase property names are load bearing and the recommended
249244
# way to do this: https://gitlab.kitware.com/cmake/cmake/-/issues/19261
250-
EXPORT_PROPERTIES "mlir_python_SOURCES_TYPE;mlir_python_EXTENSION_MODULE_NAME;mlir_python_EMBED_CAPI_LINK_LIBS;mlir_python_DEPENDS;mlir_python_BINDINGS_LIBRARY"
245+
EXPORT_PROPERTIES "mlir_python_SOURCES_TYPE;mlir_python_EXTENSION_MODULE_NAME;mlir_python_EMBED_CAPI_LINK_LIBS;mlir_python_DEPENDS"
251246
mlir_python_SOURCES_TYPE extension
252247
mlir_python_EXTENSION_MODULE_NAME "${ARG_MODULE_NAME}"
253248
mlir_python_EMBED_CAPI_LINK_LIBS "${ARG_EMBED_CAPI_LINK_LIBS}"
254249
mlir_python_DEPENDS ""
255-
mlir_python_BINDINGS_LIBRARY "${ARG_PYTHON_BINDINGS_LIBRARY}"
256250
)
257251

258252
# Set the interface source and link_libs properties of the target
@@ -341,14 +335,12 @@ function(add_mlir_python_modules name)
341335
elseif(_source_type STREQUAL "extension")
342336
# Native CPP extension.
343337
get_target_property(_module_name ${sources_target} mlir_python_EXTENSION_MODULE_NAME)
344-
get_target_property(_bindings_library ${sources_target} mlir_python_BINDINGS_LIBRARY)
345338
# Transform relative source to based on root dir.
346339
set(_extension_target "${modules_target}.extension.${_module_name}.dso")
347340
add_mlir_python_extension(${_extension_target} "${_module_name}"
348341
INSTALL_COMPONENT ${modules_target}
349342
INSTALL_DIR "${ARG_INSTALL_PREFIX}/_mlir_libs"
350343
OUTPUT_DIRECTORY "${ARG_ROOT_PREFIX}/_mlir_libs"
351-
PYTHON_BINDINGS_LIBRARY ${_bindings_library}
352344
LINK_LIBS PRIVATE
353345
${sources_target}
354346
${ARG_COMMON_CAPI_LINK_LIBS}
@@ -753,78 +745,69 @@ endfunction()
753745
function(add_mlir_python_extension libname extname)
754746
cmake_parse_arguments(ARG
755747
""
756-
"INSTALL_COMPONENT;INSTALL_DIR;OUTPUT_DIRECTORY;PYTHON_BINDINGS_LIBRARY"
748+
"INSTALL_COMPONENT;INSTALL_DIR;OUTPUT_DIRECTORY"
757749
"SOURCES;LINK_LIBS"
758750
${ARGN})
759751
if(ARG_UNPARSED_ARGUMENTS)
760752
message(FATAL_ERROR "Unhandled arguments to add_mlir_python_extension(${libname}, ... : ${ARG_UNPARSED_ARGUMENTS}")
761753
endif()
762754

763755
# The extension itself must be compiled with RTTI and exceptions enabled.
764-
# Also, some warning classes triggered by pybind11 are disabled.
756+
# Also, some warning classes triggered by nanobind are disabled.
765757
set(eh_rtti_enable)
766758
if (MSVC)
767759
set(eh_rtti_enable /EHsc /GR)
768760
elseif(LLVM_COMPILER_IS_GCC_COMPATIBLE OR CLANG_CL)
769761
set(eh_rtti_enable -frtti -fexceptions)
770762
endif ()
771763

772-
# The actual extension library produces a shared-object or DLL and has
773-
# sources that must be compiled in accordance with pybind11 needs (RTTI and
774-
# exceptions).
775-
if(NOT DEFINED ARG_PYTHON_BINDINGS_LIBRARY OR ARG_PYTHON_BINDINGS_LIBRARY STREQUAL "pybind11")
776-
pybind11_add_module(${libname}
777-
${ARG_SOURCES}
778-
)
779-
elseif(ARG_PYTHON_BINDINGS_LIBRARY STREQUAL "nanobind")
780-
nanobind_add_module(${libname}
781-
NB_DOMAIN ${MLIR_BINDINGS_PYTHON_NB_DOMAIN}
782-
FREE_THREADED
783-
${ARG_SOURCES}
784-
)
764+
nanobind_add_module(${libname}
765+
NB_DOMAIN ${MLIR_BINDINGS_PYTHON_NB_DOMAIN}
766+
FREE_THREADED
767+
${ARG_SOURCES}
768+
)
785769

786-
if (NOT MLIR_DISABLE_CONFIGURE_PYTHON_DEV_PACKAGES
787-
AND (LLVM_COMPILER_IS_GCC_COMPATIBLE OR CLANG_CL))
788-
# Avoid some warnings from upstream nanobind.
789-
# If a superproject set MLIR_DISABLE_CONFIGURE_PYTHON_DEV_PACKAGES, let
790-
# the super project handle compile options as it wishes.
791-
get_property(NB_LIBRARY_TARGET_NAME TARGET ${libname} PROPERTY LINK_LIBRARIES)
792-
target_compile_options(${NB_LIBRARY_TARGET_NAME}
793-
PRIVATE
794-
-Wall -Wextra -Wpedantic
795-
-Wno-c++98-compat-extra-semi
796-
-Wno-cast-qual
797-
-Wno-covered-switch-default
798-
-Wno-deprecated-literal-operator
799-
-Wno-nested-anon-types
800-
-Wno-unused-parameter
801-
-Wno-zero-length-array
802-
${eh_rtti_enable})
803-
804-
target_compile_options(${libname}
805-
PRIVATE
806-
-Wall -Wextra -Wpedantic
807-
-Wno-c++98-compat-extra-semi
808-
-Wno-cast-qual
809-
-Wno-covered-switch-default
810-
-Wno-deprecated-literal-operator
811-
-Wno-nested-anon-types
812-
-Wno-unused-parameter
813-
-Wno-zero-length-array
814-
${eh_rtti_enable})
815-
endif()
770+
if (NOT MLIR_DISABLE_CONFIGURE_PYTHON_DEV_PACKAGES
771+
AND (LLVM_COMPILER_IS_GCC_COMPATIBLE OR CLANG_CL))
772+
# Avoid some warnings from upstream nanobind.
773+
# If a superproject set MLIR_DISABLE_CONFIGURE_PYTHON_DEV_PACKAGES, let
774+
# the super project handle compile options as it wishes.
775+
get_property(NB_LIBRARY_TARGET_NAME TARGET ${libname} PROPERTY LINK_LIBRARIES)
776+
target_compile_options(${NB_LIBRARY_TARGET_NAME}
777+
PRIVATE
778+
-Wall -Wextra -Wpedantic
779+
-Wno-c++98-compat-extra-semi
780+
-Wno-cast-qual
781+
-Wno-covered-switch-default
782+
-Wno-deprecated-literal-operator
783+
-Wno-nested-anon-types
784+
-Wno-unused-parameter
785+
-Wno-zero-length-array
786+
${eh_rtti_enable})
787+
788+
target_compile_options(${libname}
789+
PRIVATE
790+
-Wall -Wextra -Wpedantic
791+
-Wno-c++98-compat-extra-semi
792+
-Wno-cast-qual
793+
-Wno-covered-switch-default
794+
-Wno-deprecated-literal-operator
795+
-Wno-nested-anon-types
796+
-Wno-unused-parameter
797+
-Wno-zero-length-array
798+
${eh_rtti_enable})
799+
endif()
816800

817-
if(APPLE)
818-
# NanobindAdaptors.h uses PyClassMethod_New to build `pure_subclass`es but nanobind
819-
# doesn't declare this API as undefined in its linker flags. So we need to declare it as such
820-
# for downstream users that do not do something like `-undefined dynamic_lookup`.
821-
# Same for the rest.
822-
target_link_options(${libname} PUBLIC
823-
"LINKER:-U,_PyClassMethod_New"
824-
"LINKER:-U,_PyCode_Addr2Location"
825-
"LINKER:-U,_PyFrame_GetLasti"
826-
)
827-
endif()
801+
if(APPLE)
802+
# NanobindAdaptors.h uses PyClassMethod_New to build `pure_subclass`es but nanobind
803+
# doesn't declare this API as undefined in its linker flags. So we need to declare it as such
804+
# for downstream users that do not do something like `-undefined dynamic_lookup`.
805+
# Same for the rest.
806+
target_link_options(${libname} PUBLIC
807+
"LINKER:-U,_PyClassMethod_New"
808+
"LINKER:-U,_PyCode_Addr2Location"
809+
"LINKER:-U,_PyFrame_GetLasti"
810+
)
828811
endif()
829812

830813
target_compile_options(${libname} PRIVATE ${eh_rtti_enable})
@@ -862,11 +845,11 @@ function(add_mlir_python_extension libname extname)
862845
if(WIN32)
863846
# On Windows, pyconfig.h (and by extension python.h) hardcode the version of the
864847
# python library which will be used for linkage depending on the flavor of the build.
865-
# pybind11 has a workaround which depends on the definition of Py_DEBUG (if Py_DEBUG
866-
# is not passed in as a compile definition, pybind11 undefs _DEBUG when including
848+
# nanobind has a workaround which depends on the definition of Py_DEBUG (if Py_DEBUG
849+
# is not passed in as a compile definition, nanobind undefs _DEBUG when including
867850
# python.h, so that the release python library would be used).
868-
# Since mlir uses pybind11, we can leverage their workaround by never directly
869-
# pyconfig.h or python.h and instead relying on the pybind11 headers to include the
851+
# Since mlir uses nanobind, we can leverage their workaround by never directly
852+
# pyconfig.h or python.h and instead relying on the nanobind headers to include the
870853
# necessary python headers. This results in mlir always linking against the
871854
# release python library via the (undocumented) cmake property Python3_LIBRARY_RELEASE.
872855
target_link_libraries(${libname} PRIVATE ${Python3_LIBRARY_RELEASE})

mlir/cmake/modules/MLIRDetectPythonEnv.cmake

Lines changed: 15 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -46,81 +46,20 @@ macro(mlir_configure_python_dev_packages)
4646
message(STATUS "Found python include dirs: ${Python3_INCLUDE_DIRS}")
4747
message(STATUS "Found python libraries: ${Python3_LIBRARIES}")
4848
message(STATUS "Found numpy v${Python3_NumPy_VERSION}: ${Python3_NumPy_INCLUDE_DIRS}")
49-
mlir_detect_pybind11_install()
50-
find_package(pybind11 2.10 CONFIG REQUIRED)
51-
message(STATUS "Found pybind11 v${pybind11_VERSION}: ${pybind11_INCLUDE_DIR}")
52-
message(STATUS "Python prefix = '${PYTHON_MODULE_PREFIX}', "
53-
"suffix = '${PYTHON_MODULE_SUFFIX}', "
54-
"extension = '${PYTHON_MODULE_EXTENSION}")
55-
56-
mlir_detect_nanobind_install()
57-
find_package(nanobind 2.9 CONFIG REQUIRED)
58-
message(STATUS "Found nanobind v${nanobind_VERSION}: ${nanobind_INCLUDE_DIR}")
59-
message(STATUS "Python prefix = '${PYTHON_MODULE_PREFIX}', "
60-
"suffix = '${PYTHON_MODULE_SUFFIX}', "
61-
"extension = '${PYTHON_MODULE_EXTENSION}")
62-
endif()
63-
endmacro()
64-
65-
# Detects a pybind11 package installed in the current python environment
66-
# and sets variables to allow it to be found. This allows pybind11 to be
67-
# installed via pip, which typically yields a much more recent version than
68-
# the OS install, which will be available otherwise.
69-
function(mlir_detect_pybind11_install)
70-
if(pybind11_DIR)
71-
message(STATUS "Using explicit pybind11 cmake directory: ${pybind11_DIR} (-Dpybind11_DIR to change)")
72-
else()
73-
message(STATUS "Checking for pybind11 in python path...")
74-
execute_process(
75-
COMMAND "${Python3_EXECUTABLE}"
76-
-c "import pybind11;print(pybind11.get_cmake_dir(), end='')"
77-
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
78-
RESULT_VARIABLE STATUS
79-
OUTPUT_VARIABLE PACKAGE_DIR
80-
ERROR_QUIET)
81-
if(NOT STATUS EQUAL "0")
82-
message(STATUS "not found (install via 'pip install pybind11' or set pybind11_DIR)")
83-
return()
84-
endif()
85-
message(STATUS "found (${PACKAGE_DIR})")
86-
set(pybind11_DIR "${PACKAGE_DIR}" PARENT_SCOPE)
87-
endif()
88-
endfunction()
89-
90-
91-
# Detects a nanobind package installed in the current python environment
92-
# and sets variables to allow it to be found. This allows nanobind to be
93-
# installed via pip, which typically yields a much more recent version than
94-
# the OS install, which will be available otherwise.
95-
function(mlir_detect_nanobind_install)
96-
if(nanobind_DIR)
97-
message(STATUS "Using explicit nanobind cmake directory: ${nanobind_DIR} (-Dnanobind_DIR to change)")
98-
else()
99-
message(STATUS "Checking for nanobind in python path...")
100-
execute_process(
101-
COMMAND "${Python3_EXECUTABLE}"
102-
-c "import nanobind;print(nanobind.cmake_dir(), end='')"
103-
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
104-
RESULT_VARIABLE STATUS
105-
OUTPUT_VARIABLE PACKAGE_DIR
106-
ERROR_QUIET)
107-
if(NOT STATUS EQUAL "0")
108-
message(STATUS "not found (install via 'pip install nanobind' or set nanobind_DIR)")
109-
return()
49+
message(STATUS "Python extension suffix for modules: '${Python3_SOABI}'")
50+
if(nanobind_DIR)
51+
message(STATUS "Using explicit nanobind cmake directory: ${nanobind_DIR} (-Dnanobind_DIR to change)")
52+
find_package(nanobind 2.9 CONFIG REQUIRED)
53+
else()
54+
include(FetchContent)
55+
FetchContent_Declare(
56+
nanobind
57+
GIT_REPOSITORY https://github.com/wjakob/nanobind.git
58+
GIT_TAG v2.9.0
59+
GIT_SHALLOW TRUE
60+
)
61+
FetchContent_MakeAvailable(nanobind)
11062
endif()
111-
message(STATUS "found (${PACKAGE_DIR})")
112-
set(nanobind_DIR "${PACKAGE_DIR}" PARENT_SCOPE)
113-
execute_process(
114-
COMMAND "${Python3_EXECUTABLE}"
115-
-c "import nanobind;print(nanobind.include_dir(), end='')"
116-
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
117-
RESULT_VARIABLE STATUS
118-
OUTPUT_VARIABLE PACKAGE_DIR
119-
ERROR_QUIET)
120-
if(NOT STATUS EQUAL "0")
121-
message(STATUS "not found (install via 'pip install nanobind' or set nanobind_DIR)")
122-
return()
123-
endif()
124-
set(nanobind_INCLUDE_DIR "${PACKAGE_DIR}" PARENT_SCOPE)
63+
message(STATUS "Found nanobind: ${NB_DIR}")
12564
endif()
126-
endfunction()
65+
endmacro()

mlir/docs/Dialects/Linalg/OpDSL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@ corresponding `linalg.generic` IR for the composition.
1616
## Basic usage
1717

1818
The tool is bundled with the MLIR Python bindings. To use from the CMake build
19-
tree, MLIR must be build with Python bindings enabled
19+
tree, MLIR must be built with Python bindings enabled
2020
(`-DMLIR_ENABLE_BINDINGS_PYTHON=ON`). Then add the `python` directory in the
2121
build tree to your `PYTHONPATH` environment variable (i.e. `export
2222
PYTHONPATH=$PWD/build/tools/mlir/python_packages/mlir_core`). Optionally, use an
2323
installed MLIR package, if available, to avoid building.
2424

2525
```shell
2626
# Dump the `core_named_ops.py` module as YAML.
27-
python -m mlir.dialects.linalg.opdsl.dump_oplib .ops.core_named_ops
27+
python -m mlir.dialects.linalg.opdsl.dump_oplib.ops.core_named_ops
2828
```
2929

3030
Alternatively, run the `$PWD/build/bin/update_core_linalg_named_ops.sh` script,

mlir/examples/standalone/pyproject.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@ Discussions = "https://discourse.llvm.org/"
2323
[build-system]
2424
requires = [
2525
"scikit-build-core>=0.10.7",
26-
"typing_extensions>=4.12.2",
27-
"nanobind>=2.9, <3.0",
28-
"pybind11>=2.10.0, <=2.13.6",
26+
"typing_extensions>=4.12.2"
2927
]
3028
build-backend = "scikit_build_core.build"
3129

mlir/examples/standalone/python/CMakeLists.txt

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,10 @@ declare_mlir_dialect_python_bindings(
1616
ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/mlir_standalone"
1717
TD_FILE dialects/StandaloneOps.td
1818
SOURCES
19-
dialects/standalone_pybind11.py
2019
dialects/standalone_nanobind.py
2120
_mlir_libs/_standaloneDialectsNanobind/py.typed
2221
DIALECT_NAME standalone)
2322

24-
25-
declare_mlir_python_extension(StandalonePythonSources.Pybind11Extension
26-
MODULE_NAME _standaloneDialectsPybind11
27-
ADD_TO_PARENT StandalonePythonSources
28-
SOURCES
29-
StandaloneExtensionPybind11.cpp
30-
PRIVATE_LINK_LIBS
31-
LLVMSupport
32-
EMBED_CAPI_LINK_LIBS
33-
MLIRCAPIIR
34-
MLIRCAPIArith
35-
MLIRCAPITransforms
36-
StandaloneCAPI
37-
PYTHON_BINDINGS_LIBRARY pybind11
38-
)
39-
4023
declare_mlir_python_extension(StandalonePythonSources.NanobindExtension
4124
MODULE_NAME _standaloneDialectsNanobind
4225
ADD_TO_PARENT StandalonePythonSources
@@ -49,7 +32,6 @@ declare_mlir_python_extension(StandalonePythonSources.NanobindExtension
4932
MLIRCAPIArith
5033
MLIRCAPITransforms
5134
StandaloneCAPI
52-
PYTHON_BINDINGS_LIBRARY nanobind
5335
)
5436

5537

0 commit comments

Comments
 (0)