Recently, while working on a baremetal project, I encountered a bug in the QEMU version I was using. And unfortunately, it was the latest version that was available for my host distribution. However, the official QEMU lineup was much ahead and already had the fix for the bug, that I was stuck with. This is one of the reason why you may want to build the QEMU yourself from the source. Another scenario could be when you want to enable QEMU debugging logs or control certain QEMU features.

In this post, we are going to look how you can pull the QEMU source yourself and build on your linux host machine. I am sitting on an Ubuntu 20.04.3 LTS, but the steps should be the same for your host machine, you might just need to change the commands corresponding to your package manager.

Step 1 : Pulling the source

You can pull the source either as a tar file from QEMU downloads page or from its git repository https://gitlab.com/qemu-project/qemu.git.

code@slashinit

code@slashinit:/opt$ sudo wget https://download.qemu.org/qemu-6.2.0.tar.xz
--2022-01-05 17:44:25-- https://download.qemu.org/qemu-6.2.0.tar.xz
Resolving proxy-wsa.esl.cisco.com (proxy-wsa.esl.cisco.com)... 72.163.217.104
Connecting to proxy-wsa.esl.cisco.com (proxy-wsa.esl.cisco.com)|72.163.217.104|:80... connected.
Proxy request sent, awaiting response... 200 OK
Length: 115667324 (110M) [application/x-xz]
Saving to: ‘qemu-6.2.0.tar.xz’

qemu-6.2.0.tar.xz 100%[=================================================================================================================>] 110.31M 814KB/s in 2m 23s

2022-01-05 17:46:49 (791 KB/s) - ‘qemu-6.2.0.tar.xz’ saved [115667324/115667324]

code@slashinit:/opt$

Step 2 : Extract the tar file

In case you downloaded the source as a tar file, extract it.

code@slashinit

code@slashinit:/opt$ sudo tar -xvf qemu-6.2.0.tar.xz
qemu-6.2.0/
qemu-6.2.0/.patchew.yml
qemu-6.2.0/ebpf/
qemu-6.2.0/ebpf/meson.build
qemu-6.2.0/ebpf/rss.bpf.skeleton.h
qemu-6.2.0/ebpf/ebpf_rss.c
qemu-6.2.0/ebpf/ebpf_rss.h
qemu-6.2.0/ebpf/trace.h
qemu-6.2.0/ebpf/trace-events
qemu-6.2.0/ebpf/ebpf_rss-stub.c
qemu-6.2.0/.gitlab-ci.yml
...
...
qemu-6.2.0/subprojects/
qemu-6.2.0/subprojects/libvhost-user/
qemu-6.2.0/subprojects/libvhost-user/libvhost-user.c
qemu-6.2.0/subprojects/libvhost-user/meson.build
qemu-6.2.0/subprojects/libvhost-user/libvhost-user-glib.c
qemu-6.2.0/subprojects/libvhost-user/link-test.c
qemu-6.2.0/subprojects/libvhost-user/standard-headers/
qemu-6.2.0/subprojects/libvhost-user/standard-headers/linux
qemu-6.2.0/subprojects/libvhost-user/libvhost-user.h
qemu-6.2.0/subprojects/libvhost-user/include/
qemu-6.2.0/subprojects/libvhost-user/include/atomic.h
qemu-6.2.0/subprojects/libvhost-user/libvhost-user-glib.h
qemu-6.2.0/qemu.nsi
code@slashinit:/opt$

Step 3 : Install dependencies

code@slashinit

code@slashinit:/opt$ sudo apt-get install ninja-build libglib2.0-dev libpixman-1-dev

Step 4 : Configure

code@slashinit

code@slashinit:/opt$ cd qemu-6.2.0
code@slashinit:/opt/qemu-6.2.0$
code@slashinit:/opt/qemu-6.2.0$ ./configure
Using './build' as the directory for build output
The Meson build system
Version: 0.59.3
Source dir: /opt/qemu-6.2.0
Build dir: /opt/qemu-6.2.0/build
Build type: native build
Project name: qemu
Project version: 6.2.0
...
...
libdaxctl support : NO
libudev : NO
FUSE lseek : NO
selinux : YES 3.0

Subprojects
libvhost-user : YES

Found ninja-1.10.0 at /usr/bin/ninja

code@slashinit:/opt/qemu-6.2.0$

Step 5 : Make

code@slashinit

code@slashinit:/opt/qemu-6.2.0$ make -j24
changing dir to build for make ""...
make[1]: Entering directory '/opt/qemu-6.2.0/build'
/usr/bin/ninja build.ninja && touch build.ninja.stamp
ninja: no work to do.
/usr/bin/python3 -B /opt/qemu-6.2.0/meson/meson.py introspect --targets --tests --benchmarks | /usr/bin/python3 -B scripts/mtest2make.py > Makefile.mtest
AS multiboot.o
AS multiboot_dma.o
AS linuxboot.o
CC linuxboot_dma.o
AS kvmvapic.o
AS pvh.o
CC pvh_main.o
BUILD multiboot.img
BUILD multiboot_dma.img
BUILD linuxboot.img
BUILD linuxboot_dma.img
BUILD kvmvapic.img
BUILD pvh.img
BUILD multiboot_dma.raw
BUILD linuxboot.raw
BUILD linuxboot_dma.raw
BUILD multiboot.raw
BUILD pvh.raw
BUILD kvmvapic.raw
SIGN multiboot_dma.bin
SIGN multiboot.bin
SIGN kvmvapic.bin
SIGN pvh.bin
SIGN linuxboot_dma.bin
SIGN linuxboot.bin
[1/9610] Generating 'libqemu-alpha-linux-user.fa.p/syscall_nr.h'.
[2/9610] Compiling C object libcapstone.a.p/capstone_MCInstrDesc.c.o
...
...
[9609/9610] Compiling C object libqemu-xtensaeb-linux-user.fa.p/target_xtensa_core-dsp3400.c.o
[9610/9610] Linking target qemu-xtensaeb
make[1]: Leaving directory '/opt/qemu-6.2.0/build'
changing dir to build for make ""...
make[1]: Entering directory '/opt/qemu-6.2.0/build'
[1/177] Generating QAPI test (include) with a custom command
[2/144] Generating qemu-version.h with a custom command (wrapped by meson to capture output)
make[1]: Leaving directory '/opt/qemu-6.2.0/build'
code@slashinit:/opt/qemu-6.2.0$

The binaries can be found in the build/ folder.