| The QEMU build system architecture |
| ================================== |
| |
| This document aims to help developers understand the architecture of the |
| QEMU build system. As with projects using GNU autotools, the QEMU build |
| system has two stages, first the developer runs the "configure" script |
| to determine the local build environment characteristics, then they run |
| "make" to build the project. There is about where the similarities with |
| GNU autotools end, so try to forget what you know about them. |
| |
| |
| Stage 1: configure |
| ================== |
| |
| The QEMU configure script is written directly in shell, and should be |
| compatible with any POSIX shell, hence it uses #!/bin/sh. An important |
| implication of this is that it is important to avoid using bash-isms on |
| development platforms where bash is the primary host. |
| |
| In contrast to autoconf scripts, QEMU's configure is expected to be |
| silent while it is checking for features. It will only display output |
| when an error occurs, or to show the final feature enablement summary |
| on completion. |
| |
| Adding new checks to the configure script usually comprises the |
| following tasks: |
| |
| - Initialize one or more variables with the default feature state. |
| |
| Ideally features should auto-detect whether they are present, |
| so try to avoid hardcoding the initial state to either enabled |
| or disabled, as that forces the user to pass a --enable-XXX |
| / --disable-XXX flag on every invocation of configure. |
| |
| - Add support to the command line arg parser to handle any new |
| --enable-XXX / --disable-XXX flags required by the feature XXX. |
| |
| - Add information to the help output message to report on the new |
| feature flag. |
| |
| - Add code to perform the actual feature check. As noted above, try to |
| be fully dynamic in checking enablement/disablement. |
| |
| - Add code to print out the feature status in the configure summary |
| upon completion. |
| |
| - Add any new makefile variables to $config_host_mak on completion. |
| |
| |
| Taking (a simplified version of) the probe for gnutls from configure, |
| we have the following pieces: |
| |
| # Initial variable state |
| gnutls="" |
| |
| ..snip.. |
| |
| # Configure flag processing |
| --disable-gnutls) gnutls="no" |
| ;; |
| --enable-gnutls) gnutls="yes" |
| ;; |
| |
| ..snip.. |
| |
| # Help output feature message |
| gnutls GNUTLS cryptography support |
| |
| ..snip.. |
| |
| # Test for gnutls |
| if test "$gnutls" != "no"; then |
| if ! $pkg_config --exists "gnutls"; then |
| gnutls_cflags=`$pkg_config --cflags gnutls` |
| gnutls_libs=`$pkg_config --libs gnutls` |
| libs_softmmu="$gnutls_libs $libs_softmmu" |
| libs_tools="$gnutls_libs $libs_tools" |
| QEMU_CFLAGS="$QEMU_CFLAGS $gnutls_cflags" |
| gnutls="yes" |
| elif test "$gnutls" = "yes"; then |
| feature_not_found "gnutls" "Install gnutls devel" |
| else |
| gnutls="no" |
| fi |
| fi |
| |
| ..snip.. |
| |
| # Completion feature summary |
| echo "GNUTLS support $gnutls" |
| |
| ..snip.. |
| |
| # Define make variables |
| if test "$gnutls" = "yes" ; then |
| echo "CONFIG_GNUTLS=y" >> $config_host_mak |
| fi |
| |
| |
| Helper functions |
| ---------------- |
| |
| The configure script provides a variety of helper functions to assist |
| developers in checking for system features: |
| |
| - do_cc $ARGS... |
| |
| Attempt to run the system C compiler passing it $ARGS... |
| |
| - do_cxx $ARGS... |
| |
| Attempt to run the system C++ compiler passing it $ARGS... |
| |
| - compile_object $CFLAGS |
| |
| Attempt to compile a test program with the system C compiler using |
| $CFLAGS. The test program must have been previously written to a file |
| called $TMPC. |
| |
| - compile_prog $CFLAGS $LDFLAGS |
| |
| Attempt to compile a test program with the system C compiler using |
| $CFLAGS and link it with the system linker using $LDFLAGS. The test |
| program must have been previously written to a file called $TMPC. |
| |
| - has $COMMAND |
| |
| Determine if $COMMAND exists in the current environment, either as a |
| shell builtin, or executable binary, returning 0 on success. |
| |
| - path_of $COMMAND |
| |
| Return the fully qualified path of $COMMAND, printing it to stdout, |
| and returning 0 on success. |
| |
| - check_define $NAME |
| |
| Determine if the macro $NAME is defined by the system C compiler |
| |
| - check_include $NAME |
| |
| Determine if the include $NAME file is available to the system C |
| compiler |
| |
| - write_c_skeleton |
| |
| Write a minimal C program main() function to the temporary file |
| indicated by $TMPC |
| |
| - feature_not_found $NAME $REMEDY |
| |
| Print a message to stderr that the feature $NAME was not available |
| on the system, suggesting the user try $REMEDY to address the |
| problem. |
| |
| - error_exit $MESSAGE $MORE... |
| |
| Print $MESSAGE to stderr, followed by $MORE... and then exit from the |
| configure script with non-zero status |
| |
| - query_pkg_config $ARGS... |
| |
| Run pkg-config passing it $ARGS. If QEMU is doing a static build, |
| then --static will be automatically added to $ARGS |
| |
| |
| Stage 2: makefiles |
| ================== |
| |
| The use of GNU make is required with the QEMU build system. |
| |
| Although the source code is spread across multiple subdirectories, the |
| build system should be considered largely non-recursive in nature, in |
| contrast to common practices seen with automake. There is some recursive |
| invocation of make, but this is related to the things being built, |
| rather than the source directory structure. |
| |
| QEMU currently supports both VPATH and non-VPATH builds, so there are |
| three general ways to invoke configure & perform a build. |
| |
| - VPATH, build artifacts outside of QEMU source tree entirely |
| |
| cd ../ |
| mkdir build |
| cd build |
| ../qemu/configure |
| make |
| |
| - VPATH, build artifacts in a subdir of QEMU source tree |
| |
| mkdir build |
| cd build |
| ../configure |
| make |
| |
| - non-VPATH, build artifacts everywhere |
| |
| ./configure |
| make |
| |
| The QEMU maintainers generally recommend that a VPATH build is used by |
| developers. Patches to QEMU are expected to ensure VPATH build still |
| works. |
| |
| |
| Module structure |
| ---------------- |
| |
| There are a number of key outputs of the QEMU build system: |
| |
| - Tools - qemu-img, qemu-nbd, qga (guest agent), etc |
| - System emulators - qemu-system-$ARCH |
| - Userspace emulators - qemu-$ARCH |
| - Unit tests |
| |
| The source code is highly modularized, split across many files to |
| facilitate building of all of these components with as little duplicated |
| compilation as possible. There can be considered to be two distinct |
| groups of files, those which are independent of the QEMU emulation |
| target and those which are dependent on the QEMU emulation target. |
| |
| In the target-independent set lives various general purpose helper code, |
| such as error handling infrastructure, standard data structures, |
| platform portability wrapper functions, etc. This code can be compiled |
| once only and the .o files linked into all output binaries. |
| |
| In the target-dependent set lives CPU emulation, device emulation and |
| much glue code. This sometimes also has to be compiled multiple times, |
| once for each target being built. |
| |
| The utility code that is used by all binaries is built into a |
| static archive called libqemuutil.a, which is then linked to all the |
| binaries. In order to provide hooks that are only needed by some of the |
| binaries, code in libqemuutil.a may depend on other functions that are |
| not fully implemented by all QEMU binaries. To deal with this there is a |
| second library called libqemustub.a which provides dummy stubs for all |
| these functions. These will get lazy linked into the binary if the real |
| implementation is not present. In this way, the libqemustub.a static |
| library can be thought of as a portable implementation of the weak |
| symbols concept. All binaries should link to both libqemuutil.a and |
| libqemustub.a. e.g. |
| |
| qemu-img$(EXESUF): qemu-img.o ..snip.. libqemuutil.a libqemustub.a |
| |
| |
| Windows platform portability |
| ---------------------------- |
| |
| On Windows, all binaries have the suffix '.exe', so all Makefile rules |
| which create binaries must include the $(EXESUF) variable on the binary |
| name. e.g. |
| |
| qemu-img$(EXESUF): qemu-img.o ..snip.. |
| |
| This expands to '.exe' on Windows, or '' on other platforms. |
| |
| A further complication for the system emulator binaries is that |
| two separate binaries need to be generated. |
| |
| The main binary (e.g. qemu-system-x86_64.exe) is linked against the |
| Windows console runtime subsystem. These are expected to be run from a |
| command prompt window, and so will print stderr to the console that |
| launched them. |
| |
| The second binary generated has a 'w' on the end of its name (e.g. |
| qemu-system-x86_64w.exe) and is linked against the Windows graphical |
| runtime subsystem. These are expected to be run directly from the |
| desktop and will open up a dedicated console window for stderr output. |
| |
| The Makefile.target will generate the binary for the graphical subsystem |
| first, and then use objcopy to relink it against the console subsystem |
| to generate the second binary. |
| |
| |
| Object variable naming |
| ---------------------- |
| |
| The QEMU convention is to define variables to list different groups of |
| object files. These are named with the convention $PREFIX-obj-y. For |
| example the libqemuutil.a file will be linked with all objects listed |
| in a variable 'util-obj-y'. So, for example, util/Makefile.obj will |
| contain a set of definitions looking like |
| |
| util-obj-y += bitmap.o bitops.o hbitmap.o |
| util-obj-y += fifo8.o |
| util-obj-y += acl.o |
| util-obj-y += error.o qemu-error.o |
| |
| When there is an object file which needs to be conditionally built based |
| on some characteristic of the host system, the configure script will |
| define a variable for the conditional. For example, on Windows it will |
| define $(CONFIG_POSIX) with a value of 'n' and $(CONFIG_WIN32) with a |
| value of 'y'. It is now possible to use the config variables when |
| listing object files. For example, |
| |
| util-obj-$(CONFIG_WIN32) += oslib-win32.o qemu-thread-win32.o |
| util-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o |
| |
| On Windows this expands to |
| |
| util-obj-y += oslib-win32.o qemu-thread-win32.o |
| util-obj-n += oslib-posix.o qemu-thread-posix.o |
| |
| Since libqemutil.a links in $(util-obj-y), the POSIX specific files |
| listed against $(util-obj-n) are ignored on the Windows platform builds. |
| |
| |
| CFLAGS / LDFLAGS / LIBS handling |
| -------------------------------- |
| |
| There are many different binaries being built with differing purposes, |
| and some of them might even be 3rd party libraries pulled in via git |
| submodules. As such the use of the global CFLAGS variable is generally |
| avoided in QEMU, since it would apply to too many build targets. |
| |
| Flags that are needed by any QEMU code (i.e. everything *except* GIT |
| submodule projects) are put in $(QEMU_CFLAGS) variable. For linker |
| flags the $(LIBS) variable is sometimes used, but a couple of more |
| targeted variables are preferred. $(libs_softmmu) is used for |
| libraries that must be linked to system emulator targets, $(LIBS_TOOLS) |
| is used for tools like qemu-img, qemu-nbd, etc and $(LIBS_QGA) is used |
| for the QEMU guest agent. There is currently no specific variable for |
| the userspace emulator targets as the global $(LIBS), or more targeted |
| variables shown below, are sufficient. |
| |
| In addition to these variables, it is possible to provide cflags and |
| libs against individual source code files, by defining variables of the |
| form $FILENAME-cflags and $FILENAME-libs. For example, the curl block |
| driver needs to link to the libcurl library, so block/Makefile defines |
| some variables: |
| |
| curl.o-cflags := $(CURL_CFLAGS) |
| curl.o-libs := $(CURL_LIBS) |
| |
| The scope is a little different between the two variables. The libs get |
| used when linking any target binary that includes the curl.o object |
| file, while the cflags get used when compiling the curl.c file only. |
| |
| |
| Statically defined files |
| ------------------------ |
| |
| The following key files are statically defined in the source tree, with |
| the rules needed to build QEMU. Their behaviour is influenced by a |
| number of dynamically created files listed later. |
| |
| - Makefile |
| |
| The main entry point used when invoking make to build all the components |
| of QEMU. The default 'all' target will naturally result in the build of |
| every component. The various tools and helper binaries are built |
| directly via a non-recursive set of rules. |
| |
| Each system/userspace emulation target needs to have a slightly |
| different set of make rules / variables. Thus, make will be recursively |
| invoked for each of the emulation targets. |
| |
| The recursive invocation will end up processing the toplevel |
| Makefile.target file (more on that later). |
| |
| |
| - */Makefile.objs |
| |
| Since the source code is spread across multiple directories, the rules |
| for each file are similarly modularized. Thus each subdirectory |
| containing .c files will usually also contain a Makefile.objs file. |
| These files are not directly invoked by a recursive make, but instead |
| they are imported by the top level Makefile and/or Makefile.target |
| |
| Each Makefile.objs usually just declares a set of variables listing the |
| .o files that need building from the source files in the directory. They |
| will also define any custom linker or compiler flags. For example in |
| block/Makefile.objs |
| |
| block-obj-$(CONFIG_LIBISCSI) += iscsi.o |
| block-obj-$(CONFIG_CURL) += curl.o |
| |
| ..snip... |
| |
| iscsi.o-cflags := $(LIBISCSI_CFLAGS) |
| iscsi.o-libs := $(LIBISCSI_LIBS) |
| curl.o-cflags := $(CURL_CFLAGS) |
| curl.o-libs := $(CURL_LIBS) |
| |
| If there are any rules defined in the Makefile.objs file, they should |
| all use $(obj) as a prefix to the target, e.g. |
| |
| $(obj)/generated-tcg-tracers.h: $(obj)/generated-tcg-tracers.h-timestamp |
| |
| |
| - Makefile.target |
| |
| This file provides the entry point used to build each individual system |
| or userspace emulator target. Each enabled target has its own |
| subdirectory. For example if configure is run with the argument |
| '--target-list=x86_64-softmmu', then a sub-directory 'x86_64-softmu' |
| will be created, containing a 'Makefile' which symlinks back to |
| Makefile.target |
| |
| So when the recursive '$(MAKE) -C x86_64-softmmu' is invoked, it ends up |
| using Makefile.target for the build rules. |
| |
| |
| - rules.mak |
| |
| This file provides the generic helper rules for invoking build tools, in |
| particular the compiler and linker. This also contains the magic (hairy) |
| 'unnest-vars' function which is used to merge the variable definitions |
| from all Makefile.objs in the source tree down into the main Makefile |
| context. |
| |
| |
| - default-configs/*.mak |
| |
| The files under default-configs/ control what emulated hardware is built |
| into each QEMU system and userspace emulator targets. They merely |
| contain a long list of config variable definitions. For example, |
| default-configs/x86_64-softmmu.mak has: |
| |
| include pci.mak |
| include sound.mak |
| include usb.mak |
| CONFIG_QXL=$(CONFIG_SPICE) |
| CONFIG_VGA_ISA=y |
| CONFIG_VGA_CIRRUS=y |
| CONFIG_VMWARE_VGA=y |
| CONFIG_VIRTIO_VGA=y |
| ...snip... |
| |
| These files rarely need changing unless new devices / hardware need to |
| be enabled for a particular system/userspace emulation target |
| |
| |
| - tests/Makefile |
| |
| Rules for building the unit tests. This file is included directly by the |
| top level Makefile, so anything defined in this file will influence the |
| entire build system. Care needs to be taken when writing rules for tests |
| to ensure they only apply to the unit test execution / build. |
| |
| - tests/docker/Makefile.include |
| |
| Rules for Docker tests. Like tests/Makefile, this file is included |
| directly by the top level Makefile, anything defined in this file will |
| influence the entire build system. |
| |
| - po/Makefile |
| |
| Rules for building and installing the binary message catalogs from the |
| text .po file sources. This almost never needs changing for any reason. |
| |
| |
| Dynamically created files |
| ------------------------- |
| |
| The following files are generated dynamically by configure in order to |
| control the behaviour of the statically defined makefiles. This avoids |
| the need for QEMU makefiles to go through any pre-processing as seen |
| with autotools, where Makefile.am generates Makefile.in which generates |
| Makefile. |
| |
| |
| - config-host.mak |
| |
| When configure has determined the characteristics of the build host it |
| will write a long list of variables to config-host.mak file. This |
| provides the various install directories, compiler / linker flags and a |
| variety of CONFIG_* variables related to optionally enabled features. |
| This is imported by the top level Makefile in order to tailor the build |
| output. |
| |
| The variables defined here are those which are applicable to all QEMU |
| build outputs. Variables which are potentially different for each |
| emulator target are defined by the next file... |
| |
| It is also used as a dependency checking mechanism. If make sees that |
| the modification timestamp on configure is newer than that on |
| config-host.mak, then configure will be re-run. |
| |
| |
| - config-host.h |
| |
| The config-host.h file is used by source code to determine what features |
| are enabled. It is generated from the contents of config-host.mak using |
| the scripts/create_config program. This extracts all the CONFIG_* variables, |
| most of the HOST_* variables and a few other misc variables from |
| config-host.mak, formatting them as C preprocessor macros. |
| |
| |
| - $TARGET-NAME/config-target.mak |
| |
| TARGET-NAME is the name of a system or userspace emulator, for example, |
| x86_64-softmmu denotes the system emulator for the x86_64 architecture. |
| This file contains the variables which need to vary on a per-target |
| basis. For example, it will indicate whether KVM or Xen are enabled for |
| the target and any other potential custom libraries needed for linking |
| the target. |
| |
| |
| - $TARGET-NAME/config-devices.mak |
| |
| TARGET-NAME is again the name of a system or userspace emulator. The |
| config-devices.mak file is automatically generated by make using the |
| scripts/make_device_config.sh program, feeding it the |
| default-configs/$TARGET-NAME file as input. |
| |
| |
| - $TARGET-NAME/Makefile |
| |
| This is the entrypoint used when make recurses to build a single system |
| or userspace emulator target. It is merely a symlink back to the |
| Makefile.target in the top level. |