diff options
author | Nirbheek Chauhan <nirbheek@centricular.com> | 2017-02-19 03:19:13 +0530 |
---|---|---|
committer | Nirbheek Chauhan <nirbheek@centricular.com> | 2017-02-19 03:49:31 +0530 |
commit | 7e805a019ae4d923403af8032776c0c302e3a50c (patch) | |
tree | f235ff5c0039b8e43469dce0d9606bb30a722595 | |
parent | 280346da3ac5904ec097afe89ef45ad34bd4a173 (diff) | |
download | meson-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.py | 14 | ||||
-rw-r--r-- | mesonbuild/backend/vs2010backend.py | 2 | ||||
-rw-r--r-- | mesonbuild/dependencies.py | 49 | ||||
-rw-r--r-- | mesonbuild/interpreter.py | 6 | ||||
-rw-r--r-- | mesonbuild/modules/qt4.py | 6 | ||||
-rw-r--r-- | mesonbuild/modules/qt5.py | 6 | ||||
-rw-r--r-- | mesonbuild/modules/rpm.py | 2 | ||||
-rwxr-xr-x | run_unittests.py | 12 | ||||
-rw-r--r-- | test cases/common/105 find program path/meson.build | 19 |
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 |