aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2016-07-30 18:52:09 +0300
committerGitHub <noreply@github.com>2016-07-30 18:52:09 +0300
commitfb3f4420b2b4ac2b664bc7f853851d5f283b15d6 (patch)
treea67f62c86fba06abda14e11490d4b9fb4cbe312a
parent933c11821e21879eac6bd2c8e3c4b7902abeccfd (diff)
parent9f67c29eb46884d9d18611897a9f32542d4566b4 (diff)
downloadmeson-fb3f4420b2b4ac2b664bc7f853851d5f283b15d6.zip
meson-fb3f4420b2b4ac2b664bc7f853851d5f283b15d6.tar.gz
meson-fb3f4420b2b4ac2b664bc7f853851d5f283b15d6.tar.bz2
Merge pull request #659 from centricular/find-program-scripts-windows
find_program: Find scripts without extensions on Windows
-rw-r--r--mesonbuild/dependencies.py87
-rw-r--r--test cases/windows/9 find program/meson.build4
-rw-r--r--test cases/windows/9 find program/test-script3
3 files changed, 69 insertions, 25 deletions
diff --git a/mesonbuild/dependencies.py b/mesonbuild/dependencies.py
index 3f1e214..b4f825b 100644
--- a/mesonbuild/dependencies.py
+++ b/mesonbuild/dependencies.py
@@ -353,37 +353,13 @@ class WxDependency(Dependency):
class ExternalProgram():
def __init__(self, name, fullpath=None, silent=False, search_dir=None):
self.name = name
- self.fullpath = None
if fullpath is not None:
if not isinstance(fullpath, list):
self.fullpath = [fullpath]
else:
self.fullpath = fullpath
else:
- self.fullpath = [shutil.which(name)]
- if self.fullpath[0] is None and search_dir is not None:
- trial = os.path.join(search_dir, name)
- suffix = os.path.splitext(trial)[-1].lower()[1:]
- if mesonlib.is_windows() and (suffix == 'exe' or suffix == 'com'\
- or suffix == 'bat'):
- self.fullpath = [trial]
- elif not mesonlib.is_windows() and os.access(trial, os.X_OK):
- self.fullpath = [trial]
- else:
- # Now getting desperate. Maybe it is a script file that is a) not chmodded
- # executable or b) we are on windows so they can't be directly executed.
- try:
- first_line = open(trial).readline().strip()
- if first_line.startswith('#!'):
- commands = first_line[2:].split('#')[0].strip().split()
- if mesonlib.is_windows():
- # Windows does not have /usr/bin.
- commands[0] = commands[0].split('/')[-1]
- if commands[0] == 'env':
- commands = commands[1:]
- self.fullpath = commands + [trial]
- except Exception:
- pass
+ self.fullpath = self._search(name, search_dir)
if not silent:
if self.found():
mlog.log('Program', mlog.bold(name), 'found:', mlog.green('YES'),
@@ -391,6 +367,67 @@ class ExternalProgram():
else:
mlog.log('Program', mlog.bold(name), 'found:', mlog.red('NO'))
+ @staticmethod
+ def _shebang_to_cmd(script):
+ """
+ Windows does not understand shebangs, so we check if the file has a
+ shebang and manually parse it to figure out the interpreter to use
+ """
+ try:
+ first_line = open(script).readline().strip()
+ if first_line.startswith('#!'):
+ commands = first_line[2:].split('#')[0].strip().split()
+ if mesonlib.is_windows():
+ # Windows does not have /usr/bin.
+ commands[0] = commands[0].split('/')[-1]
+ if commands[0] == 'env':
+ commands = commands[1:]
+ return commands + [script]
+ except Exception:
+ pass
+ return False
+
+ @staticmethod
+ def _is_executable(path):
+ suffix = os.path.splitext(path)[-1].lower()[1:]
+ if mesonlib.is_windows():
+ if suffix == 'exe' or suffix == 'com' or suffix == 'bat':
+ return True
+ elif os.access(path, os.X_OK):
+ return True
+ return False
+
+ def _search_dir(self, name, search_dir):
+ if search_dir is None:
+ return False
+ trial = os.path.join(search_dir, name)
+ if not os.path.exists(trial):
+ return False
+ if self._is_executable(trial):
+ return [trial]
+ # Now getting desperate. Maybe it is a script file that is a) not chmodded
+ # executable or b) we are on windows so they can't be directly executed.
+ return self._shebang_to_cmd(trial)
+
+ def _search(self, name, search_dir):
+ 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():
+ # On UNIX-like platforms, the standard PATH search is enough
+ 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):
return self.fullpath[0] is not None
diff --git a/test cases/windows/9 find program/meson.build b/test cases/windows/9 find program/meson.build
new file mode 100644
index 0000000..ef34586
--- /dev/null
+++ b/test cases/windows/9 find program/meson.build
@@ -0,0 +1,4 @@
+project('find program', 'c')
+
+prog = find_program('test-script')
+test('script', prog)
diff --git a/test cases/windows/9 find program/test-script b/test cases/windows/9 find program/test-script
new file mode 100644
index 0000000..d105a81
--- /dev/null
+++ b/test cases/windows/9 find program/test-script
@@ -0,0 +1,3 @@
+#!/usr/bin/env python
+
+print('1')