[mlir] Allow out-of-tree python building from installed MLIR.
authorStella Laurenzo <stellaraccident@gmail.com>
Fri, 12 Nov 2021 01:31:39 +0000 (17:31 -0800)
committerStella Laurenzo <stellaraccident@gmail.com>
Fri, 12 Nov 2021 02:04:31 +0000 (18:04 -0800)
* Depends on D111504, which provides the boilerplate for building aggregate shared libraries from installed MLIR.
* Adds a full-fledged Python example dialect and tests to the Standalone example (need to do a bit of tweaking in the top level CMake and lit tests to adapt better to if not building with Python enabled).
* Rips out remnants of custom extension building in favor of `pybind11_add_module` which does the right thing.
* Makes python and extension sources installable (outputs to src/python/${name} in the install tree): Both Python and C++ extension sources get installed as downstreams need all of this in order to build a derived version of the API.
* Exports sources targets (with our properties that make everything work) by converting them to INTERFACE libraries (which have export support), as recommended for the forseeable future by CMake devs. Renames custom properties to start with lower-case letter, as also recommended/required (groan).
* Adds a ROOT_DIR argument to `declare_mlir_python_extension` since now all C++ sources for an extension must be under the same directory (to line up at install time).
* Need to validate against a downstream or two and adjust, prior to submitting.

Downstreams will need to adapt by:

* Remove absolute paths from any SOURCES for `declare_mlir_python_extension` (I believe all downstreams are just using `${CMAKE_CURRENT_SOURCE_DIR}` here, which can just be ommitted). May need to set `ROOT_DIR` if not relative to the current source directory.
* To allow further downstreams to install/build, will need to make sure that all C++ extension headers are also listed under SOURCES for `declare_mlir_python_extension`.

Reviewed By: stephenneuendorffer, mikeurbach

Differential Revision: https://reviews.llvm.org/D111513

15 files changed:
mlir/cmake/modules/AddMLIRPython.cmake
mlir/cmake/modules/MLIRConfig.cmake.in
mlir/examples/standalone/CMakeLists.txt
mlir/examples/standalone/include/Standalone/StandaloneOps.td
mlir/examples/standalone/python/CMakeLists.txt [new file with mode: 0644]
mlir/examples/standalone/python/StandaloneExtension.cpp [new file with mode: 0644]
mlir/examples/standalone/python/mlir_standalone/dialects/StandaloneOps.td [new file with mode: 0644]
mlir/examples/standalone/python/mlir_standalone/dialects/standalone.py [new file with mode: 0644]
mlir/examples/standalone/test/CMakeLists.txt
mlir/examples/standalone/test/lit.cfg.py
mlir/examples/standalone/test/lit.site.cfg.py.in
mlir/examples/standalone/test/python/lit.local.cfg [new file with mode: 0644]
mlir/examples/standalone/test/python/smoketest.py [new file with mode: 0644]
mlir/python/CMakeLists.txt
mlir/test/Examples/standalone/test.toy

