QEMU下的qt开发环境构建
构建与运行
环境准备
首先,安装必要的宿主机依赖包:
sudo apt update
sudo apt install build-essential libncurses5-dev rsync git bc qemu-system-arm qemu-utils
获取并配置 Buildroot
建议使用官方预设的 qemu_arm_vexpress_defconfig,它是最稳定的 ARM 模拟器配置。
# 下载 Buildroot (我们使用2019.11.x分支)
git clone -b 2019.11.x --single-branch https://github.com/buildroot/buildroot.git
cd buildroot
# 使用 ARM VExpress 配置
make qemu_arm_vexpress_defconfig
配置 QT 和 图形支持
为了能跑 QT 并支持 Framebuffer,需要进入菜单进行微调:
make menuconfig
在菜单中勾选以下关键项:
- Target options -> Target Architecture Variant: 选
Cortex-A7。 - Toolchain -> Custom kernel headers series: 选
5.3.x。 - Toolchain -> C library: 选
glibc。 - Toolchain -> Enable C++ support: 选中。
- Kernel -> Kernel version: 选
Latest version (5.3)。 - Target packages -> Graphic libraries and applications:
- 勾选
Qt5 - 勾选
qt5base-> 勾选gui module-> 勾选widgets module - 勾选
qt5base-> 勾选linuxfb support -
勾选
qt5base-> 勾选PNG support/JPEG support -
System configuration -> Root password: 设置一个密码(如
123),方便登录。
4. 编译
编译过程会下载交叉编译器并构建整个系统。
# 使用多核编译(例如 8 核)
make -j$(nproc)
在 QEMU 中运行
编译完成后,在 output/images/ 目录下会生成:
zImage(内核)vexpress-v2p-ca9.dtb(设备树)rootfs.ext2(根文件系统)
使用以下脚本启动 QEMU:
qemu-system-arm -M vexpress-a9 \
-cpu cortex-a15 \
-m 512M \
-kernel output/images/zImage \
-dtb output/images/vexpress-v2p-ca9.dtb \
-drive file=output/images/rootfs.ext2,if=sd,format=raw \
-append "console=ttyAMA0 root=/dev/mmcblk0 rw video=VGA-1:800x480-16" \
-net nic -net user,hostfwd=tcp::2222-:22 \
-vga std \
-serial mon:stdio
注:如果你是在纯终端(无桌面)的 Ubuntu 下运行,请移除 -display gtk 并使用 -vnc :0。
在模拟器中运行 QT 程序
进入系统后(用户名 root),你可以直接运行自带的 QT 示例程序:
# 运行并指定使用 linuxfb 驱动
/usr/lib/qt/examples/widgets/widgets/calculator/calculator -platform linuxfb
空间大小
在 Buildroot 的默认配置中,SD 卡镜像(rootfs.ext2)的大小通常是自动生成的,它会根据你勾选的包多少,自动计算出一个刚好能装下所有文件的最小容量。
但在实际开发(尤其是配合 QtCreator 和 QEMU 调试)时,有几个关于“大小”的关键点你需要注意:
1. 默认大小可能不够用
Buildroot 默认生成的 rootfs.ext2 往往只有几十 MB,剩下的空余空间极小。
如果你想通过 QtCreator 远程部署(Deploy)一个几十 MB 的 Qt 程序,或者在运行过程中产生日志,可能会报 "No space left on device"。
2. 如何手动指定大小
如果你需要给 SD 卡预留一些空间存放调试程序,建议在 make menuconfig 中手动指定一个固定大小(例如 512MB):
- 路径:
Filesystem images ---> - 找到
exact size(或者Size of the generated image) - 输入:
512M(或者根据你的需求输入,比如1G)
这样生成的 rootfs.ext2 就会有足够的空余空间让你折腾。
3. QEMU 挂载时的注意事项
在 QEMU 命令中,你使用的是 -drive file=output/images/rootfs.ext2,if=sd,format=raw。
- 物理模拟: QEMU 会把这个文件当成一张物理 SD 卡。
- 动态扩容: 如果你不想重新编译 Buildroot 改变大小,也可以直接在 Ubuntu 宿主机上用命令给这个镜像文件“扩容”:
# 在镜像末尾增加 512MB 空间
qemu-img resize output/images/rootfs.ext2 +512M
注意:扩容后你可能需要在 QEMU 虚拟机里运行 resize2fs /dev/mmcblk0 来让文件系统识别新空间。
建议
为了调试方便,建议在 make menuconfig 里把 Filesystem images 的大小固定设置为 256M 或 512M。
这样你在 QtCreator 里配置远程路径 /root/ 时,可以反复部署、替换二进制文件,而不用担心虚拟磁盘爆满导致的奇怪崩溃。
字体
在嵌入式 Linux 中,Qt 不会自带字体。如果没有字体,你的qt界面可能会显示,但上面的数字和文字会变成一个个空白方块或者完全不显示。
为了让系统自适应字体并支持中文,建议在 Buildroot 中勾选字体包:
- 进入
make menuconfig。 - 找到 Target packages -> Fonts, images and graphics。
- 勾选
DejaVu fonts(最通用的开源字体)。 - 关键一步:回到 Target packages -> Graphic libraries and applications -> Qt5 -> qt5base。
-
勾选
fontconfig support(这样 Qt 就会自动寻找系统中安装的所有字体,而不需要你指定目录)。 -
重新编译:
make。
qt例程运行
所有例程都在 /usr/lib/qt/examples/
比如运行calculator
export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0:size=800x480:offset=0x0
export QT_QPA_FONTDIR=/usr/share/fonts/dejavu
/usr/lib/qt/examples/widgets/widgets/calculator/calculator
增加ssh远程登陆
1. 配置 Buildroot 开启 OpenSSH
- 在 Buildroot 根目录下运行:
make menuconfig - 进入以下路径:
Target packages --->Networking applications --->[*] openssh - (可选)如果你希望系统启动时自动运行 SSH,请确保勾选了
openssh后,Buildroot 会默认在/etc/init.d/下生成S50sshd脚本。
2. 关键:允许 Root 直接登录
出于安全考虑,OpenSSH 默认禁止 root 用户通过密码登录。但在开发阶段(尤其是 QEMU 模拟),我们需要开启它,否则 Qt Creator 连接时会报 Permission denied。
在 make menuconfig 中:
System configuration --->[*] Root password(设置一个密码,比如root或留空)- 然后在
Target packages -> Networking applications -> openssh下面,通常没有直接的“允许 root”勾选项,我们需要通过 Rootfs Overlay 或者手动修改。
手动修改 QEMU 中的配置文件** 可以在 QEMU 启动后直接修改:
- 执行
vi /etc/ssh/sshd_config。 - 找到
#PermitRootLogin ...这一行。 - 修改为:
PermitRootLogin yes(注意去掉前面的#)。 - 找到
#PasswordAuthentication yes,确保它是yes。 - 保存退出后,重启服务:
/etc/init.d/S50sshd restart。
3. 保存配置并编译
make
编译完成后,output/images/rootfs.ext2 会更新。
4. 在 QEMU 中映射端口
之前的启动参数里已经包含了端口映射:
-net nic -net user,hostfwd=tcp::2222-:22
这代表:访问宿主机(Ubuntu)的 2222 端口,等于访问虚拟机的 22 端口。
5. 验证连接
在 Ubuntu 宿主机打开一个新终端,输入:
ssh root@localhost -p 2222
- 提示:如果报错
Host key verification failed,是因为你之前可能运行过别的虚拟机占用了 2222 端口,执行ssh-keygen -f "/home/zqboard/.ssh/known_hosts" -R "[localhost]:2222"清除一下即可。
defconfig 文件
使用 buildroot 2019.11.x分支
BR2_arm=y
BR2_cortex_a7=y
BR2_ARM_FPU_VFPV3D16=y
BR2_TOOLCHAIN_BUILDROOT_GLIBC=y
BR2_TOOLCHAIN_BUILDROOT_CXX=y
BR2_TARGET_GENERIC_ROOT_PASSWD="123"
BR2_TARGET_GENERIC_GETTY_PORT="ttyAMA0"
BR2_SYSTEM_DHCP="eth0"
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_DEFCONFIG="vexpress"
BR2_LINUX_KERNEL_DTS_SUPPORT=y
BR2_LINUX_KERNEL_INTREE_DTS_NAME="vexpress-v2p-ca9"
BR2_PACKAGE_DEJAVU=y
BR2_PACKAGE_QT5=y
BR2_PACKAGE_QT5BASE_EXAMPLES=y
BR2_PACKAGE_QT5BASE_GUI=y
BR2_PACKAGE_QT5BASE_WIDGETS=y
BR2_PACKAGE_QT5BASE_FONTCONFIG=y
BR2_PACKAGE_QT5BASE_JPEG=y
BR2_PACKAGE_QT5BASE_PNG=y
BR2_PACKAGE_OPENSSH=y
BR2_TARGET_ROOTFS_EXT2=y
BR2_TARGET_ROOTFS_EXT2_SIZE="256M"
# BR2_TARGET_ROOTFS_TAR is not set
BR2_PACKAGE_HOST_QEMU=y
BR2_PACKAGE_HOST_QEMU_SYSTEM_MODE=y