dependencies: Handle /usr/bin/env shebangs on Haiku

/usr/bin/env does not exist on Haiku since there's no /usr. The actual
location is /bin/env. Detect that case and directly use the
interpreter being passed to `env` in the shebang.

Also reorganize the Windows special cases which does the same thing.
pull/2745/head
Nirbheek Chauhan 7 years ago
parent 75bc95bd66
commit 5a1d294b5e
  1. 53
      mesonbuild/dependencies/base.py

@ -626,9 +626,20 @@ class ExternalProgram:
# Windows does not ship python3.exe, but we know the path to it # Windows does not ship python3.exe, but we know the path to it
if len(commands) > 0 and commands[0] == 'python3': if len(commands) > 0 and commands[0] == 'python3':
commands = mesonlib.python_command + commands[1:] commands = mesonlib.python_command + commands[1:]
elif mesonlib.is_haiku():
# Haiku does not have /usr, but a lot of scripts assume that
# /usr/bin/env always exists. Detect that case and run the
# script with the interpreter after it.
if commands[0] == '/usr/bin/env':
commands = commands[1:]
# We know what python3 is, we're running on it
if len(commands) > 0 and commands[0] == 'python3':
commands = mesonlib.python_command + commands[1:]
return commands + [script] return commands + [script]
except Exception: except Exception as e:
mlog.debug(e)
pass pass
mlog.debug('Unusable script {!r}'.format(script))
return False return False
def _is_executable(self, path): def _is_executable(self, path):
@ -659,21 +670,17 @@ class ExternalProgram:
return [trial_ext] return [trial_ext]
return False return False
def _search(self, name, search_dir): def _search_windows_special_cases(self, name, command):
''' '''
Search in the specified dir for the specified executable by name Lots of weird Windows quirks:
and if not found search in PATH 1. PATH search for @name returns files with extensions from PATHEXT,
but only self.windows_exts are executable without an interpreter.
2. @name might be an absolute path to an executable, but without the
extension. This works inside MinGW so people use it a lot.
3. The script is specified without an extension, in which case we have
to manually search in PATH.
4. More special-casing for the shebang inside the script.
''' '''
commands = self._search_dir(name, search_dir)
if commands:
return commands
# Do a standard search in PATH
command = shutil.which(name)
if not mesonlib.is_windows():
# On UNIX-like platforms, shutil.which() is enough to find
# all executables whether in PATH or with an absolute path
return [command]
# HERE BEGINS THE TERROR OF WINDOWS
if command: if command:
# On Windows, even if the PATH search returned a full path, we can't be # 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. # sure that it can be run directly if it's not a native executable.
@ -687,7 +694,7 @@ class ExternalProgram:
commands = self._shebang_to_cmd(command) commands = self._shebang_to_cmd(command)
if commands: if commands:
return commands return commands
else: return [None]
# Maybe the name is an absolute path to a native Windows # Maybe the name is an absolute path to a native Windows
# executable, but without the extension. This is technically wrong, # executable, but without the extension. This is technically wrong,
# but many people do it because it works in the MinGW shell. # but many people do it because it works in the MinGW shell.
@ -706,6 +713,22 @@ class ExternalProgram:
return commands return commands
return [None] return [None]
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
command = shutil.which(name)
if mesonlib.is_windows():
return self._search_windows_special_cases(name, command)
# On UNIX-like platforms, shutil.which() is enough to find
# all executables whether in PATH or with an absolute path
return [command]
def found(self): def found(self):
return self.command[0] is not None return self.command[0] is not None

Loading…
Cancel
Save