diff options
-rw-r--r-- | docs/markdown/Reference-manual.md | 9 | ||||
-rw-r--r-- | docs/markdown/snippets/run_command_check.md | 4 | ||||
-rw-r--r-- | mesonbuild/interpreter.py | 20 | ||||
-rw-r--r-- | test cases/failing/75 run_command unclean exit/meson.build | 4 | ||||
-rwxr-xr-x | test cases/failing/75 run_command unclean exit/returncode.py | 4 |
5 files changed, 35 insertions, 6 deletions
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index 2498b98..1e0e4c9 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -1016,7 +1016,7 @@ Project supports the following keyword arguments. ### run_command() ``` meson - runresult run_command(command, list_of_args) + runresult run_command(command, list_of_args, ...) ``` Runs the command specified in positional arguments. @@ -1031,6 +1031,13 @@ Meson will set three environment variables `MESON_SOURCE_ROOT`, directory, build directory and subdirectory the target was defined in, respectively. +This function has one keyword argument. + + - `check` takes a boolean. If `true`, the exit status code of the command will + be checked, and the configuration will fail if it is non-zero. The default is + `false`. + Since 0.47.0 + See also [External commands](External-commands.md). ### run_target 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])) |