Skip to content

Commit

Permalink
Added warning if run_command is called without the check kwarg
Browse files Browse the repository at this point in the history
  • Loading branch information
Volker-Weissmann committed Oct 10, 2021
1 parent 32b7cbd commit bb0ee05
Show file tree
Hide file tree
Showing 30 changed files with 83 additions and 59 deletions.
11 changes: 6 additions & 5 deletions docs/markdown/External-commands.md
Expand Up @@ -8,18 +8,19 @@ As a part of the software configuration, you may want to get extra
data by running external commands. The basic syntax is the following.

```meson
r = run_command('command', 'arg1', 'arg2', 'arg3')
if r.returncode() != 0
# it failed
endif
r = run_command('command', 'arg1', 'arg2', 'arg3', check: true)
output = r.stdout().strip()
errortxt = r.stderr().strip()
```

If `check: true` is given, meson will error out if `command` returns with a
non-zero exit code. Alternatively, you can set `check: false` and get the exit
code with `r.returncode()`.

Since 0.52.0, you can pass the command environment as a dictionary:

```meson
run_command('command', 'arg1', 'arg2', env: {'FOO': 'bar'})
run_command('command', 'arg1', 'arg2', env: {'FOO': 'bar'}, check: true)
```

Since 0.50.0, you can also pass the command [[@env]] object:
Expand Down
2 changes: 1 addition & 1 deletion docs/markdown/FAQ.md
Expand Up @@ -103,7 +103,7 @@ Then you need to run this script in your Meson file, convert the
output into a string array and use the result in a target.

```meson
c = run_command('grabber.sh')
c = run_command('grabber.sh', check: true)
sources = c.stdout().strip().split('\n')
e = executable('prog', sources)
```
Expand Down
2 changes: 1 addition & 1 deletion docs/markdown/howtox.md
Expand Up @@ -133,7 +133,7 @@ endif
## Set a command's output to configuration

