summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNirbheek Chauhan <nirbheek@centricular.com>2018-04-15 14:44:41 +0530
committerNirbheek Chauhan <nirbheek@centricular.com>2018-06-10 07:44:49 +0530
commit6df3cb7ab0e686ae976c67a24ce9664ffe5e1d86 (patch)
treebabfe469706c95e56783313fe97e4516b1e814d0
parent2d1fc25599adf349ae62504ce2197e2d821398f7 (diff)
downloadmeson-nirbheek/run_command_capture.tar.gz
run_command: Add new kwarg 'capture'nirbheek/run_command_capture
capture: false means we won't try to read the stdout at all. Closes https://github.com/mesonbuild/meson/issues/3364
-rw-r--r--docs/markdown/snippets/run_command_check.md9
-rw-r--r--mesonbuild/interpreter.py25
-rw-r--r--mesonbuild/mesonlib.py15
-rw-r--r--test cases/common/38 run program/meson.build16
4 files changed, 46 insertions, 19 deletions
diff --git a/docs/markdown/snippets/run_command_check.md b/docs/markdown/snippets/run_command_check.md
index 018456b19..35bdcdd7e 100644
--- a/docs/markdown/snippets/run_command_check.md
+++ b/docs/markdown/snippets/run_command_check.md
@@ -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`.
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 421ddd950..1f3ac87e3 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -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
@@ -95,10 +96,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,
@@ -119,12 +121,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('')
@@ -1738,7 +1745,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,
@@ -2022,7 +2029,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)
@@ -2032,6 +2039,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()
@@ -2091,7 +2099,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):
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index e4951f957..21a6e29e2 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -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)
diff --git a/test cases/common/38 run program/meson.build b/test cases/common/38 run program/meson.build
index 1563decc5..ab800ef68 100644
--- a/test cases/common/38 run program/meson.build
+++ b/test cases/common/38 run program/meson.build
@@ -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