☝️ 写在前面
MLIR项目的构建和环境配置绝不是一件易事, 首先建议使用Linux系统, 如果你在Windows上, 请务必使用WSL, 在Windows下开发MLIR绝对是自讨苦吃😫. 其次, 如果你的Linux发行版提供了LLVM(这个一般都会有)和MLIR(这个貌似Arch上就没有)的预构建包,
建议直接从发行版的包管理器安装, 因为MLIR的编译和链接时间非常长. 最后, 如果你需要从源码编译和安装LLVM/MLIR, 请使用ccache
缓存编译结果. 入门MLIR的前提是你对C/C++
的编译链接过程有一定的了解, 否则MLIR的链接能让你只用十几行代码就吐出几千行的链接错误. 如果不幸运的是, 你对这些都没有了解, 那最好先补足功课再开始学习MLIR, 否则会给你的心灵带来极大的震撼. 以下内容均假设你已有一定的编译链接知识, 并且默认你会使用cmake
的最基础功能.
😫 环境配置
🤓 安装MLIR/LLVM
如果你的发行版有提供预构建包, 那么
sudo apt install llvm-toolchain # On Debian/Ubuntu 已经包含了LLVM/MLIR
sudo dnf install llvm llvm-devel llvm-libs mlir mlir-devel # On Fedora
sudo pacman -S llvm # On Arch
很遗憾的是, Arch上没有MLIR的预构建包, 因此接下来介绍如何从源码编译
git clone https://github.com/llvm/llvm-project.git
cd llvm-project
git checkout llvmorg-19.1.7 # 选择你自己想要的版本
mkdir build && cd build
cmake -G Ninja ../llvm \
-DLLVM_ENABLE_PROJECTS=mlir \
-DLLVM_BUILD_EXAMPLES=ON \
-DLLVM_TARGETS_TO_BUILD="Native;NVPTX;AMDGPU" \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_ENABLE_ASSERTIONS=ON \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DLLVM_CCACHE_BUILD=ON \
-DCMAKE_INSTALL_PREFIX=/path/to/install \
# -DLLVM_ENABLE_RTTI=ON \ 启用`RTTI`, LLVM默认禁用
# -DLLVM_ENABLE_LLD=ON \ 启用`lld`编译器
# -DLLVM_USE_SANITIZER="Address;Undefined" \ 需要`compiler-rt`支持
# -DMLIR_INCLUDE_INTEGRATION_TESTS=ON \
cmake --build . --target check-mlir
编译过程建议启用lld
编译器, 因为编译速度能比Linux上默认的ld
快非常多(虽然还是很慢). 同时建议启用ccache
编译缓存. 如果你要使用两个sanitizer
, 那么需要先安装compiler-rt
(对于clang
系编译器, 如果你是用gcc
系, 那Linux上一般已经装好了需要的libgcc
库).
重点是指定CMAKE_INSTALL_PREFIX
, 这个路径是编译完成后要安装MLIR静态库/头文件/CMake Config
文件的路径, 建议不要直接用/usr/local
或者/usr
, 防止覆盖系统原本的LLVM库引发问题. 可以指定在一个用户目录下, 例如
/home/your_username/workspace
|-- llvm-project
| |-- build
|-- install
|-- your_mlir_project
然后等待漫长的编译过程. 上面的cmake
的目标check-mlir
大概率是失败的, 因为MLIR里面其实有UB和内存泄漏的问题, 所以会被sanitizer
检测到. 但是貌似用gcc
编译不会报错, 那这么看应该是写出UB了.
编译完成后
ninja install
就能将MLIR的头文件和库安装到指定的路径下.
🤓 检验安装结果
首先新建你的MLIR项目, 也可以直接在llvm-project
下面新建目录, 例如
├── llvm-project
├ ├── build
├── install
├── your_project
├ ├── CMakeLists.txt
├ ├── main.cpp
├ ├── test.mlir
然后编写CMakeLists.txt
文件
cmake_minimum_required(VERSION 3.12)
project(MLIR-Toy VERSION 0.0 LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # for clangd
set(MLIR_DIR /path/to/install/lib/cmake/mlir) # set /path/to/install
find_package(MLIR REQUIRED CONFIG)
list(APPEND CMAKE_MODULE_PATH ${MLIR_CMAKE_DIR})
list(APPEND CMAKE_MODULE_PATH ${LLVM_CMAKE_DIR})
include(TableGen)
include(AddLLVM)
include(AddMLIR)
include(HandleLLVMOptions)
include_directories(${MLIR_INCLUDE_DIRS})
include_directories(${LLVM_INCLUDE_DIRS})
add_executable(mlir_toy main.cpp)
target_link_options(mlir-toy PRIVATE -fuse-ld=lld) # if you use lld
target_link_libraries(mlir-toy
PRIVATE
MLIRIR
MLIRParser
MLIRArithDialect
MLIRFuncDialect
-fsanitize=address # if you enabled AddressSanitizer when building MLIR
)
然后添加main.cpp
文件
#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/IR/AsmState.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/Parser/Parser.h"
#include "llvm/Support/raw_ostream.h"
using namespace mlir;
int main(int argc, char **argv) {
MLIRContext ctx;
ctx.loadDialect<func::FuncDialect, arith::ArithDialect>();
auto src = parseSourceFile<ModuleOp>(argv[1], &ctx);
src->print(llvm::outs());
src->dump();
return 0;
}
再添加一个test.mlir
文件
func.func @test(%a: i32, %b: i32) -> i32 {
%c = arith.addi %a, %b : i32
func.return %c : i32
}
编译并且运行程序
mkdir build && cd build
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ..
ninja
./mlir_toy ../test.mlir
如果能够正常链接和编译, 那么就说明环境配置基本上成功了. 如果你在编译过程中遇到问题, 主要检查CMake
输出的错误信息, 很多情况下是链接库少了, 根据报错找漏掉的库加上即可. 可以通过ninja -v -n
查看编译过程的具体指令.
🤓 配置IDE
如果使用VSCode, 建议使用clangd
插件, 官方的Intellisense
很容易卡爆. 当然如果你的项目大起来了, clangd
插件也未必好用, 有的时候会崩溃, 可以通过Command Palette
中clangd: Restart Language Server
重启clangd
服务器. 如果
电脑配置不差的话, 建议直接上CLion. 索引速度快得多, 而且也不容易崩溃.