```meson
txt = run_command('script', 'argument').stdout().strip()
txt = run_command('script', 'argument', check: true).stdout().strip()
cdata = configuration_data()
cdata.set('SOMETHING', txt)
configure_file(...)
Expand Down
14 changes: 14 additions & 0 deletions docs/markdown/snippets/check_false_warning.md
@@ -0,0 +1,14 @@
## Warning if check kwarg of run_command is missing

The `check` kwarg of `run_command` currently defaults to `false`.
Because we want to change that, running
```meson
run_command('cmd')
```
now results in:
```text
WARNING: You should add the boolean check kwarg to the run_command call.
It currently defaults to false,
but it will default to true in future releases of meson.
See also: https://github.com/mesonbuild/meson/issues/9300
```
3 changes: 2 additions & 1 deletion docs/yaml/functions/run_command.yaml
Expand Up @@ -27,7 +27,8 @@ kwargs:
default: false
description: |
If `true`, the exit status code of the command will be checked,
and the configuration will fail if it is non-zero.
and the configuration will fail if it is non-zero. Note that
the default value will be `true` in future releases.
env:
type: env | list[str] | dict[str]
Expand Down
10 changes: 9 additions & 1 deletion mesonbuild/interpreter/interpreter.py
Expand Up @@ -231,6 +231,10 @@ def dump_value(self, arr, list_sep, indent):
'version',
}

implicit_check_false_warning = """You should add the boolean check kwarg to the run_command call.
It currently defaults to false,
but it will default to true in future releases of meson.
See also: https://github.com/mesonbuild/meson/issues/9300"""
class Interpreter(InterpreterBase, HoldableObject):

def __init__(
Expand Down Expand Up @@ -690,7 +694,11 @@ def run_command_impl(self,
srcdir = self.environment.get_source_dir()
builddir = self.environment.get_build_dir()

check = kwargs.get('check', False)
check = kwargs.get('check')
if check is None:
mlog.warning(implicit_check_false_warning, once=True)
check = False

if not isinstance(check, bool):
raise InterpreterException('Check must be boolean.')

Expand Down
Expand Up @@ -2,7 +2,7 @@ project('mesonintrospect from scripts', 'c')

python = import('python3').find_python()

ret = run_command(python, ['check_env.py', '1'])
ret = run_command(python, ['check_env.py', '1'], check: false)
if ret.returncode() == 0
find_program(ret.stdout())
else
Expand Down
14 changes: 7 additions & 7 deletions test cases/common/14 configure file/meson.build
Expand Up @@ -40,7 +40,7 @@ outf = configure_file(input : 'dummy.dat',
output : 'config2.h',
command : [genprog, scriptfile, ifile, ofile],
install_dir : 'share/appdir')
ret = run_command(check_file, outf)
ret = run_command(check_file, outf, check: false)
if ret.returncode() != 0
error('Error running command: @0@\n@1@'.format(ret.stdout(), ret.stderr()))
endif
Expand All @@ -53,7 +53,7 @@ outf = configure_file(
output : 'config2b.h',
command : [genprog, genscript2b, ofile2b],
install_dir : 'share/appdir')
ret = run_command(check_file, outf)
ret = run_command(check_file, outf, check: false)
if ret.returncode() != 0
error('Error running command: @0@\n@1@'.format(ret.stdout(), ret.stderr()))
endif
Expand All @@ -64,7 +64,7 @@ outf = configure_file(
output : 'config2deps.h',
depfile : 'depfile.d',
command : [genprog, genscript2deps, ofile2deps, '@DEPFILE@'])
ret = run_command(check_file, outf)
ret = run_command(check_file, outf, check: false)
if ret.returncode() != 0
error('Error running command: @0@\n@1@'.format(ret.stdout(), ret.stderr()))
endif
Expand Down Expand Up @@ -116,7 +116,7 @@ basename_py = find_program('basename.py')
file_contains_py = find_program('file_contains.py')
test_string = 'hello world'
test_input_file = join_paths(meson.current_build_dir(), test_string)
run_command(find_program('touch.py'), test_input_file)
run_command(find_program('touch.py'), test_input_file, check: true)
configs = [
# no input
configure_file(command: [ basename_py, test_string ], capture: true, output: 'capture test 1'),
Expand Down Expand Up @@ -182,13 +182,13 @@ inf = 'invalid-utf8.bin.in'
outf = configure_file(input : inf,
output : 'invalid-utf8.bin',
copy: true)
ret = run_command(check_file, inf, outf)
ret = run_command(check_file, inf, outf, check: false)
if ret.returncode() != 0
error('Error running command: @0@\n@1@'.format(ret.stdout(), ret.stderr()))
endif
# Now the same, but using a File object as an argument.
inf2 = files('invalid-utf8.bin.in')[0]
ret = run_command(check_file, inf2, outf)
ret = run_command(check_file, inf2, outf, check: false)
if ret.returncode() != 0
error('Error running command: @0@\n@1@'.format(ret.stdout(), ret.stderr()))
endif
Expand All @@ -197,7 +197,7 @@ endif
outf = configure_file(input : inf,
output : 'somebinary.bin',
copy : true)
ret = run_command(check_file, inf, outf)
ret = run_command(check_file, inf, outf, check: false)
if ret.returncode() != 0
error('Error running command: @0@\n@1@'.format(ret.stdout(), ret.stderr()))
endif
Expand Down
6 changes: 3 additions & 3 deletions test cases/common/14 configure file/subdir/meson.build
Expand Up @@ -3,20 +3,20 @@ configure_file(input : '../dummy.dat',
output : 'config2-1.h',
command : [genprog, scriptfile, ifile, 'config2-1.h'],
install_dir : 'share/appdireh')
run_command(check_file, join_paths(meson.current_build_dir(), 'config2-1.h'))
run_command(check_file, join_paths(meson.current_build_dir(), 'config2-1.h'), check: true)

# Configure in subdir with files() for input and relative for output
configure_file(input : '../dummy.dat',
output : 'config2-2.h',
command : [genprog, scriptfile, files('../dummy.dat'), 'config2-2.h'],
install_dir : 'share/appdirok')
run_command(check_file, join_paths(meson.current_build_dir(), 'config2-2.h'))
run_command(check_file, join_paths(meson.current_build_dir(), 'config2-2.h'), check: true)

# Configure in subdir with string templates for input and output
configure_file(input : '../dummy.dat',
output : 'config2-3.h',
command : [found_script, '@INPUT@', '@OUTPUT@'])
run_command(check_file, join_paths(meson.current_build_dir(), 'config2-3.h'))
run_command(check_file, join_paths(meson.current_build_dir(), 'config2-3.h'), check: true)

# Test that overwriting an existing file creates a warning.
configure_file(
Expand Down
4 changes: 2 additions & 2 deletions test cases/common/156 config tool variable/meson.build
Expand Up @@ -23,9 +23,9 @@ endif
includedir = dep_llvm.get_configtool_variable('includedir')
includedir = join_paths(includedir, 'llvm')
if host_machine.system() == 'windows'
cmd = run_command(['dir', includedir])
cmd = run_command(['dir', includedir], check: false)
else
cmd = run_command(['ls', includedir])
cmd = run_command(['ls', includedir], check: false)
endif

assert(cmd.returncode() == 0, 'did not run successfully')
2 changes: 1 addition & 1 deletion test cases/common/179 escape and unicode/meson.build
Expand Up @@ -4,7 +4,7 @@ gen = generator(find_program('file.py'), arguments:['@INPUT@', 'erd\u0151', '@OU

gen_file = gen.process('file.c.in')

find_file_list = run_command(find_program('find.py'))
find_file_list = run_command(find_program('find.py'), check: true)
assert(find_file_list.returncode() == 0, 'Didn\'t find any files.')

# Strings should support both octal \ooo and hex \xhh encodings
Expand Down
2 changes: 1 addition & 1 deletion test cases/common/220 fs module/meson.build
Expand Up @@ -15,7 +15,7 @@ if not is_windows and build_machine.system() != 'cygwin'
# * Windows user permissions to create symlinks, and/or Windows in Developer mode
# so at this time the symlink test is skipped for Windows.
symlink = meson.current_build_dir() / 'a_symlink'
run_command('ln', '-s', meson.current_source_dir() / 'meson.build', symlink)
run_command('ln', '-s', '-f', meson.current_source_dir() / 'meson.build', symlink, check: true)
assert(fs.is_symlink(symlink), 'Symlink not detected.')
assert(not fs.is_symlink('meson.build'), 'Regular file detected as symlink.')
assert(not fs.is_symlink(f[0]), 'Regular file detected as symlink.')
Expand Down
2 changes: 1 addition & 1 deletion test cases/common/227 very long commmand line/meson.build
Expand Up @@ -26,7 +26,7 @@ namelen = 260
nfiles = 50 + limit / namelen
message('Expected link commandline length is approximately ' + '@0@'.format((nfiles * (namelen+28))))

seq = run_command('name_gen.py', nfiles.to_string(), meson.build_root()).stdout().strip().split('\n')
seq = run_command('name_gen.py', nfiles.to_string(), meson.build_root(), check: true).stdout().strip().split('\n')

sources = []
codegen = find_program('codegen.py')
Expand Down
20 changes: 10 additions & 10 deletions test cases/common/33 run program/meson.build
@@ -1,9 +1,9 @@
project('run command', version : run_command('get-version.py', check : true).stdout().strip())

if build_machine.system() == 'windows'
c = run_command('cmd', '/c', 'echo', 'hello')
c = run_command('cmd', '/c', 'echo', 'hello', check: false)
else
c = run_command('echo', 'hello')
c = run_command('echo', 'hello', check: false)
endif

correct = 'hello'
Expand All @@ -25,9 +25,9 @@ endif
# Now the same with a script.

if build_machine.system() == 'windows'
cs = run_command('scripts/hello.bat')
cs = run_command('scripts/hello.bat', check: false)
else
cs = run_command('scripts/hello.sh')
cs = run_command('scripts/hello.sh', check: false)
endif

if cs.returncode() != 0
Expand All @@ -46,9 +46,9 @@ endif
f = files('meson.build')

if build_machine.system() == 'windows'
c = run_command('cmd', '/c', 'echo', f)
c = run_command('cmd', '/c', 'echo', f, check: false)
else
c = run_command('echo', f)
c = run_command('echo', f, check: false)
endif

if c.returncode() != 0
Expand All @@ -57,23 +57,23 @@ endif

py3 = import('python3').find_python()

ret = run_command(py3, '-c', 'print("some output")')
ret = run_command(py3, '-c', 'print("some output")', 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")', capture : false)
ret = run_command(py3, '-c', 'print("some output")', 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()))

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)
ret = run_command(py3, '-c', 'import os; print(os.environ.get("CUSTOM_ENV_VAR"))', env: c_env, check: false)
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)
ret = run_command(dd, 'if=/dev/urandom', 'bs=10', 'count=1', 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
Expand Down
2 changes: 1 addition & 1 deletion test cases/common/44 pkgconfig-gen/meson.build
Expand Up @@ -13,7 +13,7 @@ if not pkgconfig.found()
error('MESON_SKIP_TEST: pkg-config not found')
endif

v = run_command(pkgconfig, '--version').stdout().strip()
v = run_command(pkgconfig, '--version', check: true).stdout().strip()
if v.version_compare('<0.29')
error('MESON_SKIP_TEST: pkg-config version \'' + v + '\' too old')
endif
Expand Down
4 changes: 2 additions & 2 deletions test cases/common/48 file grabber/meson.build
Expand Up @@ -10,10 +10,10 @@ project('grabber', 'c')
# file bugs when it fails. :)

if build_machine.system() == 'windows'
c = run_command('grabber.bat')
c = run_command('grabber.bat', check: false)
grabber = find_program('grabber2.bat')
else
c = run_command('grabber.sh')
c = run_command('grabber.sh', check: false)
grabber = find_program('grabber.sh')
endif

Expand Down
2 changes: 1 addition & 1 deletion test cases/common/48 file grabber/subdir/meson.build
@@ -1,4 +1,4 @@
sc = run_command(grabber)
sc = run_command(grabber, check: true)
subsources = sc.stdout().strip().split(newline)

se = executable('subprog', subsources)
Expand Down
4 changes: 2 additions & 2 deletions test cases/common/97 find program path/meson.build
Expand Up @@ -12,11 +12,11 @@ py = configure_file(input : 'program.py',
configuration : configuration_data())

foreach f : [prog, progf, py, find_program(py), find_program(progf)]
ret = run_command(python, f)
ret = run_command(python, f, check: false)
assert(ret.returncode() == 0, 'can\'t manually run @0@'.format(prog.path()))
assert(ret.stdout().strip() == 'Found', 'wrong output from manually-run @0@'.format(prog.path()))

ret = run_command(f)
ret = run_command(f, check: false)
assert(ret.returncode() == 0, 'can\'t run @0@'.format(prog.path()))
assert(ret.stdout().strip() == 'Found', 'wrong output from @0@'.format(prog.path()))
endforeach
2 changes: 1 addition & 1 deletion test cases/failing/80 override exe config/meson.build
Expand Up @@ -3,4 +3,4 @@ project('myexe', 'c')
foo = executable('foo', 'foo.c')
meson.override_find_program('bar', foo)
bar = find_program('bar')
run_command(bar)
run_command(bar, check: true)
4 changes: 2 additions & 2 deletions test cases/fortran/15 include/meson.build
Expand Up @@ -10,8 +10,8 @@ syntax_exe = executable('include_syntax', 'include_syntax.f90')
test('Fortran include file syntax', syntax_exe)

# older CI runs into problems with too-old Ninja and CMake and Fortran
ninja_version = run_command('ninja', '--version').stdout().strip()
cmake_version = run_command('cmake', '--version').stdout().split()[2]
ninja_version = run_command('ninja', '--version', check: true).stdout().strip()
cmake_version = run_command('cmake', '--version', check: true).stdout().split()[2]
if ninja_version.version_compare('>=1.10.0') and cmake_version.version_compare('>=3.17.0')
cm.subproject('cmake_inc')
else
Expand Down
2 changes: 1 addition & 1 deletion test cases/frameworks/10 gtk-doc/meson.build
Expand Up @@ -15,7 +15,7 @@ subdir('include')

# disable this test unless a bug fix for spaces in pathnames is present
# https://bugzilla.gnome.org/show_bug.cgi?id=753145
result = run_command(gtkdoc, ['--version'])
result = run_command(gtkdoc, ['--version'], check: true)
gtkdoc_ver = result.stdout().strip()
if gtkdoc_ver == ''
gtkdoc_ver = result.stderr().strip()
Expand Down
2 changes: 1 addition & 1 deletion test cases/frameworks/11 gir subproject/meson.build
Expand Up @@ -7,7 +7,7 @@ endif

python3 = import('python3')
py3 = python3.find_python()
if run_command(py3, '-c', 'import gi;').returncode() != 0
if run_command(py3, '-c', 'import gi;', check: false).returncode() != 0
error('MESON_SKIP_TEST python3-gi not found')
endif

Expand Down
4 changes: 2 additions & 2 deletions test cases/frameworks/7 gnome/meson.build
Expand Up @@ -12,7 +12,7 @@ endif

python3 = import('python3')
py3 = python3.find_python()
if run_command(py3, '-c', 'import gi;').returncode() != 0
if run_command(py3, '-c', 'import gi;', check: false).returncode() != 0
error('MESON_SKIP_TEST python3-gi not found')
endif

Expand All @@ -33,7 +33,7 @@ sys.exit(1)
'''

pretend_glib_old = false
res = run_command(py3, '-c', pycode)
res = run_command(py3, '-c', pycode, check: false)
if res.returncode() == 0
pretend_glib_old = true
endif
Expand Down
2 changes: 1 addition & 1 deletion test cases/linuxlike/13 cmake dependency/meson.build
Expand Up @@ -7,7 +7,7 @@ if not find_program('cmake', required: false).found()
endif

# CMake version
cm_vers = run_command(find_program('./cmVers.sh')).stdout().strip()
cm_vers = run_command(find_program('./cmVers.sh'), check: true).stdout().strip()

# Zlib is probably on all dev machines.

Expand Down
2 changes: 1 addition & 1 deletion test cases/linuxlike/15 ld binary/meson.build
@@ -1,4 +1,4 @@
project('ld binary')

ld = find_program('ld')
assert(run_command(ld, '--version').returncode() == 0)
assert(run_command(ld, '--version', check: false).returncode() == 0)

0 comments on commit bb0ee05

Please sign in to comment.