MLIR 与 TVM Python 绑定生成过程:详细对比
本文基于 LLVM 工程中的 mlir 子树与 Apache TVM 源码仓库中的实现,从构建系统、代码生成、目录与安装布局、运行时加载、扩展方式等维度,对两套 Python 绑定 的生成过程与设计做尽可能细的说明,并对比差异。
**说明**:若你未初始化 TVM 的 `git submodule`(例如 `3rdparty/tvm-ffi`),本地可能缺少部分 C++ 文件,但 CMake 与 Python 侧的**约定**仍可从主仓与 `pyproject.toml` 中还原。
第一部分:MLIR(llvm-project/mlir)
MLIR 的 Python 绑定是 LLVM 子工程的一部分:与 mlir-tblgen、mlir-c(C API)、以及 `lib/` 下的 C++ 实现 强耦合,通过 CMake 宏 把「纯 Python + TableGen 生成代码 + 多个 nanobind 扩展模块 + 聚合 CAPI 动态库」装配成可安装包。
1.1 顶层开关与环境
在 mlir/CMakeLists.txt 中:
变量 | 作用 |
MLIR_ENABLE_BINDINGS_PYTHON | 总开关(默认 0)。为 ON 时 include(MLIRDetectPythonEnv) 并 mlir_configure_python_dev_packages(),且 add_subdirectory(python)。 |
MLIR_MINIMUM_PYTHON_VERSION | 在 MLIRDetectPythonEnv.cmake 中设为 3.10。 |
MLIR_ENABLE_PYTHON_STABLE_ABI | 使用 PEP 384 有限 API / abi3 构建扩展(与 nanobind 的 STABLE_ABI、-abi3 命名等联动)。要求 CMake ≥ 3.26(Python::SABIModule),文档注释要求 Python 3.12+。 |
MLIR_BINDINGS_PYTHON_NB_DOMAIN | nanobind 域字符串(默认 mlir),用于 NB_DOMAIN=...,使不同绑定包可隔离 nanobind 类型系统;第三方项目应改成唯一名字以免冲突。 |
MLIR_PYTHON_PACKAGE_PREFIX | 顶层 Python 包前缀(默认 mlir),通过 add_compile_definitions("MLIR_PYTHON_PACKAGE_PREFIX=${MLIR_PYTHON_PACKAGE_PREFIX}.") 传入 C++/Python 约定。 |
MLIR_BINDINGS_PYTHON_INSTALL_PREFIX | 安装树中放置绑定的路径前缀(默认 python_packages/mlir_core/mlir)。 |
MLIR_PYTHON_STUBGEN_ENABLED | 是否用 nanobind stubgen 生成 .pyi。交叉编译或 LLVM Sanitizer 非空时默认关闭。 |
MLIR_DISABLE_CONFIGURE_PYTHON_DEV_PACKAGES | 为 ON 时跳过 mlir_configure_python_dev_packages(),供超大工程自行 find_package(Python3) / nanobind。 |
MLIR_DETECT_PYTHON_ENV_PRIME_SEARCH | 是否先按完整 Development 探测 Python(缓解部分环境下 CMake 只找 Development.Module 的问题)。 |
Python 与 nanobind 探测(mlir_configure_python_dev_packages)要点:
·find_package(Python3 … COMPONENTS Interpreter Development.Module),若 stable ABI 则加上 Development.SABIModule。
·再 find_package(Python …) —— 因 nanobind 的 CMake 使用 `Python_` 前缀变量。
·NumPy:打印 Python3_NumPy_INCLUDE_DIRS 等(用于绑定中与数组互操作等)。
·nanobind:优先 -Dnanobind_DIR;否则执行
python3 -c "import nanobind; print(nanobind.cmake_dir())" 得到路径,再 find_package(nanobind 2.9 CONFIG REQUIRED)。
1.2 CMake 模块职责(`mlir/cmake/modules/`)
`AddMLIRPython.cmake`(核心)
该文件定义一整套 声明式 API,把 Python 包拆成可组合的 INTERFACE 目标,最终在 add_mlir_python_modules 里展开为真实目标。
(1)`declare_mlir_python_sources(name …)`
·创建一个 `INTERFACE` 库${name},属性包括:
·mlir_python_SOURCES_TYPE = pure
·mlir_python_DEPENDS = 子分组列表(DAG)
·源文件可来自 SOURCES / SOURCES_GLOB,ROOT_DIR 默认为当前源目录。
·安装:非 LLVM_INSTALL_TOOLCHAIN_ONLY 时,通过 _mlir_python_install_sources 把文件安装到 src/python/${name}/...,并挂到全局 MLIR_EXPORTS。
·设计目的:同一套「逻辑包」可在构建树与安装树用生成表达式区分路径(BUILD_INTERFACE / INSTALL_INTERFACE)。
(2)`declare_mlir_python_extension` / `add_mlir_python_extension`
·声明:declare_mlir_python_extension 记录 C++ 源、MODULE_NAME(如 _mlir、_mlirDialectsLinalg)、EMBED_CAPI_LINK_LIBS(需要打进聚合 CAPI 的静态库列表)、PRIVATE_LINK_LIBS。
·实现:add_mlir_python_extension 内部:
·普通扩展:**nanobind_add_module**,带 NB_DOMAIN、NB_SHARED、FREE_THREADED,可选 STABLE_ABI。
·Support 库(MLIRPythonSupport,_PRIVATE_SUPPORT_LIB):打成 SHARED,供运行时辅助,使用 nanobind_link_options,并定义 MLIR_CAPI_BUILDING_LIBRARY=1。
·统一链接 `nanobind` 为该 domain 构建的共享运行时库(见下节 build_nanobind_lib)。
·输出名 = MODULE_NAME,输出目录 = 调用方传入的 _mlir_libs 目录。
·链接:--exclude-libs,ALL(Linux)避免把静态库符号再导出;Windows 上链接 `Python3_LIBRARY_RELEASE`(与 nanobind 一致,避免 Debug/Release Python 混用)。
·Apple:-twolevel_namespace;额外 -U 若干 Python 符号,适配不同链接模式。
(3)`build_nanobind_lib`
·调用 nanobind_build_library,目标名形如 nanobind[-ft][-abi3]-。
·Free-threaded Python:若 NB_ABI 匹配 [0-9]t 则带 -ft。
·Stable ABI:非 free-threaded 时可为 nanobind-abi3-...,并对 nanobind 目标定义 Py_LIMITED_API、链接 Python::SABIModule。
·Linux:对 LLVM 全局 -z,defs 的抵消:LINKER:-z,undefs。
·输出与扩展同一 _mlir_libs 目录,并 install 到 INSTALL_DESTINATION。
(4)`declare_mlir_dialect_python_bindings`
·先 declare_mlir_python_sources 挂手写 dialects/xxx.py 等。
·若提供 TD_FILE:
·设 LLVM_TARGET_DEFINITIONS 指向该 .td,调用 `mlir_tablegen`:
·-gen-python-op-bindings -bind-dialect=${DIALECT_NAME}
·生成路径形如:${relative_td_directory}/_${DIALECT_NAME}_ops_gen.py(在 build 目录)。
·可选 枚举:-gen-python-enum-bindings,生成 _*_enum_gen.py。
·add_public_tablegen_target 便于依赖追踪。
·生成的文件再 `declare_mlir_python_sources(... ROOT_DIR "${CMAKE_CURRENT_BINARY_DIR}")` 挂到 ${_dialect_target}.ops_gen。
(5)`add_mlir_python_common_capi_library`
·收集所有声明扩展上的 `mlir_python_EMBED_CAPI_LINK_LIBS`(去重)。
·调用 `add_mlir_aggregate(SHARED … EMBED_LIBS …)` 生成 单一共享库(如 MLIRPythonCAPI),内嵌所有需要的 MLIRCAPI* 静态库。
·同时把 mlir-c 头文件 通过 DECLARED_HEADERS 声明的目标拷贝到 _mlir_libs/include。
·意义:Python 各扩展模块动态链接同一 CAPI 实现,避免重复注册、重复静态初始化、以及链接器层面的符号重复问题。
(6)`add_mlir_python_modules`
·_flatten_mlir_python_targets 展开 DAG,判断是否需要 build_nanobind_lib。
·对每个 pure 源:add_mlir_python_sources_target(拷贝/链接到 ROOT_PREFIX)。
·对每个 extension:生成目标名如 MLIRPythonModules.extension._mlir.dso,调用 add_mlir_python_extension,并 mlir_python_setup_extension_rpath。
·Support 类型扩展先编(_PRIVATE_SUPPORT_LIB),命名带 -domain 后缀以配合加载器。
·注册 install-${name} 组件(非 LLVM_ENABLE_IDE 时)。
(7)`mlir_generate_type_stubs`
·定位 stubgen.py(MLIR_NB_STUBGEN / 下载指定版本 / nanobind 安装树)。
·用 `Python_EXECUTABLE stubgen.py --module...` 生成 .pyi;处理 `PYTHONPATH` 与安装前缀冲突(避免 _mlir 重复加载)。
·生成 DEPFILE 以便增量构建。
(8)`mlir_python_setup_extension_rpath`
·非 Windows:设置 BUILD_RPATH / INSTALL_RPATH 为 $ORIGIN 或 @loader_path。
·`BUILD_SHARED_LIBS` 时追加 LLVM 的 lib 目录(构建时绝对路径)及安装树相对路径,保证能找到 libLLVM、libMLIR 等。
`MLIRDetectPythonEnv.cmake`
·集中 最低版本、find_package 组合、虚拟环境一致性警告(Python3_FIND_VIRTUALENV vs Python_FIND_VIRTUALENV)。
·注释仍提及历史 pybind11 FindPython 模式,当前实际依赖 nanobind。
1.3 `mlir/python/CMakeLists.txt` 在做什么
这是 上游 MLIR Python 包 的「清单」:
1.`MLIR_PYTHON_PACKAGE_PREFIX` 与 `MLIRPythonModules_ROOT_PREFIX`(${MLIR_BINARY_DIR}/${MLIR_BINDINGS_PYTHON_INSTALL_PREFIX})确定构建产物根目录。
2.`declare_mlir_python_sources(MLIRPythonSources…)` 形成树:Core、Dialects 等。
3.大量 `declare_mlir_dialect_python_bindings`:每个上游方言一个块,TD_FILE 指向 python/mlir/dialects/*Ops.td 等,生成 _*_ops_gen.py。
4.`declare_mlir_python_extension`:
·`MLIRPythonExtension.Core` → MODULE_NAME _mlir,源文件 MainModule.cpp、IRAffine.cpp、IRInterfaces.cpp、Pass.cpp、Rewrite.cpp 等,EMBED_CAPI_LINK_LIBS 含 MLIRCAPIIR、MLIRCAPIInterfaces 等。
·`MLIRPythonExtension.RegisterEverything` → _mlirRegisterEverything,仅 RegisterEverything.cpp,嵌入 MLIRCAPIRegisterEverything 等(体积极大)。
·各方言 Nanobind:如 _mlirDialectsLinalg、DialectLinalg.cpp + MLIRCAPILinalg。
·Pass 插件:AsyncDialectPasses、LinalgPasses 等独立 .so。
·`MLIRPythonExtension.MLIRPythonSupport`:MODULE_NAME MLIRPythonSupport,`_PRIVATE_SUPPORT_LIB`,实现 Globals.cpp、IRCore.cpp 等(与注释一致:刻意不依赖 C++ LLVM/MLIR 库,只走 C API 或标准库)。
5.`add_mlir_python_common_capi_library(MLIRPythonCAPI …)` 聚合所有 EMBED_CAPI_LINK_LIBS。
6.可选 stubgen:依赖 MLIRPythonModules.extension._mlir.dso 等,生成 _mlir/__init__.pyi 等。
7.`add_mlir_python_modules(MLIRPythonModules …)` 汇总 DECLARED_SOURCES 与 COMMON_CAPI_LINK_LIBS MLIRPythonCAPI。
1.4 C++ 绑定实现位置(`mlir/lib/Bindings/Python/`)
文件 | 角色 |
MainModule.cpp | NB_MODULE(_mlir, m):创建子模块 ir、rewrite、passmanager,调用 populateIRCore、populateIRAttributes 等。 |
RegisterEverything.cpp | NB_MODULE(_mlirRegisterEverything, m):register_dialects、register_llvm_translations,并 mlirRegisterAllPasses()(导入即注册全部 Pass)。 |
Dialect*.cpp | 各方言额外类型/辅助绑定(如 DialectLinalg.cpp)。 |
IRCore.cpp / IRAttributes.cpp / … | IR、属性、类型、Affine 等核心映射。 |
编译宏:源码中使用 MLIR_BINDINGS_PYTHON_DOMAIN 命名空间宏(与 NB_DOMAIN 一致),便于多包共存。
1.5 纯 Python 与加载逻辑(`mlir/python/mlir/_mlir_libs/__init__.py`)
文档字符串说明了 site 初始化 协议:
·探测 `_mlirRegisterEverything` 以及 `_site_initialize_{i}` 模块。
·若模块有 `register_dialects(registry)`,立即调用。
·`context_init_hook`、disable_multithreading 等用于定制 `mlir.ir.Context` 行为。
·这解释了为何 `RegisterEverything` 是单独扩展:下游可只链接自己的方言,替换自己的注册模块,而不必链接「全世界」。
1.6 TableGen 生成器(`mlir-tblgen`)
·实现文件:mlir/tools/mlir-tblgen/OpPythonBindingGen.cpp、EnumPythonBindingGen.cpp。
·OpPythonBindingGen:基于 ODS 里 op 定义,生成 包装通用 Operation API 的 Python 类;内置 C++ 类型 → `_ods_ir.*` 注解、属性 def → Python 类型 的映射表(见文件前几十行)。
·方言可在自己的 TableGen 中 include `PythonBindings.td`,增加 PythonTypeName / PythonAttrType 等映射。
·测试参考:mlir/test/mlir-tblgen/op-python-bindings.td、enums-python-bindings.td。
1.7 下游工程模板(`mlir/examples/standalone/python/`)
演示 自定义方言 + nanobind 扩展 + 依赖 MLIR 核心 `MLIRPythonSources.Core` 与 `builtin`:
·declare_mlir_dialect_python_bindings + StandaloneExtensionNanobind.cpp。
·add_mlir_python_common_capi_library(StandalonePythonCAPI … DECLARED_SOURCES StandalonePythonSources MLIRPythonSources.Core MLIRPythonSources.Dialects.builtin)。
·add_mlir_python_modules(StandalonePythonModules … COMMON_CAPI_LINK_LIBS StandalonePythonCAPI)。
·Stubgen 在 `EXTERNAL_PROJECT_BUILD` 时复用已存在的 core stub 目标。
1.8 典型构建思路(概念命令)
在配置 LLVM/MLIR 时打开:
-DMLIR_ENABLE_BINDINGS_PYTHON=ON
并确保环境已安装 nanobind(pip install nanobind)及对应 Python 开发头文件。构建目标通常包括 `MLIRPythonModules`、`mlir-python-sources` 等(视生成器与 IDE 而定)。
产物在构建树下位于大致
${MLIR_BINARY_DIR}/${MLIR_BINDINGS_PYTHON_INSTALL_PREFIX}/,其中 `_mlir_libs/` 下放 `_mlir*.so`/`.pyd`、`libMLIRPythonCAPI.so`、nanobind 共享库 等。
第二部分:TVM(apache/tvm)
TVM 的 Python 层不是在 CMake 里用 TableGen 批量生成业务代码,而是:
8.C++ 侧:libtvm / libtvm_runtime 与 `tvm-ffi`(3rdparty/tvm-ffi)配合,用 `TVM_FFI_*` 宏注册函数与对象。
9.Python 侧:大量 `python/tvm//*.py**;每个子域通过 **tvm_ffi.init_ffi_api("模块名", __name__)` 把 C++ 注册的符号** 绑定到 Python 模块命名空间。
10.打包:可选 `scikit-build-core` + `pyproject.toml`,把 预编译动态库 + 纯 Python 打成 wheel;`apache-tvm-ffi` 作为 独立 PyPI 依赖。
2.1 CMake 中的核心目标
摘自 tvm/CMakeLists.txt 逻辑:
目标 | 说明 |
tvm_objs / tvm_runtime_objs / tvm_libinfo_objs | OBJECT 库,聚合编译单元。 |
tvm | SHARED,链接 tvm_ffi_shared(非 dummy 时包含 compiler + runtime 对象)。 |
tvm_runtime | 可静态可共享,同样依赖 tvm_ffi。 |
add_subdirectory(3rdparty/tvm-ffi) | 提供 FFI 头文件目标 tvm_ffi_header 与 tvm_ffi_shared / tvm_ffi_static。 |
版本与标准:CMAKE_CXX_STANDARD 17;大量可选后端(CUDA、Vulkan、Hexagon 等)通过 tvm_option 与独立 cmake/modules 注入源文件与链接库。
2.2 `TVM_BUILD_PYTHON_MODULE`(wheel 安装段)
当 `TVM_BUILD_PYTHON_MODULE=ON`(pyproject.toml 里 `cmake.args` 已默认传入)时,额外:
·为 `tvm`、`tvm_runtime` 设置 `INSTALL_RPATH`(macOS @loader_path,Linux $ORIGIN),使 wheel 内同目录 .so 可被找到。
·`install(TARGETS tvm tvm_runtime DESTINATION ".")`:库放在 wheel 根目录(与 scikit-build 布局配合)。
·安装 `include/tvm/runtime`、`src/runtime`(部分)、`cmake/utils`、可选 CUTLASS 头、`web/`、`licenses/`、README/LICENSE/NOTICE 等。
目的:让 `pip install` 后的包既包含 Python 源码树,又包含 原生库与头文件(供需要编译扩展或调试的用户)。
2.3 `pyproject.toml`(scikit-build-core)
要点:
·`[build-system]`:requires = ["scikit-build-core>=0.10.0"],build-backend = "scikit_build_core.build"。
·`[tool.scikit-build]`:
·cmake.source-dir = "."
·cmake.args = ["-DTVM_BUILD_PYTHON_MODULE=ON"]
·`wheel.packages = ["python/tvm"]`,wheel.install-dir = "tvm":安装到 site-packages/tvm/。
·`wheel.py-api = "py3"`:wheel 标签策略与「单一大扩展模块」类项目不同。
·`dependencies` 含 `apache-tvm-ffi`:Python 与 FFI 运行时 的版本由 PyPI 约束。
2.4 原生库如何被 Python 加载
`python/tvm/base.py`:
·`ctypes.CDLL(lib_path[0], ctypes.RTLD_GLOBAL)` 加载 `libtvm` 或 `libtvm_runtime`(由 libinfo.find_lib_path() 决定具体文件名)。
·`_RUNTIME_ONLY`:若库名含 "runtime",则从 `tvm_ffi.registry` 设置 `_SKIP_UNKNOWN_OBJECTS`,避免仅运行时场景下缺类定义报错。
·环境变量 `TVM_FFI`:若为 `ctypes`,直接 `ImportError`(注释写「已弃用 ctypes,转向 cython」—— 历史表述;当前主线为 `tvm_ffi`)。
`python/tvm/libinfo.py`:
·`find_lib_path` 搜索 `TVM_LIBRARY_PATH`、LD_LIBRARY_PATH、TVM_HOME、build/、build/Release、lib/、以及 与 `libinfo` 相对路径相关的 site-packages 布局 等。
即:TVM 主仓仍用 ctypes 只做「加载 .so」,不再通过 ctypes 逐符号调用;业务 FFI 走 `tvm_ffi`。
2.5 Python 与 C++ 的绑定模式:`init_ffi_api`
典型文件 `python/tvm/ir/_ffi_api.py`:
import tvm_ffi tvm_ffi.init_ffi_api("ir", __name__)
含义(语义层面):
·C++ 在静态初始化或注册块中,把函数/类按 逻辑模块名(如 "ir")注册进 tvm-ffi 注册表。
·`init_ffi_api("ir", __name__)` 把当前 Python 包 `tvm.ir` 的命名空间与这些符号对接,从而在 tvm.ir 其它代码里 `from . import _ffi_api` 即可调用 C++ 实现。
仓库内有 大量_ffi_api.py(relax、s_tir、runtime 等),模式统一,无需每个模块单独编译一个 .pyd。
2.6 C++ 侧注册(示例)
在 tvm/src/**/*.cc 中广泛使用 `TVM_FFI_STATIC_INIT_BLOCK() { ... }`(例如在 topi 算子注册中),在静态初始化阶段把算子/API 注册进 FFI。具体宏定义在 `3rdparty/tvm-ffi` 头文件中(子模块未检出时本地不可见,但调用模式一致)。
2.7 与 MLIR 不同的「生成」含义
方面 | TVM |
Python 语法/API 表面 | 几乎全部手写(python/tvm)。 |
「生成」 | 指 C++ 编译 产生带注册的 libtvm,而非 CMake 调用 TableGen 生成成批 .py。 |
类型存根 | 主仓 pyproject 未内置类似 MLIR 的 stubgen 流水线;部分目录可能有 .pyi(见 sdist.include 中的 python/tvm/**/*.pyi)。 |
2.8 典型使用路径
·开发者:cmake 构建 libtvm.so / libtvm_runtime.so,设置 `PYTHONPATH=python` 或 pip install -e .(若配置 editable)。
·用户:pip install tvm(或源码构建 wheel),依赖 `apache-tvm-ffi`,运行时 `libinfo` 找到同包或系统路径下的动态库。
第三部分:并排对比与小结
3.1 架构对照
维度 | MLIR | TVM |
绑定技术 | nanobind(每块功能可对应独立 extension module) | tvm-ffi(统一 FFI 注册 + 少量 ctypes 仅用于 dlopen) |
CMake 角色 | 声明源、TableGen、编 .so、聚合 CAPI、stubgen、安装 全流程 | 编 C++ 库;Python wheel 安装规则 由 TVM_BUILD_PYTHON_MODULE 打开 |
Python 代码体量来源 | TableGen 大量生成 _*_ops_gen.py + 手写 dialects/*.py | 手写为主 + 薄 _ffi_api.py |
与 C++ 的边界 | mlir-c + MLIRPythonCAPI 聚合库 + 多 nanobind 模块 | libtvm 内 TVM_FFI 注册,Python 通过 tvm_ffi** 解析 |
方言/算子扩展 | ODS + declare_mlir_dialect_python_bindings + 可选 DialectX.cpp | C++ 注册宏 + Python 手写封装 |
「注册全世界」 | 独立模块 _mlirRegisterEverything,可选加载 | TVM 通常 全量注册在 lib 或按模块静态初始化;无同一级「单独 Python 模块只负责 register」的固定模式 |
分包/多项目 | MLIR_BINDINGS_PYTHON_NB_DOMAIN、MLIR_PYTHON_PACKAGE_PREFIX、standalone 示例 | tvm + apache-tvm-ffi 分包;库名 libtvm/runtime |
类型提示 | 构建期 nanobind stubgen(可选) | 维护负担在 手写 / 独立工具,非 LLVM 式集成 |
3.2 设计取向差异(为何如此)
·MLIR 面向 编译器 IR + 极多方言,ODS 与 TableGen 是单一事实来源;Python 需与 Operation/Attribute/Type 模型一致,故 生成 Python 包装类 性价比最高;C API 聚合 解决 多 `.so` 共享同一 MLIR 核心 的链接与初始化问题。
·TVM 面向 深度学习编译流水线,Python API 更偏 脚本与调度;历史从 ctypes 演进到 tvm_ffi,把 注册与类型系统 收敛到 独立 FFI 层,降低 每个子模块一个 pybind 扩展 的维护成本;wheel 与 PyPI 分发是首要场景之一。
3.3 扩展新功能时「改哪里」(速查)
MLIR 新方言(上游式)
11.增加 ODS / *Ops.td 与 `PythonBindings.td` 映射(若需自定义类型注解)。
12.mlir/python/CMakeLists.txt:declare_mlir_dialect_python_bindings + 必要时 `DialectNew.cpp` + declare_mlir_python_extension。
13.将新 `MLIRCAPI*` 加入 `EMBED_CAPI_LINK_LIBS` 与 `add_mlir_python_common_capi_library` 的聚合列表(若走 C API 封装)。
TVM 新算子/API
14.C++:在对应 .cc 的 `TVM_FFI_STATIC_INIT_BLOCK`(或项目使用的注册宏)中注册。
15.Python:在合适包下增加 `_ffi_api.py`(init_ffi_api)与业务 .py。
16.无需在 TVM CMake 中为该 API 新增一个 Python 扩展目标(除非引入新的原生依赖库)。
附录:关键文件路径速查
MLIR
·mlir/cmake/modules/AddMLIRPython.cmake
·mlir/cmake/modules/MLIRDetectPythonEnv.cmake
·mlir/CMakeLists.txt(MLIR_ENABLE_BINDINGS_PYTHON)
·mlir/python/CMakeLists.txt
·mlir/lib/Bindings/Python/*.cpp
·mlir/python/mlir/_mlir_libs/__init__.py
·mlir/tools/mlir-tblgen/OpPythonBindingGen.cpp
·mlir/include/mlir/Bindings/Python/PythonBindings.td
·mlir/examples/standalone/python/CMakeLists.txt
TVM
·tvm/CMakeLists.txt(tvm、tvm_runtime、tvm-ffi、TVM_BUILD_PYTHON_MODULE)
·tvm/pyproject.toml
·tvm/python/tvm/__init__.py、base.py、libinfo.py
·tvm/python/tvm/**/_ffi_api.py(大量)
·tvm/src/**/*.cc(TVM_FFI_STATIC_INIT_BLOCK 等)
·tvm/3rdparty/tvm-ffi(子模块,未检出则仅能从链接关系推断)
*文档基于上述仓库内相对路径与 CMake 配置整理;LLVM/TVM 版本升级时选项名或默认值可能微调,请以对应版本源码树中的 CMakeLists.txt 与官方文档为准。*