Repository: mesonbuild/meson

Issue:
Allow running run_command() without capturing binary output which will fail to decode
```
Program glslc found: YES (/usr/local/bin/glslc)
Traceback (most recent call last):
  File "/data/git/meson/mesonbuild/mesonmain.py", line 369, in run
    app.generate()
  File "/data/git/meson/mesonbuild/mesonmain.py", line 151, in generate
    self._generate(env)
  File "/data/git/meson/mesonbuild/mesonmain.py", line 198, in _generate
    intr.run()
  File "/data/git/meson/mesonbuild/interpreter.py", line 3125, in run
    super().run()
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 189, in run
    self.evaluate_codeblock(self.ast, start=1)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 211, in evaluate_codeblock
    raise e
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 205, in evaluate_codeblock
    self.evaluate_statement(cur)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 216, in evaluate_statement
    return self.function_call(cur)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 472, in function_call
    return self.funcs[func_name](node, self.flatten(posargs), kwargs)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 79, in wrapped
    return f(s, node_or_state, args, kwargs)
  File "/data/git/meson/mesonbuild/interpreter.py", line 2791, in func_subdir
    self.evaluate_codeblock(codeblock)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 211, in evaluate_codeblock
    raise e
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 205, in evaluate_codeblock
    self.evaluate_statement(cur)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 216, in evaluate_statement
    return self.function_call(cur)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 472, in function_call
    return self.funcs[func_name](node, self.flatten(posargs), kwargs)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 79, in wrapped
    return f(s, node_or_state, args, kwargs)
  File "/data/git/meson/mesonbuild/interpreter.py", line 2791, in func_subdir
    self.evaluate_codeblock(codeblock)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 211, in evaluate_codeblock
    raise e
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 205, in evaluate_codeblock
    self.evaluate_statement(cur)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 226, in evaluate_statement
    return self.evaluate_if(cur)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 279, in evaluate_if
    self.evaluate_codeblock(i.block)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 211, in evaluate_codeblock
    raise e
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 205, in evaluate_codeblock
    self.evaluate_statement(cur)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 226, in evaluate_statement
    return self.evaluate_if(cur)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 279, in evaluate_if
    self.evaluate_codeblock(i.block)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 211, in evaluate_codeblock
    raise e
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 205, in evaluate_codeblock
    self.evaluate_statement(cur)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 218, in evaluate_statement
    return self.assignment(cur)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 690, in assignment
    value = self.evaluate_statement(node.value)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 216, in evaluate_statement
    return self.function_call(cur)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 472, in function_call
    return self.funcs[func_name](node, self.flatten(posargs), kwargs)
  File "/data/git/meson/mesonbuild/interpreterbase.py", line 47, in wrapped
    return f(self, node, args, kwargs)
  File "/data/git/meson/mesonbuild/interpreter.py", line 1779, in func_run_command
    return self.run_command_impl(node, args, kwargs)
  File "/data/git/meson/mesonbuild/interpreter.py", line 1840, in run_command_impl
    self.environment.get_build_command() + ['introspect'], in_builddir)
  File "/data/git/meson/mesonbuild/interpreter.py", line 87, in __init__
    pc, self.stdout, self.stderr = self.run_command(cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir)
  File "/data/git/meson/mesonbuild/interpreter.py", line 109, in run_command
    p, o, e = Popen_safe(command_array, env=child_env, cwd=cwd)
  File "/data/git/meson/mesonbuild/mesonlib.py", line 743, in Popen_safe
    o, e = p.communicate(write)
  File "/usr/lib64/python3.6/subprocess.py", line 843, in communicate
    stdout, stderr = self._communicate(input, endtime, timeout)
  File "/usr/lib64/python3.6/subprocess.py", line 1554, in _communicate
    self.stdout.errors)
  File "/usr/lib64/python3.6/subprocess.py", line 740, in _translate_newlines
    data = data.decode(encoding, errors)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xae in position 112: invalid start byte
samu: job failed: /usr/bin/python3 /usr/bin/meson --internal regenerate /data/git/taisei /data/taisei-build/dev/clang --backend ninja
samu: subcommand failed
```


Discussion:

Resolving patch:
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -749,7 +749,9 @@ def expand_arguments(args):
     return expended_args
 
 def Popen_safe(args, write=None, stderr=subprocess.PIPE, **kwargs):
-    if sys.version_info < (3, 6) or not sys.stdout.encoding:
+    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,


Test patch: