3. QEMU 源码编译与安装:从源码获取到 RISC-V 目标支持
这一章,我们来搞定 QEMU 的源码编译。说实话,很多初学者喜欢直接用 apt 装现成的包,图省事。但我个人建议,做嵌入式开发,尤其是 RISC-V 这种还在快速演进的架构,最好还是从源码编译。为什么?因为你能拿到最新的特性,还能按需裁剪,出了问题也知道去哪翻代码。
好,我们一步步来。
3.1 获取 QEMU 源码
源码获取方式很简单,就两种:Git 克隆或下载压缩包。我推荐用 Git,方便后续切换版本和打补丁。
核心命令:
# 方式一:Git 克隆(推荐)
git clone https://gitlab.com/qemu-project/qemu.git
cd qemu
# 方式二:下载稳定版压缩包
wget https://download.qemu.org/qemu-8.2.0.tar.xz
tar -xf qemu-8.2.0.tar.xz
cd qemu-8.2.0
这里有个小坑。我曾经在某个项目中直接用 master 分支编译,结果发现某个 RISC-V 扩展的模拟有 bug。后来切到稳定分支才搞定。所以我的建议是:学习用稳定版,开发用 Git 分支。
| 获取方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Git 克隆 | 版本切换灵活,可打补丁 | 首次下载较大 | 开发、调试、定制 |
| 压缩包 | 体积小,解压即用 | 版本固定,不易更新 | 快速搭建、学习 |
3.2 配置 RISC-V 目标支持
源码拿到手,接下来就是配置。QEMU 的配置系统基于 Meson,比以前用的 configure 脚本要清晰不少。但选项依然很多,我们只关心 RISC-V 相关的。
说白了,你要告诉 QEMU:我要编译哪些目标架构。RISC-V 分 32 位和 64 位,还有软浮点和硬浮点之分。我们做嵌入式调试,一般用 riscv64-softmmu 就够了。
我的配置习惯:
mkdir build
cd build
../configure --target-list=riscv64-softmmu \
--enable-debug \
--enable-kvm \
--enable-virtfs \
--prefix=/opt/qemu-riscv
这里 --enable-debug 会保留调试符号,方便后续用 GDB 调试 QEMU 本身。--prefix 指定安装路径,避免污染系统目录。
你可能会问:为什么只编一个目标?因为全编的话,时间够你喝两杯咖啡。我刚开始不懂,直接 ./configure 不加参数,结果编译了快一个小时。后来学乖了,只编需要的。
来看一下配置选项的对比:
| 配置选项 | 作用 | 我的建议 |
|---|---|---|
--target-list=riscv64-softmmu |
只编译 RISC-V 64 位系统仿真 | 必选,节省编译时间 |
--enable-debug |
保留调试信息 | 强烈推荐,方便排查问题 |
--enable-kvm |
启用 KVM 加速 | 如果宿主机支持,建议开启 |
--enable-virtfs |
支持主机与虚拟机文件共享 | 调试时传文件很方便 |
--prefix=/opt/qemu-riscv |
指定安装路径 | 推荐,便于管理多个版本 |
3.3 编译与安装
配置没问题,接下来就是编译。这一步其实没什么技术含量,就是等。不过有几个细节要注意。
编译前的依赖检查:
我曾经在一台刚装好的 Ubuntu 上直接编译,结果报了一堆缺少依赖的错误。后来我学乖了,先装好基础依赖包:
sudo apt install build-essential pkg-config \
libglib2.0-dev libpixman-1-dev \
libslirp-dev libfdt-dev
如果你要用 KVM,还要装 libcap-dev 和 libattr1-dev。
编译命令很简单:
make -j$(nproc)
-j$(nproc) 的意思是启用所有 CPU 核心并行编译。嗯,这里要注意,如果你的机器内存不大(比如 4GB),建议用 -j2 或 -j4,否则编译过程中内存吃紧,反而更慢。
编译完成后,安装:
sudo make install
安装后,验证一下:
/opt/qemu-riscv/bin/qemu-system-riscv64 --version
如果看到版本号输出,说明安装成功。
3.4 核心流程一览
我把整个流程画了张图,方便你对照操作:
3.5 常见问题与避坑
编译过程中,你可能会遇到一些问题。我把常见的列出来:
- 缺少 glib 库:报错信息会提示
glib-2.0 not found。装libglib2.0-dev即可。 - pixman 找不到:装
libpixman-1-dev。 - 编译到一半卡死:大概率是内存不够。按 Ctrl+C 中断,用
make -j2重新编。 - 安装后命令找不到:检查
--prefix路径是否在PATH环境变量中。我习惯在~/.bashrc里加一行:export PATH=/opt/qemu-riscv/bin:$PATH。
一个小技巧:
如果你需要同时维护多个 QEMU 版本,可以用不同的 --prefix 路径。比如 --prefix=/opt/qemu-8.2 和 --prefix=/opt/qemu-9.0。切换时改一下 PATH 就行。我在项目中就是这么干的,方便对比不同版本的行为差异。