2727from copy import deepcopy
2828from tools .config import Config
2929from abc import ABCMeta , abstractmethod
30+ from distutils .spawn import find_executable
3031
3132from multiprocessing import Pool , cpu_count
3233from tools .utils import run_cmd , mkdir , rel_path , ToolException , NotSupportedException , split_path , compile_worker
@@ -188,23 +189,6 @@ def __str__(self):
188189}
189190
190191
191- def check_toolchain_path (function ):
192- """Check if the path to toolchain is valid. Exit if not.
193- Use this function as a decorator. Causes a system exit if the path does
194- not exist. Execute the function as normal if the path does exist.
195-
196- Positional arguments:
197- function -- the function to decorate
198- """
199- def perform_check (self , * args , ** kwargs ):
200- if not exists (self .toolchain_path ) and not exists (self .toolchain_path + '.exe' ):
201- error_string = 'Could not find executable for %s.\n Currently ' \
202- 'set search path: %s' % (self .name , self .toolchain_path )
203- raise Exception (error_string )
204- return function (self , * args , ** kwargs )
205- return perform_check
206-
207-
208192class mbedToolchain :
209193 # Verbose logging
210194 VERBOSE = True
@@ -723,7 +707,6 @@ def get_arch_file(self, objects):
723707
724708 # THIS METHOD IS BEING CALLED BY THE MBED ONLINE BUILD SYSTEM
725709 # ANY CHANGE OF PARAMETERS OR RETURN VALUES WILL BREAK COMPATIBILITY
726- @check_toolchain_path
727710 def compile_sources (self , resources , build_path , inc_dirs = None ):
728711 # Web IDE progress bar for project build
729712 files_to_compile = resources .s_sources + resources .c_sources + resources .cpp_sources
@@ -922,7 +905,6 @@ def compile_output(self, output=[]):
922905 else :
923906 raise ToolException (_stderr )
924907
925- @check_toolchain_path
926908 def build_library (self , objects , dir , name ):
927909 needed_update = False
928910 lib = self .STD_LIB_NAME % name
@@ -934,7 +916,6 @@ def build_library(self, objects, dir, name):
934916
935917 return needed_update
936918
937- @check_toolchain_path
938919 def link_program (self , r , tmp_path , name ):
939920 needed_update = False
940921 ext = 'bin'
@@ -1114,6 +1095,51 @@ def get_config_header(self):
11141095 self .config_processed = True
11151096 return self .config_file
11161097
1098+ @staticmethod
1099+ def generic_check_executable (tool_key , executable_name , levels_up ,
1100+ nested_dir = None ):
1101+ """
1102+ Positional args:
1103+ tool_key: the key to index TOOLCHAIN_PATHS
1104+ executable_name: the toolchain's named executable (ex. armcc)
1105+ levels_up: each toolchain joins the toolchain_path, some
1106+ variable directories (bin, include), and the executable name,
1107+ so the TOOLCHAIN_PATH value must be appropriately distanced
1108+
1109+ Keyword args:
1110+ nested_dir: the directory within TOOLCHAIN_PATHS where the executable
1111+ is found (ex: 'bin' for ARM\b in\a rmcc (necessary to check for path
1112+ that will be used by toolchain's compile)
1113+
1114+ Returns True if the executable location specified by the user
1115+ exists and is valid OR the executable can be found on the PATH.
1116+ Returns False otherwise.
1117+ """
1118+ # Search PATH if user did not specify a path or specified path doesn't
1119+ # exist.
1120+ if not TOOLCHAIN_PATHS [tool_key ] or not exists (TOOLCHAIN_PATHS [tool_key ]):
1121+ exe = find_executable (executable_name )
1122+ if not exe :
1123+ return False
1124+ for level in range (levels_up ):
1125+ # move up the specified number of directories
1126+ exe = dirname (exe )
1127+ TOOLCHAIN_PATHS [tool_key ] = exe
1128+ if nested_dir :
1129+ subdir = join (TOOLCHAIN_PATHS [tool_key ], nested_dir ,
1130+ executable_name )
1131+ else :
1132+ subdir = join (TOOLCHAIN_PATHS [tool_key ],executable_name )
1133+ # User could have specified a path that exists but does not contain exe
1134+ return exists (subdir ) or exists (subdir + '.exe' )
1135+
1136+ @abstractmethod
1137+ def check_executable (self ):
1138+ """Returns True if the executable (armcc) location specified by the
1139+ user exists OR the executable can be found on the PATH.
1140+ Returns False otherwise."""
1141+ raise NotImplemented
1142+
11171143 @abstractmethod
11181144 def get_config_option (self , config_header ):
11191145 """Generate the compiler option that forces the inclusion of the configuration
0 commit comments