aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml21
-rw-r--r--.gitlab-ci.yml6
-rw-r--r--.travis.yml21
-rw-r--r--Makefile135
-rwxr-xr-xconfigure101
-rw-r--r--docs/conf.py2
-rw-r--r--docs/devel/build-system.rst6
-rw-r--r--docs/meson.build46
-rw-r--r--docs/sphinx/kerneldoc.py2
m---------meson0
-rw-r--r--meson.build185
-rw-r--r--meson_options.txt6
-rw-r--r--scripts/mtest2make.py3
-rwxr-xr-xscripts/ninjatool.py1008
-rw-r--r--target/i386/hax-cpus.c1
-rw-r--r--tests/Makefile.include2
-rw-r--r--tests/docker/dockerfiles/centos7.docker1
-rw-r--r--tests/docker/dockerfiles/centos8.docker5
-rw-r--r--tests/docker/dockerfiles/debian10.docker1
-rw-r--r--tests/docker/dockerfiles/fedora.docker1
-rw-r--r--tests/docker/dockerfiles/travis.docker2
-rw-r--r--tests/docker/dockerfiles/ubuntu.docker1
-rw-r--r--tests/docker/dockerfiles/ubuntu1804.docker1
-rw-r--r--tests/docker/dockerfiles/ubuntu2004.docker1
-rw-r--r--tests/include/meson.build8
-rw-r--r--tests/meson.build14
-rw-r--r--tests/qapi-schema/meson.build88
-rw-r--r--tests/qtest/fuzz/fuzz.c8
-rwxr-xr-xtests/vm/centos2
-rwxr-xr-xtests/vm/centos.aarch642
-rwxr-xr-xtests/vm/fedora2
-rwxr-xr-xtests/vm/freebsd1
-rwxr-xr-xtests/vm/netbsd1
-rwxr-xr-xtests/vm/openbsd1
-rwxr-xr-xtests/vm/ubuntu.aarch642
-rwxr-xr-xtests/vm/ubuntu.i3862
-rw-r--r--ui/meson.build7
37 files changed, 388 insertions, 1308 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 99d1182..81a2960 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -9,11 +9,11 @@ freebsd_12_task:
install_script:
- ASSUME_ALWAYS_YES=yes pkg bootstrap -f ;
- pkg install -y bash curl cyrus-sasl git glib gmake gnutls gsed
- nettle perl5 pixman pkgconf png usbredir
+ nettle perl5 pixman pkgconf png usbredir ninja
script:
- mkdir build
- cd build
- - ../configure --enable-werror || { cat config.log; exit 1; }
+ - ../configure --enable-werror || { cat config.log meson-logs/meson-log.txt; exit 1; }
- gmake -j$(sysctl -n hw.ncpu)
- gmake -j$(sysctl -n hw.ncpu) check V=1
@@ -21,13 +21,13 @@ macos_task:
osx_instance:
image: catalina-base
install_script:
- - brew install pkg-config python gnu-sed glib pixman make sdl2 bash
+ - brew install pkg-config python gnu-sed glib pixman make sdl2 bash ninja
script:
- mkdir build
- cd build
- ../configure --python=/usr/local/bin/python3 --enable-werror
--extra-cflags='-Wno-error=deprecated-declarations'
- || { cat config.log; exit 1; }
+ || { cat config.log meson-logs/meson-log.txt; exit 1; }
- gmake -j$(sysctl -n hw.ncpu)
- gmake check V=1
@@ -36,12 +36,12 @@ macos_xcode_task:
# this is an alias for the latest Xcode
image: catalina-xcode
install_script:
- - brew install pkg-config gnu-sed glib pixman make sdl2 bash
+ - brew install pkg-config gnu-sed glib pixman make sdl2 bash ninja
script:
- mkdir build
- cd build
- ../configure --extra-cflags='-Wno-error=deprecated-declarations'
- --enable-werror --cc=clang || { cat config.log; exit 1; }
+ --enable-werror --cc=clang || { cat config.log meson-logs/meson-log.txt; exit 1; }
- gmake -j$(sysctl -n hw.ncpu)
- gmake check V=1
@@ -76,7 +76,6 @@ windows_msys2_task:
((Get-Content -path C:\tools\msys64\etc\\post-install\\07-pacman-key.post -Raw) -replace '--refresh-keys', '--version') | Set-Content -Path C:\tools\msys64\etc\\post-install\\07-pacman-key.post
C:\tools\msys64\usr\bin\bash.exe -lc "sed -i 's/^CheckSpace/#CheckSpace/g' /etc/pacman.conf"
C:\tools\msys64\usr\bin\bash.exe -lc "export"
- C:\tools\msys64\usr\bin\bash.exe -lc "grep -rl 'repo.msys2.org/' /etc/pacman.d/mirrorlist.* | xargs sed -i 's/repo.msys2.org\//mirrors.tuna.tsinghua.edu.cn\/msys2\//g'"
C:\tools\msys64\usr\bin\pacman.exe --noconfirm -Sy
echo Y | C:\tools\msys64\usr\bin\pacman.exe --noconfirm -Suu --overwrite=*
taskkill /F /FI "MODULES eq msys-2.0.dll"
@@ -111,6 +110,11 @@ windows_msys2_task:
mingw-w64-x86_64-curl \
mingw-w64-x86_64-gnutls \
"
+ bitsadmin /transfer msys_download /dynamic /download /priority FOREGROUND `
+ https://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-python-sphinx-2.3.1-1-any.pkg.tar.xz `
+ C:\tools\mingw-w64-x86_64-python-sphinx-2.3.1-1-any.pkg.tar.xz
+ C:\tools\msys64\usr\bin\bash.exe -lc "pacman --noconfirm -U /c/tools/mingw-w64-x86_64-python-sphinx-2.3.1-1-any.pkg.tar.xz"
+ del C:\tools\mingw-w64-x86_64-python-sphinx-2.3.1-1-any.pkg.tar.xz
C:\tools\msys64\usr\bin\bash.exe -lc "rm -rf /var/cache/pacman/pkg/*"
cd C:\tools\msys64
echo "Start archive"
@@ -123,8 +127,7 @@ windows_msys2_task:
script:
- C:\tools\msys64\usr\bin\bash.exe -lc "mkdir build"
- - C:\tools\msys64\usr\bin\bash.exe -lc "cd build && ../configure
- --python=python3 --ninja=ninja"
+ - C:\tools\msys64\usr\bin\bash.exe -lc "cd build && ../configure --python=python3"
- C:\tools\msys64\usr\bin\bash.exe -lc "cd build && make -j8"
test_script:
- C:\tools\msys64\usr\bin\bash.exe -lc "cd build && make V=1 check"
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 8ffd415..66ad7aa 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -32,7 +32,7 @@ include:
../configure --enable-werror $CONFIGURE_ARGS --target-list="$TARGETS" ;
else
../configure --enable-werror $CONFIGURE_ARGS ;
- fi
+ fi || { cat config.log meson-logs/meson-log.txt && exit 1; }
- make -j"$JOBS"
- if test -n "$MAKE_CHECK_ARGS";
then
@@ -229,7 +229,7 @@ build-tcg-disabled:
script:
- mkdir build
- cd build
- - ../configure --disable-tcg --audio-drv-list=""
+ - ../configure --disable-tcg --audio-drv-list="" || { cat config.log meson-logs/meson-log.txt && exit 1; }
- make -j"$JOBS"
- make check-unit
- make check-qapi-schema
@@ -322,7 +322,7 @@ build-tci:
- mkdir build
- cd build
- ../configure --enable-tcg-interpreter
- --target-list="$(for tg in $TARGETS; do echo -n ${tg}'-softmmu '; done)"
+ --target-list="$(for tg in $TARGETS; do echo -n ${tg}'-softmmu '; done)" || { cat config.log meson-logs/meson-log.txt && exit 1; }
- make -j"$JOBS"
- make run-tcg-tests-x86_64-softmmu
- make tests/qtest/boot-serial-test tests/qtest/cdrom-test tests/qtest/pxe-test
diff --git a/.travis.yml b/.travis.yml
index 1054ec5..a3d7817 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -49,6 +49,7 @@ addons:
- libvdeplug-dev
- libvte-2.91-dev
- libzstd-dev
+ - ninja-build
- sparse
- uuid-dev
- gcovr
@@ -94,7 +95,7 @@ before_install:
# Configure step - may be overridden
before_script:
- mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR}
- - ${SRC_DIR}/configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; }
+ - ${SRC_DIR}/configure ${BASE_CONFIG} ${CONFIG} || { cat config.log meson-logs/meson-log.txt && exit 1; }
# Main build & test - rarely overridden - controlled by TEST_CMD
script:
@@ -177,6 +178,7 @@ jobs:
addons:
apt:
packages:
+ - ninja-build
- python3-sphinx
- perl
@@ -197,7 +199,7 @@ jobs:
compiler: clang
before_script:
- mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR}
- - ${SRC_DIR}/configure ${CONFIG} --extra-cflags="-fsanitize=undefined -Werror" || { cat config.log && exit 1; }
+ - ${SRC_DIR}/configure ${CONFIG} --extra-cflags="-fsanitize=undefined -Werror" || { cat config.log meson-logs/meson-log.txt && exit 1; }
- name: "Clang (other-softmmu)"
@@ -211,6 +213,10 @@ jobs:
# gprof/gcov are GCC features
- name: "GCC gprof/gcov"
dist: bionic
+ addons:
+ apt:
+ packages:
+ - ninja-build
env:
- CONFIG="--enable-gprof --enable-gcov --disable-libssh
--target-list=${MAIN_SOFTMMU_TARGETS}"
@@ -281,6 +287,7 @@ jobs:
- liburcu-dev
- libusb-1.0-0-dev
- libvte-2.91-dev
+ - ninja-build
- sparse
- uuid-dev
language: generic
@@ -291,7 +298,7 @@ jobs:
- TEST_CMD=""
before_script:
- mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR}
- - ${SRC_DIR}/configure ${CONFIG} --extra-cflags="-g3 -O0 -fsanitize=thread" || { cat config.log && exit 1; }
+ - ${SRC_DIR}/configure ${CONFIG} --extra-cflags="-g3 -O0 -fsanitize=thread" || { cat config.log meson-logs/meson-log.txt && exit 1; }
# Run check-tcg against linux-user
@@ -346,6 +353,7 @@ jobs:
- libusb-1.0-0-dev
- libvdeplug-dev
- libvte-2.91-dev
+ - ninja-build
# Tests dependencies
- genisoimage
env:
@@ -379,6 +387,7 @@ jobs:
- libusb-1.0-0-dev
- libvdeplug-dev
- libvte-2.91-dev
+ - ninja-build
# Tests dependencies
- genisoimage
env:
@@ -411,6 +420,7 @@ jobs:
- libusb-1.0-0-dev
- libvdeplug-dev
- libvte-2.91-dev
+ - ninja-build
# Tests dependencies
- genisoimage
env:
@@ -450,6 +460,7 @@ jobs:
- libzstd-dev
- nettle-dev
- xfslibs-dev
+ - ninja-build
# Tests dependencies
- genisoimage
env:
@@ -463,6 +474,7 @@ jobs:
apt_packages:
- libgcrypt20-dev
- libgnutls28-dev
+ - ninja-build
env:
- CONFIG="--disable-containers --disable-system"
@@ -493,6 +505,7 @@ jobs:
- libusb-1.0-0-dev
- libvdeplug-dev
- libvte-2.91-dev
+ - ninja-build
env:
- TEST_CMD="make check-unit"
- CONFIG="--disable-containers --disable-tcg --enable-kvm
@@ -517,7 +530,7 @@ jobs:
- ls -l ${SRC_DIR}/qemu-${QEMU_VERSION}.tar.bz2
- tar -xf ${SRC_DIR}/qemu-${QEMU_VERSION}.tar.bz2 && cd qemu-${QEMU_VERSION}
- mkdir -p release-build && cd release-build
- - ../configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; }
+ - ../configure ${BASE_CONFIG} ${CONFIG} || { cat config.log meson-logs/meson-log.txt && exit 1; }
- make install
allow_failures:
- env: UNRELIABLE=true
diff --git a/Makefile b/Makefile
index c37e513..18f026e 100644
--- a/Makefile
+++ b/Makefile
@@ -14,6 +14,8 @@ SRC_PATH=.
# we have explicit rules for everything
MAKEFLAGS += -rR
+SHELL = /usr/bin/env bash -o pipefail
+
# Usage: $(call quiet-command,command and args,"NAME","args to print")
# This will run "command and args", and either:
# if V=1 just print the whole command and args
@@ -28,13 +30,21 @@ UNCHECKED_GOALS := %clean TAGS cscope ctags dist \
help check-help print-% \
docker docker-% vm-help vm-test vm-build-%
+all:
+.PHONY: all clean distclean recurse-all dist msi FORCE
+
+# Don't try to regenerate Makefile or configure
+# We don't generate any of them
+Makefile: ;
+configure: ;
+
# All following code might depend on configuration variables
ifneq ($(wildcard config-host.mak),)
-# Put the all: rule here so that config-host.mak can contain dependencies.
-all:
include config-host.mak
git-submodule-update:
+.git-submodule-status: git-submodule-update config-host.mak
+Makefile: .git-submodule-status
.PHONY: git-submodule-update
@@ -62,28 +72,7 @@ git-submodule-update:
endif
endif
-export NINJA=./ninjatool
-
-# Running meson regenerates both build.ninja and ninjatool, and that is
-# enough to prime the rest of the build.
-ninjatool: build.ninja
-
-Makefile.ninja: build.ninja ninjatool
- ./ninjatool -t ninja2make --omit clean dist uninstall cscope TAGS ctags < $< > $@
--include Makefile.ninja
-
-${ninja-targets-c_COMPILER} ${ninja-targets-cpp_COMPILER}: .var.command += -MP
-
-# If MESON is empty, the rule will be re-evaluated after Makefiles are
-# reread (and MESON won't be empty anymore).
-ifneq ($(MESON),)
-Makefile.mtest: build.ninja scripts/mtest2make.py
- $(MESON) introspect --targets --tests --benchmarks | $(PYTHON) scripts/mtest2make.py > $@
--include Makefile.mtest
-endif
-
-Makefile: .git-submodule-status
-.git-submodule-status: git-submodule-update config-host.mak
+# 0. ensure the build tree is okay
# Check that we're not trying to do an out-of-tree build from
# a tree that's been used for an in-tree build.
@@ -95,6 +84,21 @@ seems to have been used for an in-tree build. You can fix this by running \
endif
endif
+# force a rerun of configure if config-host.mak is too old or corrupted
+ifeq ($(MESON),)
+.PHONY: config-host.mak
+x := $(shell rm -rf meson-private meson-info meson-logs)
+endif
+ifeq ($(NINJA),)
+.PHONY: config-host.mak
+x := $(shell rm -rf meson-private meson-info meson-logs)
+endif
+ifeq ($(wildcard build.ninja),)
+.PHONY: config-host.mak
+x := $(shell rm -rf meson-private meson-info meson-logs)
+endif
+
+# 1. ensure config-host.mak is up-to-date
config-host.mak: $(SRC_PATH)/configure $(SRC_PATH)/pc-bios $(SRC_PATH)/VERSION
@echo $@ is out-of-date, running configure
@if test -f meson-private/coredata.dat; then \
@@ -103,6 +107,46 @@ config-host.mak: $(SRC_PATH)/configure $(SRC_PATH)/pc-bios $(SRC_PATH)/VERSION
./config.status; \
fi
+# 2. ensure generated build files are up-to-date
+
+ifneq ($(NINJA),)
+# A separate rule is needed for Makefile dependencies to avoid -n
+export NINJA
+Makefile.ninja: build.ninja
+ $(quiet-@){ echo 'ninja-targets = \'; $(NINJA) -t targets all | sed 's/:.*//; $$!s/$$/ \\/'; } > $@
+-include Makefile.ninja
+endif
+
+ifneq ($(MESON),)
+# The dependency on config-host.mak ensures that meson has run
+Makefile.mtest: build.ninja scripts/mtest2make.py config-host.mak
+ $(MESON) introspect --targets --tests --benchmarks | $(PYTHON) scripts/mtest2make.py > $@
+-include Makefile.mtest
+endif
+
+# 3. Rules to bridge to other makefiles
+
+ifneq ($(NINJA),)
+NINJAFLAGS = $(if $V,-v,) \
+ $(filter-out -j, $(lastword -j1 $(filter -l% -j%, $(MAKEFLAGS)))) \
+ $(subst -k, -k0, $(filter -n -k,$(MAKEFLAGS)))
+
+ninja-cmd-goals = $(or $(MAKECMDGOALS), all)
+ninja-cmd-goals += $(foreach t, $(.tests), $(.test.deps.$t))
+
+makefile-targets := build.ninja ctags TAGS cscope dist clean uninstall
+ninja-targets := $(filter-out $(makefile-targets), $(ninja-targets))
+.PHONY: $(ninja-targets) run-ninja
+$(ninja-targets): run-ninja
+
+# Use "| cat" to give Ninja a more "make-y" output. Use "+" to bypass the
+# --output-sync line.
+run-ninja: config-host.mak
+ifneq ($(filter $(ninja-targets), $(ninja-cmd-goals)),)
+ +@$(NINJA) $(NINJAFLAGS) $(sort $(filter $(ninja-targets), $(ninja-cmd-goals))) | cat
+endif
+endif
+
# Force configure to re-run if the API symbols are updated
ifeq ($(CONFIG_PLUGIN),y)
config-host.mak: $(SRC_PATH)/plugins/qemu-plugins.symbols
@@ -112,37 +156,21 @@ plugins:
$(call quiet-command,\
$(MAKE) $(SUBDIR_MAKEFLAGS) -C contrib/plugins V="$(V)", \
"BUILD", "example plugins")
-endif
+endif # $(CONFIG_PLUGIN)
-else
+else # config-host.mak does not exist
config-host.mak:
ifneq ($(filter-out $(UNCHECKED_GOALS),$(MAKECMDGOALS)),$(if $(MAKECMDGOALS),,fail))
@echo "Please call configure before running make!"
@exit 1
endif
-endif
-
-# Only needed in case Makefile.ninja does not exist.
-.PHONY: ninja-clean ninja-distclean clean-ctlist
-clean-ctlist:
-ninja-clean::
-ninja-distclean::
-build.ninja: config-host.mak
-
-# Don't try to regenerate Makefile or configure
-# We don't generate any of them
-Makefile: ;
-configure: ;
-
-.PHONY: all clean distclean install \
- recurse-all dist msi FORCE
+endif # config-host.mak does not exist
SUBDIR_MAKEFLAGS=$(if $(V),,--no-print-directory --quiet)
include $(SRC_PATH)/tests/Makefile.include
all: recurse-all
-Makefile:
ROM_DIRS = $(addprefix pc-bios/, $(ROMS))
ROM_DIRS_RULES=$(foreach t, all clean, $(addsuffix /$(t), $(ROM_DIRS)))
@@ -157,8 +185,9 @@ recurse-clean: $(addsuffix /clean, $(ROM_DIRS))
######################################################################
-clean: recurse-clean ninja-clean clean-ctlist
- if test -f ninjatool; then ./ninjatool $(if $(V),-v,) -t clean; fi
+clean: recurse-clean
+ -@test -f build.ninja && $(quiet-@)$(NINJA) $(NINJAFLAGS) -t clean || :
+ -@test -f build.ninja && $(NINJA) $(NINJAFLAGS) clean-ctlist || :
# avoid old build problems by removing potentially incorrect old files
rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
find . \( -name '*.so' -o -name '*.dll' -o -name '*.[oda]' \) -type f \
@@ -175,8 +204,8 @@ dist: qemu-$(VERSION).tar.bz2
qemu-%.tar.bz2:
$(SRC_PATH)/scripts/make-release "$(SRC_PATH)" "$(patsubst qemu-%.tar.bz2,%,$@)"
-distclean: clean ninja-distclean
- -test -f ninjatool && ./ninjatool $(if $(V),-v,) -t clean -g
+distclean: clean
+ -@test -f build.ninja && $(quiet-@)$(NINJA) $(NINJAFLAGS) -t clean -g || :
rm -f config-host.mak config-host.h*
rm -f tests/tcg/config-*.mak
rm -f config-all-disas.mak config.status
@@ -185,7 +214,7 @@ distclean: clean ninja-distclean
rm -f qemu-plugins-ld.symbols qemu-plugins-ld64.symbols
rm -f *-config-target.h *-config-devices.mak *-config-devices.h
rm -rf meson-private meson-logs meson-info compile_commands.json
- rm -f Makefile.ninja ninjatool ninjatool.stamp Makefile.mtest
+ rm -f Makefile.ninja Makefile.mtest
rm -f config.log
rm -f linux-headers/asm
rm -Rf .sdk
@@ -194,19 +223,19 @@ find-src-path = find "$(SRC_PATH)/" -path "$(SRC_PATH)/meson" -prune -o -name "*
.PHONY: ctags
ctags:
- rm -f tags
- $(find-src-path) -exec ctags --append {} +
+ rm -f "$(SRC_PATH)/"tags
+ $(find-src-path) -exec ctags -f "$(SRC_PATH)/"tags --append {} +
.PHONY: TAGS
TAGS:
- rm -f TAGS
- $(find-src-path) -exec etags --append {} +
+ rm -f "$(SRC_PATH)/"TAGS
+ $(find-src-path) -exec etags -f "$(SRC_PATH)/"TAGS --append {} +
.PHONY: cscope
cscope:
rm -f "$(SRC_PATH)"/cscope.*
$(find-src-path) -print | sed -e 's,^\./,,' > "$(SRC_PATH)/cscope.files"
- cscope -b -i"$(SRC_PATH)/cscope.files"
+ cscope -b -i"$(SRC_PATH)/cscope.files" -f"$(SRC_PATH)"/cscope.out
# Needed by "meson install"
export DESTDIR
diff --git a/configure b/configure
index f498a37..a73fb87 100755
--- a/configure
+++ b/configure
@@ -297,12 +297,13 @@ brlapi=""
curl=""
iconv="auto"
curses="auto"
-docs=""
+docs="auto"
fdt="auto"
netmap="no"
sdl="auto"
sdl_image="auto"
virtfs=""
+libudev="auto"
mpath="auto"
vnc="enabled"
sparse="auto"
@@ -537,8 +538,6 @@ QEMU_CFLAGS="-fno-strict-aliasing -fno-common -fwrapv $QEMU_CFLAGS"
QEMU_CFLAGS="-Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS"
QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS"
QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS"
-QEMU_INCLUDES="-iquote . -iquote ${source_path} -iquote ${source_path}/accel/tcg -iquote ${source_path}/include"
-QEMU_INCLUDES="$QEMU_INCLUDES -iquote ${source_path}/disas/libvixl"
# Flags that are needed during configure but later taken care of by Meson
CONFIGURE_CFLAGS="-std=gnu99 -Wall"
@@ -796,7 +795,6 @@ Linux)
audio_possible_drivers="oss alsa sdl pa"
linux="yes"
linux_user="yes"
- QEMU_INCLUDES="-isystem ${source_path}/linux-headers -Ilinux-headers $QEMU_INCLUDES"
;;
esac
@@ -822,15 +820,6 @@ do
fi
done
-sphinx_build=
-for binary in sphinx-build-3 sphinx-build
-do
- if has "$binary"
- then
- sphinx_build=$(command -v "$binary")
- break
- fi
-done
# Check for ancillary tools used in testing
genisoimage=
@@ -971,7 +960,7 @@ for opt do
;;
--with-suffix=*) qemu_suffix="$optarg"
;;
- --docdir=*) qemu_docdir="$optarg"
+ --docdir=*) docdir="$optarg"
;;
--sysconfdir=*) sysconfdir="$optarg"
;;
@@ -1005,6 +994,10 @@ for opt do
;;
--enable-virtfs) virtfs="yes"
;;
+ --disable-libudev) libudev="disabled"
+ ;;
+ --enable-libudev) libudev="enabled"
+ ;;
--disable-mpath) mpath="disabled"
;;
--enable-mpath) mpath="enabled"
@@ -1226,9 +1219,9 @@ for opt do
;;
--disable-crypto-afalg) crypto_afalg="no"
;;
- --disable-docs) docs="no"
+ --disable-docs) docs="disabled"
;;
- --enable-docs) docs="yes"
+ --enable-docs) docs="enabled"
;;
--disable-vhost-net) vhost_net="no"
;;
@@ -1762,6 +1755,7 @@ disabled with --disable-FEATURE, default is enabled if available:
vnc-png PNG compression for VNC server
cocoa Cocoa UI (Mac OS X only)
virtfs VirtFS
+ libudev Use libudev to enumerate host devices
mpath Multipath persistent reservation passthrough
xen xen backend driver support
xen-pci-passthrough PCI passthrough support for Xen
@@ -1866,7 +1860,7 @@ python_version=$($python -c 'import sys; print("%d.%d.%d" % (sys.version_info[0]
python="$python -B"
if test -z "$meson"; then
- if test "$explicit_python" = no && has meson && version_ge "$(meson --version)" 0.55.1; then
+ if test "$explicit_python" = no && has meson && version_ge "$(meson --version)" 0.55.3; then
meson=meson
elif test -e "${source_path}/.git" && test $git_update = 'yes' ; then
meson=git
@@ -1908,7 +1902,7 @@ case "$meson" in
*) meson=$(command -v "$meson") ;;
esac
-# Probe for ninja (used for compdb)
+# Probe for ninja
if test -z "$ninja"; then
for c in ninja ninja-build samu; do
@@ -1917,6 +1911,9 @@ if test -z "$ninja"; then
break
fi
done
+ if test -z "$ninja"; then
+ error_exit "Cannot find Ninja"
+ fi
fi
# Check that the C compiler works. Doing this here before testing
@@ -4413,45 +4410,6 @@ if check_include linux/btrfs.h ; then
btrfs=yes
fi
-# If we're making warnings fatal, apply this to Sphinx runs as well
-sphinx_werror=""
-if test "$werror" = "yes"; then
- sphinx_werror="-W"
-fi
-
-# Check we have a new enough version of sphinx-build
-has_sphinx_build() {
- # This is a bit awkward but works: create a trivial document and
- # try to run it with our configuration file (which enforces a
- # version requirement). This will fail if either
- # sphinx-build doesn't exist at all or if it is too old.
- mkdir -p "$TMPDIR1/sphinx"
- touch "$TMPDIR1/sphinx/index.rst"
- "$sphinx_build" $sphinx_werror -c "$source_path/docs" \
- -b html "$TMPDIR1/sphinx" \
- "$TMPDIR1/sphinx/out" >> config.log 2>&1
-}
-
-# Check if tools are available to build documentation.
-if test "$docs" != "no" ; then
- if has_sphinx_build; then
- sphinx_ok=yes
- else
- sphinx_ok=no
- fi
- if test "$sphinx_ok" = "yes"; then
- docs=yes
- else
- if test "$docs" = "yes" ; then
- if has $sphinx_build && test "$sphinx_ok" != "yes"; then
- echo "Warning: $sphinx_build exists but it is either too old or uses too old a Python version" >&2
- fi
- feature_not_found "docs" "Install a Python 3 version of python-sphinx"
- fi
- docs=no
- fi
-fi
-
# Search for bswap_32 function
byteswap_h=no
cat > $TMPC << EOF
@@ -5770,7 +5728,6 @@ fi
qemu_confdir="$sysconfdir/$qemu_suffix"
qemu_moddir="$libdir/$qemu_suffix"
qemu_datadir="$datadir/$qemu_suffix"
-qemu_docdir="$docdir/$qemu_suffix"
qemu_localedir="$datadir/locale"
qemu_icondir="$datadir/icons"
qemu_desktopdir="$datadir/applications"
@@ -6088,9 +6045,6 @@ qemu_version=$(head $source_path/VERSION)
echo "PKGVERSION=$pkgversion" >>$config_host_mak
echo "SRC_PATH=$source_path" >> $config_host_mak
echo "TARGET_DIRS=$target_list" >> $config_host_mak
-if [ "$docs" = "yes" ] ; then
- echo "BUILD_DOCS=yes" >> $config_host_mak
-fi
if test "$modules" = "yes"; then
# $shacmd can generate a hash started with digit, which the compiler doesn't
# like as an symbol. So prefix it with an underscore
@@ -6777,28 +6731,12 @@ if test "$secret_keyring" = "yes" ; then
echo "CONFIG_SECRET_KEYRING=y" >> $config_host_mak
fi
-if test "$tcg_interpreter" = "yes"; then
- QEMU_INCLUDES="-iquote ${source_path}/tcg/tci $QEMU_INCLUDES"
-elif test "$ARCH" = "sparc64" ; then
- QEMU_INCLUDES="-iquote ${source_path}/tcg/sparc $QEMU_INCLUDES"
-elif test "$ARCH" = "s390x" ; then
- QEMU_INCLUDES="-iquote ${source_path}/tcg/s390 $QEMU_INCLUDES"
-elif test "$ARCH" = "x86_64" || test "$ARCH" = "x32" ; then
- QEMU_INCLUDES="-iquote ${source_path}/tcg/i386 $QEMU_INCLUDES"
-elif test "$ARCH" = "ppc64" ; then
- QEMU_INCLUDES="-iquote ${source_path}/tcg/ppc $QEMU_INCLUDES"
-elif test "$ARCH" = "riscv32" || test "$ARCH" = "riscv64" ; then
- QEMU_INCLUDES="-I${source_path}/tcg/riscv $QEMU_INCLUDES"
-else
- QEMU_INCLUDES="-iquote ${source_path}/tcg/${ARCH} $QEMU_INCLUDES"
-fi
-
echo "ROMS=$roms" >> $config_host_mak
echo "MAKE=$make" >> $config_host_mak
echo "PYTHON=$python" >> $config_host_mak
-echo "SPHINX_BUILD=$sphinx_build" >> $config_host_mak
echo "GENISOIMAGE=$genisoimage" >> $config_host_mak
echo "MESON=$meson" >> $config_host_mak
+echo "NINJA=$ninja" >> $config_host_mak
echo "CC=$cc" >> $config_host_mak
if $iasl -h > /dev/null 2>&1; then
echo "CONFIG_IASL=$iasl" >> $config_host_mak
@@ -6819,7 +6757,6 @@ echo "WINDRES=$windres" >> $config_host_mak
echo "CFLAGS_NOPIE=$CFLAGS_NOPIE" >> $config_host_mak
echo "QEMU_CFLAGS=$QEMU_CFLAGS" >> $config_host_mak
echo "QEMU_CXXFLAGS=$QEMU_CXXFLAGS" >> $config_host_mak
-echo "QEMU_INCLUDES=$QEMU_INCLUDES" >> $config_host_mak
echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak
echo "GLIB_LIBS=$glib_libs" >> $config_host_mak
echo "QEMU_LDFLAGS=$QEMU_LDFLAGS" >> $config_host_mak
@@ -7051,7 +6988,7 @@ fi
mv $cross config-meson.cross
rm -rf meson-private meson-info meson-logs
-NINJA=${ninja:-$PWD/ninjatool} $meson setup \
+NINJA=$ninja $meson setup \
--prefix "$prefix" \
--libdir "$libdir" \
--libexecdir "$libexecdir" \
@@ -7077,14 +7014,14 @@ NINJA=${ninja:-$PWD/ninjatool} $meson setup \
-Dvnc=$vnc -Dvnc_sasl=$vnc_sasl -Dvnc_jpeg=$vnc_jpeg -Dvnc_png=$vnc_png \
-Dgettext=$gettext -Dxkbcommon=$xkbcommon -Du2f=$u2f \
-Dcapstone=$capstone -Dslirp=$slirp -Dfdt=$fdt \
- -Diconv=$iconv -Dcurses=$curses \
+ -Diconv=$iconv -Dcurses=$curses -Dlibudev=$libudev\
+ -Ddocs=$docs -Dsphinx_build=$sphinx_build \
$cross_arg \
"$PWD" "$source_path"
if test "$?" -ne 0 ; then
error_exit "meson setup failed"
fi
-touch ninjatool.stamp
fi
if test -n "${deprecated_features}"; then
diff --git a/docs/conf.py b/docs/conf.py
index 00e1b75..e584f68 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -241,7 +241,7 @@ texinfo_documents = [
# We use paths starting from qemu_docdir here so that you can run
# sphinx-build from anywhere and the kerneldoc extension can still
# find everything.
-kerneldoc_bin = os.path.join(qemu_docdir, '../scripts/kernel-doc')
+kerneldoc_bin = ['perl', os.path.join(qemu_docdir, '../scripts/kernel-doc')]
kerneldoc_srctree = os.path.join(qemu_docdir, '..')
hxtool_srctree = os.path.join(qemu_docdir, '..')
qapidoc_srctree = os.path.join(qemu_docdir, '..')
diff --git a/docs/devel/build-system.rst b/docs/devel/build-system.rst
index 2ee368f..6fcf885 100644
--- a/docs/devel/build-system.rst
+++ b/docs/devel/build-system.rst
@@ -404,10 +404,8 @@ Built by Meson:
Built by Makefile:
`Makefile.ninja`
- A Makefile conversion of the build rules in build.ninja. The conversion
- is straightforward and, were it necessary to debug the rules produced
- by Meson, it should be enough to look at build.ninja. The conversion
- is performed by scripts/ninjatool.py.
+ A Makefile include that bridges to ninja for the actual build. The
+ Makefile is mostly a list of targets that Meson included in build.ninja.
`Makefile.mtest`
The Makefile definitions that let "make check" run tests defined in
diff --git a/docs/meson.build b/docs/meson.build
index 0340d48..8c222f9 100644
--- a/docs/meson.build
+++ b/docs/meson.build
@@ -1,4 +1,50 @@
+if get_option('sphinx_build') == ''
+ sphinx_build = find_program(['sphinx-build-3', 'sphinx-build'],
+ required: get_option('docs'))
+else
+ sphinx_build = find_program(get_option('sphinx_build'),
+ required: get_option('docs'))
+endif
+
+# Check if tools are available to build documentation.
+build_docs = false
+if sphinx_build.found()
+ SPHINX_ARGS = [sphinx_build]
+ # If we're making warnings fatal, apply this to Sphinx runs as well
+ if get_option('werror')
+ SPHINX_ARGS += [ '-W' ]
+ endif
+
+ # This is a bit awkward but works: create a trivial document and
+ # try to run it with our configuration file (which enforces a
+ # version requirement). This will fail if sphinx-build is too old.
+ run_command('mkdir', ['-p', tmpdir / 'sphinx'])
+ run_command('touch', [tmpdir / 'sphinx/index.rst'])
+ sphinx_build_test_out = run_command(SPHINX_ARGS + [
+ '-c', meson.current_source_dir(),
+ '-b', 'html', tmpdir / 'sphinx',
+ tmpdir / 'sphinx/out'])
+ build_docs = (sphinx_build_test_out.returncode() == 0)
+
+ if not build_docs
+ warning('@0@ exists but it is either too old or uses too old a Python version'.format(get_option('sphinx_build')))
+ if get_option('docs').enabled()
+ error('Install a Python 3 version of python-sphinx')
+ endif
+ endif
+endif
+
if build_docs
+ SPHINX_ARGS += ['-Dversion=' + meson.project_version(), '-Drelease=' + config_host['PKGVERSION']]
+
+ sphinx_extn_depends = [ meson.source_root() / 'docs/sphinx/depfile.py',
+ meson.source_root() / 'docs/sphinx/hxtool.py',
+ meson.source_root() / 'docs/sphinx/kerneldoc.py',
+ meson.source_root() / 'docs/sphinx/kernellog.py',
+ meson.source_root() / 'docs/sphinx/qapidoc.py',
+ meson.source_root() / 'docs/sphinx/qmp_lexer.py',
+ qapi_gen_depends ]
+
configure_file(output: 'index.html',
input: files('index.html.in'),
configuration: {'VERSION': meson.project_version()},
diff --git a/docs/sphinx/kerneldoc.py b/docs/sphinx/kerneldoc.py
index 3e87940..3ac277d 100644
--- a/docs/sphinx/kerneldoc.py
+++ b/docs/sphinx/kerneldoc.py
@@ -67,7 +67,7 @@ class KernelDocDirective(Directive):
def run(self):
env = self.state.document.settings.env
- cmd = [env.config.kerneldoc_bin, '-rst', '-enable-lineno']
+ cmd = env.config.kerneldoc_bin + ['-rst', '-enable-lineno']
filename = env.config.kerneldoc_srctree + '/' + self.arguments[0]
export_file_patterns = []
diff --git a/meson b/meson
-Subproject 68ed748f84f14c2d4e62dcbd123816e5898eb04
+Subproject 776acd2a805c9b42b4f0375150977df42130317
diff --git a/meson.build b/meson.build
index 2c6169f..7627a0a 100644
--- a/meson.build
+++ b/meson.build
@@ -17,7 +17,13 @@ cc = meson.get_compiler('c')
config_host = keyval.load(meson.current_build_dir() / 'config-host.mak')
enable_modules = 'CONFIG_MODULES' in config_host
enable_static = 'CONFIG_STATIC' in config_host
-build_docs = 'BUILD_DOCS' in config_host
+
+# Temporary directory used for files created while
+# configure runs. Since it is in the build directory
+# we can safely blow away any previous version of it
+# (and we need not jump through hoops to try to delete
+# it when configure exits.)
+tmpdir = meson.current_build_dir() / 'meson-private/temp'
if get_option('qemu_suffix').startswith('/')
error('qemu_suffix cannot start with a /')
@@ -47,10 +53,6 @@ supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv32', 'riscv64', 'x86', 'x86_64'
cpu = host_machine.cpu_family()
targetos = host_machine.system()
-configure_file(input: files('scripts/ninjatool.py'),
- output: 'ninjatool',
- configuration: config_host)
-
if cpu in ['x86', 'x86_64']
kvm_targets = ['i386-softmmu', 'x86_64-softmmu']
elif cpu == 'aarch64'
@@ -93,9 +95,35 @@ add_project_arguments(config_host['QEMU_CXXFLAGS'].split(),
native: false, language: 'cpp')
add_project_link_arguments(config_host['QEMU_LDFLAGS'].split(),
native: false, language: ['c', 'cpp', 'objc'])
-add_project_arguments(config_host['QEMU_INCLUDES'].split(),
- language: ['c', 'cpp', 'objc'])
+if targetos == 'linux'
+ add_project_arguments('-isystem', meson.current_source_dir() / 'linux-headers',
+ '-isystem', 'linux-headers',
+ language: ['c', 'cpp'])
+endif
+
+if 'CONFIG_TCG_INTERPRETER' in config_host
+ tcg_arch = 'tci'
+elif config_host['ARCH'] == 'sparc64'
+ tcg_arch = 'sparc'
+elif config_host['ARCH'] == 's390x'
+ tcg_arch = 's390'
+elif config_host['ARCH'] in ['x86_64', 'x32']
+ tcg_arch = 'i386'
+elif config_host['ARCH'] == 'ppc64'
+ tcg_arch = 'ppc'
+elif config_host['ARCH'] in ['riscv32', 'riscv64']
+ tcg_arch = 'riscv'
+else
+ tcg_arch = config_host['ARCH']
+endif
+add_project_arguments('-iquote', meson.current_source_dir() / 'tcg' / tcg_arch,
+ '-iquote', '.',
+ '-iquote', meson.current_source_dir(),
+ '-iquote', meson.current_source_dir() / 'accel/tcg',
+ '-iquote', meson.current_source_dir() / 'include',
+ '-iquote', meson.current_source_dir() / 'disas/libvixl',
+ language: ['c', 'cpp', 'objc'])
link_language = meson.get_external_property('link_language', 'cpp')
if link_language == 'cpp'
@@ -360,10 +388,11 @@ endif
libudev = not_found
if targetos == 'linux' and (have_system or have_tools)
libudev = dependency('libudev',
- required: get_option('mpath').enabled(),
+ required: get_option('libudev'),
static: enable_static)
endif
+mpathlibs = [libudev]
mpathpersist = not_found
mpathpersist_new_api = false
if targetos == 'linux' and have_tools and not get_option('mpath').disabled()
@@ -394,46 +423,52 @@ if targetos == 'linux' and have_tools and not get_option('mpath').disabled()
mpath_lib_init(udev);
return 0;
}'''
- mpathlibs = [libudev]
- if enable_static
- mpathlibs += cc.find_library('devmapper',
- required: get_option('mpath'),
- static: enable_static)
- endif
- mpathlibs += cc.find_library('multipath',
- required: get_option('mpath'),
- static: enable_static)
- mpathlibs += cc.find_library('mpathpersist',
- required: get_option('mpath'),
- static: enable_static)
- foreach lib: mpathlibs
- if not lib.found()
- mpathlibs = []
- break
+ libmpathpersist = cc.find_library('mpathpersist',
+ required: get_option('mpath'),
+ static: enable_static)
+ if libmpathpersist.found()
+ mpathlibs += libmpathpersist
+ if enable_static
+ mpathlibs += cc.find_library('devmapper',
+ required: get_option('mpath'),
+ static: enable_static)
endif
- endforeach
- if mpathlibs.length() > 0
- if cc.links(mpath_test_source_new, dependencies: mpathlibs)
+ mpathlibs += cc.find_library('multipath',
+ required: get_option('mpath'),
+ static: enable_static)
+ foreach lib: mpathlibs
+ if not lib.found()
+ mpathlibs = []
+ break
+ endif
+ endforeach
+ if mpathlibs.length() == 0
+ msg = 'Dependencies missing for libmpathpersist'
+ elif cc.links(mpath_test_source_new, dependencies: mpathlibs)
mpathpersist = declare_dependency(dependencies: mpathlibs)
mpathpersist_new_api = true
elif cc.links(mpath_test_source_old, dependencies: mpathlibs)
mpathpersist = declare_dependency(dependencies: mpathlibs)
else
+ msg = 'Cannot detect libmpathpersist API'
+ endif
+ if not mpathpersist.found()
if get_option('mpath').enabled()
- error('Cannot detect libmpathpersist API')
+ error(msg)
else
- warning('Cannot detect libmpathpersist API, disabling')
+ warning(msg + ', disabling')
endif
endif
endif
endif
iconv = not_found
-if not get_option('iconv').disabled()
- libiconv = cc.find_library('iconv',
- required: false,
- static: enable_static)
- if libiconv.found()
+curses = not_found
+if have_system and not get_option('curses').disabled()
+ if not get_option('iconv').disabled()
+ libiconv = cc.find_library('iconv',
+ required: false,
+ static: enable_static)
if cc.links('''
#include <iconv.h>
int main(void) {
@@ -443,28 +478,25 @@ if not get_option('iconv').disabled()
iconv = declare_dependency(dependencies: [libiconv])
endif
endif
-endif
-if get_option('iconv').enabled() and not iconv.found()
- error('Cannot detect iconv API')
-endif
-
-curses = not_found
-if iconv.found() and not get_option('curses').disabled()
- curses_libname_list = ['ncursesw', 'ncurses', 'cursesw', 'pdcurses']
- curses_test = '''
- #include <locale.h>
- #include <curses.h>
- #include <wchar.h>
- int main(void) {
- wchar_t wch = L'w';
- setlocale(LC_ALL, "");
- resize_term(0, 0);
- addwstr(L"wide chars\n");
- addnwstr(&wch, 1);
- add_wch(WACS_DEGREE);
- return 0;
- }'''
- foreach curses_libname : curses_libname_list
+ if get_option('iconv').enabled() and not iconv.found()
+ error('Cannot detect iconv API')
+ endif
+ if iconv.found()
+ curses_libname_list = ['ncursesw', 'ncurses', 'cursesw', 'pdcurses']
+ curses_test = '''
+ #include <locale.h>
+ #include <curses.h>
+ #include <wchar.h>
+ int main(void) {
+ wchar_t wch = L'w';
+ setlocale(LC_ALL, "");
+ resize_term(0, 0);
+ addwstr(L"wide chars\n");
+ addnwstr(&wch, 1);
+ add_wch(WACS_DEGREE);
+ return 0;
+ }'''
+ foreach curses_libname : curses_libname_list
libcurses = dependency(curses_libname,
required: false,
method: 'pkg-config',
@@ -486,13 +518,18 @@ if iconv.found() and not get_option('curses').disabled()
break
endif
endif
- endforeach
-endif
-if get_option('curses').enabled() and not curses.found()
- if not iconv.found()
- error('Cannot detect iconv API')
- else
- error('Cannot detect curses API')
+ endforeach
+ endif
+ if not curses.found()
+ if iconv.found()
+ if get_option('curses').enabled()
+ error('Cannot find curses')
+ endif
+ elif get_option('curses').enabled()
+ error('iconv required for curses UI but not available')
+ else
+ warning('iconv required for curses UI but not available, disabling')
+ endif
endif
endif
@@ -1237,22 +1274,6 @@ foreach d : hx_headers
endforeach
genh += hxdep
-SPHINX_ARGS = [config_host['SPHINX_BUILD'],
- '-Dversion=' + meson.project_version(),
- '-Drelease=' + config_host['PKGVERSION']]
-
-if get_option('werror')
- SPHINX_ARGS += [ '-W' ]
-endif
-
-sphinx_extn_depends = [ meson.source_root() / 'docs/sphinx/depfile.py',
- meson.source_root() / 'docs/sphinx/hxtool.py',
- meson.source_root() / 'docs/sphinx/kerneldoc.py',
- meson.source_root() / 'docs/sphinx/kernellog.py',
- meson.source_root() / 'docs/sphinx/qapidoc.py',
- meson.source_root() / 'docs/sphinx/qmp_lexer.py',
- qapi_gen_depends ]
-
###################
# Collect sources #
###################
@@ -1837,8 +1858,8 @@ endif
subdir('scripts')
subdir('tools')
subdir('pc-bios')
-subdir('tests')
subdir('docs')
+subdir('tests')
if 'CONFIG_GTK' in config_host
subdir('po')
endif
@@ -1920,7 +1941,7 @@ summary_info += {'QEMU_CFLAGS': config_host['QEMU_CFLAGS']}
summary_info += {'QEMU_LDFLAGS': config_host['QEMU_LDFLAGS']}
summary_info += {'make': config_host['MAKE']}
summary_info += {'python': '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
-summary_info += {'sphinx-build': config_host['SPHINX_BUILD']}
+summary_info += {'sphinx-build': sphinx_build.found()}
summary_info += {'genisoimage': config_host['GENISOIMAGE']}
# TODO: add back version
summary_info += {'slirp support': slirp_opt == 'disabled' ? false : slirp_opt}
@@ -1988,7 +2009,7 @@ if config_host.has_key('CONFIG_XEN_BACKEND')
summary_info += {'xen ctrl version': config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']}
endif
summary_info += {'brlapi support': config_host.has_key('CONFIG_BRLAPI')}
-summary_info += {'Documentation': config_host.has_key('BUILD_DOCS')}
+summary_info += {'Documentation': build_docs}
summary_info += {'PIE': get_option('b_pie')}
summary_info += {'vde support': config_host.has_key('CONFIG_VDE')}
summary_info += {'netmap support': config_host.has_key('CONFIG_NETMAP')}
diff --git a/meson_options.txt b/meson_options.txt
index e6cb1e5..967229b 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -2,7 +2,11 @@ option('qemu_suffix', type : 'string', value: 'qemu',
description: 'Suffix for QEMU data/modules/config directories (can be empty)')
option('docdir', type : 'string', value : 'doc',
description: 'Base directory for documentation installation (can be empty)')
+option('sphinx_build', type : 'string', value : '',
+ description: 'Use specified sphinx-build [$sphinx_build] for building document (default to be empty)')
+option('docs', type : 'feature', value : 'auto',
+ description: 'Documentations build support')
option('gettext', type : 'boolean', value : true,
description: 'Localization of the GTK+ user interface')
option('sparse', type : 'feature', value : 'auto',
@@ -36,6 +40,8 @@ option('iconv', type : 'feature', value : 'auto',
description: 'Font glyph conversion support')
option('curses', type : 'feature', value : 'auto',
description: 'curses UI')
+option('libudev', type : 'feature', value : 'auto',
+ description: 'Use libudev to enumerate host devices')
option('sdl', type : 'feature', value : 'auto',
description: 'SDL user interface')
option('sdl_image', type : 'feature', value : 'auto',
diff --git a/scripts/mtest2make.py b/scripts/mtest2make.py
index c3489a4..25ee688 100644
--- a/scripts/mtest2make.py
+++ b/scripts/mtest2make.py
@@ -70,8 +70,9 @@ def process_tests(test, targets, suites):
print('.test.driver.%d := %s' % (i, driver))
print('.test.env.%d := $(.test.env) %s' % (i, env))
print('.test.cmd.%d := %s' % (i, cmd))
+ print('.test.deps.%d := %s' % (i, ' '.join(deps)))
print('.PHONY: run-test-%d' % (i,))
- print('run-test-%d: %s' % (i, ' '.join(deps)))
+ print('run-test-%d: $(.test.deps.%d)' % (i,i))
print('\t@$(call .test.run,%d,$(.test.output-format))' % (i,))
test_suites = test['suite'] or ['default']
diff --git a/scripts/ninjatool.py b/scripts/ninjatool.py
deleted file mode 100755
index 6f0e35c..0000000
--- a/scripts/ninjatool.py
+++ /dev/null
@@ -1,1008 +0,0 @@
-#! /bin/sh
-
-# Python module for parsing and processing .ninja files.
-#
-# Author: Paolo Bonzini
-#
-# Copyright (C) 2019 Red Hat, Inc.
-
-
-# We don't want to put "#! @PYTHON@" as the shebang and
-# make the file executable, so instead we make this a
-# Python/shell polyglot. The first line below starts a
-# multiline string literal for Python, while it is just
-# ":" for bash. The closing of the multiline string literal
-# is never parsed by bash since it exits before.
-
-'''':
-case "$0" in
- /*) me=$0 ;;
- *) me=$(command -v "$0") ;;
-esac
-python="@PYTHON@"
-case $python in
- @*) python=python3 ;;
-esac
-exec $python "$me" "$@"
-exit 1
-'''
-
-
-from collections import namedtuple, defaultdict
-import sys
-import os
-import re
-import json
-import argparse
-import hashlib
-import shutil
-
-
-class InvalidArgumentError(Exception):
- pass
-
-# faster version of os.path.normpath: do nothing unless there is a double
-# slash or a "." or ".." component. The filter does not have to be super
-# precise, but it has to be fast. os.path.normpath is the hottest function
-# for ninja2make without this optimization!
-if os.path.sep == '/':
- def normpath(path, _slow_re=re.compile('/[./]')):
- return os.path.normpath(path) if _slow_re.search(path) or path[0] == '.' else path
-else:
- normpath = os.path.normpath
-
-
-def sha1_text(text):
- return hashlib.sha1(text.encode()).hexdigest()
-
-# ---- lexer and parser ----
-
-PATH_RE = r"[^$\s:|]+|\$[$ :]|\$[a-zA-Z0-9_-]+|\$\{[a-zA-Z0-9_.-]+\}"
-
-SIMPLE_PATH_RE = re.compile(r"^[^$\s:|]+$")
-IDENT_RE = re.compile(r"[a-zA-Z0-9_.-]+$")
-STRING_RE = re.compile(r"(" + PATH_RE + r"|[\s:|])(?:\r?\n)?|.")
-TOPLEVEL_RE = re.compile(r"([=:#]|\|\|?|^ +|(?:" + PATH_RE + r")+)\s*|.")
-VAR_RE=re.compile(r'\$\$|\$\{([^}]*)\}')
-
-BUILD = 1
-POOL = 2
-RULE = 3
-DEFAULT = 4
-EQUALS = 5
-COLON = 6
-PIPE = 7
-PIPE2 = 8
-IDENT = 9
-INCLUDE = 10
-INDENT = 11
-EOL = 12
-
-
-class LexerError(Exception):
- pass
-
-
-class ParseError(Exception):
- pass
-
-
-class NinjaParserEvents(object):
- def __init__(self, parser):
- self.parser = parser
-
- def dollar_token(self, word, in_path=False):
- return '$$' if word == '$' else word
-
- def variable_expansion_token(self, varname):
- return '${%s}' % varname
-
- def variable(self, name, arg):
- pass
-
- def begin_file(self):
- pass
-
- def end_file(self):
- pass
-
- def end_scope(self):
- pass
-
- def begin_pool(self, name):
- pass
-
- def begin_rule(self, name):
- pass
-
- def begin_build(self, out, iout, rule, in_, iin, orderdep):
- pass
-
- def default(self, targets):
- pass
-
-
-class NinjaParser(object):
-
- InputFile = namedtuple('InputFile', 'filename iter lineno')
-
- def __init__(self, filename, input):
- self.stack = []
- self.top = None
- self.iter = None
- self.lineno = None
- self.match_keyword = False
- self.push(filename, input)
-
- def file_changed(self):
- self.iter = self.top.iter
- self.lineno = self.top.lineno
- if self.top.filename is not None:
- os.chdir(os.path.dirname(self.top.filename) or '.')
-
- def push(self, filename, input):
- if self.top:
- self.top.lineno = self.lineno
- self.top.iter = self.iter
- self.stack.append(self.top)
- self.top = self.InputFile(filename=filename or 'stdin',
- iter=self._tokens(input), lineno=0)
- self.file_changed()
-
- def pop(self):
- if len(self.stack):
- self.top = self.stack[-1]
- self.stack.pop()
- self.file_changed()
- else:
- self.top = self.iter = None
-
- def next_line(self, input):
- line = next(input).rstrip()
- self.lineno += 1
- while len(line) and line[-1] == '$':
- line = line[0:-1] + next(input).strip()
- self.lineno += 1
- return line
-
- def print_token(self, tok):
- if tok == EOL:
- return "end of line"
- if tok == BUILD:
- return '"build"'
- if tok == POOL:
- return '"pool"'
- if tok == RULE:
- return '"rule"'
- if tok == DEFAULT:
- return '"default"'
- if tok == EQUALS:
- return '"="'
- if tok == COLON:
- return '":"'
- if tok == PIPE:
- return '"|"'
- if tok == PIPE2:
- return '"||"'
- if tok == INCLUDE:
- return '"include"'
- if tok == IDENT:
- return 'identifier'
- return '"%s"' % tok
-
- def error(self, msg):
- raise LexerError("%s:%d: %s" % (self.stack[-1].filename, self.lineno, msg))
-
- def parse_error(self, msg):
- raise ParseError("%s:%d: %s" % (self.stack[-1].filename, self.lineno, msg))
-
- def expected(self, expected, tok):
- msg = "found %s, expected " % (self.print_token(tok), )
- for i, exp_tok in enumerate(expected):
- if i > 0:
- msg = msg + (' or ' if i == len(expected) - 1 else ', ')
- msg = msg + self.print_token(exp_tok)
- self.parse_error(msg)
-
- def _variable_tokens(self, value):
- for m in STRING_RE.finditer(value):
- match = m.group(1)
- if not match:
- self.error("unexpected '%s'" % (m.group(0), ))
- yield match
-
- def _tokens(self, input):
- while True:
- try:
- line = self.next_line(input)
- except StopIteration:
- return
- for m in TOPLEVEL_RE.finditer(line):
- match = m.group(1)
- if not match:
- self.error("unexpected '%s'" % (m.group(0), ))
- if match == ':':
- yield COLON
- continue
- if match == '|':
- yield PIPE
- continue
- if match == '||':
- yield PIPE2
- continue
- if match[0] == ' ':
- yield INDENT
- continue
- if match[0] == '=':
- yield EQUALS
- value = line[m.start() + 1:].lstrip()
- yield from self._variable_tokens(value)
- break
- if match[0] == '#':
- break
-
- # identifier
- if self.match_keyword:
- if match == 'build':
- yield BUILD
- continue
- if match == 'pool':
- yield POOL
- continue
- if match == 'rule':
- yield RULE
- continue
- if match == 'default':
- yield DEFAULT
- continue
- if match == 'include':
- filename = line[m.start() + 8:].strip()
- self.push(filename, open(filename, 'r'))
- break
- if match == 'subninja':
- self.error('subninja is not supported')
- yield match
- yield EOL
-
- def parse(self, events):
- global_var = True
-
- def look_for(*expected):
- # The last token in the token stream is always EOL. This
- # is exploited to avoid catching StopIteration everywhere.
- tok = next(self.iter)
- if tok not in expected:
- self.expected(expected, tok)
- return tok
-
- def look_for_ident(*expected):
- tok = next(self.iter)
- if isinstance(tok, str):
- if not IDENT_RE.match(tok):
- self.parse_error('variable expansion not allowed')
- elif tok not in expected:
- self.expected(expected + (IDENT,), tok)
- return tok
-
- def parse_assignment_rhs(gen, expected, in_path):
- tokens = []
- for tok in gen:
- if not isinstance(tok, str):
- if tok in expected:
- break
- self.expected(expected + (IDENT,), tok)
- if tok[0] != '$':
- tokens.append(tok)
- elif tok == '$ ' or tok == '$$' or tok == '$:':
- tokens.append(events.dollar_token(tok[1], in_path))
- else:
- var = tok[2:-1] if tok[1] == '{' else tok[1:]
- tokens.append(events.variable_expansion_token(var))
- else:
- # gen must have raised StopIteration
- tok = None
-
- if tokens:
- # Fast path avoiding str.join()
- value = tokens[0] if len(tokens) == 1 else ''.join(tokens)
- else:
- value = None
- return value, tok
-
- def look_for_path(*expected):
- # paths in build rules are parsed one space-separated token
- # at a time and expanded
- token = next(self.iter)
- if not isinstance(token, str):
- return None, token
- # Fast path if there are no dollar and variable expansion
- if SIMPLE_PATH_RE.match(token):
- return token, None
- gen = self._variable_tokens(token)
- return parse_assignment_rhs(gen, expected, True)
-
- def parse_assignment(tok):
- name = tok
- assert isinstance(name, str)
- look_for(EQUALS)
- value, tok = parse_assignment_rhs(self.iter, (EOL,), False)
- assert tok == EOL
- events.variable(name, value)
-
- def parse_build():
- # parse outputs
- out = []
- iout = []
- while True:
- value, tok = look_for_path(COLON, PIPE)
- if value is None:
- break
- out.append(value)
- if tok == PIPE:
- while True:
- value, tok = look_for_path(COLON)
- if value is None:
- break
- iout.append(value)
-
- # parse rule
- assert tok == COLON
- rule = look_for_ident()
-
- # parse inputs and dependencies
- in_ = []
- iin = []
- orderdep = []
- while True:
- value, tok = look_for_path(PIPE, PIPE2, EOL)
- if value is None:
- break
- in_.append(value)
- if tok == PIPE:
- while True:
- value, tok = look_for_path(PIPE2, EOL)
- if value is None:
- break
- iin.append(value)
- if tok == PIPE2:
- while True:
- value, tok = look_for_path(EOL)
- if value is None:
- break
- orderdep.append(value)
- assert tok == EOL
- events.begin_build(out, iout, rule, in_, iin, orderdep)
- nonlocal global_var
- global_var = False
-
- def parse_pool():
- # pool declarations are ignored. Just gobble all the variables
- ident = look_for_ident()
- look_for(EOL)
- events.begin_pool(ident)
- nonlocal global_var
- global_var = False
-
- def parse_rule():
- ident = look_for_ident()
- look_for(EOL)
- events.begin_rule(ident)
- nonlocal global_var
- global_var = False
-
- def parse_default():
- idents = []
- while True:
- ident = look_for_ident(EOL)
- if ident == EOL:
- break
- idents.append(ident)
- events.default(idents)
-
- def parse_declaration(tok):
- if tok == EOL:
- return
-
- nonlocal global_var
- if tok == INDENT:
- if global_var:
- self.parse_error('indented line outside rule or edge')
- tok = look_for_ident(EOL)
- if tok == EOL:
- return
- parse_assignment(tok)
- return
-
- if not global_var:
- events.end_scope()
- global_var = True
- if tok == POOL:
- parse_pool()
- elif tok == BUILD:
- parse_build()
- elif tok == RULE:
- parse_rule()
- elif tok == DEFAULT:
- parse_default()
- elif isinstance(tok, str):
- parse_assignment(tok)
- else:
- self.expected((POOL, BUILD, RULE, INCLUDE, DEFAULT, IDENT), tok)
-
- events.begin_file()
- while self.iter:
- try:
- self.match_keyword = True
- token = next(self.iter)
- self.match_keyword = False
- parse_declaration(token)
- except StopIteration:
- self.pop()
- events.end_file()
-
-
-# ---- variable handling ----
-
-def expand(x, rule_vars=None, build_vars=None, global_vars=None):
- if x is None:
- return None
- changed = True
- have_dollar_replacement = False
- while changed:
- changed = False
- matches = list(VAR_RE.finditer(x))
- if not matches:
- break
-
- # Reverse the match so that expanding later matches does not
- # invalidate m.start()/m.end() for earlier ones. Do not reduce $$ to $
- # until all variables are dealt with.
- for m in reversed(matches):
- name = m.group(1)
- if not name:
- have_dollar_replacement = True
- continue
- changed = True
- if build_vars and name in build_vars:
- value = build_vars[name]
- elif rule_vars and name in rule_vars:
- value = rule_vars[name]
- elif name in global_vars:
- value = global_vars[name]
- else:
- value = ''
- x = x[:m.start()] + value + x[m.end():]
- return x.replace('$$', '$') if have_dollar_replacement else x
-
-
-class Scope(object):
- def __init__(self, events):
- self.events = events
-
- def on_left_scope(self):
- pass
-
- def on_variable(self, key, value):
- pass
-
-
-class BuildScope(Scope):
- def __init__(self, events, out, iout, rule, in_, iin, orderdep, rule_vars):
- super().__init__(events)
- self.rule = rule
- self.out = [events.expand_and_normalize(x) for x in out]
- self.in_ = [events.expand_and_normalize(x) for x in in_]
- self.iin = [events.expand_and_normalize(x) for x in iin]
- self.orderdep = [events.expand_and_normalize(x) for x in orderdep]
- self.iout = [events.expand_and_normalize(x) for x in iout]
- self.rule_vars = rule_vars
- self.build_vars = dict()
- self._define_variable('out', ' '.join(self.out))
- self._define_variable('in', ' '.join(self.in_))
-
- def expand(self, x):
- return self.events.expand(x, self.rule_vars, self.build_vars)
-
- def on_left_scope(self):
- self.events.variable('out', self.build_vars['out'])
- self.events.variable('in', self.build_vars['in'])
- self.events.end_build(self, self.out, self.iout, self.rule, self.in_,
- self.iin, self.orderdep)
-
- def _define_variable(self, key, value):
- # The value has been expanded already, quote it for further
- # expansion from rule variables
- value = value.replace('$', '$$')
- self.build_vars[key] = value
-
- def on_variable(self, key, value):
- # in and out are at the top of the lookup order and cannot
- # be overridden. Also, unlike what the manual says, build
- # variables only lookup global variables. They never lookup
- # rule variables, earlier build variables, or in/out.
- if key not in ('in', 'in_newline', 'out'):
- self._define_variable(key, self.events.expand(value))
-
-
-class RuleScope(Scope):
- def __init__(self, events, name, vars_dict):
- super().__init__(events)
- self.name = name
- self.vars_dict = vars_dict
- self.generator = False
-
- def on_left_scope(self):
- self.events.end_rule(self, self.name)
-
- def on_variable(self, key, value):
- self.vars_dict[key] = value
- if key == 'generator':
- self.generator = True
-
-
-class NinjaParserEventsWithVars(NinjaParserEvents):
- def __init__(self, parser):
- super().__init__(parser)
- self.rule_vars = defaultdict(lambda: dict())
- self.global_vars = dict()
- self.scope = None
-
- def variable(self, name, value):
- if self.scope:
- self.scope.on_variable(name, value)
- else:
- self.global_vars[name] = self.expand(value)
-
- def begin_build(self, out, iout, rule, in_, iin, orderdep):
- if rule != 'phony' and rule not in self.rule_vars:
- self.parser.parse_error("undefined rule '%s'" % rule)
-
- self.scope = BuildScope(self, out, iout, rule, in_, iin, orderdep, self.rule_vars[rule])
-
- def begin_pool(self, name):
- # pool declarations are ignored. Just gobble all the variables
- self.scope = Scope(self)
-
- def begin_rule(self, name):
- if name in self.rule_vars:
- self.parser.parse_error("duplicate rule '%s'" % name)
- self.scope = RuleScope(self, name, self.rule_vars[name])
-
- def end_scope(self):
- self.scope.on_left_scope()
- self.scope = None
-
- # utility functions:
-
- def expand(self, x, rule_vars=None, build_vars=None):
- return expand(x, rule_vars, build_vars, self.global_vars)
-
- def expand_and_normalize(self, x):
- return normpath(self.expand(x))
-
- # extra events not present in the superclass:
-
- def end_build(self, scope, out, iout, rule, in_, iin, orderdep):
- pass
-
- def end_rule(self, scope, name):
- pass
-
-
-# ---- test client that just prints back whatever it parsed ----
-
-class Writer(NinjaParserEvents):
- ARGS = argparse.ArgumentParser(description='Rewrite input build.ninja to stdout.')
-
- def __init__(self, output, parser, args):
- super().__init__(parser)
- self.output = output
- self.indent = ''
- self.had_vars = False
-
- def dollar_token(self, word, in_path=False):
- return '$' + word
-
- def print(self, *args, **kwargs):
- if len(args):
- self.output.write(self.indent)
- print(*args, **kwargs, file=self.output)
-
- def variable(self, name, value):
- self.print('%s = %s' % (name, value))
- self.had_vars = True
-
- def begin_scope(self):
- self.indent = ' '
- self.had_vars = False
-
- def end_scope(self):
- if self.had_vars:
- self.print()
- self.indent = ''
- self.had_vars = False
-
- def begin_pool(self, name):
- self.print('pool %s' % name)
- self.begin_scope()
-
- def begin_rule(self, name):
- self.print('rule %s' % name)
- self.begin_scope()
-
- def begin_build(self, outputs, implicit_outputs, rule, inputs, implicit, order_only):
- all_outputs = list(outputs)
- all_inputs = list(inputs)
-
- if implicit:
- all_inputs.append('|')
- all_inputs.extend(implicit)
- if order_only:
- all_inputs.append('||')
- all_inputs.extend(order_only)
- if implicit_outputs:
- all_outputs.append('|')
- all_outputs.extend(implicit_outputs)
-
- self.print('build %s: %s' % (' '.join(all_outputs),
- ' '.join([rule] + all_inputs)))
- self.begin_scope()
-
- def default(self, targets):
- self.print('default %s' % ' '.join(targets))
-
-
-# ---- emit compile_commands.json ----
-
-class Compdb(NinjaParserEventsWithVars):
- ARGS = argparse.ArgumentParser(description='Emit compile_commands.json.')
- ARGS.add_argument('rules', nargs='*',
- help='The ninja rules to emit compilation commands for.')
-
- def __init__(self, output, parser, args):
- super().__init__(parser)
- self.output = output
- self.rules = args.rules
- self.sep = ''
-
- def begin_file(self):
- self.output.write('[')
- self.directory = os.getcwd()
-
- def print_entry(self, **entry):
- entry['directory'] = self.directory
- self.output.write(self.sep + json.dumps(entry))
- self.sep = ',\n'
-
- def begin_build(self, out, iout, rule, in_, iin, orderdep):
- if in_ and rule in self.rules:
- super().begin_build(out, iout, rule, in_, iin, orderdep)
- else:
- self.scope = Scope(self)
-
- def end_build(self, scope, out, iout, rule, in_, iin, orderdep):
- self.print_entry(command=scope.expand('${command}'), file=in_[0])
-
- def end_file(self):
- self.output.write(']\n')
-
-
-# ---- clean output files ----
-
-class Clean(NinjaParserEventsWithVars):
- ARGS = argparse.ArgumentParser(description='Remove output build files.')
- ARGS.add_argument('-g', dest='generator', action='store_true',
- help='clean generated files too')
-
- def __init__(self, output, parser, args):
- super().__init__(parser)
- self.dry_run = args.dry_run
- self.verbose = args.verbose or args.dry_run
- self.generator = args.generator
-
- def begin_file(self):
- print('Cleaning... ', end=(None if self.verbose else ''), flush=True)
- self.cnt = 0
-
- def end_file(self):
- print('%d files' % self.cnt)
-
- def do_clean(self, *files):
- for f in files:
- if self.dry_run:
- if os.path.exists(f):
- self.cnt += 1
- print('Would remove ' + f)
- continue
- else:
- try:
- if os.path.isdir(f):
- shutil.rmtree(f)
- else:
- os.unlink(f)
- self.cnt += 1
- if self.verbose:
- print('Removed ' + f)
- except FileNotFoundError:
- pass
-
- def end_build(self, scope, out, iout, rule, in_, iin, orderdep):
- if rule == 'phony':
- return
- if self.generator:
- rspfile = scope.expand('${rspfile}')
- if rspfile:
- self.do_clean(rspfile)
- if self.generator or not scope.expand('${generator}'):
- self.do_clean(*out, *iout)
- depfile = scope.expand('${depfile}')
- if depfile:
- self.do_clean(depfile)
-
-
-# ---- convert build.ninja to makefile ----
-
-class Ninja2Make(NinjaParserEventsWithVars):
- ARGS = argparse.ArgumentParser(description='Convert build.ninja to a Makefile.')
- ARGS.add_argument('--clean', dest='emit_clean', action='store_true',
- help='Emit clean/distclean rules.')
- ARGS.add_argument('--doublecolon', action='store_true',
- help='Emit double-colon rules for phony targets.')
- ARGS.add_argument('--omit', metavar='TARGET', nargs='+',
- help='Targets to omit.')
-
- def __init__(self, output, parser, args):
- super().__init__(parser)
- self.output = output
-
- self.emit_clean = args.emit_clean
- self.doublecolon = args.doublecolon
- self.omit = set(args.omit)
-
- if self.emit_clean:
- self.omit.update(['clean', 'distclean'])
-
- # Lists of targets are kept in memory and emitted only at the
- # end because appending is really inefficient in GNU make.
- # We only do it when it's O(#rules) or O(#variables), but
- # never when it could be O(#targets).
- self.depfiles = list()
- self.rspfiles = list()
- self.build_vars = defaultdict(lambda: dict())
- self.rule_targets = defaultdict(lambda: list())
- self.stamp_targets = defaultdict(lambda: list())
- self.all_outs = set()
- self.all_ins = set()
- self.all_phony = set()
- self.seen_default = False
-
- def print(self, *args, **kwargs):
- print(*args, **kwargs, file=self.output)
-
- def dollar_token(self, word, in_path=False):
- if in_path and word == ' ':
- self.parser.parse_error('Make does not support spaces in filenames')
- return '$$' if word == '$' else word
-
- def print_phony(self, outs, ins):
- targets = ' '.join(outs).replace('$', '$$')
- deps = ' '.join(ins).replace('$', '$$')
- deps = deps.strip()
- if self.doublecolon:
- self.print(targets + '::' + (' ' if deps else '') + deps + ';@:')
- else:
- self.print(targets + ':' + (' ' if deps else '') + deps)
- self.all_phony.update(outs)
-
- def begin_file(self):
- self.print(r'# This is an automatically generated file, and it shows.')
- self.print(r'ninja-default:')
- self.print(r'.PHONY: ninja-default ninja-clean ninja-distclean')
- if self.emit_clean:
- self.print(r'ninja-clean:: ninja-clean-start; $(if $V,,@)rm -f ${ninja-depfiles}')
- self.print(r'ninja-clean-start:; $(if $V,,@echo Cleaning...)')
- self.print(r'ninja-distclean:: clean; $(if $V,,@)rm -f ${ninja-rspfiles}')
- self.print(r'.PHONY: ninja-clean-start')
- self.print_phony(['clean'], ['ninja-clean'])
- self.print_phony(['distclean'], ['ninja-distclean'])
- self.print(r'vpath')
- self.print(r'NULL :=')
- self.print(r'SPACE := ${NULL} #')
- self.print(r'MAKEFLAGS += -rR')
- self.print(r'define NEWLINE')
- self.print(r'')
- self.print(r'endef')
- self.print(r'.var.in_newline = $(subst $(SPACE),$(NEWLINE),${.var.in})')
- self.print(r"ninja-command = $(if $V,,$(if ${.var.description},@printf '%s\n' '$(subst ','\'',${.var.description})' && ))${.var.command}")
- self.print(r"ninja-command-restat = $(if $V,,$(if ${.var.description},@printf '%s\n' '$(subst ','\'',${.var.description})' && ))${.var.command} && if test -e $(firstword ${.var.out}); then printf '%s\n' ${.var.out} > $@; fi")
-
- def end_file(self):
- def natural_sort_key(s, _nsre=re.compile('([0-9]+)')):
- return [int(text) if text.isdigit() else text.lower()
- for text in _nsre.split(s)]
-
- self.print()
- self.print('ninja-outputdirs :=')
- for rule in self.rule_vars:
- if rule == 'phony':
- continue
- self.print('ninja-targets-%s := %s' % (rule, ' '.join(self.rule_targets[rule])))
- self.print('ninja-stamp-%s := %s' % (rule, ' '.join(self.stamp_targets[rule])))
- self.print('ninja-outputdirs += $(sort $(dir ${ninja-targets-%s}))' % rule)
- self.print()
- self.print('dummy := $(shell mkdir -p . $(sort $(ninja-outputdirs)))')
- self.print('ninja-depfiles :=' + ' '.join(self.depfiles))
- self.print('ninja-rspfiles :=' + ' '.join(self.rspfiles))
- self.print('-include ${ninja-depfiles}')
- self.print()
- for targets in self.build_vars:
- for name, value in self.build_vars[targets].items():
- self.print('%s: private .var.%s := %s' %
- (targets, name, value.replace('$', '$$')))
- self.print()
- if not self.seen_default:
- default_targets = sorted(self.all_outs - self.all_ins, key=natural_sort_key)
- self.print('ninja-default: ' + ' '.join(default_targets))
-
- # This is a hack... Meson declares input meson.build files as
- # phony, because Ninja does not have an equivalent of Make's
- # "path/to/file:" declaration that ignores "path/to/file" even
- # if it is absent. However, Makefile.ninja wants to depend on
- # build.ninja, which in turn depends on these phony targets which
- # would cause Makefile.ninja to be rebuilt in a loop.
- phony_targets = sorted(self.all_phony - self.all_ins, key=natural_sort_key)
- self.print('.PHONY: ' + ' '.join(phony_targets))
-
- def variable(self, name, value):
- super().variable(name, value)
- if self.scope is None:
- self.global_vars[name] = self.expand(value)
- self.print('.var.%s := %s' % (name, self.global_vars[name]))
-
- def begin_build(self, out, iout, rule, in_, iin, orderdep):
- if any(x in self.omit for x in out):
- self.scope = Scope(self)
- return
-
- super().begin_build(out, iout, rule, in_, iin, orderdep)
- self.current_targets = ' '.join(self.scope.out + self.scope.iout).replace('$', '$$')
-
- def end_build(self, scope, out, iout, rule, in_, iin, orderdep):
- self.rule_targets[rule] += self.scope.out
- self.rule_targets[rule] += self.scope.iout
-
- self.all_outs.update(self.scope.iout)
- self.all_outs.update(self.scope.out)
- self.all_ins.update(self.scope.in_)
- self.all_ins.update(self.scope.iin)
-
- targets = self.current_targets
- self.current_targets = None
- if rule == 'phony':
- # Phony rules treat order-only dependencies as normal deps
- self.print_phony(out + iout, in_ + iin + orderdep)
- return
-
- inputs = ' '.join(in_ + iin).replace('$', '$$')
- orderonly = ' '.join(orderdep).replace('$', '$$')
-
- rspfile = scope.expand('${rspfile}')
- if rspfile:
- rspfile_content = scope.expand('${rspfile_content}')
- with open(rspfile, 'w') as f:
- f.write(rspfile_content)
- inputs += ' ' + rspfile
- self.rspfiles.append(rspfile)
-
- restat = 'restat' in self.scope.build_vars or 'restat' in self.rule_vars[rule]
- depfile = scope.expand('${depfile}')
- build_vars = {
- 'command': scope.expand('${command}'),
- 'description': scope.expand('${description}'),
- 'out': scope.expand('${out}')
- }
-
- if restat and not depfile:
- if len(out) == 1:
- stamp = out[0] + '.stamp'
- else:
- stamp = '%s@%s.stamp' % (rule, sha1_text(targets)[0:11])
- self.print('%s: %s; @:' % (targets, stamp))
- self.print('ifneq (%s, $(wildcard %s))' % (targets, targets))
- self.print('.PHONY: %s' % (stamp, ))
- self.print('endif')
- self.print('%s: %s | %s; ${ninja-command-restat}' % (stamp, inputs, orderonly))
- self.rule_targets[rule].append(stamp)
- self.stamp_targets[rule].append(stamp)
- self.build_vars[stamp] = build_vars
- else:
- self.print('%s: %s | %s; ${ninja-command}' % (targets, inputs, orderonly))
- self.build_vars[targets] = build_vars
- if depfile:
- self.depfiles.append(depfile)
-
- def end_rule(self, scope, name):
- # Note that the generator pseudo-variable could also be attached
- # to a build block rather than a rule. This is not handled here
- # in order to reduce the number of "rm" invocations. However,
- # "ninjatool.py -t clean" does that correctly.
- target = 'distclean' if scope.generator else 'clean'
- self.print('ninja-%s:: ; $(if $V,,@)rm -f ${ninja-stamp-%s}' % (target, name))
- if self.emit_clean:
- self.print('ninja-%s:: ; $(if $V,,@)rm -rf ${ninja-targets-%s}' % (target, name))
-
- def default(self, targets):
- self.print("ninja-default: " + ' '.join(targets))
- self.seen_default = True
-
-
-# ---- command line parsing ----
-
-# we cannot use subparsers because tools are chosen through the "-t"
-# option.
-
-class ToolAction(argparse.Action):
- def __init__(self, option_strings, dest, choices, metavar='TOOL', nargs=None, **kwargs):
- if nargs is not None:
- raise ValueError("nargs not allowed")
- super().__init__(option_strings, dest, required=True, choices=choices,
- metavar=metavar, **kwargs)
-
- def __call__(self, parser, namespace, value, option_string):
- tool = self.choices[value]
- setattr(namespace, self.dest, tool)
- tool.ARGS.prog = '%s %s %s' % (parser.prog, option_string, value)
-
-
-class ToolHelpAction(argparse.Action):
- def __init__(self, option_strings, dest, nargs=None, **kwargs):
- if nargs is not None:
- raise ValueError("nargs not allowed")
- super().__init__(option_strings, dest, nargs=0, **kwargs)
-
- def __call__(self, parser, namespace, values, option_string=None):
- if namespace.tool:
- namespace.tool.ARGS.print_help()
- else:
- parser.print_help()
- parser.exit()
-
-
-tools = {
- 'test': Writer,
- 'ninja2make': Ninja2Make,
- 'compdb': Compdb,
- 'clean': Clean,
-}
-
-parser = argparse.ArgumentParser(description='Process and transform build.ninja files.',
- add_help=False)
-parser.add_argument('-C', metavar='DIR', dest='dir', default='.',
- help='change to DIR before doing anything else')
-parser.add_argument('-f', metavar='FILE', dest='file', default='build.ninja',
- help='specify input build file [default=build.ninja]')
-parser.add_argument('-n', dest='dry_run', action='store_true',
- help='do not actually do anything')
-parser.add_argument('-v', dest='verbose', action='store_true',
- help='be more verbose')
-
-parser.add_argument('-t', dest='tool', choices=tools, action=ToolAction,
- help='choose the tool to run')
-parser.add_argument('-h', '--help', action=ToolHelpAction,
- help='show this help message and exit')
-
-if len(sys.argv) >= 2 and sys.argv[1] == '--version':
- print('1.8')
- sys.exit(0)
-
-args, tool_args = parser.parse_known_args()
-args.tool.ARGS.parse_args(tool_args, args)
-
-os.chdir(args.dir)
-with open(args.file, 'r') as f:
- parser = NinjaParser(args.file, f)
- try:
- events = args.tool(sys.stdout, parser, args)
- except InvalidArgumentError as e:
- parser.error(str(e))
- parser.parse(events)
diff --git a/target/i386/hax-cpus.c b/target/i386/hax-cpus.c
index 99770e5..f72c85b 100644
--- a/target/i386/hax-cpus.c
+++ b/target/i386/hax-cpus.c
@@ -38,6 +38,7 @@ static void *hax_cpu_thread_fn(void *arg)
qemu_thread_get_self(cpu->thread);
cpu->thread_id = qemu_get_thread_id();
+ current_cpu = cpu;
hax_init_vcpu(cpu);
cpu_thread_signal_created(cpu);
qemu_guest_random_seed_thread_part2(cpu->random_seed);
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 5aca98e..3a0524c 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -140,7 +140,7 @@ QEMU_IOTESTS_HELPERS-$(CONFIG_LINUX) = tests/qemu-iotests/socket_scm_helper$(EXE
check: check-block
check-block: $(SRC_PATH)/tests/check-block.sh qemu-img$(EXESUF) \
qemu-io$(EXESUF) qemu-nbd$(EXESUF) $(QEMU_IOTESTS_HELPERS-y) \
- $(patsubst %-softmmu,qemu-system-%,$(filter %-softmmu,$(TARGET_DIRS)))
+ $(filter qemu-system-%, $(ninja-targets))
@$<
endif
diff --git a/tests/docker/dockerfiles/centos7.docker b/tests/docker/dockerfiles/centos7.docker
index 4627777..8b27372 100644
--- a/tests/docker/dockerfiles/centos7.docker
+++ b/tests/docker/dockerfiles/centos7.docker
@@ -27,6 +27,7 @@ ENV PACKAGES \
mesa-libEGL-devel \
mesa-libgbm-devel \
nettle-devel \
+ ninja-build \
perl-Test-Harness \
pixman-devel \
python3 \
diff --git a/tests/docker/dockerfiles/centos8.docker b/tests/docker/dockerfiles/centos8.docker
index 0fc2697..585dfad 100644
--- a/tests/docker/dockerfiles/centos8.docker
+++ b/tests/docker/dockerfiles/centos8.docker
@@ -19,6 +19,7 @@ ENV PACKAGES \
make \
mesa-libEGL-devel \
nettle-devel \
+ ninja-build \
perl-Test-Harness \
pixman-devel \
python36 \
@@ -28,5 +29,7 @@ ENV PACKAGES \
tar \
zlib-devel
-RUN dnf install -y $PACKAGES
+RUN dnf install -y dnf-plugins-core && \
+ dnf config-manager --set-enabled PowerTools && \
+ dnf install -y $PACKAGES
RUN rpm -q $PACKAGES | sort > /packages.txt
diff --git a/tests/docker/dockerfiles/debian10.docker b/tests/docker/dockerfiles/debian10.docker
index 1e4188b..21cc671 100644
--- a/tests/docker/dockerfiles/debian10.docker
+++ b/tests/docker/dockerfiles/debian10.docker
@@ -26,6 +26,7 @@ RUN apt update && \
gettext \
git \
libncurses5-dev \
+ ninja-build \
pkg-config \
psmisc \
python3 \
diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker
index 85c9755..ac79d95 100644
--- a/tests/docker/dockerfiles/fedora.docker
+++ b/tests/docker/dockerfiles/fedora.docker
@@ -75,6 +75,7 @@ ENV PACKAGES \
mingw64-SDL2 \
ncurses-devel \
nettle-devel \
+ ninja-build \
nss-devel \
numactl-devel \
perl \
diff --git a/tests/docker/dockerfiles/travis.docker b/tests/docker/dockerfiles/travis.docker
index 5912825..cd1435a 100644
--- a/tests/docker/dockerfiles/travis.docker
+++ b/tests/docker/dockerfiles/travis.docker
@@ -9,7 +9,7 @@ ENV LC_ALL en_US.UTF-8
RUN sed -i "s/# deb-src/deb-src/" /etc/apt/sources.list
RUN apt-get update
RUN apt-get -y build-dep qemu
-RUN apt-get -y install device-tree-compiler python3 python3-yaml dh-autoreconf gdb strace lsof net-tools gcovr
+RUN apt-get -y install device-tree-compiler python3 python3-yaml dh-autoreconf gdb strace lsof net-tools gcovr ninja-build
# Travis tools require PhantomJS / Neo4j / Maven accessible
# in their PATH (QEMU build won't access them).
ENV PATH /usr/local/phantomjs/bin:/usr/local/phantomjs:/usr/local/neo4j-3.2.7/bin:/usr/local/maven-3.5.2/bin:/usr/local/cmake-3.9.2/bin:/usr/local/clang-5.0.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
diff --git a/tests/docker/dockerfiles/ubuntu.docker b/tests/docker/dockerfiles/ubuntu.docker
index b556ed1..b5ef7a8 100644
--- a/tests/docker/dockerfiles/ubuntu.docker
+++ b/tests/docker/dockerfiles/ubuntu.docker
@@ -60,6 +60,7 @@ ENV PACKAGES \
libxen-dev \
libzstd-dev \
make \
+ ninja-build \
python3-yaml \
python3-sphinx \
sparse \
diff --git a/tests/docker/dockerfiles/ubuntu1804.docker b/tests/docker/dockerfiles/ubuntu1804.docker
index a6a7617..9b0a19b 100644
--- a/tests/docker/dockerfiles/ubuntu1804.docker
+++ b/tests/docker/dockerfiles/ubuntu1804.docker
@@ -48,6 +48,7 @@ ENV PACKAGES \
make \
python3-yaml \
python3-sphinx \
+ ninja-build \
sparse \
xfslibs-dev
RUN apt-get update && \
diff --git a/tests/docker/dockerfiles/ubuntu2004.docker b/tests/docker/dockerfiles/ubuntu2004.docker
index f4b9556..17b37cd 100644
--- a/tests/docker/dockerfiles/ubuntu2004.docker
+++ b/tests/docker/dockerfiles/ubuntu2004.docker
@@ -47,6 +47,7 @@ ENV PACKAGES flex bison \
libxen-dev \
libzstd-dev \
make \
+ ninja-build \
python3-numpy \
python3-opencv \
python3-pil \
diff --git a/tests/include/meson.build b/tests/include/meson.build
index fea3a63..9abba30 100644
--- a/tests/include/meson.build
+++ b/tests/include/meson.build
@@ -10,7 +10,7 @@ test_qapi_outputs_extra = [
'test-qapi-visit-sub-module.h',
]
-test_qapi_outputs_extra = custom_target('QAPI test (include)',
- output: test_qapi_outputs_extra,
- input: test_qapi_files,
- command: 'true')
+test_qapi_files_extra = custom_target('QAPI test (include)',
+ output: test_qapi_outputs_extra,
+ input: test_qapi_files,
+ command: 'true')
diff --git a/tests/meson.build b/tests/meson.build
index bf47a38..afeb6be 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -56,8 +56,18 @@ test_qapi_files = custom_target('Test QAPI files',
# perhaps change qapi_gen to replace / with _, like Meson itself does?
subdir('include')
-libtestqapi = static_library('testqapi', sources: [test_qapi_files, genh, test_qapi_outputs_extra])
-testqapi = declare_dependency(link_with: libtestqapi)
+test_qapi_sources = []
+test_qapi_headers = []
+i = 0
+foreach o: test_qapi_files.to_list() + test_qapi_files_extra.to_list()
+ if o.full_path().endswith('.h')
+ test_qapi_headers += o
+ endif
+ test_qapi_sources += o
+endforeach
+
+libtestqapi = static_library('testqapi', sources: [genh, test_qapi_sources])
+testqapi = declare_dependency(link_with: libtestqapi, sources: [genh, test_qapi_headers])
testblock = declare_dependency(dependencies: [block], sources: 'iothread.c')
diff --git a/tests/qapi-schema/meson.build b/tests/qapi-schema/meson.build
index 1f222a7..304ef93 100644
--- a/tests/qapi-schema/meson.build
+++ b/tests/qapi-schema/meson.build
@@ -219,53 +219,53 @@ qapi_doc = custom_target('QAPI doc',
'-p', 'doc-good-', '@INPUT0@' ],
depend_files: qapi_gen_depends)
-# Test the document-comment document generation code by running a test schema
-# file through Sphinx's plain-text builder and comparing the result against
-# a golden reference. This is in theory susceptible to failures if Sphinx
-# changes its output, but the text output has historically been very stable
-# (no changes between Sphinx 1.6 and 3.0), so it is a better bet than
-# texinfo or HTML generation, both of which have had changes. We might
-# need to add more sophisticated logic here in future for some sort of
-# fuzzy comparison if future Sphinx versions produce different text,
-# but for now the simple comparison suffices.
-qapi_doc_out = custom_target('QAPI rST doc',
- output: ['doc-good.txt'],
- input: files('doc-good.json', 'doc-good.rst'),
- build_by_default: build_docs,
- depend_files: sphinx_extn_depends,
- # We use -E to suppress Sphinx's caching, because
- # we want it to always really run the QAPI doc
- # generation code. It also means we don't
- # clutter up the build dir with the cache.
- command: [SPHINX_ARGS,
- '-b', 'text', '-E',
- '-c', meson.source_root() / 'docs',
- '-D', 'master_doc=doc-good',
- meson.current_source_dir(),
- meson.current_build_dir()])
+if build_docs
+ # Test the document-comment document generation code by running a test schema
+ # file through Sphinx's plain-text builder and comparing the result against
+ # a golden reference. This is in theory susceptible to failures if Sphinx
+ # changes its output, but the text output has historically been very stable
+ # (no changes between Sphinx 1.6 and 3.0), so it is a better bet than
+ # texinfo or HTML generation, both of which have had changes. We might
+ # need to add more sophisticated logic here in future for some sort of
+ # fuzzy comparison if future Sphinx versions produce different text,
+ # but for now the simple comparison suffices.
+ qapi_doc_out = custom_target('QAPI rST doc',
+ output: ['doc-good.txt'],
+ input: files('doc-good.json', 'doc-good.rst'),
+ build_by_default: true,
+ depend_files: sphinx_extn_depends,
+ # We use -E to suppress Sphinx's caching, because
+ # we want it to always really run the QAPI doc
+ # generation code. It also means we don't
+ # clutter up the build dir with the cache.
+ command: [SPHINX_ARGS,
+ '-b', 'text', '-E',
+ '-c', meson.source_root() / 'docs',
+ '-D', 'master_doc=doc-good',
+ meson.current_source_dir(),
+ meson.current_build_dir()])
-# Fix possible inconsistency in line endings in generated output and
-# in the golden reference (which could otherwise cause test failures
-# on Windows hosts). Unfortunately diff --strip-trailing-cr
-# is GNU-diff only. The odd-looking perl is because we must avoid
-# using an explicit '\' character in the command arguments to
-# a custom_target(), as Meson will unhelpfully replace it with a '/'
-# (https://github.com/mesonbuild/meson/issues/1564)
-qapi_doc_out_nocr = custom_target('QAPI rST doc newline-sanitized',
- output: ['doc-good.txt.nocr'],
- input: qapi_doc_out[0],
- build_by_default: build_docs,
- command: ['perl', '-pe', '$x = chr 13; s/$x$//', '@INPUT@'],
- capture: true)
+ # Fix possible inconsistency in line endings in generated output and
+ # in the golden reference (which could otherwise cause test failures
+ # on Windows hosts). Unfortunately diff --strip-trailing-cr
+ # is GNU-diff only. The odd-looking perl is because we must avoid
+ # using an explicit '\' character in the command arguments to
+ # a custom_target(), as Meson will unhelpfully replace it with a '/'
+ # (https://github.com/mesonbuild/meson/issues/1564)
+ qapi_doc_out_nocr = custom_target('QAPI rST doc newline-sanitized',
+ output: ['doc-good.txt.nocr'],
+ input: qapi_doc_out[0],
+ build_by_default: true,
+ command: ['perl', '-pe', '$x = chr 13; s/$x$//', '@INPUT@'],
+ capture: true)
-qapi_doc_ref_nocr = custom_target('QAPI rST doc reference newline-sanitized',
- output: ['doc-good.ref.nocr'],
- input: files('doc-good.txt'),
- build_by_default: build_docs,
- command: ['perl', '-pe', '$x = chr 13; s/$x$//', '@INPUT@'],
- capture: true)
+ qapi_doc_ref_nocr = custom_target('QAPI rST doc reference newline-sanitized',
+ output: ['doc-good.ref.nocr'],
+ input: files('doc-good.txt'),
+ build_by_default: true,
+ command: ['perl', '-pe', '$x = chr 13; s/$x$//', '@INPUT@'],
+ capture: true)
-if build_docs
# "full_path()" needed here to work around
# https://github.com/mesonbuild/meson/issues/7585
test('QAPI rST doc', diff, args: ['-u', qapi_doc_ref_nocr[0].full_path(),
diff --git a/tests/qtest/fuzz/fuzz.c b/tests/qtest/fuzz/fuzz.c
index d926c49..eb00704 100644
--- a/tests/qtest/fuzz/fuzz.c
+++ b/tests/qtest/fuzz/fuzz.c
@@ -217,5 +217,13 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp)
/* re-enable the rcu atfork, which was previously disabled in qemu_init */
rcu_enable_atfork();
+ /*
+ * Disable QEMU's signal handlers, since we manually control the main_loop,
+ * and don't check for main_loop_should_exit
+ */
+ signal(SIGINT, SIG_DFL);
+ signal(SIGHUP, SIG_DFL);
+ signal(SIGTERM, SIG_DFL);
+
return 0;
}
diff --git a/tests/vm/centos b/tests/vm/centos
index 0ad4ecf..efe3dbb 100755
--- a/tests/vm/centos
+++ b/tests/vm/centos
@@ -42,7 +42,7 @@ class CentosVM(basevm.BaseVM):
self.wait_ssh()
self.ssh_root_check("touch /etc/cloud/cloud-init.disabled")
self.ssh_root_check("yum update -y")
- self.ssh_root_check("yum install -y docker make git python3")
+ self.ssh_root_check("yum install -y docker make ninja-build git python3")
self.ssh_root_check("systemctl enable docker")
self.ssh_root("poweroff")
self.wait()
diff --git a/tests/vm/centos.aarch64 b/tests/vm/centos.aarch64
index d5232ec..e687b93 100755
--- a/tests/vm/centos.aarch64
+++ b/tests/vm/centos.aarch64
@@ -23,7 +23,7 @@ import aarch64vm
DEFAULT_CONFIG = {
'cpu' : "max",
'machine' : "virt,gic-version=max",
- 'install_cmds' : "yum install -y make git python3 gcc gcc-c++ flex bison, "\
+ 'install_cmds' : "yum install -y make ninja-build git python3 gcc gcc-c++ flex bison, "\
"yum install -y glib2-devel pixman-devel zlib-devel, "\
"yum install -y perl-Test-Harness, "\
"alternatives --set python /usr/bin/python3, "\
diff --git a/tests/vm/fedora b/tests/vm/fedora
index b2b478f..b977efe 100755
--- a/tests/vm/fedora
+++ b/tests/vm/fedora
@@ -32,7 +32,7 @@ class FedoraVM(basevm.BaseVM):
pkgs = [
# tools
'git-core',
- 'gcc', 'binutils', 'make',
+ 'gcc', 'binutils', 'make', 'ninja-build',
# perl
'perl-Test-Harness',
diff --git a/tests/vm/freebsd b/tests/vm/freebsd
index 5f866e0..04ee793 100755
--- a/tests/vm/freebsd
+++ b/tests/vm/freebsd
@@ -34,6 +34,7 @@ class FreeBSDVM(basevm.BaseVM):
"bzip2",
"python37",
"py37-setuptools",
+ "ninja",
# gnu tools
"bash",
diff --git a/tests/vm/netbsd b/tests/vm/netbsd
index ffb65a8..447de97 100755
--- a/tests/vm/netbsd
+++ b/tests/vm/netbsd
@@ -32,6 +32,7 @@ class NetBSDVM(basevm.BaseVM):
"xz",
"python37",
"py37-setuptools",
+ "ninja-build",
# gnu tools
"bash",
diff --git a/tests/vm/openbsd b/tests/vm/openbsd
index 8356646..ad882a7 100755
--- a/tests/vm/openbsd
+++ b/tests/vm/openbsd
@@ -31,6 +31,7 @@ class OpenBSDVM(basevm.BaseVM):
"pkgconf",
"bzip2", "xz",
"py3-setuptools",
+ "ninja",
# gnu tools
"bash",
diff --git a/tests/vm/ubuntu.aarch64 b/tests/vm/ubuntu.aarch64
index 21d454c..b291945 100755
--- a/tests/vm/ubuntu.aarch64
+++ b/tests/vm/ubuntu.aarch64
@@ -22,7 +22,7 @@ DEFAULT_CONFIG = {
'machine' : "virt,gic-version=3",
'install_cmds' : "apt-get update,"\
"apt-get build-dep -y --arch-only qemu,"\
- "apt-get install -y libfdt-dev pkg-config language-pack-en",
+ "apt-get install -y libfdt-dev pkg-config language-pack-en ninja-build",
# We increase beyond the default time since during boot
# it can take some time (many seconds) to log into the VM
# especially using softmmu.
diff --git a/tests/vm/ubuntu.i386 b/tests/vm/ubuntu.i386
index 5ce7261..47681b6 100755
--- a/tests/vm/ubuntu.i386
+++ b/tests/vm/ubuntu.i386
@@ -18,7 +18,7 @@ import ubuntuvm
DEFAULT_CONFIG = {
'install_cmds' : "apt-get update,"\
"apt-get build-dep -y qemu,"\
- "apt-get install -y libfdt-dev language-pack-en",
+ "apt-get install -y libfdt-dev language-pack-en ninja-build",
}
class UbuntuX86VM(ubuntuvm.UbuntuVM):
diff --git a/ui/meson.build b/ui/meson.build
index 6ce8148..ab4de98 100644
--- a/ui/meson.build
+++ b/ui/meson.build
@@ -113,8 +113,11 @@ if have_system or xkbcommon.found()
endif
subdir('shader')
-subdir('icons')
-install_data('qemu.desktop', install_dir: config_host['qemu_desktopdir'])
+if have_system
+ subdir('icons')
+
+ install_data('qemu.desktop', install_dir: config_host['qemu_desktopdir'])
+endif
modules += {'ui': ui_modules}