run_command: Add new kwarg 'capture'
capture: false means we won't try to read the stdout at all. Closes https://github.com/mesonbuild/meson/issues/3364
This commit is contained in:
parent
cbe18e01e4
commit
c9a89027ac
|
@ -1,4 +1,9 @@
|
|||
## New 'check' keyword argument for the run_command function
|
||||
## New keyword arguments: 'check' and 'capture' for run_command()
|
||||
|
||||
If `check` is `true`, then the configuration will fail if the command returns a
|
||||
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.
|
||||
|
||||
`run_command()` used to always capture the output and stored it for use in
|
||||
build files. However, sometimes the stdout is in a binary format which is meant
|
||||
to be discarded. For that case, you can now set the `capture:` keyword argument
|
||||
to `false`.
|
||||
|
|
|
@ -33,6 +33,7 @@ from .modules import ModuleReturnValue
|
|||
|
||||
import os, sys, shutil, uuid
|
||||
import re, shlex
|
||||
import subprocess
|
||||
from collections import namedtuple
|
||||
from pathlib import PurePath
|
||||
|
||||
|
@ -144,10 +145,11 @@ class TryRunResultHolder(InterpreterObject):
|
|||
|
||||
class RunProcess(InterpreterObject):
|
||||
|
||||
def __init__(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir=False, check=False):
|
||||
def __init__(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir=False, check=False, capture=True):
|
||||
super().__init__()
|
||||
if not isinstance(cmd, ExternalProgram):
|
||||
raise AssertionError('BUG: RunProcess must be passed an ExternalProgram')
|
||||
self.capture = capture
|
||||
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,
|
||||
|
@ -168,12 +170,17 @@ class RunProcess(InterpreterObject):
|
|||
cwd = os.path.join(source_dir, subdir)
|
||||
child_env = os.environ.copy()
|
||||
child_env.update(env)
|
||||
stdout = subprocess.PIPE if self.capture else subprocess.DEVNULL
|
||||
mlog.debug('Running command:', ' '.join(command_array))
|
||||
try:
|
||||
p, o, e = Popen_safe(command_array, env=child_env, cwd=cwd)
|
||||
mlog.debug('--- stdout----')
|
||||
mlog.debug(o)
|
||||
mlog.debug('----stderr----')
|
||||
p, o, e = Popen_safe(command_array, stdout=stdout, env=child_env, cwd=cwd)
|
||||
if self.capture:
|
||||
mlog.debug('--- stdout ---')
|
||||
mlog.debug(o)
|
||||
else:
|
||||
o = ''
|
||||
mlog.debug('--- stdout disabled ---')
|
||||
mlog.debug('--- stderr ---')
|
||||
mlog.debug(e)
|
||||
mlog.debug('')
|
||||
|
||||
|
@ -1796,7 +1803,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_command': {'check', 'capture'},
|
||||
'run_target': {'command', 'depends'},
|
||||
'shared_library': build.known_shlib_kwargs,
|
||||
'shared_module': build.known_shmod_kwargs,
|
||||
|
@ -2080,7 +2087,7 @@ external dependencies (including libraries) must go to "dependencies".''')
|
|||
if not isinstance(actual, wanted):
|
||||
raise InvalidArguments('Incorrect argument type.')
|
||||
|
||||
@FeatureNewKwargs('run_command', '0.47.0', ['check'])
|
||||
@FeatureNewKwargs('run_command', '0.47.0', ['check', 'capture'])
|
||||
@permittedKwargs(permitted_kwargs['run_command'])
|
||||
def func_run_command(self, node, args, kwargs):
|
||||
return self.run_command_impl(node, args, kwargs)
|
||||
|
@ -2090,6 +2097,7 @@ external dependencies (including libraries) must go to "dependencies".''')
|
|||
raise InterpreterException('Not enough arguments')
|
||||
cmd = args[0]
|
||||
cargs = args[1:]
|
||||
capture = kwargs.get('capture', True)
|
||||
srcdir = self.environment.get_source_dir()
|
||||
builddir = self.environment.get_build_dir()
|
||||
|
||||
|
@ -2149,7 +2157,8 @@ 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, check)
|
||||
self.environment.get_build_command() + ['introspect'],
|
||||
in_builddir=in_builddir, check=check, capture=capture)
|
||||
|
||||
@stringArgs
|
||||
def func_gettext(self, nodes, args, kwargs):
|
||||
|
|
|
@ -796,22 +796,19 @@ def expand_arguments(args):
|
|||
return None
|
||||
return expended_args
|
||||
|
||||
def Popen_safe(args, write=None, stderr=subprocess.PIPE, **kwargs):
|
||||
def Popen_safe(args, write=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs):
|
||||
import locale
|
||||
encoding = locale.getpreferredencoding()
|
||||
if sys.version_info < (3, 6) or not sys.stdout.encoding or encoding.upper() != 'UTF-8':
|
||||
return Popen_safe_legacy(args, write=write, stderr=stderr, **kwargs)
|
||||
p = subprocess.Popen(args, universal_newlines=True,
|
||||
close_fds=False,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=stderr, **kwargs)
|
||||
return Popen_safe_legacy(args, write=write, stdout=stdout, stderr=stderr, **kwargs)
|
||||
p = subprocess.Popen(args, universal_newlines=True, close_fds=False,
|
||||
stdout=stdout, stderr=stderr, **kwargs)
|
||||
o, e = p.communicate(write)
|
||||
return p, o, e
|
||||
|
||||
def Popen_safe_legacy(args, write=None, stderr=subprocess.PIPE, **kwargs):
|
||||
def Popen_safe_legacy(args, write=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs):
|
||||
p = subprocess.Popen(args, universal_newlines=False,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=stderr, **kwargs)
|
||||
stdout=stdout, stderr=stderr, **kwargs)
|
||||
if write is not None:
|
||||
write = write.encode('utf-8')
|
||||
o, e = p.communicate(write)
|
||||
|
|
|
@ -55,3 +55,19 @@ if c.returncode() != 0
|
|||
error('Using files() in argument failed.')
|
||||
endif
|
||||
|
||||
py3 = import('python3').find_python()
|
||||
|
||||
ret = run_command(py3, '-c', 'print("some output")')
|
||||
assert(ret.returncode() == 0, 'failed to run python3: ' + ret.stderr())
|
||||
assert(ret.stdout() == 'some output\n', 'failed to run python3')
|
||||
|
||||
ret = run_command(py3, '-c', 'print("some output")', capture : false)
|
||||
assert(ret.returncode() == 0, 'failed to run python3: ' + ret.stderr())
|
||||
assert(ret.stdout() == '', 'stdout is "@0@" instead of empty'.format(ret.stdout()))
|
||||
|
||||
dd = find_program('dd', required : false)
|
||||
if dd.found()
|
||||
ret = run_command(dd, 'if=/dev/urandom', 'bs=10', 'count=1', capture: false)
|
||||
assert(ret.returncode() == 0, 'failed to run dd: ' + ret.stderr())
|
||||
assert(ret.stdout() == '', 'stdout is "@0@" instead of empty'.format(ret.stdout()))
|
||||
endif
|
||||
|
|
Loading…
Reference in New Issue