@ -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