在RISC-V上安装并使用LazyVim
背景
LazyVim 是基于 lazy.nvim 的 Neovim 预配置发行版,提供了开箱即用的现代编辑器体验。然而,lazy.nvim 强制要求 Neovim 必须使用 LuaJIT 构建,而官方 LuaJIT 并不支持 RISC-V 架构。
本文记录了在 RISC-V Linux 环境(Ubuntu/Debian)上,从零开始编译安装 Neovim + LazyVim 的完整流程,包括所有踩坑和解决方案。
测试环境:
- 架构:riscv64gc
- 系统:Ubuntu (bianbu/resolute)
- 板卡:K3 开发板
1. 编译安装 RISC-V LuaJIT
官方 LuaJIT 不支持 RISC-V,但社区有一个活跃的移植分支:IgnotaYun/LuaJIT(riscv 分支)。该项目持续维护,CI 全绿,可用于生产。
1.1 安装编译依赖
sudo apt install -y \ |
1.2 编译 LuaJIT
git clone -b riscv https://github.com/IgnotaYun/LuaJIT.git ~/luajit-riscv |
1.3 配置动态链接
如果 LuaJIT 安装到了 /usr/local/lib,需要让系统链接器能找到它:
echo "/usr/local/lib" | sudo tee /etc/ld.so.conf.d/luajit.conf |
1.4 验证
luajit -v |
2. 编译安装 Neovim
2.1 安装编译依赖
sudo apt install -y \ |
2.2 获取源码
git clone https://github.com/neovim/neovim.git ~/neovim |
2.3 编译第三方依赖
关键:使用 -DUSE_BUNDLED_LUAJIT=OFF 跳过 Neovim 自带的 LuaJIT 下载,改用系统安装的 RISC-V LuaJIT。
cmake -S cmake.deps -B .deps \ |
2.4 编译 Neovim 本体
cmake -S . -B build \ |
如果 cmake 找不到系统 LuaJIT,手动指定路径:
cmake -S . -B build \ |
可以用以下命令确认路径:
find /usr -name "luajit.h" 2>/dev/null |
2.5 安装
sudo cmake --install build |
2.6 验证
nvim --version |
输出中应包含 LuaJIT 2.1.xxx 字样,说明 Neovim 已正确链接 RISC-V LuaJIT。
3. 安装 LazyVim
参考官方文档:https://www.lazyvim.org/installation
3.1 备份已有配置(如有)
mv ~/.config/nvim{,.bak} |
3.2 克隆 LazyVim Starter
git clone https://github.com/LazyVim/starter ~/.config/nvim |
3.3 启动 Neovim
nvim |
首次启动时 lazy.nvim 会自动下载并安装所有插件。
4. 解决 tree-sitter-cli 缺失问题
4.1 问题现象
启动 nvim 后,nvim-treesitter 报错:
❌ tree-sitter (CLI) |
4.2 原因
tree-sitter-cli 通过 Mason 安装时会下载预编译二进制,但官方没有提供 RISC-V 架构的预编译包。
4.3 解决方案:通过 Rust/cargo 从源码编译
首先安装 Rust(如果还没有):
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh |
在 RISC-V 上,Rust 的 bindgen 会遇到 clang target triple 不匹配的问题,需要安装依赖并设置环境变量:
sudo apt install -y libclang-dev clang llvm |
# 加入 ~/.zshrc 或 ~/.bashrc,以后所有 cargo build 都需要 |
然后编译安装:
cargo install tree-sitter-cli |
验证:
tree-sitter --version |
5. 解决 lua_ls (Lua Language Server) 安装失败
5.1 问题现象
Mason 报错无法安装 lua_ls。
5.2 原因
与 tree-sitter-cli 相同,Mason 下载预编译二进制,没有 RISC-V 版本。
5.3 解决方案:从源码编译 lua_ls
cd ~ |
将编译产物加入 PATH:
echo 'export PATH="$HOME/lua-language-server/bin:$PATH"' >> ~/.zshrc |
然后在 LazyVim 配置中告诉 nvim-lspconfig 不要通过 Mason 管理 lua_ls:
-- ~/.config/nvim/lua/plugins/lsp.lua |
6. 解决 blink.cmp 报错
6.1 问题现象
启动 nvim 时报错:
blink.cmp ENOENT: no such file or directory: ... |
6.2 原因
blink.cmp 是 LazyVim 默认的补全插件,它包含一个用 Rust 编写的高性能 fuzzy matching 库。插件启动时会尝试下载预编译的 .so 文件,但没有 RISC-V 版本,因此报错并 fallback 到纯 Lua 实现。
6.3 解决方案:在本机编译 blink.cmp 的 Rust 原生库
进入插件目录:
cd ~/.local/share/nvim/lazy/blink.cmp |
编译:
cargo build --release |
编译完成后,产物位于 target/release/libblink_cmp_fuzzy.so。blink.cmp 的 Lua 加载代码会自动在 <插件根目录>/target/release/ 下搜索该文件,无需手动移动。
验证产物存在:
ls target/release/libblink_cmp_fuzzy.so |
然后在 LazyVim 配置中禁用预编译下载(可省略, 如果还报错就执行该步骤):
-- ~/.config/nvim/lua/plugins/blink.lua |
重启 nvim,blink.cmp 将使用本地编译的原生 Rust 库。
注意: 每次 blink.cmp 插件更新后,可能需要重新执行
cargo build --release,因为 Rust 源码可能有变更。
7. 解决 snacks.nvim indent/scope 报错
7.1 问题现象
用 nvim 打开 Lua 文件(或其他文件)时报错:
Error in BufReadPost Autocommands for "*": |
7.2 原因
尚不确定是 snacks.nvim 本身的 bug 还是 RISC-V LuaJIT 实现的兼容性问题。
推测是后者:snacks/scope.lua 在第 136 行使用了 __eq metamethod 比较两个 scope 对象。在标准 LuaJIT 中,当比较对象之一为 nil 时,__eq 不应被触发(Lua 规范规定只有两个操作数类型相同且都有 __eq 时才调用元方法)。但 IgnotaYun 的 RISC-V LuaJIT 分支可能在 __eq 的 JIT 编译路径上存在细微行为差异,导致 nil 值意外进入了元方法调用,从而触发 attempt to index local 'self' (a nil value) 错误。
7.3 解决方案:禁用 snacks.nvim 的 indent 功能
-- ~/.config/nvim/lua/plugins/snacks.lua |
影响:失去缩进参考线和当前代码块 scope 高亮。这是纯视觉功能,不影响编辑、LSP、补全、treesitter 等核心功能。
8. 总结
| 组件 | 问题 | 解决方式 |
|---|---|---|
| LuaJIT | 官方不支持 RISC-V | 使用 IgnotaYun/LuaJIT riscv 分支 |
| Neovim | 默认拉取不支持 RV 的 LuaJIT | -DUSE_BUNDLED_LUAJIT=OFF 使用系统 LuaJIT |
| tree-sitter-cli | 无预编译包 | cargo install tree-sitter-cli |
| lua_ls | Mason 无预编译包 | 源码编译 + mason = false |
| blink.cmp | 无预编译 .so | 插件目录内 cargo build --release |
| snacks.nvim | indent/scope 触发 LuaJIT __eq 异常 | 配置 indent = { enabled = false } |
建议写入 shell 配置的环境变量
# ~/.zshrc 或 ~/.bashrc |
完成以上步骤后,你将在 RISC-V 上拥有一个功能完整的 LazyVim 开发环境。
