run_command: add env kwarg

pull/4838/head
Jan Tojnar 6 years ago committed by Jussi Pakkanen
parent c07e5124bc
commit 33d82201bd
  1. 8
      docs/markdown/External-commands.md
  2. 6
      docs/markdown/Reference-manual.md
  3. 9
      docs/markdown/snippets/run_command_env.md
  4. 18
      mesonbuild/interpreter.py
  5. 6
      test cases/common/36 run program/meson.build

@ -16,6 +16,14 @@ output = r.stdout().strip()
errortxt = r.stderr().strip()
```
Additionally, since 0.50.0, you can pass the command [`environment`](Reference-manual.html#environment-object) object:
```meson
env = environment()
env.set('FOO', 'bar')
run_command('command', 'arg1', 'arg2', env: env)
```
The `run_command` function returns an object that can be queried for
return value and text written to stdout and stderr. The `strip` method
call is used to strip trailing and leading whitespace from

@ -1183,12 +1183,14 @@ and 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.
This function supports the following keyword arguments:
- `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
- `env` an [environment object](#environment-object) to use a custom environment
Since 0.50.0
See also [External commands](External-commands.md).
@ -2175,7 +2177,7 @@ and has the following methods:
This object is returned by [`environment()`](#environment) and stores
detailed information about how environment variables should be set
during tests. It should be passed as the `env` keyword argument to
tests. It has the following methods.
tests and other functions. It has the following methods.
- `append(varname, value1, value2, ...)` appends the given values to
the old value of the environment variable, e.g. `env.append('FOO',

@ -0,0 +1,9 @@
## `run_command` accepts `env` kwarg
You can pass [`environment`](Reference-manual.html#environment-object) object to [`run_command`](Reference-manual.html#run-command), just like to `test`:
```meson
env = environment()
env.set('FOO', 'bar')
run_command('command', 'arg1', 'arg2', env: env)
```

@ -143,21 +143,21 @@ class TryRunResultHolder(InterpreterObject):
class RunProcess(InterpreterObject):
def __init__(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir=False, check=False, capture=True):
def __init__(self, cmd, args, env, 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)
pc, self.stdout, self.stderr = self.run_command(cmd, args, env, 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, check=False):
def run_command(self, cmd, args, env, source_dir, build_dir, subdir, mesonintrospect, in_builddir, check=False):
command_array = cmd.get_command() + args
env = {'MESON_SOURCE_ROOT': source_dir,
menv = {'MESON_SOURCE_ROOT': source_dir,
'MESON_BUILD_ROOT': build_dir,
'MESON_SUBDIR': subdir,
'MESONINTROSPECT': ' '.join([shlex.quote(x) for x in mesonintrospect]),
@ -167,7 +167,8 @@ class RunProcess(InterpreterObject):
else:
cwd = os.path.join(source_dir, subdir)
child_env = os.environ.copy()
child_env.update(env)
child_env.update(menv)
child_env = env.get_env(child_env)
stdout = subprocess.PIPE if self.capture else subprocess.DEVNULL
mlog.debug('Running command:', ' '.join(command_array))
try:
@ -1954,7 +1955,7 @@ permitted_kwargs = {'add_global_arguments': {'language', 'native'},
'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', 'capture'},
'run_command': {'check', 'capture', 'env'},
'run_target': {'command', 'depends'},
'shared_library': build.known_shlib_kwargs,
'shared_module': build.known_shmod_kwargs,
@ -2259,6 +2260,7 @@ external dependencies (including libraries) must go to "dependencies".''')
if not isinstance(actual, wanted):
raise InvalidArguments('Incorrect argument type.')
@FeatureNewKwargs('run_command', '0.50.0', ['env'])
@FeatureNewKwargs('run_command', '0.47.0', ['check', 'capture'])
@permittedKwargs(permitted_kwargs['run_command'])
def func_run_command(self, node, args, kwargs):
@ -2277,6 +2279,8 @@ external dependencies (including libraries) must go to "dependencies".''')
if not isinstance(check, bool):
raise InterpreterException('Check must be boolean.')
env = self.unpack_env_kwarg(kwargs)
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):
@ -2326,7 +2330,7 @@ external dependencies (including libraries) must go to "dependencies".''')
if not a.startswith('..'):
if a not in self.build_def_files:
self.build_def_files.append(a)
return RunProcess(cmd, expanded_args, srcdir, builddir, self.subdir,
return RunProcess(cmd, expanded_args, env, srcdir, builddir, self.subdir,
self.environment.get_build_command() + ['introspect'],
in_builddir=in_builddir, check=check, capture=capture)

@ -65,6 +65,12 @@ 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()))
c_env = environment()
c_env.append('CUSTOM_ENV_VAR', 'FOOBAR')
ret = run_command(py3, '-c', 'import os; print(os.environ.get("CUSTOM_ENV_VAR"))', env : c_env)
assert(ret.returncode() == 0, 'failed to run python3: ' + ret.stderr())
assert(ret.stdout() == 'FOOBAR\n', 'stdout is "@0@" instead of FOOBAR'.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)

Loading…
Cancel
Save