index cc9770001ea7bf8483bf6098fba3a0b22f8c4a86..dd5b7093c143feca8352d287cb639314dc0f91b8 100644 (file)
@@ -35,6 +35,7 @@ function(declare_mlir_python_sources name)
   if(NOT ARG_ROOT_DIR)
     set(ARG_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
   endif()
+  set(_install_destination "src/python/${name}")
 
   # Process the glob.
   set(_glob_sources)
@@ -50,21 +51,44 @@ function(declare_mlir_python_sources name)
 
   # We create a custom target to carry properties and dependencies for
   # generated sources.
-  add_custom_target(${name})
+  add_library(${name} INTERFACE)
   set(_file_depends "${ARG_SOURCES}")
   list(TRANSFORM _file_depends PREPEND "${ARG_ROOT_DIR}/")
   set_target_properties(${name} PROPERTIES
-    PYTHON_SOURCES_TYPE pure
-    PYTHON_ROOT_DIR "${ARG_ROOT_DIR}"
-    PYTHON_DEST_PREFIX "${ARG_DEST_PREFIX}"
-    PYTHON_SOURCES "${ARG_SOURCES}"
-    PYTHON_FILE_DEPENDS "${_file_depends}"
-    PYTHON_DEPENDS ""
+    # Yes: Leading-lowercase property names are load bearing and the recommended
+    # way to do this: https://gitlab.kitware.com/cmake/cmake/-/issues/19261
+    # Note that ROOT_DIR and FILE_DEPENDS are not exported because they are
+    # only relevant to in-tree uses.
+    EXPORT_PROPERTIES "mlir_python_SOURCES_TYPE;mlir_python_DEST_PREFIX;mlir_python_DEST_PREFIX;mlir_python_SOURCES;mlir_python_DEPENDS"
+    mlir_python_SOURCES_TYPE pure
+    mlir_python_ROOT_DIR "${ARG_ROOT_DIR}"
+    mlir_python_DEST_PREFIX "${ARG_DEST_PREFIX}"
+    mlir_python_SOURCES "${ARG_SOURCES}"
+    mlir_python_FILE_DEPENDS "${_file_depends}"
+    mlir_python_DEPENDS ""
+  )
+  # Note that an "include" directory has no meaning to such faux targets,
+  # but it is a CMake supported way to specify a directory search list in a
+  # way that works both in-tree and out. It has some super powers which are
+  # not possible to emulate with custom properties (because of the prohibition
+  # on using generator expressions in exported custom properties and the
+  # special dispensation for $<INSTALL_PREFIX>).
+  target_include_directories(${name} INTERFACE
+    "$<BUILD_INTERFACE:${ARG_ROOT_DIR}>"
+    "$<INSTALL_INTERFACE:${_install_destination}>"
   )
 
   # Add to parent.
   if(ARG_ADD_TO_PARENT)
-    set_property(TARGET ${ARG_ADD_TO_PARENT} APPEND PROPERTY PYTHON_DEPENDS ${name})
+    set_property(TARGET ${ARG_ADD_TO_PARENT} APPEND PROPERTY mlir_python_DEPENDS ${name})
+  endif()
+
+  # Install.
+  if(NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
+    _mlir_python_install_sources(
+      ${name} "${ARG_ROOT_DIR}" "${_install_destination}"
+      ${ARG_SOURCES}
+    )
   endif()
 endfunction()
 
@@ -72,6 +96,8 @@ endfunction()
 # Declares a buildable python extension from C++ source files. The built
 # module is considered a python source file and included as everything else.
 # Arguments:
+#   ROOT_DIR: Root directory where sources are interpreted relative to.
+#     Defaults to CMAKE_CURRENT_SOURCE_DIR.
 #   MODULE_NAME: Local import name of the module (i.e. "_mlir").
 #   ADD_TO_PARENT: Same as for declare_mlir_python_sources.
 #   SOURCES: C++ sources making up the module.
@@ -84,27 +110,77 @@ endfunction()
 function(declare_mlir_python_extension name)
   cmake_parse_arguments(ARG
     ""
-    "MODULE_NAME;ADD_TO_PARENT"
+    "ROOT_DIR;MODULE_NAME;ADD_TO_PARENT"
     "SOURCES;PRIVATE_LINK_LIBS;EMBED_CAPI_LINK_LIBS"
     ${ARGN})
 
-  add_custom_target(${name})
+  if(NOT ARG_ROOT_DIR)
+    set(ARG_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
+  endif()
+  set(_install_destination "src/python/${name}")
+
+  add_library(${name} INTERFACE)
   set_target_properties(${name} PROPERTIES
-    PYTHON_SOURCES_TYPE extension
-    PYTHON_EXTENSION_MODULE_NAME "${ARG_MODULE_NAME}"
-    PYTHON_CPP_SOURCES "${ARG_SOURCES}"
-    PYTHON_PRIVATE_LINK_LIBS "${ARG_PRIVATE_LINK_LIBS}"
-    PYTHON_EMBED_CAPI_LINK_LIBS "${ARG_EMBED_CAPI_LINK_LIBS}"
-    PYTHON_FILE_DEPENDS ""
-    PYTHON_DEPENDS ""
+    # Yes: Leading-lowercase property names are load bearing and the recommended
+    # way to do this: https://gitlab.kitware.com/cmake/cmake/-/issues/19261
+    # Note that ROOT_DIR and FILE_DEPENDS are not exported because they are
+    # only relevant to in-tree uses.
+    EXPORT_PROPERTIES "mlir_python_SOURCES_TYPE;mlir_python_EXTENSION_MODULE_NAME;mlir_python_CPP_SOURCES;mlir_python_PRIVATE_LINK_LIBS;mlir_python_EMBED_CAPI_LINK_LIBS;mlir_python_DEPENDS"
+    mlir_python_SOURCES_TYPE extension
+    mlir_python_ROOT_DIR "${ARG_ROOT_DIR}"
+    mlir_python_EXTENSION_MODULE_NAME "${ARG_MODULE_NAME}"
+    mlir_python_CPP_SOURCES "${ARG_SOURCES}"
+    mlir_python_PRIVATE_LINK_LIBS "${ARG_PRIVATE_LINK_LIBS}"
+    mlir_python_EMBED_CAPI_LINK_LIBS "${ARG_EMBED_CAPI_LINK_LIBS}"
+    mlir_python_FILE_DEPENDS ""
+    mlir_python_DEPENDS ""
+  )
+  # Note that an "include" directory has no meaning to such faux targets,
+  # but it is a CMake supported way to specify an install-prefix relative
+  # directory. It has some super powers which are not possible to emulate
+  # with custom properties (because of the prohibition on using generator
+  # expressions in exported custom properties and the special dispensation
+  # for $<INSTALL_PREFIX> and $<INSTALL_INTERFACE>). On imported targets,
+  # this is used as a single value, not as a list, so it must only have one
+  # item in it.
+  target_include_directories(${name} INTERFACE
+    "$<INSTALL_INTERFACE:${_install_destination}>"
   )
 
   # Add to parent.
   if(ARG_ADD_TO_PARENT)
-    set_property(TARGET ${ARG_ADD_TO_PARENT} APPEND PROPERTY PYTHON_DEPENDS ${name})
+    set_property(TARGET ${ARG_ADD_TO_PARENT} APPEND PROPERTY mlir_python_DEPENDS ${name})
+  endif()
+
+  # Install.
+  if(NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
+    _mlir_python_install_sources(
+      ${name} "${ARG_ROOT_DIR}" "src/python/${name}"
+      ${ARG_SOURCES}
+    )
   endif()
 endfunction()
 
+function(_mlir_python_install_sources name source_root_dir destination)
+  foreach(source_relative_path ${ARGN})
+    # Transform "a/b/c.py" -> "${install_prefix}/a/b" for installation.
+    get_filename_component(
+      dest_relative_path "${source_relative_path}" DIRECTORY
+      BASE_DIR "${source_root_dir}"
+    )
+    install(
+      FILES "${source_root_dir}/${source_relative_path}"
+      DESTINATION "${destination}/${dest_relative_path}"
+      COMPONENT "${name}"
+    )
+  endforeach()
+  get_target_export_arg(${name} MLIR export_to_mlirtargets UMBRELLA mlir-libraries)
+  install(TARGETS ${name}
+    COMPONENT ${name}
+    ${export_to_mlirtargets}
+  )
+endfunction()
+
 # Function: add_mlir_python_modules
 # Adds python modules to a project, building them from a list of declared
 # source groupings (see declare_mlir_python_sources and
@@ -128,12 +204,26 @@ function(add_mlir_python_modules name)
     ${ARGN})
   # Helper to process an individual target.
   function(_process_target modules_target sources_target)
-    get_target_property(_source_type ${sources_target} PYTHON_SOURCES_TYPE)
+    get_target_property(_source_type ${sources_target} mlir_python_SOURCES_TYPE)
+
+    # The root directory differs based on whether it is IMPORTED (installed
+    # dep).
+    get_target_property(_is_imported ${sources_target} IMPORTED)
+    if(NOT _is_imported)
+      # In-tree.
+      get_target_property(_python_root_dir ${sources_target} mlir_python_ROOT_DIR)
+    else()
+      # Imported.
+      # Note: We only populate a single directory in
+      # INTERFACE_INCLUDE_DIRECTORIES, so we can get away with just using it
+      # as a single value.
+      get_target_property(_python_root_dir ${sources_target} INTERFACE_INCLUDE_DIRECTORIES)
+    endif()
+
     if(_source_type STREQUAL "pure")
       # Pure python sources to link into the tree.
-      get_target_property(_python_root_dir ${sources_target} PYTHON_ROOT_DIR)
-      get_target_property(_python_sources ${sources_target} PYTHON_SOURCES)
-      get_target_property(_specified_dest_prefix ${sources_target} PYTHON_DEST_PREFIX)
+      get_target_property(_python_sources ${sources_target} mlir_python_SOURCES)
+      get_target_property(_specified_dest_prefix ${sources_target} mlir_python_DEST_PREFIX)
       foreach(_source_relative_path ${_python_sources})
         set(_dest_relative_path "${_source_relative_path}")
         if(_specified_dest_prefix)
@@ -162,9 +252,11 @@ function(add_mlir_python_modules name)
       endforeach()
     elseif(_source_type STREQUAL "extension")
       # Native CPP extension.
-      get_target_property(_module_name ${sources_target} PYTHON_EXTENSION_MODULE_NAME)
-      get_target_property(_cpp_sources ${sources_target} PYTHON_CPP_SOURCES)
-      get_target_property(_private_link_libs ${sources_target} PYTHON_PRIVATE_LINK_LIBS)
+      get_target_property(_module_name ${sources_target} mlir_python_EXTENSION_MODULE_NAME)
+      get_target_property(_cpp_sources ${sources_target} mlir_python_CPP_SOURCES)
+      get_target_property(_private_link_libs ${sources_target} mlir_python_PRIVATE_LINK_LIBS)
+      # Transform relative source to based on root dir.
+      list(TRANSFORM _cpp_sources PREPEND "${_python_root_dir}/")
       set(_extension_target "${name}.extension.${_module_name}.dso")
       add_mlir_python_extension(${_extension_target} "${_module_name}"
         INSTALL_COMPONENT ${modules_target}
@@ -187,8 +279,10 @@ function(add_mlir_python_modules name)
   # Collect dependencies.
   set(_depends)
   foreach(sources_target ${_flat_targets})
-    get_target_property(_local_depends ${sources_target} PYTHON_FILE_DEPENDS)
-    list(APPEND _depends ${_local_depends})
+    get_target_property(_local_depends ${sources_target} mlir_python_FILE_DEPENDS)
+    if(_local_depends)
+      list(APPEND _depends ${_local_depends})
+    endif()
   endforeach()
 
   # Build the modules target.
@@ -334,7 +428,7 @@ function(add_mlir_python_common_capi_library name)
   set(_embed_libs ${ARG_EMBED_LIBS})
   _flatten_mlir_python_targets(_all_source_targets ${ARG_DECLARED_SOURCES})
   foreach(t ${_all_source_targets})
-    get_target_property(_local_embed_libs ${t} PYTHON_EMBED_CAPI_LINK_LIBS)
+    get_target_property(_local_embed_libs ${t} mlir_python_EMBED_CAPI_LINK_LIBS)
     if(_local_embed_libs)
       list(APPEND _embed_libs ${_local_embed_libs})
     endif()
@@ -372,8 +466,8 @@ endfunction()
 function(_flatten_mlir_python_targets output_var)
   set(_flattened)
   foreach(t ${ARGN})
-    get_target_property(_source_type ${t} PYTHON_SOURCES_TYPE)
-    get_target_property(_depends ${t} PYTHON_DEPENDS)
+    get_target_property(_source_type ${t} mlir_python_SOURCES_TYPE)
+    get_target_property(_depends ${t} mlir_python_DEPENDS)
     if(_source_type)
       list(APPEND _flattened "${t}")
       if(_depends)
index 93ca16230c85b6acf6e7304f45c3b6042cc7f162..9f70647b6a00318bed107a8cd8f34046ef191f7b 100644 (file)
@@ -10,6 +10,7 @@ set(MLIR_CMAKE_DIR "@MLIR_CONFIG_CMAKE_DIR@")
 set(MLIR_INCLUDE_DIRS "@MLIR_CONFIG_INCLUDE_DIRS@")
 set(MLIR_TABLEGEN_EXE "@MLIR_TABLEGEN_EXE@")
 set(MLIR_INSTALL_AGGREGATE_OBJECTS "@MLIR_INSTALL_AGGREGATE_OBJECTS@")
+set(MLIR_ENABLE_BINDINGS_PYTHON "@MLIR_ENABLE_BINDINGS_PYTHON@")
 
 # For mlir_tablegen()
 set(MLIR_INCLUDE_DIR "@MLIR_INCLUDE_DIR@")
index fc42e3e5aba4bb5a9796a27f9bd70d923e3a44fc..3c6d5d0e7be8f8d55875a79b5021e21e96014160 100644 (file)
@@ -20,6 +20,12 @@ include(TableGen)
 include(AddLLVM)
 include(AddMLIR)
 include(HandleLLVMOptions)
+include(MLIRDetectPythonEnv)
+
+if(MLIR_ENABLE_BINDINGS_PYTHON)
+  include(MLIRDetectPythonEnv)
+  mlir_configure_python_dev_packages()
+endif()
 
 include_directories(${LLVM_INCLUDE_DIRS})
 include_directories(${MLIR_INCLUDE_DIRS})
@@ -30,6 +36,10 @@ add_definitions(${LLVM_DEFINITIONS})
 
 add_subdirectory(include)
 add_subdirectory(lib)
+if(MLIR_ENABLE_BINDINGS_PYTHON)
+  message(STATUS "Enabling Python API")
+  add_subdirectory(python)
+endif()
 add_subdirectory(test)
 add_subdirectory(standalone-opt)
 add_subdirectory(standalone-translate)
index 19c7dab3d8010df45ed65a919ebd24b5d164829d..3cf0310bcab062a44f5b6c927669ed1998087021 100644 (file)
@@ -9,7 +9,7 @@
 #ifndef STANDALONE_OPS
 #define STANDALONE_OPS
 
-include "StandaloneDialect.td"
+include "Standalone/StandaloneDialect.td"
 include "mlir/Interfaces/SideEffectInterfaces.td"
 
 def Standalone_FooOp : Standalone_Op<"foo", [NoSideEffect,
diff --git a/mlir/examples/standalone/python/CMakeLists.txt b/mlir/examples/standalone/python/CMakeLists.txt
new file mode 100644 (file)
index 0000000..014d606
--- /dev/null
@@ -0,0 +1,58 @@
+include(AddMLIRPython)
+
+# Specifies that all MLIR packages are co-located under the `mlir_standalone`
+# top level package (the API has been embedded in a relocatable way).
+# TODO: Add an upstream cmake param for this vs having a global here.
+add_compile_definitions("MLIR_PYTHON_PACKAGE_PREFIX=mlir_standalone.")
+
+
+################################################################################
+# Sources
+################################################################################
+
+declare_mlir_python_sources(StandalonePythonSources)
+
+declare_mlir_dialect_python_bindings(
+  ADD_TO_PARENT StandalonePythonSources
+  ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/mlir_standalone"
+  TD_FILE dialects/StandaloneOps.td
+  SOURCES
+    dialects/standalone.py
+  DIALECT_NAME standalone)
+
+declare_mlir_python_extension(StandalonePythonSources.Extension
+  MODULE_NAME _standaloneDialects
+  ADD_TO_PARENT StandalonePythonSources
+  SOURCES
+    StandaloneExtension.cpp
+  EMBED_CAPI_LINK_LIBS
+    StandaloneCAPI
+)
+
+################################################################################
+# Common CAPI
+################################################################################
+
+add_mlir_python_common_capi_library(StandalonePythonCAPI
+  INSTALL_COMPONENT StandalonePythonModules
+  INSTALL_DESTINATION python_packages/standalone/mlir_standalone/_mlir_libs
+  OUTPUT_DIRECTORY "${MLIR_BINARY_DIR}/python_packages/standalone/mlir_standalone/_mlir_libs"
+  RELATIVE_INSTALL_ROOT "../../../.."
+  DECLARED_SOURCES
+    StandalonePythonSources
+    MLIRPythonSources.Core
+)
+
+################################################################################
+# Instantiation of all Python modules
+################################################################################
+
+add_mlir_python_modules(StandalonePythonModules
+  ROOT_PREFIX "${MLIR_BINARY_DIR}/python_packages/standalone/mlir_standalone"
+  INSTALL_PREFIX "python_packages/standalone/mlir_standalone"
+  DECLARED_SOURCES
+    StandalonePythonSources
+    MLIRPythonSources
+  COMMON_CAPI_LINK_LIBS
+    StandalonePythonCAPI
+  )
diff --git a/mlir/examples/standalone/python/StandaloneExtension.cpp b/mlir/examples/standalone/python/StandaloneExtension.cpp
new file mode 100644 (file)
index 0000000..4c2043a
--- /dev/null
@@ -0,0 +1,31 @@
+//===- StandaloneExtension.cpp - Extension module -------------------------===//
+//
+// 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/Bindings/Python/PybindAdaptors.h"
+
+namespace py = pybind11;
+using namespace mlir::python::adaptors;
+
+PYBIND11_MODULE(_standaloneDialects, m) {
+  //===--------------------------------------------------------------------===//
+  // standalone dialect
+  //===--------------------------------------------------------------------===//
+  auto standalone_m = m.def_submodule("standalone");
+
+  standalone_m.def(
+      "register_dialect",
+      [](MlirContext context, bool load) {
+        MlirDialectHandle handle = mlirGetDialectHandle__standalone__();
+        mlirDialectHandleRegisterDialect(handle, context);
+        if (load) {
+          mlirDialectHandleLoadDialect(handle, context);
+        }
+      },
+      py::arg("context") = py::none(), py::arg("load") = true);
+}
diff --git a/mlir/examples/standalone/python/mlir_standalone/dialects/StandaloneOps.td b/mlir/examples/standalone/python/mlir_standalone/dialects/StandaloneOps.td
new file mode 100644 (file)
index 0000000..6cfa6b7
--- /dev/null
@@ -0,0 +1,15 @@
+//===-- StandaloneOps.td - Python bindings for standalone --*- tablegen -*-===//
+//
+// 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
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef PYTHON_BINDINGS_STANDALONE_OPS
+#define PYTHON_BINDINGS_STANDALONE_OPS
+
+include "mlir/Bindings/Python/Attributes.td"
+include "Standalone/StandaloneOps.td"
+
+#endif
diff --git a/mlir/examples/standalone/python/mlir_standalone/dialects/standalone.py b/mlir/examples/standalone/python/mlir_standalone/dialects/standalone.py
new file mode 100644 (file)
index 0000000..c958b2a
--- /dev/null
@@ -0,0 +1,6 @@
+#  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._standaloneDialects.standalone import *
index 50327ffef21ef2dc99797a6886d3834ef3128435..1405c981efa437f32de36ff673ff722e0703f3b8 100644 (file)
@@ -1,3 +1,7 @@
+llvm_canonicalize_cmake_booleans(
+        MLIR_ENABLE_BINDINGS_PYTHON
+)
+
 configure_lit_site_cfg(
         ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in
         ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py
index 1f600a61184543d879302747f9245a0676bb273a..96dbd3159263e52381510d798c81cdfa9cea1dea 100644 (file)
@@ -56,7 +56,12 @@ tool_dirs = [config.standalone_tools_dir, config.llvm_tools_dir]
 tools = [
     'standalone-capi-test',
     'standalone-opt',
-    'standalone-translate'
+    'standalone-translate',
+    ToolSubst('%PYTHON', config.python_executable, unresolved='ignore'),
 ]
 
 llvm_config.add_tool_substitutions(tools, tool_dirs)
+
+llvm_config.with_environment('PYTHONPATH', [
+    os.path.join(config.mlir_binary_dir, 'python_packages', 'standalone'),
+], append_path=True)
index 26fb8aab87f6c779e52cfc2ba8dd950d77793abd..f2c9e76f46ea934108fb8157e42e353019ee42fe 100644 (file)
@@ -12,7 +12,9 @@ config.llvm_shlib_dir = "@SHLIBDIR@"
 config.llvm_shlib_ext = "@SHLIBEXT@"
 config.llvm_exe_ext = "@EXEEXT@"
 config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@"
-config.python_executable = "@PYTHON_EXECUTABLE@"
+config.mlir_binary_dir = "@MLIR_BINARY_DIR@"
+config.python_executable = "@Python3_EXECUTABLE@"
+config.enable_bindings_python = @MLIR_ENABLE_BINDINGS_PYTHON@
 config.gold_executable = "@GOLD_EXECUTABLE@"
 config.ld64_executable = "@LD64_EXECUTABLE@"
 config.enable_shared = @ENABLE_SHARED@
diff --git a/mlir/examples/standalone/test/python/lit.local.cfg b/mlir/examples/standalone/test/python/lit.local.cfg
new file mode 100644 (file)
index 0000000..b70b9d7
--- /dev/null
@@ -0,0 +1,4 @@
+config.suffixes.add('.py')
+
+if not config.enable_bindings_python:
+  config.unsupported = True
diff --git a/mlir/examples/standalone/test/python/smoketest.py b/mlir/examples/standalone/test/python/smoketest.py
new file mode 100644 (file)
index 0000000..29d1e3b
--- /dev/null
@@ -0,0 +1,17 @@
+# RUN: %PYTHON %s | FileCheck %s
+
+from mlir_standalone.ir import *
+from mlir_standalone.dialects import (
+  builtin as builtin_d,
+  standalone as standalone_d
+)
+
+with Context():
+  standalone_d.register_dialect()
+  module = Module.parse("""
+    %0 = constant 2 : i32
+    %1 = standalone.foo %0 : i32
+    """)
+  # CHECK: %[[C:.*]] = constant 2 : i32
+  # CHECK: standalone.foo %[[C]] : i32
+  print(str(module))
index 6a49c773e8fe908fe8e594325236bb70c2e6912e..644530f0e37983156bd12c1aa503f9b05c96f508 100644 (file)
@@ -174,18 +174,26 @@ set(PYTHON_SOURCE_DIR "${MLIR_SOURCE_DIR}/lib/Bindings/Python")
 declare_mlir_python_extension(MLIRPythonExtension.Core
   MODULE_NAME _mlir
   ADD_TO_PARENT MLIRPythonSources.Core
+  ROOT_DIR "${PYTHON_SOURCE_DIR}"
   SOURCES
-    ${PYTHON_SOURCE_DIR}/DialectLinalg.cpp  # TODO: Break this out.
-    ${PYTHON_SOURCE_DIR}/DialectSparseTensor.cpp  # TODO: Break this out.
-    ${PYTHON_SOURCE_DIR}/MainModule.cpp
-    ${PYTHON_SOURCE_DIR}/IRAffine.cpp
-    ${PYTHON_SOURCE_DIR}/IRAttributes.cpp
-    ${PYTHON_SOURCE_DIR}/IRCore.cpp
-    ${PYTHON_SOURCE_DIR}/IRInterfaces.cpp
-    ${PYTHON_SOURCE_DIR}/IRModule.cpp
-    ${PYTHON_SOURCE_DIR}/IRTypes.cpp
-    ${PYTHON_SOURCE_DIR}/PybindUtils.cpp
-    ${PYTHON_SOURCE_DIR}/Pass.cpp
+    DialectLinalg.cpp  # TODO: Break this out.
+    DialectSparseTensor.cpp  # TODO: Break this out.
+    MainModule.cpp
+    IRAffine.cpp
+    IRAttributes.cpp
+    IRCore.cpp
+    IRInterfaces.cpp
+    IRModule.cpp
+    IRTypes.cpp
+    PybindUtils.cpp
+    Pass.cpp
+
+    # Headers must be included explicitly so they are installed.
+    Dialects.h
+    Globals.h
+    IRModule.h
+    Pass.h
+    PybindUtils.h
   PRIVATE_LINK_LIBS
     LLVMSupport
   EMBED_CAPI_LINK_LIBS
@@ -202,8 +210,9 @@ declare_mlir_python_extension(MLIRPythonExtension.Core
 
 declare_mlir_python_extension(MLIRPythonExtension.AllPassesRegistration
   MODULE_NAME _mlirAllPassesRegistration
+  ROOT_DIR "${PYTHON_SOURCE_DIR}"
   SOURCES
-    ${PYTHON_SOURCE_DIR}/AllPassesRegistration.cpp
+    AllPassesRegistration.cpp
   PRIVATE_LINK_LIBS
     LLVMSupport
   EMBED_CAPI_LINK_LIBS
@@ -214,8 +223,9 @@ declare_mlir_python_extension(MLIRPythonExtension.AllPassesRegistration
 declare_mlir_python_extension(MLIRPythonExtension.AsyncDialectPasses
   MODULE_NAME _mlirAsyncPasses
   ADD_TO_PARENT MLIRPythonSources.Dialects.async_dialect
+  ROOT_DIR "${PYTHON_SOURCE_DIR}"
   SOURCES
-    ${PYTHON_SOURCE_DIR}/AsyncPasses.cpp
+    AsyncPasses.cpp
   PRIVATE_LINK_LIBS
     LLVMSupport
   EMBED_CAPI_LINK_LIBS
@@ -225,8 +235,9 @@ declare_mlir_python_extension(MLIRPythonExtension.AsyncDialectPasses
 declare_mlir_python_extension(MLIRPythonExtension.Conversions
   MODULE_NAME _mlirConversions
   ADD_TO_PARENT MLIRPythonSources.Passes
+  ROOT_DIR "${PYTHON_SOURCE_DIR}"
   SOURCES
-    ${PYTHON_SOURCE_DIR}/Conversions/Conversions.cpp
+    Conversions/Conversions.cpp
   PRIVATE_LINK_LIBS
     LLVMSupport
   EMBED_CAPI_LINK_LIBS
@@ -236,8 +247,9 @@ declare_mlir_python_extension(MLIRPythonExtension.Conversions
 declare_mlir_python_extension(MLIRPythonExtension.ExecutionEngine
   MODULE_NAME _mlirExecutionEngine
   ADD_TO_PARENT MLIRPythonSources.ExecutionEngine
+  ROOT_DIR "${PYTHON_SOURCE_DIR}"
   SOURCES
-    ${PYTHON_SOURCE_DIR}/ExecutionEngineModule.cpp
+    ExecutionEngineModule.cpp
   PRIVATE_LINK_LIBS
     LLVMSupport
   EMBED_CAPI_LINK_LIBS
@@ -247,8 +259,9 @@ declare_mlir_python_extension(MLIRPythonExtension.ExecutionEngine
 declare_mlir_python_extension(MLIRPythonExtension.GPUDialectPasses
   MODULE_NAME _mlirGPUPasses
   ADD_TO_PARENT MLIRPythonSources.Dialects.gpu
+  ROOT_DIR "${PYTHON_SOURCE_DIR}"
   SOURCES
-    ${PYTHON_SOURCE_DIR}/GPUPasses.cpp
+    GPUPasses.cpp
   PRIVATE_LINK_LIBS
     LLVMSupport
   EMBED_CAPI_LINK_LIBS
@@ -258,8 +271,9 @@ declare_mlir_python_extension(MLIRPythonExtension.GPUDialectPasses
 declare_mlir_python_extension(MLIRPythonExtension.LinalgPasses
   MODULE_NAME _mlirLinalgPasses
   ADD_TO_PARENT MLIRPythonSources.Dialects.linalg
+  ROOT_DIR "${PYTHON_SOURCE_DIR}"
   SOURCES
-    ${PYTHON_SOURCE_DIR}/LinalgPasses.cpp
+    LinalgPasses.cpp
   PRIVATE_LINK_LIBS
     LLVMSupport
   EMBED_CAPI_LINK_LIBS
@@ -269,8 +283,9 @@ declare_mlir_python_extension(MLIRPythonExtension.LinalgPasses
 declare_mlir_python_extension(MLIRPythonExtension.SparseTensorDialectPasses
   MODULE_NAME _mlirSparseTensorPasses
   ADD_TO_PARENT MLIRPythonSources.Dialects.sparse_tensor
+  ROOT_DIR "${PYTHON_SOURCE_DIR}"
   SOURCES
-    ${PYTHON_SOURCE_DIR}/SparseTensorPasses.cpp
+    SparseTensorPasses.cpp
   PRIVATE_LINK_LIBS
     LLVMSupport
   EMBED_CAPI_LINK_LIBS
@@ -280,8 +295,9 @@ declare_mlir_python_extension(MLIRPythonExtension.SparseTensorDialectPasses
 declare_mlir_python_extension(MLIRPythonExtension.Transforms
   MODULE_NAME _mlirTransforms
   ADD_TO_PARENT MLIRPythonSources.Passes
+  ROOT_DIR "${PYTHON_SOURCE_DIR}"
   SOURCES
-    ${PYTHON_SOURCE_DIR}/Transforms/Transforms.cpp
+    Transforms/Transforms.cpp
   PRIVATE_LINK_LIBS
     LLVMSupport
   EMBED_CAPI_LINK_LIBS
index 2e5c4cd575e66c4e16ef8b26454490ce0186ef63..02385f28ead076c35b106f1fedfbc5840ee66089 100644 (file)
@@ -1,4 +1,6 @@
 # RUN: %cmake %mlir_src_root/examples/standalone -DCMAKE_CXX_COMPILER=%host_cxx -DCMAKE_C_COMPILER=%host_cc -DLLVM_ENABLE_LIBCXX=%enable_libcxx -DMLIR_DIR=%mlir_cmake_dir ; %cmake --build . --target check-standalone | tee %t | FileCheck %s
 
-# CHECK: Passed: 4
+# Note: The number of checked tests is not important. The command will fail
+# if any fail.
+# CHECK: Passed
 # UNSUPPORTED: windows, android