aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/dependencies.py
diff options
context:
space:
mode:
authorNirbheek Chauhan <nirbheek@centricular.com>2017-02-07 17:22:18 +0530
committerNirbheek Chauhan <nirbheek@centricular.com>2017-02-18 02:38:54 +0530
commit18bce476913de4deec18fcd028cb59d378c43812 (patch)
treee0c561119bc89ea4b98ffc6641a5028aa20556fc /mesonbuild/dependencies.py
parentd5b494492481a4379174786237cbc4d7eb037373 (diff)
downloadmeson-18bce476913de4deec18fcd028cb59d378c43812.zip
meson-18bce476913de4deec18fcd028cb59d378c43812.tar.gz
meson-18bce476913de4deec18fcd028cb59d378c43812.tar.bz2
find_program: Correctly use scripts found in PATH
We also need to check whether the program found in PATH can be executed directly by Windows or if we need to figure out what the interpreter is and add it to the list. Also add `msc` to the list of extensions that can be executed natively Includes a project test and a unit test for this and all expected behaviours on Windows.
Diffstat (limited to 'mesonbuild/dependencies.py')
-rw-r--r--mesonbuild/dependencies.py50
1 files changed, 38 insertions, 12 deletions
diff --git a/mesonbuild/dependencies.py b/mesonbuild/dependencies.py
index 9525ffa..920a279 100644
--- a/mesonbuild/dependencies.py
+++ b/mesonbuild/dependencies.py
@@ -402,7 +402,7 @@ class WxDependency(Dependency):
return self.is_found
class ExternalProgram:
- windows_exts = ('exe', 'com', 'bat')
+ windows_exts = ('exe', 'msc', 'com', 'bat')
def __init__(self, name, fullpath=None, silent=False, search_dir=None):
self.name = name
@@ -420,6 +420,10 @@ class ExternalProgram:
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)
+
@staticmethod
def _shebang_to_cmd(script):
"""
@@ -473,27 +477,49 @@ class ExternalProgram:
return self._shebang_to_cmd(trial)
def _search(self, name, search_dir):
+ '''
+ Search in the specified dir for the specified executable by name
+ and if not found search in PATH
+ '''
commands = self._search_dir(name, search_dir)
if commands:
return commands
# Do a standard search in PATH
fullpath = shutil.which(name)
- if fullpath or not mesonlib.is_windows():
+ if not mesonlib.is_windows():
# On UNIX-like platforms, the standard PATH search is enough
return [fullpath]
- # On Windows, if name is an absolute path, we need the extension too
- for ext in self.windows_exts:
- fullpath = '{}.{}'.format(name, ext)
- if os.path.exists(fullpath):
+ # HERE BEGINS THE TERROR OF WINDOWS
+ if fullpath:
+ # 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]
+ if name_ext[1:].lower() in self.windows_exts:
+ # Good, it can be directly executed
return [fullpath]
- # 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.
- search_dirs = os.environ.get('PATH', '').split(';')
- for search_dir in search_dirs:
- commands = self._search_dir(name, search_dir)
+ # Try to extract the interpreter from the shebang
+ commands = self._shebang_to_cmd(fullpath)
if commands:
return commands
+ else:
+ # Maybe the name is an absolute path to a native Windows
+ # executable, but without the extension. This is technically wrong,
+ # 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]
+ # 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.
+ search_dirs = os.environ.get('PATH', '').split(';')
+ for search_dir in search_dirs:
+ commands = self._search_dir(name, search_dir)
+ if commands:
+ return commands
return [None]
def found(self):