aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/Reference-manual.md7
-rw-r--r--docs/markdown/snippets/test-depends.md5
-rw-r--r--mesonbuild/backend/backends.py3
-rw-r--r--mesonbuild/interpreter.py23
-rwxr-xr-xtest cases/common/188 test depends/gen.py13
-rw-r--r--test cases/common/188 test depends/main.c1
-rw-r--r--test cases/common/188 test depends/meson.build26
-rwxr-xr-xtest cases/common/188 test depends/test.py20
8 files changed, 87 insertions, 11 deletions
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index 74e7ff2..32639b0 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -1256,6 +1256,13 @@ Keyword arguments are the following:
- `workdir` absolute path that will be used as the working directory
for the test
+- `depends` specifies that this test depends on the specified
+ target(s), even though it does not take any of them as a command
+ line argument. This is meant for cases where test finds those
+ targets internally, e.g. plugins or globbing. Those targets are built
+ before test is executed even if they have `build_by_default : false`.
+ Since 0.46.0
+
Defined tests can be run in a backend-agnostic way by calling
`meson test` inside the build dir, or by using backend-specific
commands, such as `ninja test` or `msbuild RUN_TESTS.vcxproj`.
diff --git a/docs/markdown/snippets/test-depends.md b/docs/markdown/snippets/test-depends.md
new file mode 100644
index 0000000..2f4b6b0
--- /dev/null
+++ b/docs/markdown/snippets/test-depends.md
@@ -0,0 +1,5 @@
+## test now supports depends keyword parameter
+
+Build targets and custom targets can be listed in depends argument of test
+function. These targets will be built before test is run even if they have
+`build_by_default : false`.
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 694700e..8f75dac 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -721,6 +721,9 @@ class Backend:
if not isinstance(arg, (build.CustomTarget, build.BuildTarget)):
continue
result[arg.get_id()] = arg
+ for dep in t.depends:
+ assert isinstance(dep, (build.CustomTarget, build.BuildTarget))
+ result[dep.get_id()] = dep
return result
def get_custom_target_provided_libraries(self, target):
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index c7841a8..a4c93de 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -697,12 +697,14 @@ class RunTargetHolder(InterpreterObject, ObjectHolder):
return r.format(self.__class__.__name__, h.get_id(), h.command)
class Test(InterpreterObject):
- def __init__(self, name, project, suite, exe, is_parallel, cmd_args, env, should_fail, timeout, workdir):
+ def __init__(self, name, project, suite, exe, depends, is_parallel,
+ cmd_args, env, should_fail, timeout, workdir):
InterpreterObject.__init__(self)
self.name = name
self.suite = suite
self.project_name = project
self.exe = exe
+ self.depends = depends
self.is_parallel = is_parallel
self.cmd_args = cmd_args
self.env = env
@@ -1555,7 +1557,7 @@ permitted_kwargs = {'add_global_arguments': {'language'},
'library': known_library_kwargs,
'subdir': {'if_found'},
'subproject': {'version', 'default_options'},
- 'test': {'args', 'env', 'is_parallel', 'should_fail', 'timeout', 'workdir', 'suite'},
+ 'test': {'args', 'depends', 'env', 'is_parallel', 'should_fail', 'timeout', 'workdir', 'suite'},
'vcs_tag': {'input', 'output', 'fallback', 'command', 'replace_string'},
}
@@ -2734,7 +2736,7 @@ root and issuing %s.
if 'command' not in kwargs:
raise InterpreterException('Missing "command" keyword argument')
all_args = extract_as_list(kwargs, 'command')
- deps = extract_as_list(kwargs, 'depends')
+ deps = extract_as_list(kwargs, 'depends', unholder=True)
else:
raise InterpreterException('Run_target needs at least one positional argument.')
@@ -2749,10 +2751,6 @@ root and issuing %s.
raise InterpreterException('First argument must be a string.')
cleaned_deps = []
for d in deps:
- try:
- d = d.held_object
- except AttributeError:
- pass
if not isinstance(d, (build.BuildTarget, build.CustomTarget)):
raise InterpreterException('Depends items must be build targets.')
cleaned_deps.append(d)
@@ -2835,7 +2833,12 @@ root and issuing %s.
if len(s) > 0:
s = ':' + s
suite.append(prj.replace(' ', '_').replace(':', '_') + s)
- t = Test(args[0], prj, suite, exe.held_object, par, cmd_args, env, should_fail, timeout, workdir)
+ depends = extract_as_list(kwargs, 'depends', unholder=True)
+ for dep in depends:
+ if not isinstance(dep, (build.CustomTarget, build.BuildTarget)):
+ raise InterpreterException('Depends items must be build targets.')
+ t = Test(args[0], prj, suite, exe.held_object, depends, par, cmd_args,
+ env, should_fail, timeout, workdir)
if is_base_test:
self.build.tests.append(t)
mlog.debug('Adding test "', mlog.bold(args[0]), '".', sep='')
@@ -3152,11 +3155,9 @@ different subdirectory.
if ":" not in setup_name:
setup_name = (self.subproject if self.subproject else self.build.project_name) + ":" + setup_name
try:
- inp = extract_as_list(kwargs, 'exe_wrapper')
+ inp = extract_as_list(kwargs, 'exe_wrapper', unholder=True)
exe_wrapper = []
for i in inp:
- if hasattr(i, 'held_object'):
- i = i.held_object
if isinstance(i, str):
exe_wrapper.append(i)
elif isinstance(i, dependencies.ExternalProgram):
diff --git a/test cases/common/188 test depends/gen.py b/test cases/common/188 test depends/gen.py
new file mode 100755
index 0000000..ee4ed98
--- /dev/null
+++ b/test cases/common/188 test depends/gen.py
@@ -0,0 +1,13 @@
+#!/usr/bin/env python3
+
+import sys
+
+
+def main():
+ with open(sys.argv[1], 'w') as out:
+ out.write(sys.argv[2])
+ out.write('\n')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/test cases/common/188 test depends/main.c b/test cases/common/188 test depends/main.c
new file mode 100644
index 0000000..78f2de1
--- /dev/null
+++ b/test cases/common/188 test depends/main.c
@@ -0,0 +1 @@
+int main(void) { return 0; }
diff --git a/test cases/common/188 test depends/meson.build b/test cases/common/188 test depends/meson.build
new file mode 100644
index 0000000..888c451
--- /dev/null
+++ b/test cases/common/188 test depends/meson.build
@@ -0,0 +1,26 @@
+project('test depends', 'c')
+
+gen = find_program('gen.py')
+
+custom_dep = custom_target('custom_dep',
+ build_by_default : false,
+ output : 'custom_dep.txt',
+ command : [gen, '@OUTPUT@', 'custom_dep'],
+)
+
+exe_dep = executable('exe_dep', 'main.c',
+ build_by_default : false,
+)
+
+test_prog = find_program('test.py')
+test('string dependencies', test_prog,
+ args : [
+ # This is declared for convenience,
+ # real use case might have some obscure method
+ # to find these dependencies, e.g. automatic plugin loading.
+ 'custom_dep.txt',
+ exe_dep.full_path(),
+ ],
+ depends : [custom_dep, exe_dep],
+ workdir : meson.current_build_dir(),
+)
diff --git a/test cases/common/188 test depends/test.py b/test cases/common/188 test depends/test.py
new file mode 100755
index 0000000..5b9f65c
--- /dev/null
+++ b/test cases/common/188 test depends/test.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python3
+
+import os
+import os.path
+import sys
+
+
+def main():
+ print('Looking in:', os.getcwd())
+ not_found = list()
+ for f in sys.argv[1:]:
+ if not os.path.exists(f):
+ not_found.append(f)
+ if not_found:
+ print('Not found:', ', '.join(not_found))
+ sys.exit(1)
+
+
+if __name__ == '__main__':
+ main()