run: introduce a script for running devel commands

Various aspects of the development workflow are complicated by the need
to set env variables ahead of time, or use specific paths. Meson
provides a 'devenv' command that can be used to launch a command with a
number of appropriate project specific environment variables preset.

By default it will modify $PATH to point to any build directory that
contains a binary built by the project.

This further augments that to replicate the venv 'activate' script:

 * Add $BUILD_DIR/pyvenv/bin to $PATH
 * Set VIRTUAL_ENV to $BUILD_DIR/pyvenv

And then makes functional tests more easily executable

 * Add $SRC_DIR/tests/functional and $SRC_DIR/python to $PYTHONPATH

To see the benefits of this consider this command:

  $ source ./build/pyvenv/bin/activate
  $ ./scripts/qmp/qmp-shell-wrap ./build/qemu-system-x86_64

which is now simplified to

  $ ./build/run ./scripts/qmp/qmp-shell-wrap qemu-system-x86_64 [args..]

This avoids the need repeat './build' several times and avoids polluting
the current terminal's environment and/or avoids errors from forgetting
to source the venv settings.

As another example running functional tests

  $ export PYTHONPATH=./python:./tests/functional
  $ export QEMU_TEST_QEMU_BINARY=./build/qemu-system-x86_64
  $ build/pyvenv/bin/python3 ./tests/functional/x86_64/test_virtio_version.py

which is now simplified to

  $ export QEMU_TEST_QEMU_BINARY=qemu-system-x86_64
  $ ./build/run ./tests/functional/x86_64/test_virtio_version.py

This usefulness of this will be further enhanced with the pending
removal of the QEMU python APIs from git, as that will require the use
of the python venv in even more scenarios that today.

The 'run' script does not let 'meson devenv' directly launch the command
to be run because it always requires $BUILD_DIR as the current working
directory. It is desired that 'run' script always honour the current
working directory of the terminal that invokes is. Thus the '--dump'
flag is used to export the devenv variables into the 'run' script's
shell.

This takes the liberty to assign 'run.in' to the "Build system" section
in the MAINTAINERS file, given that it leverages meson's 'devenv'
feature.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Link: https://lore.kernel.org/r/20251222113859.182395-1-berrange@redhat.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Daniel P. Berrangé
2025-12-22 11:38:59 +00:00
committed by Paolo Bonzini
parent 1a69483616
commit 757a9c91a6
5 changed files with 38 additions and 10 deletions

View File

@@ -4479,6 +4479,7 @@ R: Philippe Mathieu-Daudé <philmd@linaro.org>
S: Maintained
F: meson.build
F: meson_options.txt
F: run.in
F: scripts/check_sparse.py
F: scripts/symlink-install-tree.py

View File

@@ -515,6 +515,18 @@ generates ``Makefile`` from ``Makefile.in``.
Built by configure:
``run``
Used to run commands / scripts from the git checkout. Sets ``$PATH``
to point to locally built binaries, and activates the python venv
before running the requested command. Pass the command to run as
args, for example::
$ ./build/run ./script/qmp/qmp-shell-wrap qemu-system-x86_64
will use the ``python3`` binary and site-packages from the local
venv to run ``qmp-shell-wrap`` and spawn the QEMU emulator from
the build directory.
``config-host.mak``
When configure has determined the characteristics of the build host it
will write the paths to various tools to this file, for use in ``Makefile``

View File

@@ -53,15 +53,14 @@ the following line will only run the tests for the x86_64 target:
make check-functional-x86_64
To run a single test file without the meson test runner, you can also
execute the file directly by specifying two environment variables first,
the PYTHONPATH that has to include the python folder and the tests/functional
folder of the source tree, and QEMU_TEST_QEMU_BINARY that has to point
to the QEMU binary that should be used for the test. The current working
directory should be your build folder. For example::
execute the file directly by specifying the name of the emulator target
binary as an env variable.
$ export PYTHONPATH=../python:../tests/functional
$ export QEMU_TEST_QEMU_BINARY=$PWD/qemu-system-x86_64
$ pyvenv/bin/python3 ../tests/functional/test_file.py
Assuming the current working directory is the top level source checkout
and the build directory is './build'::
$ export QEMU_TEST_QEMU_BINARY=qemu-system-x86_64
$ ./build/run tests/functional/x86_64/test_virtio_version.py
The test framework will automatically purge any scratch files created during
the tests. If needing to debug a failed test, it is possible to keep these

View File

@@ -4,8 +4,6 @@ project('qemu', ['c'], meson_version: '>=1.5.0',
'rust_std=2021', 'build.rust_std=2021'],
version: files('VERSION'))
meson.add_devenv({ 'MESON_BUILD_ROOT' : meson.project_build_root() })
add_test_setup('quick', exclude_suites: ['slow', 'thorough'], is_default: true,
env: ['RUST_BACKTRACE=1'])
add_test_setup('slow', exclude_suites: ['thorough'],
@@ -3501,6 +3499,20 @@ endif
config_host_h = configure_file(output: 'config-host.h', configuration: config_host_data)
genh += config_host_h
devenv = environment()
devenv.set('MESON_BUILD_ROOT', meson.project_build_root())
devenv.set('VIRTUAL_ENV', meson.project_build_root() / 'pyvenv')
devenv.prepend('PATH', meson.project_build_root() / 'pyvenv'/ 'bin')
devenv.prepend('PYTHONPATH', meson.current_source_dir() / 'tests' / 'functional')
devenv.prepend('PYTHONPATH', meson.current_source_dir() / 'python')
meson.add_devenv(devenv)
run_config = configuration_data({'build_dir': meson.current_build_dir()})
run = configure_file(input: 'run.in',
output: 'run',
configuration: run_config)
run_command('chmod', 'a+x', meson.current_build_dir() / 'run', check: true)
hxtool = find_program('scripts/hxtool')
shaderinclude = find_program('scripts/shaderinclude.py')
qapi_gen = find_program('scripts/qapi-gen.py')

4
run.in Normal file
View File

@@ -0,0 +1,4 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0-or-later
exec @build_dir@/pyvenv/bin/meson devenv -C @build_dir@ -w "$PWD" "$@"