diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py index a919102607be..dd2fb9fb1e46 100644 --- a/mesonbuild/interpreter/interpreterobjects.py +++ b/mesonbuild/interpreter/interpreterobjects.py @@ -248,18 +248,20 @@ def run_command(self, child_env = os.environ.copy() child_env.update(menv) child_env = env.get_env(child_env) - stdout = subprocess.PIPE if self.capture else subprocess.DEVNULL + stdout = subprocess.PIPE if self.capture else None + stderr = subprocess.PIPE if self.capture else None mlog.debug('Running command:', mesonlib.join_args(command_array)) try: - p, o, e = Popen_safe(command_array, stdout=stdout, env=child_env, cwd=cwd) + p, o, e = Popen_safe(command_array, stdout=stdout, stderr=stderr, env=child_env, cwd=cwd) if self.capture: mlog.debug('--- stdout ---') mlog.debug(o) + mlog.debug('--- stderr ---') + mlog.debug(e) else: o = '' - mlog.debug('--- stdout disabled ---') - mlog.debug('--- stderr ---') - mlog.debug(e) + e = '' + mlog.debug('--- output disabled ---') mlog.debug('') if check and p.returncode != 0: diff --git a/test cases/common/33 run program/meson.build b/test cases/common/33 run program/meson.build index 1cd530523357..69830d74de16 100644 --- a/test cases/common/33 run program/meson.build +++ b/test cases/common/33 run program/meson.build @@ -59,14 +59,26 @@ if c.returncode() != 0 endif py3 = import('python3').find_python() - -ret = run_command(py3, '-c', 'print("some output")', check: false) +ret = run_command( + py3, + '-c', + 'import sys; print("capture: true stdout"); print("capture: true stderr", file=sys.stderr)', + check: false, +) 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")', check: false, capture: false) +assert(ret.stdout() == 'capture: true stdout\n', 'failed to run python3') +assert(ret.stderr() == 'capture: true stderr\n', 'failed to run python3') + +ret = run_command( + py3, + '-c', + 'import sys; print("capture: false stdout"); print("capture: false stderr", file=sys.stderr)', + check: false, + capture: false, +) assert(ret.returncode() == 0, 'failed to run python3: ' + ret.stderr()) assert(ret.stdout() == '', 'stdout is "@0@" instead of empty'.format(ret.stdout())) +assert(ret.stderr() == '', 'stderr is "@0@" instead of empty'.format(ret.stderr())) c_env = environment() c_env.append('CUSTOM_ENV_VAR', 'FOOBAR') @@ -76,7 +88,7 @@ assert(ret.stdout() == 'FOOBAR\n', 'stdout is "@0@" instead of FOOBAR'.format(re dd = find_program('dd', required : false) if dd.found() - ret = run_command(dd, 'if=/dev/urandom', 'bs=10', 'count=1', check: false, capture: false) + ret = run_command(dd, 'if=/dev/urandom', 'bs=10', 'count=1', 'of=/dev/null', check: false, 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 diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index b6a87af1fc7f..dc6eb73a34c7 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -5058,3 +5058,21 @@ def test_rsp_support(self): 'link', 'lld-link', 'mwldarm', 'mwldeppc', 'optlink', 'xilink', } self.assertEqual(cc.linker.get_accepts_rsp(), has_rsp) + + def test_run_command_output(self): + ''' + Test that run_command will output to stdout/stderr if `check: false`. + ''' + testdir = os.path.join(self.common_test_dir, '33 run program') + + # inprocess=False uses BasePlatformTests::_run, which by default + # redirects all stderr to stdout, so we look for the expected stderr + # in the merged stdout. + # inprocess=True captures stderr and stdout separatly, but doesn't + # return stderr (only printing it on failure) so unless we change the + # function signature we can't get at the stderr outupt + out = self.init(testdir, inprocess=False) + assert('capture: true stdout' not in out) + assert('capture: true stderr' not in out) + assert('capture: false stdout' in out) + assert('capture: false stderr' in out)