aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/interpreter.py
diff options
context:
space:
mode:
authorNirbheek Chauhan <nirbheek@centricular.com>2017-05-07 01:00:25 +0530
committerNirbheek Chauhan <nirbheek@centricular.com>2017-05-07 01:56:47 +0530
commit333085160d6cbff2b4a47fac76cb507cd1f6d1c7 (patch)
tree9c67da50c2695cbf8ea5dc61ccb7847af13db611 /mesonbuild/interpreter.py
parentb1df1a2bec053937ecb09f425248c1dbcee9237a (diff)
downloadmeson-333085160d6cbff2b4a47fac76cb507cd1f6d1c7.zip
meson-333085160d6cbff2b4a47fac76cb507cd1f6d1c7.tar.gz
meson-333085160d6cbff2b4a47fac76cb507cd1f6d1c7.tar.bz2
run_command: Refactor + improve errors and test
Refactor to use ExternalProgram for the command instead of duplicating that code (badly). Also improve messages to say "or not executable" when a script/command is not found. Also allow ExternalPrograms to be passed as arguments to run_command(). The only thing we're doing by preventing that is forcing people to use prog.path()
Diffstat (limited to 'mesonbuild/interpreter.py')
-rw-r--r--mesonbuild/interpreter.py63
1 files changed, 29 insertions, 34 deletions
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 2c6806a..5b9bb41 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -23,7 +23,7 @@ from . import compilers
from .wrap import wrap, WrapMode
from . import mesonlib
from .mesonlib import FileMode, Popen_safe, get_meson_script
-from .dependencies import InternalDependency, Dependency
+from .dependencies import InternalDependency, Dependency, ExternalProgram
from .interpreterbase import InterpreterBase
from .interpreterbase import check_stringlist, noPosargs, noKwargs, stringArgs
from .interpreterbase import InterpreterException, InvalidArguments, InvalidCode
@@ -72,17 +72,19 @@ class TryRunResultHolder(InterpreterObject):
class RunProcess(InterpreterObject):
- def __init__(self, command_array, source_dir, build_dir, subdir, mesonintrospect, in_builddir=False):
+ def __init__(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir=False):
super().__init__()
- pc, self.stdout, self.stderr = self.run_command(command_array, source_dir, build_dir, subdir, mesonintrospect, in_builddir)
+ if not isinstance(cmd, ExternalProgram):
+ raise AssertionError('BUG: RunProcess must be passed an ExternalProgram')
+ pc, self.stdout, self.stderr = self.run_command(cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir)
self.returncode = pc.returncode
self.methods.update({'returncode': self.returncode_method,
'stdout': self.stdout_method,
'stderr': self.stderr_method,
})
- def run_command(self, command_array, source_dir, build_dir, subdir, mesonintrospect, in_builddir):
- cmd_name = command_array[0]
+ def run_command(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir):
+ command_array = cmd.get_command() + args
env = {'MESON_SOURCE_ROOT': source_dir,
'MESON_BUILD_ROOT': build_dir,
'MESON_SUBDIR': subdir,
@@ -97,18 +99,6 @@ class RunProcess(InterpreterObject):
try:
return Popen_safe(command_array, env=child_env, cwd=cwd)
except FileNotFoundError:
- pass
- # Was not a command, is a program in path?
- exe = shutil.which(cmd_name)
- if exe is not None:
- command_array = [exe] + command_array[1:]
- return Popen_safe(command_array, env=child_env, cwd=cwd)
- # No? Maybe it is a script in the source tree.
- fullpath = os.path.join(source_dir, subdir, cmd_name)
- command_array = [fullpath] + command_array[1:]
- try:
- return Popen_safe(command_array, env=child_env, cwd=cwd)
- except FileNotFoundError:
raise InterpreterException('Could not execute command "%s".' % cmd_name)
def returncode_method(self, args, kwargs):
@@ -250,7 +240,6 @@ class DependencyHolder(InterpreterObject):
def found_method(self, args, kwargs):
if self.held_object.type_name == 'internal':
return True
-
return self.held_object.found()
def version_method(self, args, kwargs):
@@ -1105,7 +1094,8 @@ class MesonMain(InterpreterObject):
if found.found():
self._found_source_scripts[key] = found
else:
- raise InterpreterException('Script {!r} not found'.format(name))
+ m = 'Script or command {!r} not found or not executable'
+ raise InterpreterException(m.format(name))
return build.RunScript(found.get_command(), args)
def add_install_script_method(self, args, kwargs):
@@ -1471,31 +1461,36 @@ class Interpreter(InterpreterBase):
cargs = args[1:]
srcdir = self.environment.get_source_dir()
builddir = self.environment.get_build_dir()
+ m = 'must be a string, or the output of find_program(), files(), or ' \
+ 'configure_file(); not {!r}'
if isinstance(cmd, ExternalProgramHolder):
- cmd = cmd.get_command()
- elif isinstance(cmd, str):
- cmd = [cmd]
- elif isinstance(cmd, mesonlib.File):
- cmd = [cmd.absolute_path(srcdir, builddir)]
+ cmd = cmd.held_object
else:
- m = 'First argument must be a string, or the output of ' \
- 'find_program(), files(), or configure_file(); not {!r}'
- raise InterpreterException(m.format(cmd))
+ if isinstance(cmd, mesonlib.File):
+ cmd = cmd.absolute_path(srcdir, builddir)
+ elif not isinstance(cmd, str):
+ raise InterpreterException('First argument ' + m.format(cmd))
+ # Prefer scripts in the current source directory
+ search_dir = os.path.join(srcdir, self.subdir)
+ prog = ExternalProgram(cmd, silent=True, search_dir=search_dir)
+ if not prog.found():
+ raise InterpreterException('Program or command {!r} not found'
+ 'or not executable'.format(cmd))
+ cmd = prog
expanded_args = []
for a in mesonlib.flatten(cargs):
if isinstance(a, str):
expanded_args.append(a)
elif isinstance(a, mesonlib.File):
expanded_args.append(a.absolute_path(srcdir, builddir))
+ elif isinstance(a, ExternalProgramHolder):
+ expanded_args.append(a.held_object.get_path())
else:
- m = 'run_command() arguments must be strings, the output of ' \
- 'files(), or configure_file(); not {!r}'
- raise InterpreterException(m.format(a))
- args = cmd + expanded_args
+ raise InterpreterException('Arguments ' + m.format(a))
in_builddir = kwargs.get('in_builddir', False)
if not isinstance(in_builddir, bool):
raise InterpreterException('in_builddir must be boolean.')
- return RunProcess(args, srcdir, builddir, self.subdir,
+ return RunProcess(cmd, expanded_args, srcdir, builddir, self.subdir,
get_meson_script(self.environment, 'mesonintrospect'), in_builddir)
@stringArgs
@@ -1851,7 +1846,7 @@ class Interpreter(InterpreterBase):
if progobj.found():
return progobj
if required and not progobj.found():
- raise InvalidArguments('Program "%s" not found.' % exename)
+ raise InvalidArguments('Program "%s" not found or not executable' % exename)
return progobj
def func_find_library(self, node, args, kwargs):
@@ -2427,7 +2422,7 @@ different subdirectory.
exe_wrapper.append(i)
elif isinstance(i, dependencies.ExternalProgram):
if not i.found():
- raise InterpreterException('Tried to use non-found external executable.')
+ raise InterpreterException('Tried to use non-found executable.')
exe_wrapper += i.get_command()
else:
raise InterpreterException('Exe wrapper can only contain strings or external binaries.')