aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2020-10-26 08:41:45 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2020-12-14 10:53:36 +0100
commit79e2c52a15e896e46ff3cfa3ec16fbf3f132ee01 (patch)
treeba439b9d3acd46fbd576f63295f1b3e0517cd251 /mesonbuild
parent879e9d19f5d0db2450de2dfd6fdc9a31043f64ab (diff)
downloadmeson-79e2c52a15e896e46ff3cfa3ec16fbf3f132ee01.zip
meson-79e2c52a15e896e46ff3cfa3ec16fbf3f132ee01.tar.gz
meson-79e2c52a15e896e46ff3cfa3ec16fbf3f132ee01.tar.bz2
mtest: only build what is needed for the tests
It is a usual workflow to fix something and retest to see if it is fixed using a particular test. When tests start to become numerous, it becomes time consuming for "meson test" to relink all of them (and in fact rebuild the whole project) where the user has already specified the tests they want to run, as well as the tests' dependencies. Teach meson to be smart and only build what is needed for the test (or suite) that were specified. Fixes: #7473 Related: #7830
Diffstat (limited to 'mesonbuild')
-rw-r--r--mesonbuild/minstall.py18
-rw-r--r--mesonbuild/mtest.py38
2 files changed, 44 insertions, 12 deletions
diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py
index 47bb88b..a8ec8f3 100644
--- a/mesonbuild/minstall.py
+++ b/mesonbuild/minstall.py
@@ -19,7 +19,6 @@ from glob import glob
from .scripts import depfixer
from .scripts import destdir_join
from .mesonlib import is_windows, Popen_safe
-from .mtest import rebuild_all
from .backend.backends import InstallData
from .coredata import major_versions_differ, MesonVersionMismatchException
from .coredata import version as coredata_version
@@ -532,6 +531,23 @@ class Installer:
else:
raise
+def rebuild_all(wd: str) -> bool:
+ if not (Path(wd) / 'build.ninja').is_file():
+ print('Only ninja backend is supported to rebuild the project before installation.')
+ return True
+
+ ninja = environment.detect_ninja()
+ if not ninja:
+ print("Can't find ninja, can't rebuild test.")
+ return False
+
+ ret = subprocess.run(ninja + ['-C', wd]).returncode
+ if ret != 0:
+ print('Could not rebuild {}'.format(wd))
+ return False
+
+ return True
+
def run(opts):
datafilename = 'meson-private/install.dat'
private_dir = os.path.dirname(datafilename)
diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py
index a92b5cc..4f687a5 100644
--- a/mesonbuild/mtest.py
+++ b/mesonbuild/mtest.py
@@ -45,6 +45,7 @@ from .coredata import major_versions_differ, MesonVersionMismatchException
from .coredata import version as coredata_version
from .dependencies import ExternalProgram
from .mesonlib import MesonException, get_wine_shortpath, split_args, join_args
+from .mintro import get_infodir, load_info_file
from .backend.backends import TestProtocol, TestSerialisation
# GNU autotools interprets a return code of 77 from tests it executes to
@@ -1019,13 +1020,21 @@ class TestHarness:
def total_failure_count(self) -> int:
return self.fail_count + self.unexpectedpass_count + self.timeout_count
- def doit(self) -> int:
+ def doit(self, options: argparse.Namespace) -> int:
if self.is_run:
raise RuntimeError('Test harness object can only be used once.')
self.is_run = True
tests = self.get_tests()
if not tests:
return 0
+ if not options.no_rebuild and not rebuild_deps(options.wd, tests):
+ # We return 125 here in case the build failed.
+ # The reason is that exit code 125 tells `git bisect run` that the current
+ # commit should be skipped. Thus users can directly use `meson test` to
+ # bisect without needing to handle the does-not-build case separately in a
+ # wrapper script.
+ sys.exit(125)
+
self.run_tests(tests)
return self.total_failure_count()
@@ -1272,7 +1281,7 @@ def list_tests(th: TestHarness) -> bool:
print(th.get_pretty_suite(t))
return not tests
-def rebuild_all(wd: str) -> bool:
+def rebuild_deps(wd: str, tests: T.List[TestSerialisation]) -> bool:
if not (Path(wd) / 'build.ninja').is_file():
print('Only ninja backend is supported to rebuild tests before running them.')
return True
@@ -1282,7 +1291,21 @@ def rebuild_all(wd: str) -> bool:
print("Can't find ninja, can't rebuild test.")
return False
- ret = subprocess.run(ninja + ['-C', wd]).returncode
+ depends = set() # type: T.Set[str]
+ targets = set() # type: T.Set[str]
+ intro_targets = dict() # type: T.Dict[str, T.List[str]]
+ for target in load_info_file(get_infodir(wd), kind='targets'):
+ intro_targets[target['id']] = [
+ os.path.relpath(f, wd)
+ for f in target['filename']]
+ for t in tests:
+ for d in t.depends:
+ if d in depends:
+ continue
+ depends.update(d)
+ targets.update(intro_targets[d])
+
+ ret = subprocess.run(ninja + ['-C', wd] + sorted(targets)).returncode
if ret != 0:
print('Could not rebuild {}'.format(wd))
return False
@@ -1318,18 +1341,11 @@ def run(options: argparse.Namespace) -> int:
print('Could not find requested program: {!r}'.format(check_bin))
return 1
- if not options.list and not options.no_rebuild:
- if not rebuild_all(options.wd):
- # We return 125 here in case the build failed.
- # The reason is that exit code 125 tells `git bisect run` that the current commit should be skipped.
- # Thus users can directly use `meson test` to bisect without needing to handle the does-not-build case separately in a wrapper script.
- return 125
-
with TestHarness(options) as th:
try:
if options.list:
return list_tests(th)
- return th.doit()
+ return th.doit(options)
except TestException as e:
print('Meson test encountered an error:\n')
if os.environ.get('MESON_FORCE_BACKTRACE'):