Here’s another bunch of tips for QEMU developer – if you are not working with the QEMU source code, you can certainly ignore this article.

Compiling QEMU is a tedious action, since it takes quite some time to compile the whole code base. But with some basic tricks, you can shorten your code-change → compile → test→ repeat cycles quite a bit. These tricks might be quite well-known to the “older” QEMU developers already, but if you just started working on QEMU, they might be useful for you:

Compile and run tests in parallel

Well, this is likely the most obvious hint, but in case you didn’t know it yet: depending on the amount of CPU cores of your build machine, you can of course build the QEMU sources in parallel, for example compile with:

 make -j$(nproc)

The nice thing is that this also works for running the test suite:

 make -j$(nproc) check

This runs quite a bit faster on modern machines than simply running make check only.

Use out-of-tree builds

While in-tree builds might initially work fine, you sooner or later get to a point where you have to compile QEMU with different options. For example, does your code still compile if you run the configure script with --disable-tcg? Or does it still compile with clang instead of gcc? Each time you re-run the configure script to test a different option, you have to re-compile most of the QEMU code base afterwards. Thus it is better to keep different configurations in different build directories, so that you don’t have to recompile almost everything when you switch back and forth between different configurations. For example:

 mkdir build-gcc
 cd build-gcc
 ../configure --cc=gcc
 make -j$(nproc)
 cd ..
 mkdir build-clang
 cd build-clang
 ../configure --cc=clang
 make -j$(nproc)
 cd ..
 cd build-gcc
 make -j$(nproc)         # This should finish quickly now

By the way, in-tree builds are frowned on by many developers and might be disabled in a future release of QEMU, so it’s better to get used to out-of-tree builds anyway.

Only compile the target that you really need

Compiling all QEMU binaries takes a long time, even if you do it in parallel. During development, you often only need one specific binaries, like qemu-system-x86_64. So instead of re-compiling the whole set of binaries each time, simply only recompile the binary that you really need. At a first glance, you might want to use the --target-list option of the configure script to limit the set of targets that get compiled during make. But this has the disadvantage that you still need a second build folder where you can compile and test the other targets before you submit a patch (which you should always do). So there is an easier way to just compile one target binary, where you do not have to use the --target-list configure option at all. Simply run:

 make -j$(nproc) x86_64-softmmu/all

This will only re-compile the x86_64-softmmu/qemu-system-x86_64 binary, in much less time than compiling all target binaries.

Note: In older QEMU versions, this target was called subdir-x86_64-softmmu instead of x86_64-softmmu/all. And in future versions of QEMU (i.e. when the meson build system has been merged), you might need to run make qemu-system-x86_64 instead.

Apart from building the QEMU emulator binaries directly, there are also special targets for the tools (e.g. run make qemu-img) and the documentation (run make html). Have a look at the output of make help for a full list of available targets.

Only test the target that you really need

Before submitting patches, you should of course always run the whole test suite with make -j$(nproc) check to make sure that there are no regressions. But while you are working on a problem, it is often enough to only run single tests that trigger the problem you are working on, or that are at least covering the area you are interested in.

Similar to the possibility to compile only single target binaries, there is also a way to run only a certain group of tests. Run make check-help to get a list of the possible test targets. For example, if you are only working on x86-related code, it might be enough to run only:

 make -j$(nproc) check-qtest-x86_64

This will only execute the x86-related qtests. If that is still taking too long and you are only interested in one single qtest for example, you can also run that test directly like this:

export QTEST_QEMU_BINARY=x86_64-softmmu/qemu-system-x86_64
tests/qtest/device-introspect-test 

The QTEST_QEMU_BINARY environment variable is required here to let the test know which QEMU binary it should use.

Once you’re done with developing your patch, you should of course run at least one cycle of the complete make check (or even make check SPEED=slow) test suite to avoid that there are unexpected side effects in other parts of QEMU.

Use the right configure options for your build

You can also speed up your builds a little bit by using the right options when running the configure script – just have a look at the output of configure --help. You are sure that you will never use/touch feature xyz? Then try to compile without it by using configure --disable-xyz. For example, are you only working with KVM (and never with TCG)? Then give --disable-tcg a try. But please note that it’s still a good idea to have a separate build folder with a configuration where you have all features enabled - so that you can double-check that everything is still working fine before submitting your patches. Alternatively, you can (and should) also use one of the CI systems on Gitlab or Github, of course, to test your patches before submitting them to the mailing list.

Apart from the --disable-feature options, there is one option which can help a little bit when you change the HEAD of your git branch quite often: Run configure with --with-pkgversion=somestring. By default, the pkgversion (which will be part of the version string of QEMU) will be created using the current commit ID of the branch you are working on. Thus each time you change your branch or add a new commit to your local branch, this will trigger a rebuild of a bunch of files. Thus if you used --with-pkgversion with a fixed string, you can avoid this recompilation of these files when the HEAD of your current branch changed.