aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNirbheek Chauhan <nirbheek@centricular.com>2017-02-19 03:19:13 +0530
committerNirbheek Chauhan <nirbheek@centricular.com>2017-02-19 03:49:31 +0530
commit7e805a019ae4d923403af8032776c0c302e3a50c (patch)
treef235ff5c0039b8e43469dce0d9606bb30a722595
parent280346da3ac5904ec097afe89ef45ad34bd4a173 (diff)
downloadmeson-7e805a019ae4d923403af8032776c0c302e3a50c.zip
meson-7e805a019ae4d923403af8032776c0c302e3a50c.tar.gz
meson-7e805a019ae4d923403af8032776c0c302e3a50c.tar.bz2
find_program: Fix implementation of .path()
And actually test that prog.path() works. The earlier test was just running the command without checking if it succeeded. Also make everything use prog.get_command() or get_path() instead of accessing the internal member prog.fullpath directly.
-rw-r--r--mesonbuild/backend/backends.py14
-rw-r--r--mesonbuild/backend/vs2010backend.py2
-rw-r--r--mesonbuild/dependencies.py49
-rw-r--r--mesonbuild/interpreter.py6
-rw-r--r--mesonbuild/modules/qt4.py6
-rw-r--r--mesonbuild/modules/qt5.py6
-rw-r--r--mesonbuild/modules/rpm.py2
-rwxr-xr-xrun_unittests.py12
-rw-r--r--test cases/common/105 find program path/meson.build19
9 files changed, 65 insertions, 51 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 46f8563..7372c4c 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -215,13 +215,13 @@ class Backend:
exe_data = os.path.join(self.environment.get_scratch_dir(), scratch_file)
with open(exe_data, 'wb') as f:
if isinstance(exe, dependencies.ExternalProgram):
- exe_fullpath = exe.fullpath
+ exe_cmd = exe.get_command()
exe_needs_wrapper = False
elif isinstance(exe, (build.BuildTarget, build.CustomTarget)):
- exe_fullpath = [self.get_target_filename_abs(exe)]
+ exe_cmd = [self.get_target_filename_abs(exe)]
exe_needs_wrapper = exe.is_cross
else:
- exe_fullpath = [exe]
+ exe_cmd = [exe]
exe_needs_wrapper = False
is_cross = exe_needs_wrapper and \
self.environment.is_cross_build() and \
@@ -235,7 +235,7 @@ class Backend:
extra_paths = self.determine_windows_extra_paths(exe)
else:
extra_paths = []
- es = ExecutableSerialisation(basename, exe_fullpath, cmd_args, env,
+ es = ExecutableSerialisation(basename, exe_cmd, cmd_args, env,
is_cross, exe_wrapper, workdir,
extra_paths, capture)
pickle.dump(es, f)
@@ -444,9 +444,9 @@ class Backend:
for t in tests:
exe = t.get_exe()
if isinstance(exe, dependencies.ExternalProgram):
- fname = exe.fullpath
+ cmd = exe.get_command()
else:
- fname = [os.path.join(self.environment.get_build_dir(), self.get_target_filename(t.get_exe()))]
+ cmd = [os.path.join(self.environment.get_build_dir(), self.get_target_filename(t.get_exe()))]
is_cross = self.environment.is_cross_build() and \
self.environment.cross_info.need_cross_compiler() and \
self.environment.cross_info.need_exe_wrapper()
@@ -471,7 +471,7 @@ class Backend:
cmd_args.append(self.get_target_filename(a))
else:
raise MesonException('Bad object in test command.')
- ts = TestSerialisation(t.get_name(), t.suite, fname, is_cross, exe_wrapper,
+ ts = TestSerialisation(t.get_name(), t.suite, cmd, is_cross, exe_wrapper,
t.is_parallel, cmd_args, t.env, t.should_fail,
t.timeout, t.workdir, extra_paths)
arr.append(ts)
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index 666da7d..547889c 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -395,7 +395,7 @@ class Vs2010Backend(backends.Backend):
if isinstance(i, build.BuildTarget):
cmd.append(os.path.join(self.environment.get_build_dir(), self.get_target_filename(i)))
elif isinstance(i, dependencies.ExternalProgram):
- cmd += i.fullpath
+ cmd += i.get_command()
else:
cmd.append(i)
cmd_templ = '''"%s" ''' * len(cmd)
diff --git a/mesonbuild/dependencies.py b/mesonbuild/dependencies.py
index 920a279..f7b5418 100644
--- a/mesonbuild/dependencies.py
+++ b/mesonbuild/dependencies.py
@@ -404,25 +404,25 @@ class WxDependency(Dependency):
class ExternalProgram:
windows_exts = ('exe', 'msc', 'com', 'bat')
- def __init__(self, name, fullpath=None, silent=False, search_dir=None):
+ def __init__(self, name, command=None, silent=False, search_dir=None):
self.name = name
- if fullpath is not None:
- if not isinstance(fullpath, list):
- self.fullpath = [fullpath]
+ if command is not None:
+ if not isinstance(command, list):
+ self.command = [command]
else:
- self.fullpath = fullpath
+ self.command = command
else:
- self.fullpath = self._search(name, search_dir)
+ self.command = self._search(name, search_dir)
if not silent:
if self.found():
mlog.log('Program', mlog.bold(name), 'found:', mlog.green('YES'),
- '(%s)' % ' '.join(self.fullpath))
+ '(%s)' % ' '.join(self.command))
else:
mlog.log('Program', mlog.bold(name), 'found:', mlog.red('NO'))
def __repr__(self):
r = '<{} {!r} -> {!r}>'
- return r.format(self.__class__.__name__, self.name, self.fullpath)
+ return r.format(self.__class__.__name__, self.name, self.command)
@staticmethod
def _shebang_to_cmd(script):
@@ -485,22 +485,22 @@ class ExternalProgram:
if commands:
return commands
# Do a standard search in PATH
- fullpath = shutil.which(name)
+ command = shutil.which(name)
if not mesonlib.is_windows():
# On UNIX-like platforms, the standard PATH search is enough
- return [fullpath]
+ return [command]
# HERE BEGINS THE TERROR OF WINDOWS
- if fullpath:
+ if command:
# On Windows, even if the PATH search returned a full path, we can't be
# sure that it can be run directly if it's not a native executable.
# For instance, interpreted scripts sometimes need to be run explicitly
# with an interpreter if the file association is not done properly.
- name_ext = os.path.splitext(fullpath)[1]
+ name_ext = os.path.splitext(command)[1]
if name_ext[1:].lower() in self.windows_exts:
# Good, it can be directly executed
- return [fullpath]
+ return [command]
# Try to extract the interpreter from the shebang
- commands = self._shebang_to_cmd(fullpath)
+ commands = self._shebang_to_cmd(command)
if commands:
return commands
else:
@@ -509,9 +509,9 @@ class ExternalProgram:
# but many people do it because it works in the MinGW shell.
if os.path.isabs(name):
for ext in self.windows_exts:
- fullpath = '{}.{}'.format(name, ext)
- if os.path.exists(fullpath):
- return [fullpath]
+ command = '{}.{}'.format(name, ext)
+ if os.path.exists(command):
+ return [command]
# On Windows, interpreted scripts must have an extension otherwise they
# cannot be found by a standard PATH search. So we do a custom search
# where we manually search for a script with a shebang in PATH.
@@ -523,10 +523,17 @@ class ExternalProgram:
return [None]
def found(self):
- return self.fullpath[0] is not None
+ return self.command[0] is not None
def get_command(self):
- return self.fullpath[:]
+ return self.command[:]
+
+ def get_path(self):
+ # Assume that the last element is the full path to the script
+ # If it's not a script, this will be an array of length 1
+ if self.found():
+ return self.command[-1]
+ return None
def get_name(self):
return self.name
@@ -1020,7 +1027,7 @@ class QtBaseDependency(Dependency):
if not self.qmake.found():
continue
# Check that the qmake is for qt5
- pc, stdo = Popen_safe(self.qmake.fullpath + ['-v'])[0:2]
+ pc, stdo = Popen_safe(self.qmake.get_command() + ['-v'])[0:2]
if pc.returncode != 0:
continue
if not 'Qt version ' + self.qtver in stdo:
@@ -1033,7 +1040,7 @@ class QtBaseDependency(Dependency):
return
self.version = re.search(self.qtver + '(\.\d+)+', stdo).group(0)
# Query library path, header path, and binary path
- stdo = Popen_safe(self.qmake.fullpath + ['-query'])[1]
+ stdo = Popen_safe(self.qmake.get_command() + ['-query'])[1]
qvars = {}
for line in stdo.split('\n'):
line = line.strip()
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 963cc69..bae42a4 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -285,16 +285,16 @@ class ExternalProgramHolder(InterpreterObject):
return self.found()
def path_method(self, args, kwargs):
- return self.get_command()
+ return self.held_object.get_path()
def found(self):
return self.held_object.found()
def get_command(self):
- return self.held_object.fullpath
+ return self.held_object.get_command()
def get_name(self):
- return self.held_object.name
+ return self.held_object.get_name()
class ExternalLibraryHolder(InterpreterObject):
def __init__(self, el):
diff --git a/mesonbuild/modules/qt4.py b/mesonbuild/modules/qt4.py
index 33c9f80..7146739 100644
--- a/mesonbuild/modules/qt4.py
+++ b/mesonbuild/modules/qt4.py
@@ -48,7 +48,7 @@ class Qt4Module(ExtensionModule):
raise MesonException('Moc preprocessor is not for Qt 4. Output:\n%s\n%s' %
(stdout, stderr))
mlog.log(' moc:', mlog.green('YES'), '(%s, %s)' %
- (' '.join(self.moc.fullpath), moc_ver.split()[-1]))
+ (self.moc.get_path(), moc_ver.split()[-1]))
else:
mlog.log(' moc:', mlog.red('NO'))
if self.uic.found():
@@ -61,7 +61,7 @@ class Qt4Module(ExtensionModule):
raise MesonException('Uic compiler is not for Qt4. Output:\n%s\n%s' %
(stdout, stderr))
mlog.log(' uic:', mlog.green('YES'), '(%s, %s)' %
- (' '.join(self.uic.fullpath), uic_ver.split()[-1]))
+ (self.uic.get_path(), uic_ver.split()[-1]))
else:
mlog.log(' uic:', mlog.red('NO'))
if self.rcc.found():
@@ -74,7 +74,7 @@ class Qt4Module(ExtensionModule):
raise MesonException('Rcc compiler is not for Qt 4. Output:\n%s\n%s' %
(stdout, stderr))
mlog.log(' rcc:', mlog.green('YES'), '(%s, %s)'
- % (' '.join(self.rcc.fullpath), rcc_ver.split()[-1]))
+ % (self.rcc.get_path(), rcc_ver.split()[-1]))
else:
mlog.log(' rcc:', mlog.red('NO'))
self.tools_detected = True
diff --git a/mesonbuild/modules/qt5.py b/mesonbuild/modules/qt5.py
index b4f1475..2a87a80 100644
--- a/mesonbuild/modules/qt5.py
+++ b/mesonbuild/modules/qt5.py
@@ -50,7 +50,7 @@ class Qt5Module(ExtensionModule):
raise MesonException('Moc preprocessor is not for Qt 5. Output:\n%s\n%s' %
(stdout, stderr))
mlog.log(' moc:', mlog.green('YES'), '(%s, %s)' %
- (' '.join(self.moc.fullpath), moc_ver.split()[-1]))
+ (self.moc.get_path(), moc_ver.split()[-1]))
else:
mlog.log(' moc:', mlog.red('NO'))
if self.uic.found():
@@ -65,7 +65,7 @@ class Qt5Module(ExtensionModule):
raise MesonException('Uic compiler is not for Qt 5. Output:\n%s\n%s' %
(stdout, stderr))
mlog.log(' uic:', mlog.green('YES'), '(%s, %s)' %
- (' '.join(self.uic.fullpath), uic_ver.split()[-1]))
+ (self.uic.get_path(), uic_ver.split()[-1]))
else:
mlog.log(' uic:', mlog.red('NO'))
if self.rcc.found():
@@ -80,7 +80,7 @@ class Qt5Module(ExtensionModule):
raise MesonException('Rcc compiler is not for Qt 5. Output:\n%s\n%s' %
(stdout, stderr))
mlog.log(' rcc:', mlog.green('YES'), '(%s, %s)'
- % (' '.join(self.rcc.fullpath), rcc_ver.split()[-1]))
+ % (self.rcc.get_path(), rcc_ver.split()[-1]))
else:
mlog.log(' rcc:', mlog.red('NO'))
self.tools_detected = True
diff --git a/mesonbuild/modules/rpm.py b/mesonbuild/modules/rpm.py
index bd8a3c4..b967863 100644
--- a/mesonbuild/modules/rpm.py
+++ b/mesonbuild/modules/rpm.py
@@ -108,7 +108,7 @@ class RPMModule(ExtensionModule):
fn.write('BuildRequires: %%{_bindir}/%s # FIXME\n' %
prog.get_name())
else:
- fn.write('BuildRequires: %s\n' % ' '.join(prog.fullpath))
+ fn.write('BuildRequires: {}\n'.format(prog.get_path()))
fn.write('BuildRequires: meson\n')
fn.write('\n')
fn.write('%description\n')
diff --git a/run_unittests.py b/run_unittests.py
index f72313a..95e52e3 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -585,9 +585,9 @@ class WindowsTests(BasePlatformTests):
self.assertTrue(prog1.found(), msg='cmd not found')
prog2 = ExternalProgram('cmd.exe')
self.assertTrue(prog2.found(), msg='cmd.exe not found')
- self.assertPathEqual(prog1.fullpath[0], prog2.fullpath[0])
+ self.assertPathEqual(prog1.get_path(), prog2.get_path())
# Find cmd with an absolute path that's missing the extension
- cmd_path = prog2.fullpath[0][:-4]
+ cmd_path = prog2.get_path()[:-4]
prog = ExternalProgram(cmd_path)
self.assertTrue(prog.found(), msg='{!r} not found'.format(cmd_path))
# Finding a script with no extension inside a directory works
@@ -600,13 +600,13 @@ class WindowsTests(BasePlatformTests):
os.environ['PATH'] += os.pathsep + testdir
prog = ExternalProgram('test-script-ext')
self.assertTrue(prog.found(), msg='test-script-ext not found in PATH')
- self.assertPathEqual(prog.fullpath[0], sys.executable)
- self.assertPathBasenameEqual(prog.fullpath[1], 'test-script-ext.py')
+ self.assertPathEqual(prog.get_command()[0], sys.executable)
+ self.assertPathBasenameEqual(prog.get_path(), 'test-script-ext.py')
# Finding a script in PATH with extension works and adds the interpreter
prog = ExternalProgram('test-script-ext.py')
self.assertTrue(prog.found(), msg='test-script-ext.py not found in PATH')
- self.assertPathEqual(prog.fullpath[0], sys.executable)
- self.assertPathBasenameEqual(prog.fullpath[1], 'test-script-ext.py')
+ self.assertPathEqual(prog.get_command()[0], sys.executable)
+ self.assertPathBasenameEqual(prog.get_path(), 'test-script-ext.py')
class LinuxlikeTests(BasePlatformTests):
diff --git a/test cases/common/105 find program path/meson.build b/test cases/common/105 find program path/meson.build
index 8040bb3..e1e6d2e 100644
--- a/test cases/common/105 find program path/meson.build
+++ b/test cases/common/105 find program path/meson.build
@@ -1,18 +1,25 @@
project('find program', 'c')
-prog = find_program('program.py')
-
python = find_program('python3', required : false)
if not python.found()
python = find_program('python')
endif
-run_command(python, prog.path())
-
+# Source file via string
+prog = find_program('program.py')
+# Source file via files()
progf = files('program.py')
+# Built file
py = configure_file(input : 'program.py',
output : 'builtprogram.py',
configuration : configuration_data())
-find_program(py)
-find_program(progf)
+foreach f : [prog, find_program(py), find_program(progf)]
+ ret = run_command(python, f.path())
+ 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)
+ assert(ret.returncode() == 0, 'can\'t run @0@'.format(prog.path()))
+ assert(ret.stdout().strip() == 'Found', 'wrong output from @0@'.format(prog.path()))
+endforeach