Background
LazyVim is a Neovim distribution built on lazy.nvim that provides a modern, batteries-included editor experience. However, lazy.nvim requires Neovim to be built with LuaJIT, and upstream LuaJIT does not support RISC-V.
This post documents the full process of building and running Neovim + LazyVim on a RISC-V Linux environment (Ubuntu/Debian), including all the pitfalls and solutions.
Test environment:
- Architecture: riscv64gc
- OS: Ubuntu (bianbu/resolute)
- Board: K3 development board
1. Building RISC-V LuaJIT
Upstream LuaJIT doesn’t support RISC-V, but there’s an actively maintained community port: IgnotaYun/LuaJIT (riscv branch). The project has green CI and is production-ready.
1.1 Install build dependencies
| |
1.2 Build LuaJIT
| |
1.3 Configure dynamic linker
If LuaJIT was installed to /usr/local/lib, make sure the system linker can find it:
| |
1.4 Verify
| |
2. Building Neovim
2.1 Install build dependencies
| |
2.2 Get the source
| |
2.3 Build third-party dependencies
The key here is -DUSE_BUNDLED_LUAJIT=OFF — this tells Neovim to skip downloading its bundled LuaJIT and use the system-installed RISC-V LuaJIT instead.
| |
2.4 Build Neovim
| |
If cmake can’t find the system LuaJIT, specify the paths manually:
| |
You can locate the paths with:
| |
2.5 Install
| |
2.6 Verify
| |
The output should contain LuaJIT 2.1.xxx, confirming Neovim is correctly linked against the RISC-V LuaJIT.
3. Installing LazyVim
See the official docs: https://www.lazyvim.org/installation
3.1 Back up existing config (if any)
| |
3.2 Clone LazyVim Starter
| |
3.3 Launch Neovim
| |
On first launch, lazy.nvim will automatically download and install all plugins.
4. Fixing tree-sitter-cli
4.1 Problem
LazyVim uses tree-sitter for syntax highlighting. The tree-sitter-cli npm package has no prebuilt binary for RISC-V, so :TSInstall fails.
4.2 Solution: Install via Cargo
| |
If cargo is not installed:
| |
Note: On RISC-V,
BINDGEN_EXTRA_CLANG_ARGSmay need to be set for some crates that use bindgen:
1export BINDGEN_EXTRA_CLANG_ARGS="--target=riscv64-linux-gnu -I/usr/include -I/usr/include/riscv64-linux-gnu"
5. Fixing lua_ls (Lua Language Server)
5.1 Problem
Mason can’t install lua-language-server on RISC-V because there’s no prebuilt binary.
5.2 Solution: Build from source
| |
Add to PATH:
| |
5.3 Tell LazyVim to skip Mason for lua_ls
| |
6. Fixing blink.cmp
6.1 Problem
On startup, nvim shows:
blink.cmp ENOENT: no such file or directory: ...
blink.cmp Falling back to Lua implementation due to error while downloading pre-built binary
6.2 Cause
blink.cmp is LazyVim’s default completion plugin. It includes a high-performance fuzzy matching library written in Rust. On startup, it tries to download a prebuilt .so file, but there’s no RISC-V build available, so it falls back to a pure Lua implementation.
6.3 Solution: Build the native library locally
Enter the plugin directory:
| |
Build:
| |
The output is at target/release/libblink_cmp_fuzzy.so. blink.cmp’s Lua loader automatically searches <plugin-root>/target/release/ for this file — no manual copying needed.
Verify:
| |
If the error persists, disable prebuilt downloads in the config (optional):
| |
Restart nvim — blink.cmp will now use the locally compiled native Rust library.
Note: After blink.cmp plugin updates, you may need to re-run
cargo build --releasesince the Rust source may have changed.
7. Fixing snacks.nvim indent/scope Error
7.1 Problem
Opening a file in nvim triggers:
Error in BufReadPost Autocommands for "*":
Lua callback: ...snacks.nvim/lua/snacks/scope.lua:136: attempt to index local 'self' (a nil value)
7.2 Cause
It’s unclear whether this is a snacks.nvim bug or a RISC-V LuaJIT compatibility issue.
The likely cause: snacks/scope.lua line 136 uses the __eq metamethod to compare two scope objects. Per the Lua spec, __eq should only be invoked when both operands are the same type and both have __eq. However, the IgnotaYun RISC-V LuaJIT branch may have a subtle behavioral difference in the __eq JIT compilation path, causing nil values to unexpectedly enter the metamethod call, triggering the error.
7.3 Solution: Disable snacks.nvim indent feature
| |
Impact: You lose indent guide lines and current scope highlighting. This is purely visual — it doesn’t affect editing, LSP, completion, treesitter, or any core functionality.
8. Summary
| Component | Problem | Solution |
|---|---|---|
| LuaJIT | No RISC-V support upstream | Use IgnotaYun/LuaJIT riscv branch |
| Neovim | Bundled LuaJIT doesn’t support RV | -DUSE_BUNDLED_LUAJIT=OFF to use system LuaJIT |
| tree-sitter-cli | No prebuilt binary | cargo install tree-sitter-cli |
| lua_ls | No Mason prebuilt binary | Build from source + mason = false |
| blink.cmp | No prebuilt .so | cargo build --release in plugin directory |
| snacks.nvim | indent/scope triggers LuaJIT __eq anomaly | indent = { enabled = false } |
Recommended shell environment variables
| |
After completing all the steps above, you’ll have a fully functional LazyVim development environment on RISC-V.