aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/snippets/run_command_check.md4
-rw-r--r--mesonbuild/interpreter.py20
-rw-r--r--test cases/failing/75 run_command unclean exit/meson.build4
-rwxr-xr-xtest cases/failing/75 run_command unclean exit/returncode.py4
4 files changed, 27 insertions, 5 deletions
diff --git a/docs/markdown/snippets/run_command_check.md b/docs/markdown/snippets/run_command_check.md
new file mode 100644
index 0000000..018456b
--- /dev/null
+++ b/docs/markdown/snippets/run_command_check.md
@@ -0,0 +1,4 @@
+## New 'check' keyword argument for the run_command function
+
+If `check` is `true`, then the configuration will fail if the command returns a
+non-zero exit status. The default value is `false` for compatibility reasons.
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 49e9381..070845b 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -92,18 +92,18 @@ class TryRunResultHolder(InterpreterObject):
class RunProcess(InterpreterObject):
- def __init__(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir=False):
+ def __init__(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir=False, check=False):
super().__init__()
if not isinstance(cmd, ExternalProgram):
raise AssertionError('BUG: RunProcess must be passed an ExternalProgram')
- pc, self.stdout, self.stderr = self.run_command(cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir)
+ pc, self.stdout, self.stderr = self.run_command(cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir, check)
self.returncode = pc.returncode
self.methods.update({'returncode': self.returncode_method,
'stdout': self.stdout_method,
'stderr': self.stderr_method,
})
- def run_command(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir):
+ def run_command(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir, check=False):
command_array = cmd.get_command() + args
env = {'MESON_SOURCE_ROOT': source_dir,
'MESON_BUILD_ROOT': build_dir,
@@ -124,6 +124,10 @@ class RunProcess(InterpreterObject):
mlog.debug('----stderr----')
mlog.debug(e)
mlog.debug('')
+
+ if check and p.returncode != 0:
+ raise InterpreterException('Command "{}" failed with status {}.'.format(' '.join(command_array), p.returncode))
+
return p, o, e
except FileNotFoundError:
raise InterpreterException('Could not execute command "%s".' % ' '.join(command_array))
@@ -1679,6 +1683,7 @@ permitted_kwargs = {'add_global_arguments': {'language'},
'install_subdir': {'exclude_files', 'exclude_directories', 'install_dir', 'install_mode', 'strip_directory'},
'jar': build.known_jar_kwargs,
'project': {'version', 'meson_version', 'default_options', 'license', 'subproject_dir'},
+ 'run_command': {'check'},
'run_target': {'command', 'depends'},
'shared_library': build.known_shlib_kwargs,
'shared_module': build.known_shmod_kwargs,
@@ -1957,7 +1962,7 @@ external dependencies (including libraries) must go to "dependencies".''')
if not isinstance(actual, wanted):
raise InvalidArguments('Incorrect argument type.')
- @noKwargs
+ @permittedKwargs(permitted_kwargs['run_command'])
def func_run_command(self, node, args, kwargs):
return self.run_command_impl(node, args, kwargs)
@@ -1968,6 +1973,11 @@ external dependencies (including libraries) must go to "dependencies".''')
cargs = args[1:]
srcdir = self.environment.get_source_dir()
builddir = self.environment.get_build_dir()
+
+ check = kwargs.get('check', False)
+ if not isinstance(check, bool):
+ raise InterpreterException('Check must be boolean.')
+
m = 'must be a string, or the output of find_program(), files() '\
'or configure_file(), or a compiler object; not {!r}'
if isinstance(cmd, ExternalProgramHolder):
@@ -2020,7 +2030,7 @@ external dependencies (including libraries) must go to "dependencies".''')
if a not in self.build_def_files:
self.build_def_files.append(a)
return RunProcess(cmd, expanded_args, srcdir, builddir, self.subdir,
- self.environment.get_build_command() + ['introspect'], in_builddir)
+ self.environment.get_build_command() + ['introspect'], in_builddir, check)
@stringArgs
def func_gettext(self, nodes, args, kwargs):
diff --git a/test cases/failing/75 run_command unclean exit/meson.build b/test cases/failing/75 run_command unclean exit/meson.build
new file mode 100644
index 0000000..4bc02ae
--- /dev/null
+++ b/test cases/failing/75 run_command unclean exit/meson.build
@@ -0,0 +1,4 @@
+project('run_command unclean exit', 'c')
+
+rcprog = find_program('./returncode.py')
+run_command(rcprog, '1', check : true)
diff --git a/test cases/failing/75 run_command unclean exit/returncode.py b/test cases/failing/75 run_command unclean exit/returncode.py
new file mode 100755
index 0000000..84dbc5d
--- /dev/null
+++ b/test cases/failing/75 run_command unclean exit/returncode.py
@@ -0,0 +1,4 @@
+#!/usr/bin/env python3
+
+import sys
+exit(int(sys.argv[1]))