From d04fa9c39822a89fad14a6cf09135d3cb65a058b Mon Sep 17 00:00:00 2001 From: Victor Guerra Date: Mon, 16 Oct 2023 09:40:30 +0200 Subject: [PATCH] Generating build files with cmake (#21) * ignoring cmake related build files * Adding LLVM dependency as external dependecy. Using git submodules. * Initial workspace setup with CMake * Including tests into the CMake build. Adding the LLVM module so that all `lit` related functions are available. A new target is made available for running tests: `check-mlir-tutorial`. * Including tools directory into the CMake build So that `tutorial-opt` can be built. This introduces as well a new target `tutorial-opt`. * Adding affine full unroll related passes to cmake build This introduces a new mlir lib: `AffineFullUnroll` and a new build target to build it: `MLIRAffineFullUnrollPasses`. * Adding tablgen cmake module to have access to all tablgen related cmake statements. * add mlir include dirs * Adding mul to add related passes to cmake build This introduces a new mlir lib: `MulToAdd` and a new build target to build it: `MLIRMulToAddPasses`. * Renaming `PolyOps.td` to `Poly.td` So that on the cmake side of things we can use the `add_mlir_dialect` macro without too many changes to the include directives. Ref: https://github.com/llvm/llvm-project/blob/main/mlir/cmake/modules/AddMLIR.cmake#L166-L177 * ignoring vs code metafiles plus compilation database files. * Adding poly dialect lib to cmake build * Adding CI for cmake build. * Adding canonicalizers to cmake build * Inlining cmake commands for Poly dialect generation. Instead of using `add_mlir_dialect` helper function for dialect generation, we inline it here so that we can have control over the naming of generated `*.inc` files. This avoids renaming of `PolyOps.td` so that cmake builds work well on the existing source code. --- .github/workflows/build_and_test.yml | 2 +- .github/workflows/build_and_test_cmake.yml | 47 +++++++++++++++++++ .gitignore | 14 ++++++ .gitmodules | 3 ++ CMakeLists.txt | 27 +++++++++++ externals/llvm-project | 1 + lib/CMakeLists.txt | 2 + lib/Dialect/CMakeLists.txt | 1 + lib/Dialect/Poly/CMakeLists.txt | 27 +++++++++++ lib/Dialect/Poly/PolyDialect.td | 2 +- lib/Transform/Affine/CMakeLists.txt | 13 ++++++ lib/Transform/Arith/CMakeLists.txt | 12 +++++ lib/Transform/CMakeLists.txt | 2 + tests/CMakeLists.txt | 18 ++++++++ tests/lit.cmake.cfg.py | 52 ++++++++++++++++++++++ tests/lit.cmake.site.cfg.py.in | 13 ++++++ tools/CMakeLists.txt | 19 ++++++++ 17 files changed, 253 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/build_and_test_cmake.yml create mode 100644 .gitmodules create mode 100644 CMakeLists.txt create mode 160000 externals/llvm-project create mode 100644 lib/CMakeLists.txt create mode 100644 lib/Dialect/CMakeLists.txt create mode 100644 lib/Dialect/Poly/CMakeLists.txt create mode 100644 lib/Transform/Affine/CMakeLists.txt create mode 100644 lib/Transform/Arith/CMakeLists.txt create mode 100644 lib/Transform/CMakeLists.txt create mode 100644 tests/CMakeLists.txt create mode 100644 tests/lit.cmake.cfg.py create mode 100644 tests/lit.cmake.site.cfg.py.in create mode 100644 tools/CMakeLists.txt diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index d749cb9..5f32cbb 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -1,4 +1,4 @@ -name: Build and Test +name: Build and Test w/Bazel permissions: read-all on: push: diff --git a/.github/workflows/build_and_test_cmake.yml b/.github/workflows/build_and_test_cmake.yml new file mode 100644 index 0000000..8e0cf61 --- /dev/null +++ b/.github/workflows/build_and_test_cmake.yml @@ -0,0 +1,47 @@ +name: Build and Test w/CMake +permissions: read-all +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: seanmiddleditch/gha-setup-ninja@master + + - name: Install prerequisites + run: | + sudo apt update + sudo apt install -y uuid-dev + + - name: Cache LLVM artifact + id: cache-llvm + uses: actions/cache@v3 + with: + path: | + ./externals/llvm-project + key: ${{ runner.os }}-norm-${{ hashFiles('externals/llvm-project/llvm/CMakeLists.txt') }} + + - name: Build LLVM + if: steps.cache-llvm.outputs.cache-hit != 'true' + run: | + git submodule update --init --recursive + cd externals/llvm-project + mkdir build && cd build + cmake -G Ninja ../llvm -DLLVM_ENABLE_PROJECTS=mlir -DLLVM_BUILD_EXAMPLES=ON -DLLVM_ENABLE_ASSERTIONS=ON -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_RTTI=ON -DLLVM_TARGETS_TO_BUILD="host" + cmake --build . --target check-mlir + + - name: Build and test mlir-tutorial + run: | + mkdir build && cd build + cmake -DLLVM_DIR=$PWD/../externals/llvm-project/build/lib/cmake/llvm -DMLIR_DIR=$PWD/../externals/llvm-project/build/lib/cmake/mlir .. + cmake --build . --target MLIRAffineFullUnrollPasses + cmake --build . --target MLIRMulToAddPasses + cmake --build . --target mlir-headers + cmake --build . --target tutorial-opt + cmake --build . --target check-mlir-tutorial \ No newline at end of file diff --git a/.gitignore b/.gitignore index c4c1737..be58b3d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,17 @@ bazel-bin bazel-mlir-tutorial bazel-out bazel-testlogs + +# cmake related files +# ignore the user specified CMake presets in subproject directories. +/*/CMakeUserPresets.json + +# Nested build directory +/build* + +# Visual Studio built-in CMake configuration +.vscode* +/CMakeSettings.json +# Compilation databases +compile_commands.json +tablegen_compile_commands.yml \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..32e0230 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "externals/llvm-project"] + path = externals/llvm-project + url = https://github.com/llvm/llvm-project.git diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..56aab9f --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.20.0) + +project(mlir-tutorial LANGUAGES CXX C) + +set(CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard to conform to") + +find_package(MLIR REQUIRED CONFIG) + +message(STATUS "Using MLIRConfig.cmake in: ${MLIR_DIR}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +set(MLIR_BINARY_DIR ${CMAKE_BINARY_DIR}) + +include(AddLLVM) +include(TableGen) + +list(APPEND CMAKE_MODULE_PATH "${MLIR_CMAKE_DIR}") +include(AddMLIR) +include_directories(${LLVM_INCLUDE_DIRS}) +include_directories(${MLIR_INCLUDE_DIRS}) +include_directories(${PROJECT_SOURCE_DIR}) +include_directories(${PROJECT_SOURCE_DIR}/externals/llvm-project) +include_directories(${PROJECT_BINARY_DIR}) + +add_subdirectory(tests) +add_subdirectory(tools) +add_subdirectory(lib) \ No newline at end of file diff --git a/externals/llvm-project b/externals/llvm-project new file mode 160000 index 0000000..cd5fcea --- /dev/null +++ b/externals/llvm-project @@ -0,0 +1 @@ +Subproject commit cd5fcea6d4c70a7328ca9538c9098d9f5af69682 diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt new file mode 100644 index 0000000..f66a974 --- /dev/null +++ b/lib/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(Dialect) +add_subdirectory(Transform) \ No newline at end of file diff --git a/lib/Dialect/CMakeLists.txt b/lib/Dialect/CMakeLists.txt new file mode 100644 index 0000000..aff4d19 --- /dev/null +++ b/lib/Dialect/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(Poly) \ No newline at end of file diff --git a/lib/Dialect/Poly/CMakeLists.txt b/lib/Dialect/Poly/CMakeLists.txt new file mode 100644 index 0000000..628253c --- /dev/null +++ b/lib/Dialect/Poly/CMakeLists.txt @@ -0,0 +1,27 @@ +# Inlining `add_mlir_dialect(Poly poly)` commands so that +# we can custom name `*.inc` generated files. +set(LLVM_TARGET_DEFINITIONS PolyOps.td) +mlir_tablegen(PolyOps.h.inc -gen-op-decls) +mlir_tablegen(PolyOps.cpp.inc -gen-op-defs) +mlir_tablegen(PolyTypes.h.inc -gen-typedef-decls -typedefs-dialect=poly) +mlir_tablegen(PolyTypes.cpp.inc -gen-typedef-defs -typedefs-dialect=poly) +mlir_tablegen(PolyDialect.h.inc -gen-dialect-decls -dialect=poly) +mlir_tablegen(PolyDialect.cpp.inc -gen-dialect-defs -dialect=poly) +add_public_tablegen_target(MLIRPolyOpsIncGen) +add_dependencies(mlir-headers MLIRPolyOpsIncGen) + +add_mlir_doc(PolyDialect PolyDialect Poly/ -gen-dialect-doc) + +set(LLVM_TARGET_DEFINITIONS PolyPatterns.td) +mlir_tablegen(PolyCanonicalize.cpp.inc -gen-rewriters) +add_public_tablegen_target(MLIRPolyCanonicalizationIncGen) + +add_mlir_dialect_library(MLIRPoly + PolyDialect.cpp + PolyOps.cpp + + ADDITIONAL_HEADER_DIRS + ${PROJECT_SOURCE_DIR}/lib/Dialect/Poly + + LINK_LIBS PUBLIC + ) \ No newline at end of file diff --git a/lib/Dialect/Poly/PolyDialect.td b/lib/Dialect/Poly/PolyDialect.td index c0214dd..b7df1b3 100644 --- a/lib/Dialect/Poly/PolyDialect.td +++ b/lib/Dialect/Poly/PolyDialect.td @@ -1,7 +1,7 @@ #ifndef LIB_DIALECT_POLY_POLYDIALECT_TD_ #define LIB_DIALECT_POLY_POLYDIALECT_TD_ -include "mlir/IR/DialectBase.td" +include "mlir/IR/OpBase.td" def Poly_Dialect : Dialect { let name = "poly"; diff --git a/lib/Transform/Affine/CMakeLists.txt b/lib/Transform/Affine/CMakeLists.txt new file mode 100644 index 0000000..dd3340b --- /dev/null +++ b/lib/Transform/Affine/CMakeLists.txt @@ -0,0 +1,13 @@ +add_mlir_library(AffineFullUnroll + AffineFullUnroll.cpp + AffineFullUnrollPatternRewrite.cpp + + ${PROJECT_SOURCE_DIR}/lib/Transform/Affine/ + ADDITIONAL_HEADER_DIRS + LINK_LIBS PUBLIC +) + +set(LLVM_TARGET_DEFINITIONS Passes.td) +mlir_tablegen(Passes.h.inc -gen-pass-decls -name Affine) +add_public_tablegen_target(MLIRAffineFullUnrollPasses) +add_mlir_doc(Passes AffinePasses ./ -gen-pass-doc) \ No newline at end of file diff --git a/lib/Transform/Arith/CMakeLists.txt b/lib/Transform/Arith/CMakeLists.txt new file mode 100644 index 0000000..f73be7c --- /dev/null +++ b/lib/Transform/Arith/CMakeLists.txt @@ -0,0 +1,12 @@ +add_mlir_library(MulToAdd + MulToAdd.cpp + + ${PROJECT_SOURCE_DIR}/lib/Transform/Arith/ + ADDITIONAL_HEADER_DIRS + LINK_LIBS PUBLIC +) + +set(LLVM_TARGET_DEFINITIONS Passes.td) +mlir_tablegen(Passes.h.inc -gen-pass-decls -name Arith) +add_public_tablegen_target(MLIRMulToAddPasses) +add_mlir_doc(Passes ArithPasses ./ -gen-pass-doc) \ No newline at end of file diff --git a/lib/Transform/CMakeLists.txt b/lib/Transform/CMakeLists.txt new file mode 100644 index 0000000..9caa085 --- /dev/null +++ b/lib/Transform/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(Affine) +add_subdirectory(Arith) \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..73f3503 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,18 @@ +configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/lit.cmake.site.cfg.py.in + ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py + MAIN_CONFIG + ${CMAKE_CURRENT_SOURCE_DIR}/lit.cmake.cfg.py +) + +set (MLIR_TUTORIAL_TEST_DEPENDS + FileCheck count not + mlir-opt + mlir-cpu-runner + # tutorial-opt +) + +add_lit_testsuite(check-mlir-tutorial "Running the MLIR tutorial regression tests" + ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${MLIR_TUTORIAL_TEST_DEPENDS} +) \ No newline at end of file diff --git a/tests/lit.cmake.cfg.py b/tests/lit.cmake.cfg.py new file mode 100644 index 0000000..c316a10 --- /dev/null +++ b/tests/lit.cmake.cfg.py @@ -0,0 +1,52 @@ +# -*- Python -*- + +import os + +import lit.formats +import lit.util + +from lit.llvm import llvm_config + +# Configuration file for the 'lit' test runner. + +# name: The name of this test suite. +config.name = "MLIR_TUTORIAL" + +config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell) + +# suffixes: A list of file extensions to treat as test files. +config.suffixes = [".mlir"] + +# test_source_root: The root path where tests are located. +config.test_source_root = os.path.dirname(__file__) + +# test_exec_root: The root path where tests should be run. +config.test_exec_root = os.path.join(config.project_binary_dir, "tests") + +config.substitutions.append(("%PATH%", config.environment["PATH"])) +config.substitutions.append(("%shlibext", config.llvm_shlib_ext)) + +llvm_config.with_system_environment(["HOME", "INCLUDE", "LIB", "TMP", "TEMP"]) + +llvm_config.use_default_substitutions() + +# excludes: A list of directories to exclude from the testsuite. The 'Inputs' +# subdirectories contain auxiliary inputs for various tests in their parent +# directories. +config.excludes = ["Inputs", "Examples", "CMakeLists.txt", "README.txt", "LICENSE.txt"] + +# test_exec_root: The root path where tests should be run. +config.test_exec_root = os.path.join(config.project_binary_dir, "test") +config.project_tools_dir = os.path.join(config.project_binary_dir, "tools") + +# Tweak the PATH to include the tools dir. +llvm_config.with_environment("PATH", config.llvm_tools_dir, append_path=True) + +tool_dirs = [config.project_tools_dir, config.llvm_tools_dir] +tools = [ + "mlir-opt", + "mlir-cpu-runner", + "tutorial-opt" +] + +llvm_config.add_tool_substitutions(tools, tool_dirs) \ No newline at end of file diff --git a/tests/lit.cmake.site.cfg.py.in b/tests/lit.cmake.site.cfg.py.in new file mode 100644 index 0000000..c6db456 --- /dev/null +++ b/tests/lit.cmake.site.cfg.py.in @@ -0,0 +1,13 @@ +@LIT_SITE_CFG_IN_HEADER@ + +config.llvm_tools_dir = lit_config.substitute("@LLVM_TOOLS_DIR@") +config.mlir_obj_dir = "@MLIR_BINARY_DIR@" +config.llvm_shlib_ext = "@SHLIBEXT@" +config.project_binary_dir = "@PROJECT_BINARY_DIR@" +config.project_source_dir = "@PROJECT_SOURCE_DIR@" + +import lit.llvm +lit.llvm.initialize(lit_config, config) + +# Let the main config do the real work. +lit_config.load_config(config, "@PROJECT_SOURCE_DIR@/tests/lit.cmake.cfg.py") \ No newline at end of file diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt new file mode 100644 index 0000000..930bb80 --- /dev/null +++ b/tools/CMakeLists.txt @@ -0,0 +1,19 @@ +get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS) +get_property(conversion_libs GLOBAL PROPERTY MLIR_CONVERSION_LIBS) + +set (LIBS + ${dialect_libs} + ${conversion_libs} + MLIRPoly + AffineFullUnroll + MulToAdd + MLIROptLib + MLIRPass +) + +add_llvm_executable(tutorial-opt tutorial-opt.cpp) + +llvm_update_compile_flags(tutorial-opt) +target_link_libraries(tutorial-opt PRIVATE ${LIBS}) + +mlir_check_all_link_libraries(tutorial-opt) \ No newline at end of file