@@ -48,27 +48,31 @@ class HookError(Exception):
4848caches = {}
4949def cached (func ):
5050 def wrapper (* args , ** kwargs ):
51- if not caches .has_key (func ):
52- caches [func ] = func (* args , ** kwargs )
53- return caches [func ]
51+ if not caches .has_key (( func . __name__ , args ) ):
52+ caches [( func . __name__ , args ) ] = func (* args , ** kwargs )
53+ return caches [( func . __name__ , args ) ]
5454 return wrapper
5555
5656class Target :
5757 # Cumulative attributes can have values appended to them, so they
5858 # need to be computed differently than regular attributes
5959 __cumulative_attributes = ['extra_labels' , 'macros' , 'device_has' , 'features' ]
6060
61- # {target_name: target_instance} map for all the targets in the system
62- __target_map = {}
63-
64- # List of targets that were added dynamically using "add_py_targets" (see below)
65- __py_targets = set ()
61+ # Location of the 'targets.json' file
62+ __targets_json_location = os .path .join (os .path .dirname (os .path .abspath (__file__ )), '..' , 'hal' , 'targets.json' )
6663
6764 # Load the description of JSON target data
6865 @staticmethod
6966 @cached
7067 def get_json_target_data ():
71- return json_file_to_dict (os .path .join (os .path .dirname (os .path .abspath (__file__ )), '..' , 'hal' , 'targets.json' ))
68+ return json_file_to_dict (Target .__targets_json_location )
69+
70+ # Set the location of the targets.json file
71+ @staticmethod
72+ def set_targets_json_location (location ):
73+ Target .__targets_json_location = location
74+ # Invalidate caches, since the location of the JSON file changed
75+ caches .clear ()
7276
7377 # Get the members of this module using Python's "inspect" module
7478 @staticmethod
@@ -168,42 +172,26 @@ def __getattr__(self, attrname):
168172 return v
169173
170174 # Add one or more new target(s) represented as a Python dictionary in 'new_targets'
171- # It it an error to add a target with a name that exists in "targets.json"
172- # However, it is OK to add a target that was previously added via "add_py_targets"
173- # (this makes testing easier without changing the regular semantics)
175+ # It is an error to add a target with a name that already exists.
174176 @staticmethod
175177 def add_py_targets (new_targets ):
176178 crt_data = Target .get_json_target_data ()
177- # First add all elemnts to the internal dictionary
178179 for tk , tv in new_targets .items ():
179- if crt_data .has_key (tk ) and ( not tk in Target . __py_targets ) :
180+ if crt_data .has_key (tk ):
180181 raise Exception ("Attempt to add target '%s' that already exists" % tk )
182+ # Add target data to the internal target dictionary
181183 crt_data [tk ] = tv
182- Target .__py_targets .add (tk )
183- # Then create the new instances and update global variables if needed
184- for tk , tv in new_targets .items ():
185- # Is the target already created?
186- old_target = Target .__target_map .get (tk , None )
187- # Instantiate this target. If it is public, update the data in
188- # in TARGETS, TARGET_MAP, TARGET_NAMES
184+ # Create the new target and add it to the relevant data structures
189185 new_target = Target (tk )
190- if tv .get ("public" , True ):
191- if old_target : # remove the old target from TARGETS and TARGET_NAMES
192- TARGETS .remove (old_target )
193- TARGET_NAMES .remove (tk )
194- # Add the new target
195- TARGETS .append (new_target )
196- TARGET_MAP [tk ] = new_target
197- TARGET_NAMES .append (tk )
198- # Update the target cache
199- Target .__target_map [tk ] = new_target
186+ TARGETS .append (new_target )
187+ TARGET_MAP [tk ] = new_target
188+ TARGET_NAMES .append (tk )
200189
201190 # Return the target instance starting from the target name
202191 @staticmethod
192+ @cached
203193 def get_target (name ):
204- if not Target .__target_map .has_key (name ):
205- Target .__target_map [name ] = Target (name )
206- return Target .__target_map [name ]
194+ return Target (name )
207195
208196 def __init__ (self , name ):
209197 self .name = name
@@ -414,3 +402,15 @@ def get_target_detect_codes():
414402 for detect_code in target .detect_code :
415403 result [detect_code ] = target .name
416404 return result
405+
406+ # Sets the location of the JSON file that contains the targets
407+ def set_targets_json_location (location ):
408+ # First instruct Target about the new location
409+ Target .set_targets_json_location (location )
410+ # Then re-initialize TARGETS, TARGET_MAP and TARGET_NAMES
411+ # The re-initialization does not create new variables, it keeps the old ones instead
412+ # This ensures compatibility with code that does "from tools.targets import TARGET_NAMES"
413+ TARGETS [:] = [Target .get_target (name ) for name , value in Target .get_json_target_data ().items () if value .get ("public" , True )]
414+ TARGET_MAP .clear ()
415+ TARGET_MAP .update (dict ([(t .name , t ) for t in TARGETS ]))
416+ TARGET_NAMES [:] = TARGET_MAP .keys ()
0 commit comments