123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519 |
- 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. Dummy stubs for all these
- functions are also provided by this library, and will only be linked
- into the binary if the real implementation is not present. In a way,
- the stubs can be thought of as a portable implementation of the weak
- symbols concept.
- All binaries should link to libqemuutil.a, e.g.:
- qemu-img$(EXESUF): qemu-img.o ..snip.. libqemuutil.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-softmmu'
- 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 list of config variable definitions like the machines that should be
- included. For example, default-configs/aarch64-softmmu.mak has:
- include arm-softmmu.mak
- CONFIG_XLNX_ZYNQMP_ARM=y
- CONFIG_XLNX_VERSAL=y
- 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.
- Useful make targets
- ===================
- - help
- Print a help message for the most common build targets.
- - print-VAR
- Print the value of the variable VAR. Useful for debugging the build
- system.
|